[empathy: 4/8] Let the existing call window know about new incoming calls



commit ee02c5c89132db72e5cd987cd443cd09202b6f5b
Author: Emilio Pozuelo Monfort <emilio pozuelo collabora co uk>
Date:   Wed Sep 7 15:54:29 2011 +0100

    Let the existing call window know about new incoming calls
    
    https://bugzilla.gnome.org/show_bug.cgi?id=580794

 src/empathy-call-window.c |   62 +++++++++++++++++++++++++++++++++++++++++++++
 src/empathy-call.c        |   38 +++++++++++++++++++++++++++
 2 files changed, 100 insertions(+), 0 deletions(-)
---
diff --git a/src/empathy-call-window.c b/src/empathy-call-window.c
index af06b62..81bee05 100644
--- a/src/empathy-call-window.c
+++ b/src/empathy-call-window.c
@@ -43,6 +43,7 @@
 #include <libempathy/empathy-camera-monitor.h>
 #include <libempathy/empathy-gsettings.h>
 #include <libempathy/empathy-tp-contact-factory.h>
+#include <libempathy/empathy-request-util.h>
 #include <libempathy/empathy-utils.h>
 
 #include <libempathy-gtk/empathy-avatar-image.h>
@@ -103,6 +104,7 @@ enum {
 };
 
 typedef enum {
+  RINGING,
   CONNECTING,
   CONNECTED,
   HELD,
@@ -184,6 +186,12 @@ struct _EmpathyCallWindowPriv
      easilly repack everything when toggling fullscreen */
   GtkWidget *content_hbox;
 
+  /* These are used to accept or reject an incoming call when the status
+     is RINGING. */
+  TpyCallChannel *pending_channel;
+  TpChannelDispatchOperation *pending_cdo;
+  TpAddDispatchOperationContext *pending_context;
+
   gulong video_output_motion_handler_id;
   guint bus_message_source_id;
 
@@ -1360,6 +1368,60 @@ empathy_call_window_stage_allocation_changed_cb (ClutterActor *stage,
 }
 
 static void
+empathy_call_window_set_state_ringing (EmpathyCallWindow *self)
+{
+  g_assert (self->priv->call_state != CONNECTED);
+
+  empathy_call_window_status_message (self, _("Incoming call"));
+  self->priv->call_state = RINGING;
+}
+
+static void
+empathy_call_window_stop_ringing (EmpathyCallWindow *self)
+{
+  empathy_call_window_status_message (self, _("Disconnected"));
+  self->priv->call_state = DISCONNECTED;
+}
+
+static void
+empathy_call_window_incoming_channel_invalidated_cb (TpProxy *channel,
+    guint domain,
+    gint code,
+    gchar *message,
+    EmpathyCallWindow *self)
+{
+  tp_channel_dispatch_operation_destroy_channels_async (
+      self->priv->pending_cdo, NULL, NULL);
+  empathy_call_window_stop_ringing (self);
+
+  tp_clear_object (&self->priv->pending_cdo);
+  tp_clear_object (&self->priv->pending_channel);
+  tp_clear_object (&self->priv->pending_context);
+}
+
+void
+empathy_call_window_start_ringing (EmpathyCallWindow *self,
+    TpyCallChannel *channel,
+    TpChannelDispatchOperation *dispatch_operation,
+    TpAddDispatchOperationContext *context)
+{
+  g_assert (self->priv->pending_channel == NULL);
+  g_assert (self->priv->pending_context == NULL);
+  g_assert (self->priv->pending_cdo == NULL);
+
+  /* Start ringing and delay until the user answers or hangs. */
+  self->priv->pending_channel = g_object_ref (channel);
+  self->priv->pending_context = g_object_ref (context);
+  self->priv->pending_cdo = g_object_ref (dispatch_operation);
+
+  g_signal_connect (self->priv->pending_channel, "invalidated",
+      G_CALLBACK (empathy_call_window_incoming_channel_invalidated_cb), self);
+
+  empathy_call_window_set_state_ringing (self);
+  tp_add_dispatch_operation_context_accept (context);
+}
+
+static void
 empathy_call_window_init (EmpathyCallWindow *self)
 {
   EmpathyCallWindowPriv *priv;
diff --git a/src/empathy-call.c b/src/empathy-call.c
index a5e463b..1b643de 100644
--- a/src/empathy-call.c
+++ b/src/empathy-call.c
@@ -70,6 +70,42 @@ call_window_destroyed_cb (GtkWidget *window,
   g_application_release (G_APPLICATION (app));
 }
 
+static gboolean
+find_window_for_handle (gpointer key,
+    gpointer value,
+    gpointer user_data)
+{
+  EmpathyContact *contact = key;
+  guint handle = GPOINTER_TO_UINT (user_data);
+
+  if (handle == empathy_contact_get_handle (contact))
+    return TRUE;
+
+  return FALSE;
+}
+
+static gboolean
+incoming_call_cb (EmpathyCallFactory *factory,
+    guint handle,
+    TpyCallChannel *channel,
+    TpChannelDispatchOperation *dispatch_operation,
+    TpAddDispatchOperationContext *context,
+    gpointer user_data)
+{
+  EmpathyCallWindow *window = g_hash_table_find (call_windows,
+      find_window_for_handle, GUINT_TO_POINTER (handle));
+
+  if (window != NULL)
+    {
+      /* The window takes care of accepting or rejecting the context. */
+      empathy_call_window_start_ringing (window,
+          channel, dispatch_operation, context);
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
 static void
 new_call_handler_cb (EmpathyCallFactory *factory,
     EmpathyCallHandler *handler,
@@ -123,6 +159,8 @@ activate_cb (GApplication *application)
 
   g_signal_connect (G_OBJECT (call_factory), "new-call-handler",
       G_CALLBACK (new_call_handler_cb), NULL);
+  g_signal_connect (G_OBJECT (call_factory), "incoming-call",
+      G_CALLBACK (incoming_call_cb), NULL);
 
   if (!empathy_call_factory_register (call_factory, &error))
     {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]