2 * empathy-tube-dispatch.c - Source for EmpathyTubeDispatch
3 * Copyright (C) 2008 Collabora Ltd.
4 * @author Sjoerd Simons <sjoerd.simons@collabora.co.uk>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 #include <telepathy-glib/dbus.h>
26 #include <telepathy-glib/util.h>
27 #include <telepathy-glib/proxy-subclass.h>
30 #include <glib/gi18n.h>
33 #include <libempathy/empathy-tube-handler.h>
34 #include <extensions/extensions.h>
37 #include "empathy-tube-dispatch.h"
38 #include "empathy-tube-dispatch-enumtypes.h"
41 G_DEFINE_TYPE(EmpathyTubeDispatch, empathy_tube_dispatch, G_TYPE_OBJECT)
43 static void empathy_tube_dispatch_set_ability (
44 EmpathyTubeDispatch *tube_dispatch,
45 EmpathyTubeDispatchAbility dispatchability);
47 /* private structure */
48 typedef struct _EmpathyTubeDispatchPriv EmpathyTubeDispatchPriv;
57 struct _EmpathyTubeDispatchPriv
59 gboolean dispose_has_run;
60 EmpathyDispatchOperation *operation;
61 EmpathyTubeDispatchAbility dispatchability;
69 (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
70 EMPATHY_TYPE_TUBE_DISPATCH, EmpathyTubeDispatchPriv))
73 empathy_tube_dispatch_init (EmpathyTubeDispatch *obj)
75 EmpathyTubeDispatchPriv *priv = GET_PRIV (obj);
77 priv->dispatchability = EMPATHY_TUBE_DISPATCHABILITY_UNKNOWN;
80 static void empathy_tube_dispatch_dispose (GObject *object);
81 static void empathy_tube_dispatch_finalize (GObject *object);
84 empathy_tube_dispatch_list_activatable_names_cb (TpDBusDaemon *proxy,
85 const gchar **names, const GError *error, gpointer user_data,
88 EmpathyTubeDispatch *self = EMPATHY_TUBE_DISPATCH (object);
89 EmpathyTubeDispatchPriv *priv = GET_PRIV (self);
92 for (name = (gchar **) names; *name != NULL; name++)
94 if (!tp_strdiff (*name, priv->bus_name))
96 empathy_tube_dispatch_set_ability (self,
97 EMPATHY_TUBE_DISPATCHABILITY_POSSIBLE);
102 empathy_tube_dispatch_set_ability (self,
103 EMPATHY_TUBE_DISPATCHABILITY_IMPOSSIBLE);
107 empathy_tube_dispatch_name_has_owner_cb (TpDBusDaemon *proxy,
108 gboolean has_owner, const GError *error, gpointer user_data,
111 EmpathyTubeDispatch *self = EMPATHY_TUBE_DISPATCH (object);
112 EmpathyTubeDispatchPriv *priv = GET_PRIV (self);
116 empathy_tube_dispatch_set_ability (self,
117 EMPATHY_TUBE_DISPATCHABILITY_IMPOSSIBLE);
123 empathy_tube_dispatch_set_ability (self,
124 EMPATHY_TUBE_DISPATCHABILITY_POSSIBLE);
128 tp_cli_dbus_daemon_call_list_activatable_names (priv->dbus, -1,
129 empathy_tube_dispatch_list_activatable_names_cb, NULL, NULL,
135 empathy_tube_dispatch_constructed (GObject *object)
137 EmpathyTubeDispatch *self = EMPATHY_TUBE_DISPATCH (object);
138 EmpathyTubeDispatchPriv *priv = GET_PRIV (self);
140 GHashTable *properties;
141 const gchar *service;
143 priv->dbus = tp_dbus_daemon_new (tp_get_bus());
145 channel = empathy_dispatch_operation_get_channel (priv->operation);
146 properties = tp_channel_borrow_immutable_properties (channel);
148 service = tp_asv_get_string (properties,
149 EMP_IFACE_CHANNEL_TYPE_STREAM_TUBE ".Service");
154 priv->bus_name = empathy_tube_handler_build_bus_name (
155 TP_TUBE_TYPE_STREAM, service);
157 empathy_tube_handler_build_object_path (TP_TUBE_TYPE_STREAM, service);
159 priv->service = g_strdup (service);
161 tp_cli_dbus_daemon_call_name_has_owner (priv->dbus, -1, priv->bus_name,
162 empathy_tube_dispatch_name_has_owner_cb, NULL, NULL, G_OBJECT (self));
167 empathy_tube_dispatch_set_ability (self,
168 EMPATHY_TUBE_DISPATCHABILITY_IMPOSSIBLE);
172 empathy_tube_dispatch_set_property (GObject *object,
173 guint property_id, const GValue *value, GParamSpec *pspec)
175 EmpathyTubeDispatch *tube_dispatch = EMPATHY_TUBE_DISPATCH (object);
176 EmpathyTubeDispatchPriv *priv = GET_PRIV (tube_dispatch);
181 priv->operation = g_value_dup_object (value);
184 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
190 empathy_tube_dispatch_get_property (GObject *object,
191 guint property_id, GValue *value, GParamSpec *pspec)
193 EmpathyTubeDispatch *tube_dispatch = EMPATHY_TUBE_DISPATCH (object);
194 EmpathyTubeDispatchPriv *priv = GET_PRIV (tube_dispatch);
199 g_value_set_object (value, priv->operation);
201 case PROP_DISPATCHABILITY:
202 g_value_set_enum (value, priv->dispatchability);
205 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
211 empathy_tube_dispatch_class_init (
212 EmpathyTubeDispatchClass *empathy_tube_dispatch_class)
214 GObjectClass *object_class = G_OBJECT_CLASS (empathy_tube_dispatch_class);
215 GParamSpec *param_spec;
217 g_type_class_add_private (empathy_tube_dispatch_class,
218 sizeof (EmpathyTubeDispatchPriv));
220 object_class->set_property = empathy_tube_dispatch_set_property;
221 object_class->get_property = empathy_tube_dispatch_get_property;
223 object_class->constructed = empathy_tube_dispatch_constructed;
224 object_class->dispose = empathy_tube_dispatch_dispose;
225 object_class->finalize = empathy_tube_dispatch_finalize;
227 param_spec = g_param_spec_object ("operation",
228 "operation", "The telepathy connection",
229 EMPATHY_TYPE_DISPATCH_OPERATION,
230 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
231 g_object_class_install_property (object_class, PROP_OPERATION, param_spec);
233 param_spec = g_param_spec_enum ("dispatchability",
235 "Whether or not there is a handler to dispatch the operation to",
236 EMPATHY_TYPE_TUBE_DISPATCH_ABILITY, EMPATHY_TUBE_DISPATCHABILITY_UNKNOWN,
237 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
238 g_object_class_install_property (object_class, PROP_DISPATCHABILITY,
244 empathy_tube_dispatch_dispose (GObject *object)
246 EmpathyTubeDispatch *self = EMPATHY_TUBE_DISPATCH (object);
247 EmpathyTubeDispatchPriv *priv = GET_PRIV (self);
249 if (priv->dispose_has_run)
252 priv->dispose_has_run = TRUE;
254 /* release any references held by the object here */
255 if (priv->operation != NULL)
256 g_object_unref (priv->operation);
258 priv->operation = NULL;
260 if (priv->dbus != NULL)
261 g_object_unref (priv->dbus);
266 if (G_OBJECT_CLASS (empathy_tube_dispatch_parent_class)->dispose)
267 G_OBJECT_CLASS (empathy_tube_dispatch_parent_class)->dispose (object);
271 empathy_tube_dispatch_finalize (GObject *object)
273 EmpathyTubeDispatch *self = EMPATHY_TUBE_DISPATCH (object);
274 EmpathyTubeDispatchPriv *priv = GET_PRIV (self);
276 g_free (priv->bus_name);
277 g_free (priv->object_path);
278 g_free (priv->service);
280 /* free any data held directly by the object here */
282 G_OBJECT_CLASS (empathy_tube_dispatch_parent_class)->finalize (object);
285 EmpathyTubeDispatch *
286 empathy_tube_dispatch_new (EmpathyDispatchOperation *operation)
288 return EMPATHY_TUBE_DISPATCH (g_object_new (EMPATHY_TYPE_TUBE_DISPATCH,
289 "operation", operation, NULL));
292 EmpathyTubeDispatchAbility
293 empathy_tube_dispatch_is_dispatchable (EmpathyTubeDispatch *tube_dispatch)
295 EmpathyTubeDispatchPriv *priv = GET_PRIV (tube_dispatch);
297 return priv->dispatchability;
301 empathy_tube_dispatch_set_ability (EmpathyTubeDispatch *tube_dispatch,
302 EmpathyTubeDispatchAbility dispatchability)
304 EmpathyTubeDispatchPriv *priv = GET_PRIV (tube_dispatch);
306 if (priv->dispatchability == dispatchability)
309 priv->dispatchability = dispatchability;
310 g_object_notify (G_OBJECT (tube_dispatch), "dispatchability");
314 empathy_tube_dispatch_show_error (EmpathyTubeDispatch *self, gchar *message)
318 dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL,
319 GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE, message);
321 gtk_dialog_run (GTK_DIALOG (dialog));
323 gtk_widget_destroy (dialog);
327 empathy_tube_dispatch_handle_tube_cb (TpProxy *proxy, const GError *error,
328 gpointer user_data, GObject *object)
330 EmpathyTubeDispatch *self = EMPATHY_TUBE_DISPATCH (object);
331 EmpathyTubeDispatchPriv *priv = GET_PRIV (self);
335 gchar *msg = g_strdup_printf (
336 _("Unable to start application for service %s: %s"),
337 priv->service, error->message);
339 empathy_tube_dispatch_show_error (self, msg);
343 /* Remove the ref we were holding because of the dispatching */
344 g_object_unref (object);
348 empathy_tube_do_dispatch (EmpathyTubeDispatch *self)
350 EmpathyTubeDispatchPriv *priv = GET_PRIV (self);
358 channel = empathy_dispatch_operation_get_channel (priv->operation);
360 /* Create the proxy for the tube handler */
361 thandler = g_object_new (TP_TYPE_PROXY,
362 "dbus-connection", tp_get_bus (),
363 "bus-name", priv->bus_name,
364 "object-path", priv->object_path,
367 tp_proxy_add_interface_by_id (thandler, EMP_IFACE_QUARK_TUBE_HANDLER);
369 /* Give the tube to the handler */
370 g_object_get (channel,
371 "connection", &connection,
372 "object-path", &object_path,
373 "handle_type", &handle_type,
377 emp_cli_tube_handler_call_handle_tube (thandler, -1,
378 connection->bus_name, connection->object_path,
379 object_path, handle_type, handle,
380 empathy_tube_dispatch_handle_tube_cb, NULL, NULL, G_OBJECT (self));
382 g_object_unref (thandler);
383 g_object_unref (connection);
384 g_free (object_path);
388 empathy_tube_dispatch_handle (EmpathyTubeDispatch *tube_dispatch)
390 EmpathyTubeDispatchPriv *priv = GET_PRIV (tube_dispatch);
392 /* Keep ourselves alive untill the dispatching is finished */
393 g_object_ref (tube_dispatch);
395 /* If we can't claim it, don't do anything */
396 if (!empathy_dispatch_operation_claim (priv->operation))
399 if (priv->dispatchability != EMPATHY_TUBE_DISPATCHABILITY_POSSIBLE)
404 channel = empathy_dispatch_operation_get_channel (priv->operation);
406 msg = g_strdup_printf (
407 _(" An invitation was offered for service %s, but you don't have the"
408 " needed application to handle it "), priv->service);
410 empathy_tube_dispatch_show_error (tube_dispatch, msg);
414 tp_cli_channel_call_close (channel, -1, NULL, NULL, NULL, NULL);
420 empathy_tube_do_dispatch (tube_dispatch);
425 g_object_unref (tube_dispatch);