2 * Copyright (C) 2007-2008 Collabora Ltd.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 * Authors: Xavier Claessens <xclaesse@gmail.com>
19 * Sjoerd Simons <sjoerd.simons@collabora.co.uk>
25 #include <glib/gi18n.h>
27 #include <telepathy-glib/util.h>
29 #include <libempathy/empathy-dispatcher.h>
30 #include <libempathy/empathy-contact-factory.h>
31 #include <libempathy/empathy-contact-manager.h>
32 #include <libempathy/empathy-tp-chat.h>
33 #include <libempathy/empathy-tp-call.h>
34 #include <libempathy/empathy-utils.h>
35 #include <libempathy/empathy-call-factory.h>
37 #include <extensions/extensions.h>
39 #include <libempathy-gtk/empathy-images.h>
40 #include <libempathy-gtk/empathy-contact-dialogs.h>
41 #include <libempathy-gtk/empathy-ui-utils.h>
43 #include "empathy-event-manager.h"
44 #include "empathy-main-window.h"
45 #include "empathy-tube-dispatch.h"
47 #define DEBUG_FLAG EMPATHY_DEBUG_DISPATCHER
48 #include <libempathy/empathy-debug.h>
50 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyEventManager)
53 EmpathyEventManager
*manager
;
54 EmpathyDispatchOperation
*operation
;
55 gulong approved_handler
;
56 gulong claimed_handler
;
57 gulong invalidated_handler
;
58 /* Remove contact if applicable */
59 EmpathyContact
*contact
;
60 /* Tube dispatcher if applicable */
61 EmpathyTubeDispatch
*tube_dispatch
;
62 /* option signal handler and it's instance */
64 GObject
*handler_instance
;
65 /* optional accept widget */
67 } EventManagerApproval
;
70 EmpathyDispatcher
*dispatcher
;
71 EmpathyContactManager
*contact_manager
;
73 /* Ongoing approvals */
76 /* voip ringing sound */
79 } EmpathyEventManagerPriv
;
81 typedef struct _EventPriv EventPriv
;
82 typedef void (*EventFunc
) (EventPriv
*event
);
86 EmpathyEventManager
*manager
;
87 EventManagerApproval
*approval
;
100 static guint signals
[LAST_SIGNAL
];
102 G_DEFINE_TYPE (EmpathyEventManager
, empathy_event_manager
, G_TYPE_OBJECT
);
104 static EmpathyEventManager
* manager_singleton
= NULL
;
106 static EventManagerApproval
*
107 event_manager_approval_new (EmpathyEventManager
*manager
,
108 EmpathyDispatchOperation
*operation
)
110 EventManagerApproval
*result
= g_slice_new0 (EventManagerApproval
);
111 result
->operation
= g_object_ref (operation
);
112 result
->manager
= manager
;
118 event_manager_approval_free (EventManagerApproval
*approval
)
120 g_signal_handler_disconnect (approval
->operation
,
121 approval
->approved_handler
);
122 g_signal_handler_disconnect (approval
->operation
,
123 approval
->claimed_handler
);
124 g_signal_handler_disconnect (approval
->operation
,
125 approval
->invalidated_handler
);
126 g_object_unref (approval
->operation
);
128 if (approval
->handler
!= 0)
129 g_signal_handler_disconnect (approval
->handler_instance
,
132 if (approval
->contact
!= NULL
)
133 g_object_unref (approval
->contact
);
135 if (approval
->tube_dispatch
!= NULL
)
136 g_object_unref (approval
->tube_dispatch
);
138 if (approval
->dialog
!= NULL
)
140 gtk_widget_destroy (approval
->dialog
);
143 g_slice_free (EventManagerApproval
, approval
);
146 static void event_remove (EventPriv
*event
);
149 event_free (EventPriv
*event
)
151 g_free (event
->public.icon_name
);
152 g_free (event
->public.header
);
153 g_free (event
->public.message
);
155 if (event
->public.contact
)
157 g_object_unref (event
->public.contact
);
160 g_slice_free (EventPriv
, event
);
163 static void event_manager_ringing_finished_cb (ca_context
*c
, guint id
,
164 int error_code
, gpointer user_data
);
167 event_manager_ringing_timeout_cb (gpointer data
)
169 EmpathyEventManager
*manager
= EMPATHY_EVENT_MANAGER (data
);
170 EmpathyEventManagerPriv
*priv
= GET_PRIV (manager
);
172 priv
->voip_timeout
= 0;
174 empathy_sound_play_full (empathy_main_window_get (),
175 EMPATHY_SOUND_PHONE_INCOMING
, event_manager_ringing_finished_cb
,
182 event_manager_ringing_idle_cb (gpointer data
)
184 EmpathyEventManager
*manager
= EMPATHY_EVENT_MANAGER (data
);
185 EmpathyEventManagerPriv
*priv
= GET_PRIV (manager
);
187 if (priv
->ringing
> 0)
188 priv
->voip_timeout
= g_timeout_add (500, event_manager_ringing_timeout_cb
,
195 event_manager_ringing_finished_cb (ca_context
*c
, guint id
, int error_code
,
198 if (error_code
== CA_ERROR_CANCELED
)
201 g_idle_add (event_manager_ringing_idle_cb
, user_data
);
205 event_manager_start_ringing (EmpathyEventManager
*manager
)
207 EmpathyEventManagerPriv
*priv
= GET_PRIV (manager
);
211 if (priv
->ringing
== 1)
213 empathy_sound_play_full (empathy_main_window_get (),
214 EMPATHY_SOUND_PHONE_INCOMING
, event_manager_ringing_finished_cb
,
220 event_manager_stop_ringing (EmpathyEventManager
*manager
)
222 EmpathyEventManagerPriv
*priv
= GET_PRIV (manager
);
226 if (priv
->ringing
> 0)
229 empathy_sound_stop (EMPATHY_SOUND_PHONE_INCOMING
);
231 if (priv
->voip_timeout
!= 0)
233 g_source_remove (priv
->voip_timeout
);
234 priv
->voip_timeout
= 0;
239 event_remove (EventPriv
*event
)
241 EmpathyEventManagerPriv
*priv
= GET_PRIV (event
->manager
);
243 DEBUG ("Removing event %p", event
);
244 priv
->events
= g_slist_remove (priv
->events
, event
);
245 g_signal_emit (event
->manager
, signals
[EVENT_REMOVED
], 0, event
);
250 event_manager_add (EmpathyEventManager
*manager
, EmpathyContact
*contact
,
251 const gchar
*icon_name
, const gchar
*header
, const gchar
*message
,
252 EventManagerApproval
*approval
, EventFunc func
, gpointer user_data
)
254 EmpathyEventManagerPriv
*priv
= GET_PRIV (manager
);
257 event
= g_slice_new0 (EventPriv
);
258 event
->public.contact
= contact
? g_object_ref (contact
) : NULL
;
259 event
->public.icon_name
= g_strdup (icon_name
);
260 event
->public.header
= g_strdup (header
);
261 event
->public.message
= g_strdup (message
);
262 event
->inhibit
= FALSE
;
264 event
->user_data
= user_data
;
265 event
->manager
= manager
;
266 event
->approval
= approval
;
268 DEBUG ("Adding event %p", event
);
269 priv
->events
= g_slist_prepend (priv
->events
, event
);
270 g_signal_emit (event
->manager
, signals
[EVENT_ADDED
], 0, event
);
274 event_channel_process_func (EventPriv
*event
)
276 empathy_dispatch_operation_approve (event
->approval
->operation
);
280 event_text_channel_process_func (EventPriv
*event
)
282 EmpathyTpChat
*tp_chat
;
284 if (event
->approval
->handler
!= 0)
286 tp_chat
= EMPATHY_TP_CHAT
287 (empathy_dispatch_operation_get_channel_wrapper (event
->approval
->operation
));
289 g_signal_handler_disconnect (tp_chat
, event
->approval
->handler
);
290 event
->approval
->handler
= 0;
293 empathy_dispatch_operation_approve (event
->approval
->operation
);
297 event_lookup_by_approval (EmpathyEventManager
*manager
,
298 EventManagerApproval
*approval
)
300 EmpathyEventManagerPriv
*priv
= GET_PRIV (manager
);
302 EventPriv
*retval
= NULL
;
304 for (l
= priv
->events
; l
; l
= l
->next
)
306 EventPriv
*event
= l
->data
;
308 if (event
->approval
== approval
)
319 event_update (EmpathyEventManager
*manager
, EventPriv
*event
,
320 const char *icon_name
, const char *header
, const char *msg
)
322 g_free (event
->public.icon_name
);
323 g_free (event
->public.header
);
324 g_free (event
->public.message
);
326 event
->public.icon_name
= g_strdup (icon_name
);
327 event
->public.header
= g_strdup (header
);
328 event
->public.message
= g_strdup (msg
);
330 g_signal_emit (manager
, signals
[EVENT_UPDATED
], 0, event
);
334 event_manager_call_window_confirmation_dialog_response_cb (GtkDialog
*dialog
,
335 gint response
, gpointer user_data
)
337 EventManagerApproval
*approval
= user_data
;
339 gtk_widget_destroy (approval
->dialog
);
340 approval
->dialog
= NULL
;
342 if (response
!= GTK_RESPONSE_ACCEPT
)
344 EmpathyTpCall
*call
=
346 empathy_dispatch_operation_get_channel_wrapper (
347 approval
->operation
));
350 if (empathy_dispatch_operation_claim (approval
->operation
))
351 empathy_tp_call_close (call
);
352 g_object_unref (call
);
357 EmpathyCallFactory
*factory
= empathy_call_factory_get ();
358 empathy_call_factory_claim_channel (factory
, approval
->operation
);
363 event_channel_process_voip_func (EventPriv
*event
)
369 if (event
->approval
->dialog
!= NULL
)
371 gtk_window_present (GTK_WINDOW (event
->approval
->dialog
));
375 dialog
= gtk_message_dialog_new (GTK_WINDOW (empathy_main_window_get()),
376 GTK_DIALOG_MODAL
| GTK_DIALOG_DESTROY_WITH_PARENT
,
377 GTK_MESSAGE_QUESTION
, GTK_BUTTONS_NONE
, _("Incoming call"));
378 gtk_message_dialog_format_secondary_text (
379 GTK_MESSAGE_DIALOG (dialog
),
380 _("%s is calling you, do you want to answer?"),
381 empathy_contact_get_name (event
->approval
->contact
));
383 gtk_dialog_set_default_response (GTK_DIALOG (dialog
),
386 button
= gtk_dialog_add_button (GTK_DIALOG (dialog
),
387 _("_Reject"), GTK_RESPONSE_REJECT
);
388 image
= gtk_image_new_from_icon_name (GTK_STOCK_CANCEL
,
389 GTK_ICON_SIZE_BUTTON
);
390 gtk_button_set_image (GTK_BUTTON (button
), image
);
392 button
= gtk_dialog_add_button (GTK_DIALOG (dialog
),
393 _("_Answer"), GTK_RESPONSE_ACCEPT
);
395 image
= gtk_image_new_from_icon_name (GTK_STOCK_APPLY
, GTK_ICON_SIZE_BUTTON
);
396 gtk_button_set_image (GTK_BUTTON (button
), image
);
398 g_signal_connect (dialog
, "response",
399 G_CALLBACK (event_manager_call_window_confirmation_dialog_response_cb
),
402 gtk_widget_show (dialog
);
404 event
->approval
->dialog
= dialog
;
408 event_manager_chat_message_received_cb (EmpathyTpChat
*tp_chat
,
409 EmpathyMessage
*message
, EventManagerApproval
*approval
)
411 EmpathyContact
*sender
;
417 /* try to update the event if it's referring to a chat which is already in the
419 event
= event_lookup_by_approval (approval
->manager
, approval
);
421 if (event
!= NULL
&& event
->inhibit
&& approval
->handler
!= 0)
423 g_signal_handler_disconnect (tp_chat
, approval
->handler
);
424 approval
->handler
= 0;
428 sender
= empathy_message_get_sender (message
);
429 header
= g_strdup_printf (_("New message from %s"),
430 empathy_contact_get_name (sender
));
431 msg
= empathy_message_get_body (message
);
433 channel
= empathy_tp_chat_get_channel (tp_chat
);
436 event_update (approval
->manager
, event
, EMPATHY_IMAGE_NEW_MESSAGE
, header
, msg
);
438 event_manager_add (approval
->manager
, sender
, EMPATHY_IMAGE_NEW_MESSAGE
, header
,
439 msg
, approval
, event_text_channel_process_func
, NULL
);
442 empathy_sound_play (empathy_main_window_get (),
443 EMPATHY_SOUND_CONVERSATION_NEW
);
447 event_manager_approval_done (EventManagerApproval
*approval
)
449 EmpathyEventManagerPriv
*priv
= GET_PRIV (approval
->manager
);
452 if (approval
->operation
!= NULL
)
456 channel_type
= empathy_dispatch_operation_get_channel_type_id (
457 approval
->operation
);
458 if (channel_type
== TP_IFACE_QUARK_CHANNEL_TYPE_STREAMED_MEDIA
)
460 event_manager_stop_ringing (approval
->manager
);
464 priv
->approvals
= g_slist_remove (priv
->approvals
, approval
);
466 for (l
= priv
->events
; l
; l
= l
->next
)
468 EventPriv
*event
= l
->data
;
470 if (event
->approval
== approval
)
472 event_remove (event
);
477 event_manager_approval_free (approval
);
481 event_manager_operation_approved_cb (EmpathyDispatchOperation
*operation
,
482 EventManagerApproval
*approval
)
484 event_manager_approval_done (approval
);
488 event_manager_operation_claimed_cb (EmpathyDispatchOperation
*operation
,
489 EventManagerApproval
*approval
)
491 event_manager_approval_done (approval
);
495 event_manager_operation_invalidated_cb (EmpathyDispatchOperation
*operation
,
496 guint domain
, gint code
, gchar
*message
,
497 EventManagerApproval
*approval
)
499 event_manager_approval_done (approval
);
503 event_manager_media_channel_got_name_cb (EmpathyContact
*contact
,
504 const GError
*error
, gpointer user_data
, GObject
*object
)
506 EventManagerApproval
*approval
= user_data
;
511 /* FIXME just returning assuming the operation will be invalidated as
516 header
= g_strdup_printf (_("Incoming call from %s"),
517 empathy_contact_get_name (contact
));
519 event_manager_add (approval
->manager
,
520 approval
->contact
, EMPATHY_IMAGE_VOIP
, header
, NULL
,
521 approval
, event_channel_process_voip_func
, NULL
);
524 event_manager_start_ringing (approval
->manager
);
528 event_manager_media_channel_got_contact (EventManagerApproval
*approval
)
530 empathy_contact_call_when_ready (approval
->contact
,
531 EMPATHY_CONTACT_READY_NAME
, event_manager_media_channel_got_name_cb
,
532 approval
, NULL
, G_OBJECT (approval
->manager
));
536 event_manager_media_channel_contact_changed_cb (EmpathyTpCall
*call
,
537 GParamSpec
*param
, EventManagerApproval
*approval
)
539 EmpathyContact
*contact
;
541 g_object_get (G_OBJECT (call
), "contact", &contact
, NULL
);
546 approval
->contact
= contact
;
547 event_manager_media_channel_got_contact (approval
);
551 event_manager_tube_approved_cb (EventPriv
*event
)
553 empathy_tube_dispatch_handle (event
->approval
->tube_dispatch
);
557 event_manager_add_tube_approval (EventManagerApproval
*approval
,
558 EmpathyTubeDispatchAbility ability
)
560 const gchar
*icon_name
;
564 header
= g_strdup_printf (_("%s is offering you an invitation"),
565 empathy_contact_get_name (approval
->contact
));
567 if (ability
== EMPATHY_TUBE_DISPATCHABILITY_POSSIBLE
)
569 icon_name
= GTK_STOCK_EXECUTE
;
570 msg
= _("An external application will be started to handle it.");
574 icon_name
= GTK_STOCK_DIALOG_ERROR
;
575 msg
= _("You don't have the needed external "
576 "application to handle it.");
579 event_manager_add (approval
->manager
, approval
->contact
, icon_name
, header
,
580 msg
, approval
, event_manager_tube_approved_cb
, approval
);
583 /* FIXME better sound for incoming tubes ? */
584 empathy_sound_play (empathy_main_window_get (),
585 EMPATHY_SOUND_CONVERSATION_NEW
);
589 event_manager_tube_dispatch_ability_cb (GObject
*object
,
590 GParamSpec
*spec
, gpointer user_data
)
592 EventManagerApproval
*approval
= (EventManagerApproval
*)user_data
;
593 EmpathyTubeDispatchAbility dispatchability
;
596 empathy_tube_dispatch_is_dispatchable (approval
->tube_dispatch
);
598 if (dispatchability
!= EMPATHY_TUBE_DISPATCHABILITY_UNKNOWN
)
600 event_manager_add_tube_approval (approval
, dispatchability
);
601 g_signal_handler_disconnect (object
, approval
->handler
);
602 approval
->handler
= 0;
607 event_manager_tube_got_contact_name_cb (EmpathyContact
*contact
,
608 const GError
*error
, gpointer user_data
, GObject
*object
)
610 EventManagerApproval
*approval
= (EventManagerApproval
*)user_data
;
611 EmpathyTubeDispatchAbility dispatchability
;
615 /* FIXME?, we assume that the operation gets invalidated as well (if it
620 dispatchability
= empathy_tube_dispatch_is_dispatchable
621 (approval
->tube_dispatch
);
624 switch (dispatchability
)
626 case EMPATHY_TUBE_DISPATCHABILITY_UNKNOWN
:
627 approval
->handler
= g_signal_connect (approval
->tube_dispatch
,
628 "notify::dispatchability",
629 G_CALLBACK (event_manager_tube_dispatch_ability_cb
), approval
);
630 approval
->handler_instance
= G_OBJECT (approval
->tube_dispatch
);
632 case EMPATHY_TUBE_DISPATCHABILITY_POSSIBLE
:
634 case EMPATHY_TUBE_DISPATCHABILITY_IMPOSSIBLE
:
635 event_manager_add_tube_approval (approval
, dispatchability
);
641 invite_dialog_response_cb (GtkDialog
*dialog
,
643 EventManagerApproval
*approval
)
645 EmpathyTpChat
*tp_chat
;
647 TpHandle self_handle
;
650 gtk_widget_destroy (GTK_WIDGET (approval
->dialog
));
651 approval
->dialog
= NULL
;
653 tp_chat
= EMPATHY_TP_CHAT (empathy_dispatch_operation_get_channel_wrapper (
654 approval
->operation
));
656 if (response
!= GTK_RESPONSE_OK
)
659 DEBUG ("Muc invitation rejected");
661 if (empathy_dispatch_operation_claim (approval
->operation
))
662 empathy_tp_chat_close (tp_chat
);
666 DEBUG ("Muc invitation accepted");
669 channel
= empathy_tp_chat_get_channel (tp_chat
);
671 self_handle
= tp_channel_group_get_self_handle (channel
);
672 members
= g_array_sized_new (FALSE
, FALSE
, sizeof (TpHandle
), 1);
673 g_array_append_val (members
, self_handle
);
675 tp_cli_channel_interface_group_call_add_members (channel
, -1, members
,
676 "", NULL
, NULL
, NULL
, NULL
);
678 empathy_dispatch_operation_approve (approval
->operation
);
680 g_array_free (members
, TRUE
);
684 event_room_channel_process_func (EventPriv
*event
)
686 GtkWidget
*dialog
, *button
, *image
;
687 TpChannel
*channel
= empathy_dispatch_operation_get_channel (
688 event
->approval
->operation
);
690 if (event
->approval
->dialog
!= NULL
)
692 gtk_window_present (GTK_WINDOW (event
->approval
->dialog
));
697 dialog
= gtk_message_dialog_new (NULL
, 0,
698 GTK_MESSAGE_QUESTION
, GTK_BUTTONS_NONE
, _("Room invitation"));
700 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog
),
701 _("%s is inviting you to join %s"),
702 empathy_contact_get_name (event
->approval
->contact
),
703 tp_channel_get_identifier (channel
));
705 gtk_dialog_set_default_response (GTK_DIALOG (dialog
),
708 button
= gtk_dialog_add_button (GTK_DIALOG (dialog
),
709 _("_Decline"), GTK_RESPONSE_CANCEL
);
710 image
= gtk_image_new_from_icon_name (GTK_STOCK_CANCEL
, GTK_ICON_SIZE_BUTTON
);
711 gtk_button_set_image (GTK_BUTTON (button
), image
);
713 button
= gtk_dialog_add_button (GTK_DIALOG (dialog
),
714 _("_Join"), GTK_RESPONSE_OK
);
715 image
= gtk_image_new_from_icon_name (GTK_STOCK_APPLY
, GTK_ICON_SIZE_BUTTON
);
716 gtk_button_set_image (GTK_BUTTON (button
), image
);
718 g_signal_connect (dialog
, "response",
719 G_CALLBACK (invite_dialog_response_cb
), event
->approval
);
721 gtk_widget_show (dialog
);
723 event
->approval
->dialog
= dialog
;
727 event_manager_muc_invite_got_contact_name_cb (EmpathyContact
*contact
,
732 EventManagerApproval
*approval
= (EventManagerApproval
*) user_data
;
734 const gchar
*invite_msg
;
736 TpHandle self_handle
;
738 channel
= empathy_dispatch_operation_get_channel (approval
->operation
);
740 self_handle
= tp_channel_group_get_self_handle (channel
);
741 tp_channel_group_get_local_pending_info (channel
, self_handle
, NULL
, NULL
,
744 msg
= g_strdup_printf (_("%s invited you to join %s"),
745 empathy_contact_get_name (approval
->contact
),
746 tp_channel_get_identifier (channel
));
748 event_manager_add (approval
->manager
,
749 approval
->contact
, EMPATHY_IMAGE_GROUP_MESSAGE
, msg
, invite_msg
,
750 approval
, event_room_channel_process_func
, NULL
);
752 empathy_sound_play (empathy_main_window_get (),
753 EMPATHY_SOUND_CONVERSATION_NEW
);
759 event_manager_approve_channel_cb (EmpathyDispatcher
*dispatcher
,
760 EmpathyDispatchOperation
*operation
, EmpathyEventManager
*manager
)
762 const gchar
*channel_type
;
763 EventManagerApproval
*approval
;
764 EmpathyEventManagerPriv
*priv
= GET_PRIV (manager
);
766 channel_type
= empathy_dispatch_operation_get_channel_type (operation
);
768 approval
= event_manager_approval_new (manager
, operation
);
769 priv
->approvals
= g_slist_prepend (priv
->approvals
, approval
);
771 approval
->approved_handler
= g_signal_connect (operation
, "approved",
772 G_CALLBACK (event_manager_operation_approved_cb
), approval
);
774 approval
->claimed_handler
= g_signal_connect (operation
, "claimed",
775 G_CALLBACK (event_manager_operation_claimed_cb
), approval
);
777 approval
->invalidated_handler
= g_signal_connect (operation
, "invalidated",
778 G_CALLBACK (event_manager_operation_invalidated_cb
), approval
);
780 if (!tp_strdiff (channel_type
, TP_IFACE_CHANNEL_TYPE_TEXT
))
782 EmpathyTpChat
*tp_chat
=
784 empathy_dispatch_operation_get_channel_wrapper (operation
));
785 TpChannel
*channel
= empathy_tp_chat_get_channel (tp_chat
);
787 if (tp_proxy_has_interface (channel
, TP_IFACE_CHANNEL_INTERFACE_GROUP
))
789 /* Are we in local-pending ? */
790 TpHandle self_handle
, inviter
;
792 self_handle
= tp_channel_group_get_self_handle (channel
);
794 if (self_handle
!= 0 && tp_channel_group_get_local_pending_info (
795 channel
, self_handle
, &inviter
, NULL
, NULL
))
797 /* We are invited to a room */
798 EmpathyContactFactory
*contact_factory
;
801 DEBUG ("Have been invited to %s. Ask user if he wants to accept",
802 tp_channel_get_identifier (channel
));
804 account
= empathy_tp_chat_get_account (tp_chat
);
805 contact_factory
= empathy_contact_factory_dup_singleton ();
807 approval
->contact
= empathy_contact_factory_get_from_handle (
808 contact_factory
, account
, inviter
);
810 empathy_contact_call_when_ready (approval
->contact
,
811 EMPATHY_CONTACT_READY_NAME
,
812 event_manager_muc_invite_got_contact_name_cb
, approval
, NULL
,
815 g_object_unref (contact_factory
);
819 /* if we are not invited, let's wait for the first message */
822 /* 1-1 text channel, wait for the first message */
823 approval
->handler
= g_signal_connect (tp_chat
, "message-received",
824 G_CALLBACK (event_manager_chat_message_received_cb
), approval
);
825 approval
->handler_instance
= G_OBJECT (tp_chat
);
827 else if (!tp_strdiff (channel_type
, TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA
))
829 EmpathyContact
*contact
;
830 EmpathyTpCall
*call
= EMPATHY_TP_CALL (
831 empathy_dispatch_operation_get_channel_wrapper (operation
));
833 g_object_get (G_OBJECT (call
), "contact", &contact
, NULL
);
837 g_signal_connect (call
, "notify::contact",
838 G_CALLBACK (event_manager_media_channel_contact_changed_cb
),
843 approval
->contact
= contact
;
844 event_manager_media_channel_got_contact (approval
);
848 else if (!tp_strdiff (channel_type
, TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER
))
850 EmpathyContact
*contact
;
854 EmpathyContactFactory
*factory
;
855 TpChannel
*channel
= empathy_dispatch_operation_get_channel (operation
);
857 factory
= empathy_contact_factory_dup_singleton ();
858 handle
= tp_channel_get_handle (channel
, NULL
);
859 account
= empathy_channel_get_account (channel
);
861 contact
= empathy_contact_factory_get_from_handle (factory
, account
,
864 empathy_contact_run_until_ready (contact
,
865 EMPATHY_CONTACT_READY_NAME
, NULL
);
867 header
= g_strdup_printf (_("Incoming file transfer from %s"),
868 empathy_contact_get_name (contact
));
870 event_manager_add (manager
, contact
, EMPATHY_IMAGE_DOCUMENT_SEND
,
871 header
, NULL
, approval
, event_channel_process_func
, NULL
);
873 /* FIXME better sound for incoming file transfers ?*/
874 empathy_sound_play (empathy_main_window_get (),
875 EMPATHY_SOUND_CONVERSATION_NEW
);
877 g_object_unref (factory
);
878 g_object_unref (account
);
881 else if (!tp_strdiff (channel_type
, EMP_IFACE_CHANNEL_TYPE_STREAM_TUBE
) ||
882 !tp_strdiff (channel_type
, EMP_IFACE_CHANNEL_TYPE_DBUS_TUBE
))
884 EmpathyContact
*contact
;
886 TpHandleType handle_type
;
888 EmpathyContactFactory
*factory
;
889 EmpathyTubeDispatch
*tube_dispatch
;
892 channel
= empathy_dispatch_operation_get_channel (operation
);
894 handle
= tp_channel_get_handle (channel
, &handle_type
);
896 /* Only understand p2p tubes */
897 if (handle_type
!= TP_HANDLE_TYPE_CONTACT
)
900 factory
= empathy_contact_factory_dup_singleton ();
901 account
= empathy_channel_get_account (channel
);
903 contact
= empathy_contact_factory_get_from_handle (factory
, account
,
906 tube_dispatch
= empathy_tube_dispatch_new (operation
);
908 approval
->contact
= contact
;
909 approval
->tube_dispatch
= tube_dispatch
;
911 empathy_contact_call_when_ready (contact
,
912 EMPATHY_CONTACT_READY_NAME
, event_manager_tube_got_contact_name_cb
,
913 approval
, NULL
, G_OBJECT (manager
));
915 g_object_unref (factory
);
916 g_object_unref (account
);
920 DEBUG ("Unknown channel type, ignoring..");
925 event_pending_subscribe_func (EventPriv
*event
)
927 empathy_subscription_dialog_show (event
->public.contact
, NULL
);
928 event_remove (event
);
932 event_manager_pendings_changed_cb (EmpathyContactList
*list
,
933 EmpathyContact
*contact
, EmpathyContact
*actor
,
934 guint reason
, gchar
*message
, gboolean is_pending
,
935 EmpathyEventManager
*manager
)
937 EmpathyEventManagerPriv
*priv
= GET_PRIV (manager
);
938 gchar
*header
, *event_msg
;
944 for (l
= priv
->events
; l
; l
= l
->next
)
946 EventPriv
*event
= l
->data
;
948 if (event
->public.contact
== contact
&&
949 event
->func
== event_pending_subscribe_func
)
951 event_remove (event
);
959 empathy_contact_run_until_ready (contact
, EMPATHY_CONTACT_READY_NAME
, NULL
);
961 header
= g_strdup_printf (_("Subscription requested by %s"),
962 empathy_contact_get_name (contact
));
964 if (!EMP_STR_EMPTY (message
))
965 event_msg
= g_strdup_printf (_("\nMessage: %s"), message
);
969 event_manager_add (manager
, contact
, GTK_STOCK_DIALOG_QUESTION
, header
,
970 event_msg
, NULL
, event_pending_subscribe_func
, NULL
);
977 event_manager_constructor (GType type
,
979 GObjectConstructParam
*props
)
983 if (manager_singleton
) {
984 retval
= g_object_ref (manager_singleton
);
986 retval
= G_OBJECT_CLASS (empathy_event_manager_parent_class
)->constructor
987 (type
, n_props
, props
);
989 manager_singleton
= EMPATHY_EVENT_MANAGER (retval
);
990 g_object_add_weak_pointer (retval
, (gpointer
) &manager_singleton
);
997 event_manager_finalize (GObject
*object
)
999 EmpathyEventManagerPriv
*priv
= GET_PRIV (object
);
1001 g_slist_foreach (priv
->events
, (GFunc
) event_free
, NULL
);
1002 g_slist_free (priv
->events
);
1003 g_slist_foreach (priv
->approvals
, (GFunc
) event_manager_approval_free
, NULL
);
1004 g_slist_free (priv
->approvals
);
1005 g_object_unref (priv
->contact_manager
);
1006 g_object_unref (priv
->dispatcher
);
1010 empathy_event_manager_class_init (EmpathyEventManagerClass
*klass
)
1012 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
1014 object_class
->finalize
= event_manager_finalize
;
1015 object_class
->constructor
= event_manager_constructor
;
1017 signals
[EVENT_ADDED
] =
1018 g_signal_new ("event-added",
1019 G_TYPE_FROM_CLASS (klass
),
1023 g_cclosure_marshal_VOID__POINTER
,
1027 signals
[EVENT_REMOVED
] =
1028 g_signal_new ("event-removed",
1029 G_TYPE_FROM_CLASS (klass
),
1033 g_cclosure_marshal_VOID__POINTER
,
1034 G_TYPE_NONE
, 1, G_TYPE_POINTER
);
1036 signals
[EVENT_UPDATED
] =
1037 g_signal_new ("event-updated",
1038 G_TYPE_FROM_CLASS (klass
),
1042 g_cclosure_marshal_VOID__POINTER
,
1043 G_TYPE_NONE
, 1, G_TYPE_POINTER
);
1046 g_type_class_add_private (object_class
, sizeof (EmpathyEventManagerPriv
));
1050 empathy_event_manager_init (EmpathyEventManager
*manager
)
1052 EmpathyEventManagerPriv
*priv
= G_TYPE_INSTANCE_GET_PRIVATE (manager
,
1053 EMPATHY_TYPE_EVENT_MANAGER
, EmpathyEventManagerPriv
);
1055 manager
->priv
= priv
;
1057 priv
->dispatcher
= empathy_dispatcher_dup_singleton ();
1058 priv
->contact_manager
= empathy_contact_manager_dup_singleton ();
1059 g_signal_connect (priv
->dispatcher
, "approve",
1060 G_CALLBACK (event_manager_approve_channel_cb
), manager
);
1061 g_signal_connect (priv
->contact_manager
, "pendings-changed",
1062 G_CALLBACK (event_manager_pendings_changed_cb
), manager
);
1065 EmpathyEventManager
*
1066 empathy_event_manager_dup_singleton (void)
1068 return g_object_new (EMPATHY_TYPE_EVENT_MANAGER
, NULL
);
1072 empathy_event_manager_get_events (EmpathyEventManager
*manager
)
1074 EmpathyEventManagerPriv
*priv
= GET_PRIV (manager
);
1076 g_return_val_if_fail (EMPATHY_IS_EVENT_MANAGER (manager
), NULL
);
1078 return priv
->events
;
1082 empathy_event_manager_get_top_event (EmpathyEventManager
*manager
)
1084 EmpathyEventManagerPriv
*priv
= GET_PRIV (manager
);
1086 g_return_val_if_fail (EMPATHY_IS_EVENT_MANAGER (manager
), NULL
);
1088 return priv
->events
? priv
->events
->data
: NULL
;
1092 empathy_event_activate (EmpathyEvent
*event_public
)
1094 EventPriv
*event
= (EventPriv
*) event_public
;
1096 g_return_if_fail (event_public
!= NULL
);
1099 event
->func (event
);
1101 event_remove (event
);
1105 empathy_event_inhibit_updates (EmpathyEvent
*event_public
)
1107 EventPriv
*event
= (EventPriv
*) event_public
;
1109 g_return_if_fail (event_public
!= NULL
);
1111 event
->inhibit
= TRUE
;