/* * Copyright (C) 2008 Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Authors: Elliot Fairweather */ #include #include #include #include #include #include #include #include #include #include #define DEBUG_DOMAIN "EmpathyTubesChandler" static void empathy_tubes_chandler_async_cb (TpProxy *proxy, const GError *error, gpointer data, GObject *weak_object) { if (error) empathy_debug (DEBUG_DOMAIN, "Error %s: %s", data, error->message); } static void empathy_tubes_chandler_new_tube_cb (EmpathyTubes *tubes, EmpathyTube *tube, gpointer data) { GHashTable *channels = (GHashTable *) data; TpChannel *channel; TpConnection *connection; gchar *channel_path; gchar *connection_name; gchar *connection_path; guint handle_type; guint handle; gpointer value; guint number; TpProxy *thandler; gchar *thandler_bus_name; gchar *thandler_object_path; guint id; guint type; gchar *service; guint state; g_object_get (G_OBJECT (tubes), "channel", &channel, NULL); g_object_get (G_OBJECT (channel), "connection", &connection, "object-path", &channel_path, NULL); value = g_hash_table_lookup (channels, channel_path); if (!value) { g_hash_table_insert (channels, g_strdup (channel_path), (GUINT_TO_POINTER (1))); empathy_debug (DEBUG_DOMAIN, "Started tube count for channel %s - total: 1", channel_path); } else { number = GPOINTER_TO_UINT (value); g_hash_table_replace (channels, g_strdup (channel_path), GUINT_TO_POINTER (++number)); empathy_debug (DEBUG_DOMAIN, "Increased tube count for channel %s - total: %d", channel_path, number); } g_object_get (G_OBJECT (tube), "state", &state, NULL); if (state != TP_TUBE_STATE_LOCAL_PENDING) { g_free (channel_path); g_object_unref (channel); g_object_unref (connection); return; } g_object_get (G_OBJECT (tube), "service", &service, "type", &type, NULL); if (type == TP_TUBE_TYPE_DBUS) { thandler_bus_name = g_strdup_printf ("org.gnome.Empathy.DTube.%s", service); thandler_object_path = g_strdup_printf ("/org/gnome/Empathy/DTube/%s", service); } else if (type == TP_TUBE_TYPE_STREAM) { thandler_bus_name = g_strdup_printf ("org.gnome.Empathy.StreamTube.%s", service); thandler_object_path = g_strdup_printf ("/org/gnome/Empathy/StreamTube/%s", service); } else { g_free (channel_path); g_object_unref (channel); g_object_unref (connection); return; } thandler = g_object_new (TP_TYPE_PROXY, "bus-name", thandler_bus_name, "dbus-connection", tp_get_bus (), "object-path", thandler_object_path, NULL); tp_proxy_add_interface_by_id (thandler, EMP_IFACE_QUARK_TUBE_HANDLER); g_object_get (G_OBJECT (tube), "id", &id, NULL); g_object_get (G_OBJECT (channel), "handle-type", &handle_type, "handle", &handle, NULL); g_object_get (G_OBJECT (connection), "bus-name", &connection_name, "object-path", &connection_path, NULL); empathy_debug (DEBUG_DOMAIN, "Dispatching new tube to %s", thandler_bus_name); emp_cli_tube_handler_call_handle_tube (thandler, -1, connection_name, connection_path, channel_path, handle_type, handle, id, empathy_tubes_chandler_async_cb, "handling tube", NULL, NULL); g_free (connection_path); g_free (connection_name); g_free (service); g_free (thandler_bus_name); g_free (thandler_object_path); g_object_unref (thandler); g_free (channel_path); g_object_unref (channel); g_object_unref (connection); } static void empathy_tubes_chandler_tube_closed_cb (EmpathyTubes *tubes, guint tube_id, gpointer data) { TpChannel *channel; gchar *channel_path; gpointer value; guint number; GHashTable *channels = (GHashTable *) data; g_object_get (G_OBJECT (tubes), "channel", &channel, NULL); g_object_get (G_OBJECT (channel), "object-path", &channel_path, NULL); value = g_hash_table_lookup (channels, channel_path); if (value) { number = GPOINTER_TO_UINT (value); if (number == 1) { g_hash_table_remove (channels, channel_path); empathy_tubes_close (tubes); empathy_debug (DEBUG_DOMAIN, "Ended tube count for channel %s - total: 0", channel_path); empathy_debug (DEBUG_DOMAIN, "Closing channel"); } else if (number > 1) { g_hash_table_replace (channels, channel_path, GUINT_TO_POINTER (--number)); empathy_debug (DEBUG_DOMAIN, "Decreased tube count for channel %s - total: %d", channel_path, number); } } g_free (channel_path); g_object_unref (channel); } static void empathy_tubes_new_channel_cb (EmpathyChandler *chandler, TpChannel *channel, gpointer data) { EmpathyTubes *tubes = empathy_tubes_new (channel); GHashTable *channels = (GHashTable *) data; GSList *tube_list, *list; empathy_debug (DEBUG_DOMAIN, "Handling new channel"); g_signal_connect (G_OBJECT (tubes), "new-tube", G_CALLBACK (empathy_tubes_chandler_new_tube_cb), (gpointer) channels); g_signal_connect (G_OBJECT (tubes), "tube-closed", G_CALLBACK (empathy_tubes_chandler_tube_closed_cb), (gpointer) channels); tube_list = empathy_tubes_list_tubes (tubes); for (list = tube_list; list != NULL; list = g_slist_next (list)) { EmpathyTube *tube = EMPATHY_TUBE (list->data); empathy_tubes_chandler_new_tube_cb (tubes, tube, (gpointer) channels); g_object_unref (tube); } g_slist_free (tube_list); } int main (int argc, char *argv[]) { EmpathyChandler *chandler; GMainLoop *loop; GHashTable *channels; g_type_init (); emp_cli_init (); channels = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); chandler = empathy_chandler_new ("org.gnome.Empathy.TubesChandler", "/org/gnome/Empathy/TubesChandler"); g_signal_connect (chandler, "new-channel", G_CALLBACK (empathy_tubes_new_channel_cb), (gpointer) channels); empathy_debug (DEBUG_DOMAIN, "Ready to handle new tubes channels"); loop = g_main_loop_new (NULL, FALSE); g_main_loop_run (loop); g_hash_table_unref (channels); g_object_unref (chandler); return 0; }