[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