aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/empathy-call-window.c62
-rw-r--r--src/empathy-call.c38
2 files changed, 100 insertions, 0 deletions
diff --git a/src/empathy-call-window.c b/src/empathy-call-window.c
index af06b6251..81bee0596 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 a5e463ba3..1b643dec1 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))
{