/* * © 2009, 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: Arnaud Maillet */ #include #include #include #include #include #include #define DEBUG_FLAG EMPATHY_DEBUG_SHARE_DESKTOP #include #include "empathy-share-my-desktop.h" #define DBUS_SERVICE "org.gnome.Vino" #define DBUS_INTERFACE "org.gnome.VinoScreen" typedef struct { TpContact *contact; TpChannel *channel; gulong signal_invalidated_id; } EmpathyShareMyDesktopPrivate; static void empathy_share_my_desktop_tube_invalidated (TpProxy *channel, guint domain, gint code, gchar *message, gpointer object) { EmpathyShareMyDesktopPrivate *data = (EmpathyShareMyDesktopPrivate *) object; DEBUG ("Tube is invalidated"); g_signal_handler_disconnect (G_OBJECT (data->channel), data->signal_invalidated_id); if (data->channel != NULL) { g_object_unref (data->channel); data->channel = NULL; } g_slice_free (EmpathyShareMyDesktopPrivate, data); } static void empathy_share_my_desktop_channel_ready (TpChannel *channel, const GError *error_failed, gpointer object) { EmpathyShareMyDesktopPrivate *data = (EmpathyShareMyDesktopPrivate *) object; TpConnection *connection; gchar * connection_path; gchar * tube_path; DBusGConnection *dbus_g_connection; GHashTable *channel_properties; DBusGProxy *proxy; GError *error = NULL; GdkScreen *screen; gchar *obj_path; GtkWidget *window; if (channel == NULL) { DEBUG ("The channel is not ready: %s", error_failed->message); return; } data->channel = channel; data->signal_invalidated_id = g_signal_connect (G_OBJECT (channel), "invalidated", G_CALLBACK (empathy_share_my_desktop_tube_invalidated), data); dbus_g_connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error); if (dbus_g_connection == NULL) { DEBUG ("Failed to open connection to bus: %s", error->message); g_clear_error (&error); return; } screen = gdk_screen_get_default (); obj_path = g_strdup_printf ("/org/gnome/vino/screens/%d", gdk_screen_get_number (screen)); proxy = dbus_g_proxy_new_for_name (dbus_g_connection, DBUS_SERVICE, obj_path, DBUS_INTERFACE); connection = tp_channel_borrow_connection (channel); g_object_get (connection, "object-path", &connection_path, NULL); DEBUG ("connection path : %s", connection_path); g_object_get (channel, "object-path", &tube_path, "channel-properties", &channel_properties, NULL); DEBUG ("tube path : %s", tube_path); if (!dbus_g_proxy_call (proxy, "ShareWithTube", &error, DBUS_TYPE_G_OBJECT_PATH, connection_path, DBUS_TYPE_G_OBJECT_PATH, tube_path, dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), channel_properties, G_TYPE_INVALID, G_TYPE_INVALID)) { window = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "Vino doesn't support telepathy"); gtk_dialog_run (GTK_DIALOG (window)); gtk_widget_destroy (window); DEBUG ("Failed to request name: %s", error ? error->message : "No error given"); g_clear_error (&error); } g_hash_table_unref (channel_properties); g_free (connection_path); g_free (tube_path); g_free (obj_path); g_object_unref (proxy); } static void empathy_share_my_desktop_create_channel_cb (TpConnection *connection, const gchar *object_path, GHashTable *channel_properties, const GError *error_failed, gpointer user_data, GObject *object) { EmpathyShareMyDesktopPrivate *data = (EmpathyShareMyDesktopPrivate *) user_data; TpChannel *channel; GError *error = NULL; if (object_path == NULL) { DEBUG ("CreateChannel failed: %s", error_failed->message); return; } DEBUG ("Offering a new stream tube"); channel = tp_channel_new_from_properties (connection, object_path, channel_properties, &error); if (channel == NULL) { DEBUG ("Error requesting channel: %s", error->message); g_clear_error (&error); return; } tp_channel_call_when_ready (channel, empathy_share_my_desktop_channel_ready, data); } static void empathy_share_my_desktop_connection_ready (TpConnection *connection, const GError *error, gpointer object) { EmpathyShareMyDesktopPrivate *data = (EmpathyShareMyDesktopPrivate *) object; GHashTable *request; GValue *value; if (connection == NULL) { DEBUG ("The connection is not ready: %s", error->message); return; } request = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) tp_g_value_slice_free); /* org.freedesktop.Telepathy.Channel.ChannelType */ value = tp_g_value_slice_new_static_string (TP_IFACE_CHANNEL_TYPE_STREAM_TUBE); g_hash_table_insert (request, TP_IFACE_CHANNEL ".ChannelType", value); /* org.freedesktop.Telepathy.Channel.TargetHandleType */ value = tp_g_value_slice_new_uint (TP_HANDLE_TYPE_CONTACT); g_hash_table_insert (request, TP_IFACE_CHANNEL ".TargetHandleType", value); /* org.freedesktop.Telepathy.Channel.TargetHandleType */ value = tp_g_value_slice_new_uint (tp_contact_get_handle (data->contact)); g_hash_table_insert (request, TP_IFACE_CHANNEL ".TargetHandle", value); /* org.freedesktop.Telepathy.Channel.Type.StreamTube.Service */ value = tp_g_value_slice_new_static_string ("rfb"); g_hash_table_insert (request, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE ".Service", value); tp_cli_connection_interface_requests_call_create_channel (connection, -1, request, empathy_share_my_desktop_create_channel_cb, data, NULL, NULL); g_hash_table_destroy (request); } void empathy_share_my_desktop_share_with_contact (EmpathyContact *contact) { TpConnection *connection; EmpathyShareMyDesktopPrivate *data; data = g_slice_new (EmpathyShareMyDesktopPrivate); data->contact = empathy_contact_get_tp_contact (contact); DEBUG ("Creation of ShareMyDesktop"); if (!TP_IS_CONTACT (data->contact)) { DEBUG ("It's not a tp contact"); return; } connection = tp_contact_get_connection (data->contact); tp_connection_call_when_ready (connection, empathy_share_my_desktop_connection_ready, data); }