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-tp-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-tp-file.h>
35 #include <libempathy/empathy-utils.h>
36 #include <libempathy/empathy-call-factory.h>
38 #include <extensions/extensions.h>
40 #include <libempathy-gtk/empathy-images.h>
41 #include <libempathy-gtk/empathy-contact-dialogs.h>
42 #include <libempathy-gtk/empathy-ui-utils.h>
44 #include "empathy-event-manager.h"
45 #include "empathy-main-window.h"
46 #include "empathy-tube-dispatch.h"
48 #define DEBUG_FLAG EMPATHY_DEBUG_DISPATCHER
49 #include <libempathy/empathy-debug.h>
51 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyEventManager)
54 EmpathyEventManager
*manager
;
55 EmpathyDispatchOperation
*operation
;
56 gulong approved_handler
;
57 gulong claimed_handler
;
58 gulong invalidated_handler
;
59 /* Remove contact if applicable */
60 EmpathyContact
*contact
;
61 /* Tube dispatcher if applicable */
62 EmpathyTubeDispatch
*tube_dispatch
;
63 /* option signal handler and it's instance */
65 GObject
*handler_instance
;
66 /* optional accept widget */
68 } EventManagerApproval
;
71 EmpathyDispatcher
*dispatcher
;
72 EmpathyContactManager
*contact_manager
;
74 /* Ongoing approvals */
77 /* voip ringing sound */
80 } EmpathyEventManagerPriv
;
82 typedef struct _EventPriv EventPriv
;
83 typedef void (*EventFunc
) (EventPriv
*event
);
87 EmpathyEventManager
*manager
;
88 EventManagerApproval
*approval
;
101 static guint signals
[LAST_SIGNAL
];
103 G_DEFINE_TYPE (EmpathyEventManager
, empathy_event_manager
, G_TYPE_OBJECT
);
105 static EmpathyEventManager
* manager_singleton
= NULL
;
107 static EventManagerApproval
*
108 event_manager_approval_new (EmpathyEventManager
*manager
,
109 EmpathyDispatchOperation
*operation
)
111 EventManagerApproval
*result
= g_slice_new0 (EventManagerApproval
);
112 result
->operation
= g_object_ref (operation
);
113 result
->manager
= manager
;
119 event_manager_approval_free (EventManagerApproval
*approval
)
121 g_signal_handler_disconnect (approval
->operation
,
122 approval
->approved_handler
);
123 g_signal_handler_disconnect (approval
->operation
,
124 approval
->claimed_handler
);
125 g_signal_handler_disconnect (approval
->operation
,
126 approval
->invalidated_handler
);
127 g_object_unref (approval
->operation
);
129 if (approval
->handler
!= 0)
130 g_signal_handler_disconnect (approval
->handler_instance
,
133 if (approval
->contact
!= NULL
)
134 g_object_unref (approval
->contact
);
136 if (approval
->tube_dispatch
!= NULL
)
137 g_object_unref (approval
->tube_dispatch
);
139 if (approval
->dialog
!= NULL
)
141 gtk_widget_destroy (approval
->dialog
);
144 g_slice_free (EventManagerApproval
, approval
);
147 static void event_remove (EventPriv
*event
);
150 event_free (EventPriv
*event
)
152 g_free (event
->public.icon_name
);
153 g_free (event
->public.header
);
154 g_free (event
->public.message
);
156 if (event
->public.contact
)
158 g_object_unref (event
->public.contact
);
161 g_slice_free (EventPriv
, event
);
164 static void event_manager_ringing_finished_cb (ca_context
*c
, guint id
,
165 int error_code
, gpointer user_data
);
168 event_manager_ringing_timeout_cb (gpointer data
)
170 EmpathyEventManager
*manager
= EMPATHY_EVENT_MANAGER (data
);
171 EmpathyEventManagerPriv
*priv
= GET_PRIV (manager
);
173 priv
->voip_timeout
= 0;
175 empathy_sound_play_full (empathy_main_window_get (),
176 EMPATHY_SOUND_PHONE_INCOMING
, event_manager_ringing_finished_cb
,
183 event_manager_ringing_idle_cb (gpointer data
)
185 EmpathyEventManager
*manager
= EMPATHY_EVENT_MANAGER (data
);
186 EmpathyEventManagerPriv
*priv
= GET_PRIV (manager
);
188 if (priv
->ringing
> 0)
189 priv
->voip_timeout
= g_timeout_add (500, event_manager_ringing_timeout_cb
,
196 event_manager_ringing_finished_cb (ca_context
*c
, guint id
, int error_code
,
199 if (error_code
== CA_ERROR_CANCELED
)
202 g_idle_add (event_manager_ringing_idle_cb
, user_data
);
206 event_manager_start_ringing (EmpathyEventManager
*manager
)
208 EmpathyEventManagerPriv
*priv
= GET_PRIV (manager
);
212 if (priv
->ringing
== 1)
214 empathy_sound_play_full (empathy_main_window_get (),
215 EMPATHY_SOUND_PHONE_INCOMING
, event_manager_ringing_finished_cb
,
221 event_manager_stop_ringing (EmpathyEventManager
*manager
)
223 EmpathyEventManagerPriv
*priv
= GET_PRIV (manager
);
227 if (priv
->ringing
> 0)
230 empathy_sound_stop (EMPATHY_SOUND_PHONE_INCOMING
);
232 if (priv
->voip_timeout
!= 0)
234 g_source_remove (priv
->voip_timeout
);
235 priv
->voip_timeout
= 0;
240 event_remove (EventPriv
*event
)
242 EmpathyEventManagerPriv
*priv
= GET_PRIV (event
->manager
);
244 DEBUG ("Removing event %p", event
);
245 priv
->events
= g_slist_remove (priv
->events
, event
);
246 g_signal_emit (event
->manager
, signals
[EVENT_REMOVED
], 0, event
);
251 event_manager_add (EmpathyEventManager
*manager
, EmpathyContact
*contact
,
252 const gchar
*icon_name
, const gchar
*header
, const gchar
*message
,
253 EventManagerApproval
*approval
, EventFunc func
, gpointer user_data
)
255 EmpathyEventManagerPriv
*priv
= GET_PRIV (manager
);
258 event
= g_slice_new0 (EventPriv
);
259 event
->public.contact
= contact
? g_object_ref (contact
) : NULL
;
260 event
->public.icon_name
= g_strdup (icon_name
);
261 event
->public.header
= g_strdup (header
);
262 event
->public.message
= g_strdup (message
);
263 event
->inhibit
= FALSE
;
265 event
->user_data
= user_data
;
266 event
->manager
= manager
;
267 event
->approval
= approval
;
269 DEBUG ("Adding event %p", event
);
270 priv
->events
= g_slist_prepend (priv
->events
, event
);
271 g_signal_emit (event
->manager
, signals
[EVENT_ADDED
], 0, event
);
275 event_channel_process_func (EventPriv
*event
)
277 empathy_dispatch_operation_approve (event
->approval
->operation
);
281 event_text_channel_process_func (EventPriv
*event
)
283 EmpathyTpChat
*tp_chat
;
285 if (event
->approval
->handler
!= 0)
287 tp_chat
= EMPATHY_TP_CHAT
288 (empathy_dispatch_operation_get_channel_wrapper (event
->approval
->operation
));
290 g_signal_handler_disconnect (tp_chat
, event
->approval
->handler
);
291 event
->approval
->handler
= 0;
294 empathy_dispatch_operation_approve (event
->approval
->operation
);
298 event_lookup_by_approval (EmpathyEventManager
*manager
,
299 EventManagerApproval
*approval
)
301 EmpathyEventManagerPriv
*priv
= GET_PRIV (manager
);
303 EventPriv
*retval
= NULL
;
305 for (l
= priv
->events
; l
; l
= l
->next
)
307 EventPriv
*event
= l
->data
;
309 if (event
->approval
== approval
)
320 event_update (EmpathyEventManager
*manager
, EventPriv
*event
,
321 const char *icon_name
, const char *header
, const char *msg
)
323 g_free (event
->public.icon_name
);
324 g_free (event
->public.header
);
325 g_free (event
->public.message
);
327 event
->public.icon_name
= g_strdup (icon_name
);
328 event
->public.header
= g_strdup (header
);
329 event
->public.message
= g_strdup (msg
);
331 g_signal_emit (manager
, signals
[EVENT_UPDATED
], 0, event
);
335 event_manager_call_window_confirmation_dialog_response_cb (GtkDialog
*dialog
,
336 gint response
, gpointer user_data
)
338 EventManagerApproval
*approval
= user_data
;
340 gtk_widget_destroy (approval
->dialog
);
341 approval
->dialog
= NULL
;
343 if (response
!= GTK_RESPONSE_ACCEPT
)
345 EmpathyTpCall
*call
=
347 empathy_dispatch_operation_get_channel_wrapper (
348 approval
->operation
));
351 if (empathy_dispatch_operation_claim (approval
->operation
))
352 empathy_tp_call_close (call
);
353 g_object_unref (call
);
358 EmpathyCallFactory
*factory
= empathy_call_factory_get ();
359 empathy_call_factory_claim_channel (factory
, approval
->operation
);
364 event_channel_process_voip_func (EventPriv
*event
)
370 if (event
->approval
->dialog
!= NULL
)
372 gtk_window_present (GTK_WINDOW (event
->approval
->dialog
));
376 dialog
= gtk_message_dialog_new (NULL
, 0,
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_contact (EventManagerApproval
*approval
)
507 header
= g_strdup_printf (_("Incoming call from %s"),
508 empathy_contact_get_name (approval
->contact
));
510 event_manager_add (approval
->manager
,
511 approval
->contact
, EMPATHY_IMAGE_VOIP
, header
, NULL
,
512 approval
, event_channel_process_voip_func
, NULL
);
515 event_manager_start_ringing (approval
->manager
);
519 event_manager_media_channel_contact_changed_cb (EmpathyTpCall
*call
,
520 GParamSpec
*param
, EventManagerApproval
*approval
)
522 EmpathyContact
*contact
;
524 g_object_get (G_OBJECT (call
), "contact", &contact
, NULL
);
529 approval
->contact
= contact
;
530 event_manager_media_channel_got_contact (approval
);
534 event_manager_tube_approved_cb (EventPriv
*event
)
536 empathy_tube_dispatch_handle (event
->approval
->tube_dispatch
);
540 event_manager_add_tube_approval (EventManagerApproval
*approval
,
541 EmpathyTubeDispatchAbility ability
)
543 const gchar
*icon_name
;
547 header
= g_strdup_printf (_("%s is offering you an invitation"),
548 empathy_contact_get_name (approval
->contact
));
550 if (ability
== EMPATHY_TUBE_DISPATCHABILITY_POSSIBLE
)
552 icon_name
= GTK_STOCK_EXECUTE
;
553 msg
= _("An external application will be started to handle it.");
557 icon_name
= GTK_STOCK_DIALOG_ERROR
;
558 msg
= _("You don't have the needed external "
559 "application to handle it.");
562 event_manager_add (approval
->manager
, approval
->contact
, icon_name
, header
,
563 msg
, approval
, event_manager_tube_approved_cb
, approval
);
566 /* FIXME better sound for incoming tubes ? */
567 empathy_sound_play (empathy_main_window_get (),
568 EMPATHY_SOUND_CONVERSATION_NEW
);
572 event_manager_tube_dispatch_ability_cb (GObject
*object
,
573 GParamSpec
*spec
, gpointer user_data
)
575 EventManagerApproval
*approval
= (EventManagerApproval
*) user_data
;
576 EmpathyTubeDispatchAbility dispatchability
;
579 empathy_tube_dispatch_is_dispatchable (approval
->tube_dispatch
);
581 if (dispatchability
!= EMPATHY_TUBE_DISPATCHABILITY_UNKNOWN
)
583 event_manager_add_tube_approval (approval
, dispatchability
);
584 g_signal_handler_disconnect (object
, approval
->handler
);
585 approval
->handler
= 0;
590 event_manager_tube_got_contact_cb (EmpathyTpContactFactory
*factory
,
591 EmpathyContact
*contact
,
596 EventManagerApproval
*approval
= (EventManagerApproval
*) user_data
;
597 EmpathyTubeDispatchAbility dispatchability
;
601 /* FIXME: We should probably still display the event */
602 DEBUG ("Error: %s", error
->message
);
606 approval
->contact
= g_object_ref (contact
);
608 dispatchability
= empathy_tube_dispatch_is_dispatchable
609 (approval
->tube_dispatch
);
611 switch (dispatchability
)
613 case EMPATHY_TUBE_DISPATCHABILITY_UNKNOWN
:
614 approval
->handler
= g_signal_connect (approval
->tube_dispatch
,
615 "notify::dispatchability",
616 G_CALLBACK (event_manager_tube_dispatch_ability_cb
), approval
);
617 approval
->handler_instance
= G_OBJECT (approval
->tube_dispatch
);
619 case EMPATHY_TUBE_DISPATCHABILITY_POSSIBLE
:
621 case EMPATHY_TUBE_DISPATCHABILITY_IMPOSSIBLE
:
622 event_manager_add_tube_approval (approval
, dispatchability
);
628 invite_dialog_response_cb (GtkDialog
*dialog
,
630 EventManagerApproval
*approval
)
632 EmpathyTpChat
*tp_chat
;
634 TpHandle self_handle
;
637 gtk_widget_destroy (GTK_WIDGET (approval
->dialog
));
638 approval
->dialog
= NULL
;
640 tp_chat
= EMPATHY_TP_CHAT (empathy_dispatch_operation_get_channel_wrapper (
641 approval
->operation
));
643 if (response
!= GTK_RESPONSE_OK
)
646 DEBUG ("Muc invitation rejected");
648 if (empathy_dispatch_operation_claim (approval
->operation
))
649 empathy_tp_chat_close (tp_chat
);
653 DEBUG ("Muc invitation accepted");
656 channel
= empathy_tp_chat_get_channel (tp_chat
);
658 self_handle
= tp_channel_group_get_self_handle (channel
);
659 members
= g_array_sized_new (FALSE
, FALSE
, sizeof (TpHandle
), 1);
660 g_array_append_val (members
, self_handle
);
662 tp_cli_channel_interface_group_call_add_members (channel
, -1, members
,
663 "", NULL
, NULL
, NULL
, NULL
);
665 empathy_dispatch_operation_approve (approval
->operation
);
667 g_array_free (members
, TRUE
);
671 event_room_channel_process_func (EventPriv
*event
)
673 GtkWidget
*dialog
, *button
, *image
;
674 TpChannel
*channel
= empathy_dispatch_operation_get_channel (
675 event
->approval
->operation
);
677 if (event
->approval
->dialog
!= NULL
)
679 gtk_window_present (GTK_WINDOW (event
->approval
->dialog
));
684 dialog
= gtk_message_dialog_new (NULL
, 0,
685 GTK_MESSAGE_QUESTION
, GTK_BUTTONS_NONE
, _("Room invitation"));
687 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog
),
688 _("%s is inviting you to join %s"),
689 empathy_contact_get_name (event
->approval
->contact
),
690 tp_channel_get_identifier (channel
));
692 gtk_dialog_set_default_response (GTK_DIALOG (dialog
),
695 button
= gtk_dialog_add_button (GTK_DIALOG (dialog
),
696 _("_Decline"), GTK_RESPONSE_CANCEL
);
697 image
= gtk_image_new_from_icon_name (GTK_STOCK_CANCEL
, GTK_ICON_SIZE_BUTTON
);
698 gtk_button_set_image (GTK_BUTTON (button
), image
);
700 button
= gtk_dialog_add_button (GTK_DIALOG (dialog
),
701 _("_Join"), GTK_RESPONSE_OK
);
702 image
= gtk_image_new_from_icon_name (GTK_STOCK_APPLY
, GTK_ICON_SIZE_BUTTON
);
703 gtk_button_set_image (GTK_BUTTON (button
), image
);
705 g_signal_connect (dialog
, "response",
706 G_CALLBACK (invite_dialog_response_cb
), event
->approval
);
708 gtk_widget_show (dialog
);
710 event
->approval
->dialog
= dialog
;
714 event_manager_muc_invite_got_contact_cb (EmpathyTpContactFactory
*factory
,
715 EmpathyContact
*contact
,
720 EventManagerApproval
*approval
= (EventManagerApproval
*) user_data
;
722 const gchar
*invite_msg
;
724 TpHandle self_handle
;
728 /* FIXME: We should probably still display the event */
729 DEBUG ("Error: %s", error
->message
);
733 approval
->contact
= g_object_ref (contact
);
734 channel
= empathy_dispatch_operation_get_channel (approval
->operation
);
736 self_handle
= tp_channel_group_get_self_handle (channel
);
737 tp_channel_group_get_local_pending_info (channel
, self_handle
, NULL
, NULL
,
740 msg
= g_strdup_printf (_("%s invited you to join %s"),
741 empathy_contact_get_name (approval
->contact
),
742 tp_channel_get_identifier (channel
));
744 event_manager_add (approval
->manager
,
745 approval
->contact
, EMPATHY_IMAGE_GROUP_MESSAGE
, msg
, invite_msg
,
746 approval
, event_room_channel_process_func
, NULL
);
748 empathy_sound_play (empathy_main_window_get (),
749 EMPATHY_SOUND_CONVERSATION_NEW
);
755 event_manager_ft_got_contact_cb (EmpathyTpContactFactory
*factory
,
756 EmpathyContact
*contact
,
761 EventManagerApproval
*approval
= (EventManagerApproval
*) user_data
;
764 approval
->contact
= contact
;
766 header
= g_strdup_printf (_("Incoming file transfer from %s"),
767 empathy_contact_get_name (approval
->contact
));
769 event_manager_add (approval
->manager
, approval
->contact
,
770 EMPATHY_IMAGE_DOCUMENT_SEND
, header
, NULL
, approval
,
771 event_channel_process_func
, NULL
);
773 /* FIXME better sound for incoming file transfers ?*/
774 empathy_sound_play (empathy_main_window_get (),
775 EMPATHY_SOUND_CONVERSATION_NEW
);
781 event_manager_approve_channel_cb (EmpathyDispatcher
*dispatcher
,
782 EmpathyDispatchOperation
*operation
, EmpathyEventManager
*manager
)
784 const gchar
*channel_type
;
785 EventManagerApproval
*approval
;
786 EmpathyEventManagerPriv
*priv
= GET_PRIV (manager
);
788 channel_type
= empathy_dispatch_operation_get_channel_type (operation
);
790 approval
= event_manager_approval_new (manager
, operation
);
791 priv
->approvals
= g_slist_prepend (priv
->approvals
, approval
);
793 approval
->approved_handler
= g_signal_connect (operation
, "approved",
794 G_CALLBACK (event_manager_operation_approved_cb
), approval
);
796 approval
->claimed_handler
= g_signal_connect (operation
, "claimed",
797 G_CALLBACK (event_manager_operation_claimed_cb
), approval
);
799 approval
->invalidated_handler
= g_signal_connect (operation
, "invalidated",
800 G_CALLBACK (event_manager_operation_invalidated_cb
), approval
);
802 if (!tp_strdiff (channel_type
, TP_IFACE_CHANNEL_TYPE_TEXT
))
804 EmpathyTpChat
*tp_chat
=
806 empathy_dispatch_operation_get_channel_wrapper (operation
));
807 TpChannel
*channel
= empathy_tp_chat_get_channel (tp_chat
);
809 if (tp_proxy_has_interface (channel
, TP_IFACE_CHANNEL_INTERFACE_GROUP
))
811 /* Are we in local-pending ? */
812 TpHandle self_handle
, inviter
;
814 self_handle
= tp_channel_group_get_self_handle (channel
);
816 if (self_handle
!= 0 && tp_channel_group_get_local_pending_info (
817 channel
, self_handle
, &inviter
, NULL
, NULL
))
819 /* We are invited to a room */
820 EmpathyTpContactFactory
*factory
;
821 TpConnection
*connection
;
823 DEBUG ("Have been invited to %s. Ask user if he wants to accept",
824 tp_channel_get_identifier (channel
));
826 connection
= empathy_tp_chat_get_connection (tp_chat
);
827 factory
= empathy_tp_contact_factory_dup_singleton (connection
);
829 empathy_tp_contact_factory_get_from_handle (factory
,
830 inviter
, event_manager_muc_invite_got_contact_cb
,
831 approval
, NULL
, G_OBJECT (manager
));
833 g_object_unref (factory
);
837 /* if we are not invited, let's wait for the first message */
840 /* 1-1 text channel, wait for the first message */
841 approval
->handler
= g_signal_connect (tp_chat
, "message-received",
842 G_CALLBACK (event_manager_chat_message_received_cb
), approval
);
843 approval
->handler_instance
= G_OBJECT (tp_chat
);
845 else if (!tp_strdiff (channel_type
, TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA
))
847 EmpathyContact
*contact
;
848 EmpathyTpCall
*call
= EMPATHY_TP_CALL (
849 empathy_dispatch_operation_get_channel_wrapper (operation
));
851 g_object_get (G_OBJECT (call
), "contact", &contact
, NULL
);
855 g_signal_connect (call
, "notify::contact",
856 G_CALLBACK (event_manager_media_channel_contact_changed_cb
),
861 approval
->contact
= contact
;
862 event_manager_media_channel_got_contact (approval
);
866 else if (!tp_strdiff (channel_type
, TP_IFACE_CHANNEL_TYPE_FILE_TRANSFER
))
869 TpConnection
*connection
;
871 EmpathyTpContactFactory
*factory
;
873 channel
= empathy_dispatch_operation_get_channel (operation
);
874 handle
= tp_channel_get_handle (channel
, NULL
);
876 connection
= tp_channel_borrow_connection (channel
);
877 factory
= empathy_tp_contact_factory_dup_singleton (connection
);
878 empathy_tp_contact_factory_get_from_handle (factory
, handle
,
879 event_manager_ft_got_contact_cb
, approval
, NULL
, G_OBJECT (manager
));
881 g_object_unref (factory
);
883 else if (!tp_strdiff (channel_type
, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE
) ||
884 !tp_strdiff (channel_type
, TP_IFACE_CHANNEL_TYPE_DBUS_TUBE
))
888 TpHandleType handle_type
;
889 TpConnection
*connection
;
890 EmpathyTpContactFactory
*factory
;
892 channel
= empathy_dispatch_operation_get_channel (operation
);
893 handle
= tp_channel_get_handle (channel
, &handle_type
);
895 /* Only understand p2p tubes */
896 if (handle_type
!= TP_HANDLE_TYPE_CONTACT
)
899 approval
->tube_dispatch
= empathy_tube_dispatch_new (operation
);
900 connection
= tp_channel_borrow_connection (channel
);
901 factory
= empathy_tp_contact_factory_dup_singleton (connection
);
902 empathy_tp_contact_factory_get_from_handle (factory
, handle
,
903 event_manager_tube_got_contact_cb
, approval
, NULL
, G_OBJECT (manager
));
907 DEBUG ("Unknown channel type (%s), ignoring..", channel_type
);
912 event_pending_subscribe_func (EventPriv
*event
)
914 empathy_subscription_dialog_show (event
->public.contact
, NULL
);
915 event_remove (event
);
919 event_manager_pendings_changed_cb (EmpathyContactList
*list
,
920 EmpathyContact
*contact
, EmpathyContact
*actor
,
921 guint reason
, gchar
*message
, gboolean is_pending
,
922 EmpathyEventManager
*manager
)
924 EmpathyEventManagerPriv
*priv
= GET_PRIV (manager
);
925 gchar
*header
, *event_msg
;
931 for (l
= priv
->events
; l
; l
= l
->next
)
933 EventPriv
*event
= l
->data
;
935 if (event
->public.contact
== contact
&&
936 event
->func
== event_pending_subscribe_func
)
938 event_remove (event
);
946 header
= g_strdup_printf (_("Subscription requested by %s"),
947 empathy_contact_get_name (contact
));
949 if (!EMP_STR_EMPTY (message
))
950 event_msg
= g_strdup_printf (_("\nMessage: %s"), message
);
954 event_manager_add (manager
, contact
, GTK_STOCK_DIALOG_QUESTION
, header
,
955 event_msg
, NULL
, event_pending_subscribe_func
, NULL
);
962 event_manager_constructor (GType type
,
964 GObjectConstructParam
*props
)
968 if (manager_singleton
) {
969 retval
= g_object_ref (manager_singleton
);
971 retval
= G_OBJECT_CLASS (empathy_event_manager_parent_class
)->constructor
972 (type
, n_props
, props
);
974 manager_singleton
= EMPATHY_EVENT_MANAGER (retval
);
975 g_object_add_weak_pointer (retval
, (gpointer
) &manager_singleton
);
982 event_manager_finalize (GObject
*object
)
984 EmpathyEventManagerPriv
*priv
= GET_PRIV (object
);
986 g_slist_foreach (priv
->events
, (GFunc
) event_free
, NULL
);
987 g_slist_free (priv
->events
);
988 g_slist_foreach (priv
->approvals
, (GFunc
) event_manager_approval_free
, NULL
);
989 g_slist_free (priv
->approvals
);
990 g_object_unref (priv
->contact_manager
);
991 g_object_unref (priv
->dispatcher
);
995 empathy_event_manager_class_init (EmpathyEventManagerClass
*klass
)
997 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
999 object_class
->finalize
= event_manager_finalize
;
1000 object_class
->constructor
= event_manager_constructor
;
1002 signals
[EVENT_ADDED
] =
1003 g_signal_new ("event-added",
1004 G_TYPE_FROM_CLASS (klass
),
1008 g_cclosure_marshal_VOID__POINTER
,
1012 signals
[EVENT_REMOVED
] =
1013 g_signal_new ("event-removed",
1014 G_TYPE_FROM_CLASS (klass
),
1018 g_cclosure_marshal_VOID__POINTER
,
1019 G_TYPE_NONE
, 1, G_TYPE_POINTER
);
1021 signals
[EVENT_UPDATED
] =
1022 g_signal_new ("event-updated",
1023 G_TYPE_FROM_CLASS (klass
),
1027 g_cclosure_marshal_VOID__POINTER
,
1028 G_TYPE_NONE
, 1, G_TYPE_POINTER
);
1031 g_type_class_add_private (object_class
, sizeof (EmpathyEventManagerPriv
));
1035 empathy_event_manager_init (EmpathyEventManager
*manager
)
1037 EmpathyEventManagerPriv
*priv
= G_TYPE_INSTANCE_GET_PRIVATE (manager
,
1038 EMPATHY_TYPE_EVENT_MANAGER
, EmpathyEventManagerPriv
);
1040 manager
->priv
= priv
;
1042 priv
->dispatcher
= empathy_dispatcher_dup_singleton ();
1043 priv
->contact_manager
= empathy_contact_manager_dup_singleton ();
1044 g_signal_connect (priv
->dispatcher
, "approve",
1045 G_CALLBACK (event_manager_approve_channel_cb
), manager
);
1046 g_signal_connect (priv
->contact_manager
, "pendings-changed",
1047 G_CALLBACK (event_manager_pendings_changed_cb
), manager
);
1050 EmpathyEventManager
*
1051 empathy_event_manager_dup_singleton (void)
1053 return g_object_new (EMPATHY_TYPE_EVENT_MANAGER
, NULL
);
1057 empathy_event_manager_get_events (EmpathyEventManager
*manager
)
1059 EmpathyEventManagerPriv
*priv
= GET_PRIV (manager
);
1061 g_return_val_if_fail (EMPATHY_IS_EVENT_MANAGER (manager
), NULL
);
1063 return priv
->events
;
1067 empathy_event_manager_get_top_event (EmpathyEventManager
*manager
)
1069 EmpathyEventManagerPriv
*priv
= GET_PRIV (manager
);
1071 g_return_val_if_fail (EMPATHY_IS_EVENT_MANAGER (manager
), NULL
);
1073 return priv
->events
? priv
->events
->data
: NULL
;
1077 empathy_event_activate (EmpathyEvent
*event_public
)
1079 EventPriv
*event
= (EventPriv
*) event_public
;
1081 g_return_if_fail (event_public
!= NULL
);
1084 event
->func (event
);
1086 event_remove (event
);
1090 empathy_event_inhibit_updates (EmpathyEvent
*event_public
)
1092 EventPriv
*event
= (EventPriv
*) event_public
;
1094 g_return_if_fail (event_public
!= NULL
);
1096 event
->inhibit
= TRUE
;