]> git.0d.be Git - empathy.git/blob - libempathy/empathy-dispatch-operation.c
Updated Basque language
[empathy.git] / libempathy / empathy-dispatch-operation.c
1 /*
2  * empathy-dispatch-operation.c - Source for EmpathyDispatchOperation
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/interfaces.h>
26
27 #include "empathy-dispatch-operation.h"
28 #include <libempathy/empathy-enum-types.h>
29 #include <libempathy/empathy-tp-contact-factory.h>
30 #include <libempathy/empathy-tp-chat.h>
31 #include <libempathy/empathy-tp-call.h>
32 #include <libempathy/empathy-tp-file.h>
33
34 #include "empathy-marshal.h"
35
36 #include "extensions/extensions.h"
37
38 #define DEBUG_FLAG EMPATHY_DEBUG_DISPATCHER
39 #include <libempathy/empathy-debug.h>
40
41 G_DEFINE_TYPE(EmpathyDispatchOperation, empathy_dispatch_operation,
42   G_TYPE_OBJECT)
43
44 static void empathy_dispatch_operation_set_status (
45   EmpathyDispatchOperation *self, EmpathyDispatchOperationState status);
46 static void empathy_dispatch_operation_channel_ready_cb (TpChannel *channel,
47   const GError *error, gpointer user_data);
48
49 /* signal enum */
50 enum
51 {
52     /* Ready for dispatching */
53     READY,
54     /* Approved by an approver, can only happens on incoming operations */
55     APPROVED,
56     /* Claimed by a handler */
57     CLAIMED,
58     /* Error, channel went away, inspecting it failed etc */
59     INVALIDATED,
60     LAST_SIGNAL
61 };
62
63 static guint signals[LAST_SIGNAL] = {0};
64
65 /* properties */
66 enum {
67   PROP_CONNECTION = 1,
68   PROP_CHANNEL,
69   PROP_CHANNEL_WRAPPER,
70   PROP_CONTACT,
71   PROP_INCOMING,
72   PROP_STATUS,
73 };
74
75 /* private structure */
76 typedef struct _EmpathyDispatchOperationPriv \
77   EmpathyDispatchOperationPriv;
78
79 struct _EmpathyDispatchOperationPriv
80 {
81   gboolean dispose_has_run;
82   TpConnection *connection;
83   TpChannel *channel;
84   GObject *channel_wrapper;
85   EmpathyContact *contact;
86   EmpathyDispatchOperationState status;
87   gboolean incoming;
88   gboolean approved;
89   gulong invalidated_handler;
90   gulong ready_handler;
91 };
92
93 #define GET_PRIV(o)  \
94   (G_TYPE_INSTANCE_GET_PRIVATE ((o), EMPATHY_TYPE_DISPATCH_OPERATION, \
95     EmpathyDispatchOperationPriv))
96
97 static void
98 empathy_dispatch_operation_init (EmpathyDispatchOperation *obj)
99 {
100   //EmpathyDispatchOperationPriv *priv =
101   //  GET_PRIV (obj);
102
103   /* allocate any data required by the object here */
104 }
105
106 static void empathy_dispatch_operation_dispose (GObject *object);
107 static void empathy_dispatch_operation_finalize (GObject *object);
108
109 static void
110 empathy_dispatch_operation_set_property (GObject *object,
111   guint property_id, const GValue *value, GParamSpec *pspec)
112 {
113   EmpathyDispatchOperation *operation = EMPATHY_DISPATCH_OPERATION (object);
114   EmpathyDispatchOperationPriv *priv = GET_PRIV (operation);
115
116   switch (property_id)
117     {
118       case PROP_CONNECTION:
119         priv->connection = g_value_dup_object (value);
120         break;
121       case PROP_CHANNEL:
122         priv->channel = g_value_dup_object (value);
123         break;
124       case PROP_CHANNEL_WRAPPER:
125         priv->channel_wrapper = g_value_dup_object (value);
126         break;
127       case PROP_CONTACT:
128         if (priv->contact != NULL)
129           g_object_unref (priv->contact);
130         priv->contact = g_value_dup_object (value);
131         break;
132       case PROP_INCOMING:
133         priv->incoming = g_value_get_boolean (value);
134         break;
135     }
136 }
137
138 static void
139 empathy_dispatch_operation_get_property (GObject *object,
140   guint property_id, GValue *value, GParamSpec *pspec)
141 {
142   EmpathyDispatchOperation *operation = EMPATHY_DISPATCH_OPERATION (object);
143   EmpathyDispatchOperationPriv *priv = GET_PRIV (operation);
144
145   switch (property_id)
146     {
147       case PROP_CONNECTION:
148         g_value_set_object (value, priv->connection);
149         break;
150       case PROP_CHANNEL:
151         g_value_set_object (value, priv->channel);
152         break;
153       case PROP_CHANNEL_WRAPPER:
154         g_value_set_object (value, priv->channel_wrapper);
155         break;
156       case PROP_CONTACT:
157         g_value_set_object (value, priv->contact);
158         break;
159       case PROP_INCOMING:
160         g_value_set_boolean (value, priv->incoming);
161         break;
162       case PROP_STATUS:
163         g_value_set_enum (value, priv->status);
164         break;
165     }
166 }
167
168 static void
169 empathy_dispatch_operation_invalidated (TpProxy *proxy, guint domain,
170   gint code, char *message, EmpathyDispatchOperation *self)
171 {
172   empathy_dispatch_operation_set_status (self,
173     EMPATHY_DISPATCHER_OPERATION_STATE_INVALIDATED);
174
175   g_signal_emit (self, signals[INVALIDATED], 0, domain, code, message);
176 }
177
178 static void
179 dispatcher_operation_got_contact_cb (EmpathyTpContactFactory *factory,
180                                      EmpathyContact *contact,
181                                      const GError *error,
182                                      gpointer user_data,
183                                      GObject *self)
184 {
185   EmpathyDispatchOperationPriv *priv = GET_PRIV (self);
186
187   if (error)
188     {
189       /* FIXME: We should cancel the operation */
190       DEBUG ("Error: %s", error->message);
191       return;
192     }
193
194   if (priv->contact != NULL)
195     g_object_unref (priv->contact);
196   priv->contact = g_object_ref (contact);
197   g_object_notify (G_OBJECT (self), "contact");
198
199   tp_channel_call_when_ready (priv->channel,
200     empathy_dispatch_operation_channel_ready_cb, self);
201 }
202
203 static void
204 dispatch_operation_connection_ready (TpConnection *connection,
205     const GError *error,
206     gpointer user_data)
207 {
208   EmpathyDispatchOperation *self = EMPATHY_DISPATCH_OPERATION (user_data);
209   EmpathyDispatchOperationPriv *priv = GET_PRIV (self);
210   EmpathyTpContactFactory *factory;
211   TpHandle handle;
212
213   handle = tp_channel_get_handle (priv->channel, NULL);
214
215   factory = empathy_tp_contact_factory_dup_singleton (priv->connection);
216
217   empathy_tp_contact_factory_get_from_handle (factory, handle,
218       dispatcher_operation_got_contact_cb, NULL, NULL, G_OBJECT (self));
219
220   g_object_unref (factory);
221 }
222
223 static void
224 empathy_dispatch_operation_constructed (GObject *object)
225 {
226   EmpathyDispatchOperation *self = EMPATHY_DISPATCH_OPERATION (object);
227   EmpathyDispatchOperationPriv *priv = GET_PRIV (self);
228   TpHandle handle;
229   TpHandleType handle_type;
230
231   empathy_dispatch_operation_set_status (self,
232     EMPATHY_DISPATCHER_OPERATION_STATE_PREPARING);
233
234   priv->invalidated_handler =
235     g_signal_connect (priv->channel, "invalidated",
236       G_CALLBACK (empathy_dispatch_operation_invalidated), self);
237
238   handle = tp_channel_get_handle (priv->channel, &handle_type);
239
240   if (handle_type == TP_HANDLE_TYPE_CONTACT && priv->contact == NULL)
241     {
242       tp_connection_call_when_ready (priv->connection,
243           dispatch_operation_connection_ready, object);
244       return;
245     }
246
247   tp_channel_call_when_ready (priv->channel,
248     empathy_dispatch_operation_channel_ready_cb, self);
249 }
250
251 static void
252 empathy_dispatch_operation_class_init (
253   EmpathyDispatchOperationClass *empathy_dispatch_operation_class)
254 {
255   GObjectClass *object_class =
256     G_OBJECT_CLASS (empathy_dispatch_operation_class);
257   GParamSpec *param_spec;
258
259   g_type_class_add_private (empathy_dispatch_operation_class,
260     sizeof (EmpathyDispatchOperationPriv));
261
262   object_class->set_property = empathy_dispatch_operation_set_property;
263   object_class->get_property = empathy_dispatch_operation_get_property;
264
265   object_class->dispose = empathy_dispatch_operation_dispose;
266   object_class->finalize = empathy_dispatch_operation_finalize;
267   object_class->constructed = empathy_dispatch_operation_constructed;
268
269   signals[READY] = g_signal_new ("ready",
270     G_OBJECT_CLASS_TYPE(empathy_dispatch_operation_class),
271       G_SIGNAL_RUN_LAST,
272       0,
273       NULL, NULL,
274       g_cclosure_marshal_VOID__VOID,
275       G_TYPE_NONE, 0);
276
277   signals[APPROVED] = g_signal_new ("approved",
278     G_OBJECT_CLASS_TYPE(empathy_dispatch_operation_class),
279       G_SIGNAL_RUN_LAST,
280       0,
281       NULL, NULL,
282       g_cclosure_marshal_VOID__VOID,
283       G_TYPE_NONE, 0);
284
285   signals[CLAIMED] = g_signal_new ("claimed",
286     G_OBJECT_CLASS_TYPE(empathy_dispatch_operation_class),
287       G_SIGNAL_RUN_LAST,
288       0,
289       NULL, NULL,
290       g_cclosure_marshal_VOID__VOID,
291       G_TYPE_NONE, 0);
292
293   signals[INVALIDATED] = g_signal_new ("invalidated",
294     G_OBJECT_CLASS_TYPE(empathy_dispatch_operation_class),
295       G_SIGNAL_RUN_LAST,
296       0,
297       NULL, NULL,
298       _empathy_marshal_VOID__UINT_INT_STRING,
299       G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_INT, G_TYPE_STRING);
300
301   param_spec = g_param_spec_object ("connection",
302     "connection", "The telepathy connection",
303     TP_TYPE_CONNECTION,
304     G_PARAM_CONSTRUCT_ONLY |
305     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
306   g_object_class_install_property (object_class, PROP_CONNECTION,
307                                   param_spec);
308
309   param_spec = g_param_spec_object ("channel",
310     "channel", "The telepathy channel",
311     TP_TYPE_CHANNEL,
312     G_PARAM_CONSTRUCT_ONLY |
313     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
314   g_object_class_install_property (object_class, PROP_CHANNEL,
315                                   param_spec);
316
317   param_spec = g_param_spec_object ("channel-wrapper",
318     "channel wrapper", "The empathy specific channel wrapper",
319     G_TYPE_OBJECT,
320     G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
321   g_object_class_install_property (object_class, PROP_CHANNEL_WRAPPER,
322                                   param_spec);
323
324   param_spec = g_param_spec_object ("contact",
325     "contact", "The empathy contact",
326     EMPATHY_TYPE_CONTACT,
327     G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
328   g_object_class_install_property (object_class, PROP_CONTACT,
329                                   param_spec);
330
331   param_spec = g_param_spec_boolean ("incoming",
332     "incoming", "Whether or not the channel is incoming",
333     FALSE,
334     G_PARAM_CONSTRUCT_ONLY |
335     G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
336   g_object_class_install_property (object_class, PROP_INCOMING,
337                                   param_spec);
338
339   param_spec = g_param_spec_enum ("status",
340     "status", "Status of the dispatch operation",
341     EMPATHY_TYPE_DISPATCH_OPERATION_STATE, 0,
342     G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
343   g_object_class_install_property (object_class, PROP_STATUS, param_spec);
344 }
345
346 void
347 empathy_dispatch_operation_dispose (GObject *object)
348 {
349   EmpathyDispatchOperation *self = EMPATHY_DISPATCH_OPERATION (object);
350   EmpathyDispatchOperationPriv *priv =
351     GET_PRIV (self);
352
353   if (priv->dispose_has_run)
354     return;
355
356   priv->dispose_has_run = TRUE;
357
358   g_object_unref (priv->connection);
359
360   if (priv->channel_wrapper != NULL)
361     g_object_unref (priv->channel_wrapper);
362
363   if (priv->ready_handler != 0)
364     g_signal_handler_disconnect (priv->channel_wrapper,
365       priv->invalidated_handler);
366
367
368   g_signal_handler_disconnect (priv->channel, priv->invalidated_handler);
369   g_object_unref (priv->channel);
370
371
372   if (priv->contact != NULL)
373     g_object_unref (priv->contact);
374
375   if (G_OBJECT_CLASS (empathy_dispatch_operation_parent_class)->dispose)
376     G_OBJECT_CLASS (empathy_dispatch_operation_parent_class)->dispose (object);
377 }
378
379 void
380 empathy_dispatch_operation_finalize (GObject *object)
381 {
382   /* free any data held directly by the object here */
383   G_OBJECT_CLASS (empathy_dispatch_operation_parent_class)->finalize (object);
384 }
385
386 static void
387 empathy_dispatch_operation_set_status (EmpathyDispatchOperation *self,
388   EmpathyDispatchOperationState status)
389 {
390   EmpathyDispatchOperationPriv *priv = GET_PRIV (self);
391
392   g_assert (status >= priv->status);
393
394
395   if (priv->status != status)
396     {
397       DEBUG ("Dispatch operation %s status: %d -> %d",
398         empathy_dispatch_operation_get_object_path (self),
399         priv->status, status);
400
401       priv->status = status;
402       g_object_notify (G_OBJECT (self), "status");
403
404       if (status == EMPATHY_DISPATCHER_OPERATION_STATE_PENDING)
405         g_signal_emit (self, signals[READY], 0);
406     }
407 }
408
409 static void
410 empathy_dispatcher_operation_tp_chat_ready_cb (GObject *object,
411   GParamSpec *spec, gpointer user_data)
412 {
413   EmpathyDispatchOperation *self = EMPATHY_DISPATCH_OPERATION (user_data);
414   EmpathyDispatchOperationPriv *priv = GET_PRIV (self);
415
416   if (!empathy_tp_chat_is_ready (EMPATHY_TP_CHAT (priv->channel_wrapper)))
417     return;
418
419   g_signal_handler_disconnect (priv->channel_wrapper, priv->ready_handler);
420   priv->ready_handler = 0;
421
422   empathy_dispatch_operation_set_status (self,
423     EMPATHY_DISPATCHER_OPERATION_STATE_PENDING);
424 }
425
426 static void
427 empathy_dispatch_operation_channel_ready_cb (TpChannel *channel,
428   const GError *error, gpointer user_data)
429 {
430   EmpathyDispatchOperation *self = EMPATHY_DISPATCH_OPERATION (user_data);
431   EmpathyDispatchOperationPriv *priv = GET_PRIV (self);
432   GQuark channel_type;
433
434   /* The error will be handled in empathy_dispatch_operation_invalidated */
435   if (error != NULL)
436     return;
437
438   g_assert (channel == priv->channel);
439
440   /* If the channel wrapper is defined, we assume it's ready */
441   if (priv->channel_wrapper != NULL)
442     goto ready;
443
444   channel_type = tp_channel_get_channel_type_id (channel);
445
446   if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_TEXT)
447     {
448       EmpathyTpChat *chat= empathy_tp_chat_new (channel);
449       priv->channel_wrapper = G_OBJECT (chat);
450
451       if (!empathy_tp_chat_is_ready (chat))
452         {
453           priv->ready_handler = g_signal_connect (chat, "notify::ready",
454             G_CALLBACK (empathy_dispatcher_operation_tp_chat_ready_cb), self);
455           return;
456         }
457     }
458   else if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_STREAMED_MEDIA)
459     {
460       EmpathyTpCall *call = empathy_tp_call_new (channel);
461       priv->channel_wrapper = G_OBJECT (call);
462     }
463   else if (channel_type == TP_IFACE_QUARK_CHANNEL_TYPE_FILE_TRANSFER)
464     {
465        EmpathyTpFile *file = empathy_tp_file_new (channel, priv->incoming);
466        priv->channel_wrapper = G_OBJECT (file);
467     }
468
469 ready:
470   empathy_dispatch_operation_set_status (self,
471     EMPATHY_DISPATCHER_OPERATION_STATE_PENDING);
472 }
473
474 EmpathyDispatchOperation *
475 empathy_dispatch_operation_new (TpConnection *connection, TpChannel *channel,
476   EmpathyContact *contact, gboolean incoming)
477 {
478   return empathy_dispatch_operation_new_with_wrapper (connection, channel,
479     contact, incoming, NULL);
480 }
481
482 EmpathyDispatchOperation *
483 empathy_dispatch_operation_new_with_wrapper (TpConnection *connection,
484   TpChannel *channel, EmpathyContact *contact, gboolean incoming,
485   GObject *wrapper)
486 {
487   g_return_val_if_fail (connection != NULL, NULL);
488   g_return_val_if_fail (channel != NULL, NULL);
489
490   return EMPATHY_DISPATCH_OPERATION (
491     g_object_new (EMPATHY_TYPE_DISPATCH_OPERATION,
492       "connection", connection,
493       "channel", channel,
494       "channel-wrapper", wrapper,
495       "contact", contact,
496       "incoming", incoming,
497       NULL));
498 }
499
500 void
501 empathy_dispatch_operation_start (EmpathyDispatchOperation *operation)
502 {
503   EmpathyDispatchOperationPriv *priv;
504
505   g_return_if_fail (EMPATHY_IS_DISPATCH_OPERATION (operation));
506
507   priv = GET_PRIV (operation);
508
509   g_return_if_fail (
510     priv->status == EMPATHY_DISPATCHER_OPERATION_STATE_PENDING);
511
512   if (priv->incoming && !priv->approved)
513     empathy_dispatch_operation_set_status (operation,
514       EMPATHY_DISPATCHER_OPERATION_STATE_APPROVING);
515   else
516     empathy_dispatch_operation_set_status (operation,
517       EMPATHY_DISPATCHER_OPERATION_STATE_DISPATCHING);
518 }
519
520 void
521 empathy_dispatch_operation_approve (EmpathyDispatchOperation *operation)
522 {
523   EmpathyDispatchOperationPriv *priv;
524
525   g_return_if_fail (EMPATHY_IS_DISPATCH_OPERATION (operation));
526
527   priv = GET_PRIV (operation);
528
529   if (priv->status == EMPATHY_DISPATCHER_OPERATION_STATE_APPROVING)
530     {
531       DEBUG ("Approving operation %s",
532         empathy_dispatch_operation_get_object_path (operation));
533
534       empathy_dispatch_operation_set_status (operation,
535         EMPATHY_DISPATCHER_OPERATION_STATE_DISPATCHING);
536
537       g_signal_emit (operation, signals[APPROVED], 0);
538     }
539   else if (priv->status < EMPATHY_DISPATCHER_OPERATION_STATE_APPROVING)
540     {
541       DEBUG ("Pre-approving operation %s",
542         empathy_dispatch_operation_get_object_path (operation));
543       priv->approved = TRUE;
544     }
545   else
546     {
547       DEBUG (
548         "Ignoring approval for %s as it's already past the approval stage",
549         empathy_dispatch_operation_get_object_path (operation));
550     }
551 }
552
553 /* Returns whether or not the operation was successfully claimed */
554 gboolean
555 empathy_dispatch_operation_claim (EmpathyDispatchOperation *operation)
556 {
557   EmpathyDispatchOperationPriv *priv;
558
559   g_return_val_if_fail (EMPATHY_IS_DISPATCH_OPERATION (operation), FALSE);
560
561   priv = GET_PRIV (operation);
562
563   if (priv->status == EMPATHY_DISPATCHER_OPERATION_STATE_CLAIMED)
564     return FALSE;
565
566   empathy_dispatch_operation_set_status (operation,
567     EMPATHY_DISPATCHER_OPERATION_STATE_CLAIMED);
568
569   g_signal_emit (operation, signals[CLAIMED], 0);
570
571   return TRUE;
572 }
573
574 TpConnection *
575 empathy_dispatch_operation_get_tp_connection (
576   EmpathyDispatchOperation *operation)
577 {
578   EmpathyDispatchOperationPriv *priv;
579
580   g_return_val_if_fail (EMPATHY_IS_DISPATCH_OPERATION (operation), NULL);
581
582   priv = GET_PRIV (operation);
583
584   return priv->connection;
585 }
586
587 TpChannel *
588 empathy_dispatch_operation_get_channel (EmpathyDispatchOperation *operation)
589 {
590   EmpathyDispatchOperationPriv *priv;
591
592   g_return_val_if_fail (EMPATHY_IS_DISPATCH_OPERATION (operation), NULL);
593
594   priv = GET_PRIV (operation);
595
596   return priv->channel;
597 }
598
599 GObject *
600 empathy_dispatch_operation_get_channel_wrapper (
601   EmpathyDispatchOperation *operation)
602 {
603   EmpathyDispatchOperationPriv *priv;
604
605   g_return_val_if_fail (EMPATHY_IS_DISPATCH_OPERATION (operation), NULL);
606
607   priv = GET_PRIV (operation);
608
609   return priv->channel_wrapper;
610 }
611
612 const gchar *
613 empathy_dispatch_operation_get_channel_type (
614   EmpathyDispatchOperation *operation)
615 {
616   EmpathyDispatchOperationPriv *priv;
617
618   g_return_val_if_fail (EMPATHY_IS_DISPATCH_OPERATION (operation), NULL);
619
620   priv = GET_PRIV (operation);
621
622   return tp_channel_get_channel_type (priv->channel);
623 }
624
625 GQuark
626 empathy_dispatch_operation_get_channel_type_id (
627   EmpathyDispatchOperation *operation)
628 {
629   EmpathyDispatchOperationPriv *priv;
630
631   g_return_val_if_fail (EMPATHY_IS_DISPATCH_OPERATION (operation), 0);
632
633   priv = GET_PRIV (operation);
634
635   return tp_channel_get_channel_type_id (priv->channel);
636 }
637
638 const gchar *
639 empathy_dispatch_operation_get_object_path (
640   EmpathyDispatchOperation *operation)
641 {
642   EmpathyDispatchOperationPriv *priv;
643
644   g_return_val_if_fail (EMPATHY_IS_DISPATCH_OPERATION (operation), NULL);
645
646   priv = GET_PRIV (operation);
647
648   return tp_proxy_get_object_path (TP_PROXY (priv->channel));
649 }
650
651 EmpathyDispatchOperationState
652 empathy_dispatch_operation_get_status (EmpathyDispatchOperation *operation)
653 {
654   EmpathyDispatchOperationPriv *priv;
655
656   g_return_val_if_fail (EMPATHY_IS_DISPATCH_OPERATION (operation),
657     EMPATHY_DISPATCHER_OPERATION_STATE_PREPARING);
658
659   priv = GET_PRIV (operation);
660
661   return priv->status;
662 }
663
664 gboolean
665 empathy_dispatch_operation_is_incoming (EmpathyDispatchOperation *operation)
666 {
667   EmpathyDispatchOperationPriv *priv;
668
669   g_return_val_if_fail (EMPATHY_IS_DISPATCH_OPERATION (operation), FALSE);
670
671   priv = GET_PRIV (operation);
672
673   return priv->incoming;
674 }