[telepathy-mission-control/master] Support DRAFT2 ContactCapabilities

Simon McVittie simon.mcvittie at collabora.co.uk
Fri Sep 11 11:17:22 PDT 2009


---
 src/mcd-connection-priv.h |    5 +-
 src/mcd-connection.c      |   28 +++++++++-
 src/mcd-dispatcher.c      |  135 +++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 162 insertions(+), 6 deletions(-)

diff --git a/src/mcd-connection-priv.h b/src/mcd-connection-priv.h
index 0a89103..9894a65 100644
--- a/src/mcd-connection-priv.h
+++ b/src/mcd-connection-priv.h
@@ -44,7 +44,8 @@ void _mcd_connection_set_tp_connection (McdConnection *connection,
                                         const gchar *bus_name,
                                         const gchar *obj_path, GError **error);
 
-G_GNUC_INTERNAL void _mcd_connection_start_dispatching (McdConnection *self);
+G_GNUC_INTERNAL void _mcd_connection_start_dispatching (McdConnection *self,
+    GPtrArray *client_caps);
 
 G_GNUC_INTERNAL gboolean _mcd_connection_is_ready (McdConnection *self);
 
@@ -54,6 +55,8 @@ G_GNUC_INTERNAL void _mcd_connection_set_nickname (McdConnection *self,
 G_GNUC_INTERNAL void _mcd_connection_set_avatar (McdConnection *self,
                                                  const GArray *avatar,
                                                  const gchar *mime_type);
+G_GNUC_INTERNAL void _mcd_connection_update_client_caps (McdConnection *self,
+    GPtrArray *client_caps);
 
 G_END_DECLS
 
diff --git a/src/mcd-connection.c b/src/mcd-connection.c
index ae1d63f..0292422 100644
--- a/src/mcd-connection.c
+++ b/src/mcd-connection.c
@@ -569,6 +569,12 @@ _mcd_connection_setup_capabilities (McdConnection *connection)
     GType type;
     guint i;
 
+    if (priv->has_contact_capabilities_draft2_if)
+    {
+        DEBUG ("ContactCapabilities draft 2 in use, avoiding Capabilities");
+        return;
+    }
+
     if (!priv->has_capabilities_if)
     {
         DEBUG ("connection does not support capabilities interface");
@@ -1407,7 +1413,8 @@ on_connection_ready (TpConnection *tp_conn, const GError *error,
 }
 
 void
-_mcd_connection_start_dispatching (McdConnection *self)
+_mcd_connection_start_dispatching (McdConnection *self,
+                                   GPtrArray *client_caps)
 {
     g_return_if_fail (MCD_IS_CONNECTION (self));
     g_return_if_fail (!self->priv->dispatching_started);
@@ -1421,10 +1428,29 @@ _mcd_connection_start_dispatching (McdConnection *self)
     else
         mcd_connection_setup_pre_requests (self);
 
+    _mcd_connection_update_client_caps (self, client_caps);
+
     /* and request all channels */
     request_unrequested_channels (self);
 }
 
+void
+_mcd_connection_update_client_caps (McdConnection *self,
+                                    GPtrArray *client_caps)
+{
+    g_return_if_fail (MCD_IS_CONNECTION (self));
+
+    if (!self->priv->has_contact_capabilities_draft2_if)
+    {
+        DEBUG ("ContactCapabilities.DRAFT2 unsupported");
+        return;
+    }
+
+    DEBUG ("Sending client caps to connection");
+    mc_cli_connection_interface_contact_capabilities_draft2_call_update_capabilities
+      (self->priv->tp_conn, -1, client_caps, NULL, NULL, NULL, NULL);
+}
+
 static void
 request_connection_cb (TpConnectionManager *proxy, const gchar *bus_name,
 		       const gchar *obj_path, const GError *tperror,
diff --git a/src/mcd-dispatcher.c b/src/mcd-dispatcher.c
index 592098b..d23f356 100644
--- a/src/mcd-dispatcher.c
+++ b/src/mcd-dispatcher.c
@@ -1969,6 +1969,68 @@ mcd_client_set_filters (McdClient *client,
     }
 }
 
+typedef struct {
+    TpHandleRepoIface *repo;
+    GPtrArray *array;
+} TokenAppendContext;
+
+static void
+append_token_to_ptrs (TpHandleSet *unused G_GNUC_UNUSED,
+                      TpHandle handle,
+                      gpointer data)
+{
+    TokenAppendContext *context = data;
+
+    g_ptr_array_add (context->array,
+                     g_strdup (tp_handle_inspect (context->repo, handle)));
+}
+
+static void
+mcd_dispatcher_append_client_caps (McdDispatcher *self,
+                                   McdClient *client,
+                                   GPtrArray *vas)
+{
+    GPtrArray *filters = g_ptr_array_sized_new (
+        g_list_length (client->handler_filters));
+    GPtrArray *cap_tokens = g_ptr_array_sized_new (
+        tp_handle_set_size (client->capability_tokens) + 1);
+    TokenAppendContext context = { self->priv->string_pool, cap_tokens };
+    GValueArray *va;
+    GList *list;
+
+    for (list = client->handler_filters; list != NULL; list = list->next)
+    {
+        GHashTable *copy = g_hash_table_new_full (g_str_hash, g_str_equal,
+            g_free, (GDestroyNotify) tp_g_value_slice_free);
+
+        tp_g_hash_table_update (copy, list->data,
+                                (GBoxedCopyFunc) g_strdup,
+                                (GBoxedCopyFunc) tp_g_value_slice_dup);
+        g_ptr_array_add (filters, copy);
+    }
+
+    tp_handle_set_foreach (client->capability_tokens, append_token_to_ptrs,
+                           &context);
+    g_ptr_array_add (cap_tokens, NULL);
+
+    va = g_value_array_new (3);
+    g_value_array_append (va, NULL);
+    g_value_array_append (va, NULL);
+    g_value_array_append (va, NULL);
+
+    g_value_init (va->values + 0, G_TYPE_STRING);
+    g_value_init (va->values + 1, TP_ARRAY_TYPE_CHANNEL_CLASS_LIST);
+    g_value_init (va->values + 2, G_TYPE_STRV);
+
+    g_value_take_string (va->values + 0,
+                         g_strconcat (TP_CLIENT_BUS_NAME_BASE, client->name,
+                                      NULL));
+    g_value_take_boxed (va->values + 1, filters);
+    g_value_take_boxed (va->values + 2, g_ptr_array_free (cap_tokens, FALSE));
+
+    g_ptr_array_add (vas, va);
+}
+
 static void
 mcd_dispatcher_release_startup_lock (McdDispatcher *self)
 {
@@ -1985,17 +2047,30 @@ mcd_dispatcher_release_startup_lock (McdDispatcher *self)
     if (self->priv->startup_lock == 0)
     {
         GHashTableIter iter;
-        gpointer k;
+        gpointer p;
+        GPtrArray *vas;
 
         DEBUG ("All initial clients have been inspected");
         self->priv->startup_completed = TRUE;
 
+        vas = g_ptr_array_sized_new (g_hash_table_size (self->priv->clients));
+
+        g_hash_table_iter_init (&iter, self->priv->clients);
+
+        while (g_hash_table_iter_next (&iter, NULL, &p))
+        {
+            mcd_dispatcher_append_client_caps (self, p, vas);
+        }
+
         g_hash_table_iter_init (&iter, self->priv->connections);
 
-        while (g_hash_table_iter_next (&iter, &k, NULL))
+        while (g_hash_table_iter_next (&iter, &p, NULL))
         {
-            _mcd_connection_start_dispatching (k);
+            _mcd_connection_start_dispatching (p, vas);
         }
+
+        g_ptr_array_foreach (vas, (GFunc) g_value_array_free, NULL);
+        g_ptr_array_free (vas, TRUE);
     }
 }
 
@@ -2066,6 +2141,39 @@ mcd_client_add_cap_tokens (McdClient *client,
 }
 
 static void
+mcd_dispatcher_update_client_caps (McdDispatcher *self,
+                                   McdClient *client)
+{
+    GPtrArray *vas;
+    GHashTableIter iter;
+    gpointer k;
+
+    /* If we haven't finished inspecting initial clients yet, we'll push all
+     * the client caps into all connections when we do, so do nothing.
+     *
+     * If we don't have any connections, on the other hand, then there's
+     * nothing to do. */
+    if (!self->priv->startup_completed
+        || g_hash_table_size (self->priv->connections) == 0)
+    {
+        return;
+    }
+
+    vas = g_ptr_array_sized_new (1);
+    mcd_dispatcher_append_client_caps (self, client, vas);
+
+    g_hash_table_iter_init (&iter, self->priv->connections);
+
+    while (g_hash_table_iter_next (&iter, &k, NULL))
+    {
+        _mcd_connection_update_client_caps (k, vas);
+    }
+
+    g_ptr_array_foreach (vas, (GFunc) g_value_array_free, NULL);
+    g_ptr_array_free (vas, TRUE);
+}
+
+static void
 handler_get_all_cb (TpProxy *proxy,
                     GHashTable *properties,
                     const GError *error,
@@ -2154,6 +2262,8 @@ handler_get_all_cb (TpProxy *proxy,
         }
     }
 
+    mcd_dispatcher_update_client_caps (self, client);
+
 finally:
     mcd_dispatcher_release_startup_lock (self);
 }
@@ -2501,6 +2611,7 @@ mcd_client_start_introspection (McdClientProxy *proxy,
             else
             {
                 DEBUG ("%s is a Handler but not active", client->name);
+                mcd_dispatcher_update_client_caps (dispatcher, client);
             }
         }
     }
@@ -3895,7 +4006,23 @@ _mcd_dispatcher_add_connection (McdDispatcher *self,
 
     if (self->priv->startup_completed)
     {
-        _mcd_connection_start_dispatching (connection);
+        GHashTableIter iter;
+        gpointer p;
+        GPtrArray *vas;
+
+        vas = g_ptr_array_sized_new (g_hash_table_size (self->priv->clients));
+
+        g_hash_table_iter_init (&iter, self->priv->clients);
+
+        while (g_hash_table_iter_next (&iter, NULL, &p))
+        {
+            mcd_dispatcher_append_client_caps (self, p, vas);
+        }
+
+        _mcd_connection_start_dispatching (connection, vas);
+
+        g_ptr_array_foreach (vas, (GFunc) g_value_array_free, NULL);
+        g_ptr_array_free (vas, TRUE);
     }
     /* else _mcd_connection_start_dispatching will be called when we're ready
      * for it */
-- 
1.5.6.5




More information about the telepathy-commits mailing list