]> git.0d.be Git - empathy.git/blob - src/empathy-tube-dispatch.c
Remove useless spaces in message.
[empathy.git] / src / empathy-tube-dispatch.c
1 /*
2  * empathy-tube-dispatch.c - Source for EmpathyTubeDispatch
3  * Copyright (C) 2008 Collabora Ltd.
4  * @author Sjoerd Simons <sjoerd.simons@collabora.co.uk>
5  *
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.
10  *
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.
15  *
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
19  */
20
21
22 #include <stdio.h>
23 #include <stdlib.h>
24
25 #include <telepathy-glib/dbus.h>
26 #include <telepathy-glib/util.h>
27 #include <telepathy-glib/proxy-subclass.h>
28
29 #include <gtk/gtk.h>
30 #include <glib/gi18n.h>
31
32
33 #include <libempathy/empathy-tube-handler.h>
34 #include <extensions/extensions.h>
35
36
37 #include "empathy-tube-dispatch.h"
38 #include "empathy-tube-dispatch-enumtypes.h"
39
40
41 G_DEFINE_TYPE(EmpathyTubeDispatch, empathy_tube_dispatch, G_TYPE_OBJECT)
42
43 static void empathy_tube_dispatch_set_ability (
44   EmpathyTubeDispatch *tube_dispatch,
45   EmpathyTubeDispatchAbility dispatchability);
46
47 /* private structure */
48 typedef struct _EmpathyTubeDispatchPriv EmpathyTubeDispatchPriv;
49
50 /* properties */
51 enum {
52     PROP_OPERATION = 1,
53     PROP_DISPATCHABILITY
54 };
55
56
57 struct _EmpathyTubeDispatchPriv
58 {
59   gboolean dispose_has_run;
60   EmpathyDispatchOperation *operation;
61   EmpathyTubeDispatchAbility dispatchability;
62   gchar *service;
63   gchar *bus_name;
64   gchar *object_path;
65   TpDBusDaemon *dbus;
66 };
67
68 #define GET_PRIV(o) \
69  (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
70   EMPATHY_TYPE_TUBE_DISPATCH, EmpathyTubeDispatchPriv))
71
72 static void
73 empathy_tube_dispatch_init (EmpathyTubeDispatch *obj)
74 {
75   EmpathyTubeDispatchPriv *priv = GET_PRIV (obj);
76
77   priv->dispatchability = EMPATHY_TUBE_DISPATCHABILITY_UNKNOWN;
78 }
79
80 static void empathy_tube_dispatch_dispose (GObject *object);
81 static void empathy_tube_dispatch_finalize (GObject *object);
82
83 static void
84 empathy_tube_dispatch_list_activatable_names_cb (TpDBusDaemon *proxy,
85   const gchar **names, const GError *error, gpointer user_data,
86   GObject *object)
87 {
88   EmpathyTubeDispatch *self = EMPATHY_TUBE_DISPATCH (object);
89   EmpathyTubeDispatchPriv *priv = GET_PRIV (self);
90   gchar **name;
91
92   for (name = (gchar **) names; *name != NULL; name++)
93     {
94       if (!tp_strdiff (*name, priv->bus_name))
95         {
96           empathy_tube_dispatch_set_ability (self,
97             EMPATHY_TUBE_DISPATCHABILITY_POSSIBLE);
98           return;
99         }
100     }
101
102   empathy_tube_dispatch_set_ability (self,
103     EMPATHY_TUBE_DISPATCHABILITY_IMPOSSIBLE);
104 }
105
106 static void
107 empathy_tube_dispatch_name_has_owner_cb (TpDBusDaemon *proxy,
108   gboolean has_owner, const GError *error, gpointer user_data,
109   GObject *object)
110 {
111   EmpathyTubeDispatch *self = EMPATHY_TUBE_DISPATCH (object);
112   EmpathyTubeDispatchPriv *priv = GET_PRIV (self);
113
114   if (error != NULL)
115     {
116       empathy_tube_dispatch_set_ability (self,
117         EMPATHY_TUBE_DISPATCHABILITY_IMPOSSIBLE);
118       return;
119     }
120
121   if (has_owner)
122     {
123       empathy_tube_dispatch_set_ability (self,
124         EMPATHY_TUBE_DISPATCHABILITY_POSSIBLE);
125     }
126   else
127     {
128       tp_cli_dbus_daemon_call_list_activatable_names (priv->dbus, -1,
129         empathy_tube_dispatch_list_activatable_names_cb, NULL, NULL,
130         G_OBJECT (self));
131     }
132 }
133
134 static void
135 empathy_tube_dispatch_constructed (GObject *object)
136 {
137   EmpathyTubeDispatch *self = EMPATHY_TUBE_DISPATCH (object);
138   EmpathyTubeDispatchPriv *priv = GET_PRIV (self);
139   TpChannel *channel;
140   GHashTable *properties;
141   const gchar *service;
142   const gchar *channel_type;
143   EmpathyTubeType type;
144
145   priv->dbus = tp_dbus_daemon_new (tp_get_bus());
146
147   channel = empathy_dispatch_operation_get_channel (priv->operation);
148   properties = tp_channel_borrow_immutable_properties (channel);
149
150   channel_type = tp_asv_get_string (properties,
151     TP_IFACE_CHANNEL ".ChannelType");
152   if (channel_type == NULL)
153     goto failed;
154
155   if (!tp_strdiff (channel_type, EMP_IFACE_CHANNEL_TYPE_STREAM_TUBE))
156     {
157       type = EMPATHY_TYPE_STREAM_TUBE;
158       service = tp_asv_get_string (properties,
159         EMP_IFACE_CHANNEL_TYPE_STREAM_TUBE  ".Service");
160     }
161   else if (!tp_strdiff (channel_type, EMP_IFACE_CHANNEL_TYPE_DBUS_TUBE))
162     {
163       type = EMPATHY_TYPE_DBUS_TUBE;
164       service = tp_asv_get_string (properties,
165         EMP_IFACE_CHANNEL_TYPE_DBUS_TUBE  ".ServiceName");
166     }
167   else
168     {
169       goto failed;
170     }
171
172
173   if (service == NULL)
174     goto failed;
175
176   priv->bus_name = empathy_tube_handler_build_bus_name (type, service);
177   priv->object_path = empathy_tube_handler_build_object_path (type, service);
178
179   priv->service = g_strdup (service);
180
181   tp_cli_dbus_daemon_call_name_has_owner (priv->dbus, -1, priv->bus_name,
182     empathy_tube_dispatch_name_has_owner_cb, NULL, NULL, G_OBJECT (self));
183
184   return;
185
186 failed:
187   empathy_tube_dispatch_set_ability (self,
188     EMPATHY_TUBE_DISPATCHABILITY_IMPOSSIBLE);
189 }
190
191 static void
192 empathy_tube_dispatch_set_property (GObject *object,
193   guint property_id, const GValue *value, GParamSpec *pspec)
194 {
195   EmpathyTubeDispatch *tube_dispatch = EMPATHY_TUBE_DISPATCH (object);
196   EmpathyTubeDispatchPriv *priv = GET_PRIV (tube_dispatch);
197
198   switch (property_id)
199     {
200       case PROP_OPERATION:
201         priv->operation = g_value_dup_object (value);
202         break;
203       default:
204         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
205         break;
206     }
207 }
208
209 static void
210 empathy_tube_dispatch_get_property (GObject *object,
211   guint property_id, GValue *value, GParamSpec *pspec)
212 {
213   EmpathyTubeDispatch *tube_dispatch = EMPATHY_TUBE_DISPATCH (object);
214   EmpathyTubeDispatchPriv *priv = GET_PRIV (tube_dispatch);
215
216   switch (property_id)
217     {
218       case PROP_OPERATION:
219         g_value_set_object (value, priv->operation);
220         break;
221       case PROP_DISPATCHABILITY:
222         g_value_set_enum (value, priv->dispatchability);
223         break;
224       default:
225         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
226         break;
227     }
228 }
229
230 static void
231 empathy_tube_dispatch_class_init (
232   EmpathyTubeDispatchClass *empathy_tube_dispatch_class)
233 {
234   GObjectClass *object_class = G_OBJECT_CLASS (empathy_tube_dispatch_class);
235   GParamSpec *param_spec;
236
237   g_type_class_add_private (empathy_tube_dispatch_class,
238     sizeof (EmpathyTubeDispatchPriv));
239
240   object_class->set_property = empathy_tube_dispatch_set_property;
241   object_class->get_property = empathy_tube_dispatch_get_property;
242
243   object_class->constructed = empathy_tube_dispatch_constructed;
244   object_class->dispose = empathy_tube_dispatch_dispose;
245   object_class->finalize = empathy_tube_dispatch_finalize;
246
247   param_spec = g_param_spec_object ("operation",
248     "operation", "The telepathy connection",
249     EMPATHY_TYPE_DISPATCH_OPERATION,
250     G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
251   g_object_class_install_property (object_class, PROP_OPERATION, param_spec);
252
253   param_spec = g_param_spec_enum ("dispatchability",
254     "dispatchability",
255     "Whether or not there is a handler to dispatch the operation to",
256     EMPATHY_TYPE_TUBE_DISPATCH_ABILITY, EMPATHY_TUBE_DISPATCHABILITY_UNKNOWN,
257     G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
258   g_object_class_install_property (object_class, PROP_DISPATCHABILITY,
259     param_spec);
260
261 }
262
263 void
264 empathy_tube_dispatch_dispose (GObject *object)
265 {
266   EmpathyTubeDispatch *self = EMPATHY_TUBE_DISPATCH (object);
267   EmpathyTubeDispatchPriv *priv = GET_PRIV (self);
268
269   if (priv->dispose_has_run)
270     return;
271
272   priv->dispose_has_run = TRUE;
273
274   /* release any references held by the object here */
275   if (priv->operation != NULL)
276     g_object_unref (priv->operation);
277
278   priv->operation = NULL;
279
280   if (priv->dbus != NULL)
281     g_object_unref (priv->dbus);
282
283   priv->dbus = NULL;
284
285
286   if (G_OBJECT_CLASS (empathy_tube_dispatch_parent_class)->dispose)
287     G_OBJECT_CLASS (empathy_tube_dispatch_parent_class)->dispose (object);
288 }
289
290 void
291 empathy_tube_dispatch_finalize (GObject *object)
292 {
293   EmpathyTubeDispatch *self = EMPATHY_TUBE_DISPATCH (object);
294   EmpathyTubeDispatchPriv *priv = GET_PRIV (self);
295
296   g_free (priv->bus_name);
297   g_free (priv->object_path);
298   g_free (priv->service);
299
300   /* free any data held directly by the object here */
301
302   G_OBJECT_CLASS (empathy_tube_dispatch_parent_class)->finalize (object);
303 }
304
305 EmpathyTubeDispatch *
306 empathy_tube_dispatch_new (EmpathyDispatchOperation *operation)
307 {
308   return EMPATHY_TUBE_DISPATCH (g_object_new (EMPATHY_TYPE_TUBE_DISPATCH,
309       "operation", operation, NULL));
310 }
311
312 EmpathyTubeDispatchAbility
313 empathy_tube_dispatch_is_dispatchable (EmpathyTubeDispatch *tube_dispatch)
314 {
315   EmpathyTubeDispatchPriv *priv = GET_PRIV (tube_dispatch);
316
317   return priv->dispatchability;
318 }
319
320 static void
321 empathy_tube_dispatch_set_ability (EmpathyTubeDispatch *tube_dispatch,
322   EmpathyTubeDispatchAbility dispatchability)
323 {
324   EmpathyTubeDispatchPriv *priv = GET_PRIV (tube_dispatch);
325
326   if (priv->dispatchability == dispatchability)
327     return;
328
329   priv->dispatchability = dispatchability;
330   g_object_notify (G_OBJECT (tube_dispatch), "dispatchability");
331 }
332
333 static void
334 empathy_tube_dispatch_show_error (EmpathyTubeDispatch *self, gchar *message)
335 {
336   GtkWidget *dialog;
337
338   dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_MODAL,
339       GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE, "%s", message);
340
341   gtk_dialog_run (GTK_DIALOG (dialog));
342
343   gtk_widget_destroy (dialog);
344 }
345
346 static void
347 empathy_tube_dispatch_handle_tube_cb (TpProxy *proxy, const GError *error,
348   gpointer user_data, GObject *object)
349 {
350   EmpathyTubeDispatch *self = EMPATHY_TUBE_DISPATCH (object);
351   EmpathyTubeDispatchPriv *priv = GET_PRIV (self);
352
353   if (error != NULL)
354     {
355       gchar *msg = g_strdup_printf (
356         _("Unable to start application for service %s: %s"),
357           priv->service,  error->message);
358
359       empathy_tube_dispatch_show_error (self, msg);
360       g_free (msg);
361     }
362
363   /* Remove the ref we were holding because of the dispatching */
364   g_object_unref (object);
365 }
366
367 static void
368 empathy_tube_do_dispatch (EmpathyTubeDispatch *self)
369 {
370   EmpathyTubeDispatchPriv *priv = GET_PRIV (self);
371   TpChannel *channel;
372   TpProxy *connection;
373   TpProxy *thandler;
374   gchar   *object_path;
375   guint    handle_type;
376   guint    handle;
377
378   channel = empathy_dispatch_operation_get_channel (priv->operation);
379
380   /* Create the proxy for the tube handler */
381   thandler = g_object_new (TP_TYPE_PROXY,
382     "dbus-connection", tp_get_bus (),
383     "bus-name", priv->bus_name,
384     "object-path", priv->object_path,
385     NULL);
386
387   tp_proxy_add_interface_by_id (thandler, EMP_IFACE_QUARK_TUBE_HANDLER);
388
389   /* Give the tube to the handler */
390   g_object_get (channel,
391     "connection", &connection,
392     "object-path", &object_path,
393     "handle_type", &handle_type,
394     "handle", &handle,
395     NULL);
396
397   emp_cli_tube_handler_call_handle_tube (thandler, -1,
398     connection->bus_name, connection->object_path,
399     object_path, handle_type, handle,
400     empathy_tube_dispatch_handle_tube_cb, NULL, NULL, G_OBJECT (self));
401
402   g_object_unref (thandler);
403   g_object_unref (connection);
404   g_free (object_path);
405 }
406
407 void
408 empathy_tube_dispatch_handle (EmpathyTubeDispatch *tube_dispatch)
409 {
410   EmpathyTubeDispatchPriv *priv = GET_PRIV (tube_dispatch);
411
412   /* Keep ourselves alive untill the dispatching is finished */
413   g_object_ref (tube_dispatch);
414
415   /* If we can't claim it, don't do anything */
416   if (!empathy_dispatch_operation_claim (priv->operation))
417     goto done;
418
419   if (priv->dispatchability != EMPATHY_TUBE_DISPATCHABILITY_POSSIBLE)
420     {
421       gchar *msg;
422       TpChannel *channel;
423
424       channel = empathy_dispatch_operation_get_channel (priv->operation);
425
426       msg = g_strdup_printf (
427         _("An invitation was offered for service %s, but you don't have the "
428           "needed application to handle it"), priv->service);
429
430       empathy_tube_dispatch_show_error (tube_dispatch, msg);
431
432       g_free (msg);
433
434       tp_cli_channel_call_close (channel, -1, NULL, NULL, NULL, NULL);
435
436       goto done;
437     }
438   else
439     {
440       empathy_tube_do_dispatch (tube_dispatch);
441     }
442
443   return;
444 done:
445   g_object_unref (tube_dispatch);
446 }
447