[telepathy-gabble/master] Port SetSelfCapabilities to use capability sets

Will Thompson will.thompson at collabora.co.uk
Tue Sep 8 04:10:02 PDT 2009


This ports gabble_caps_channel_manager_add_capability() to add nodes to
a GabbleCapabilitySet, rather than footling with
per_channel_manager_caps, and updates the SetSelfCapabilities
implementation accordingly.

This also alters the presence cache's capabilities-updated signal to
include GabbleCapabilitySets rather than per_channel_manager_caps hash
tables.
---
 src/caps-channel-manager.c  |   16 +++++--
 src/caps-channel-manager.h  |   11 +++--
 src/connection.c            |  102 ++++++++++++++++--------------------------
 src/presence-cache.c        |   47 ++++++++++++--------
 src/private-tubes-factory.c |   67 +++++++++-------------------
 5 files changed, 106 insertions(+), 137 deletions(-)

diff --git a/src/caps-channel-manager.c b/src/caps-channel-manager.c
index fac86aa..7ac167a 100644
--- a/src/caps-channel-manager.c
+++ b/src/caps-channel-manager.c
@@ -177,12 +177,20 @@ gboolean gabble_caps_channel_manager_capabilities_diff (
   return FALSE;
 }
 
+/**
+ * gabble_caps_channel_manager_add_capability:
+ * @cap: the Telepathy-level capability to add
+ * @cap_set: a set of XMPP namespaces, to which the namespaces corresponding to
+ *           @cap should be added
+ *
+ * Used to advertise that we support the XMPP capabilities corresponding to the
+ * Telepathy capability supplied.
+ */
 void
 gabble_caps_channel_manager_add_capability (
     GabbleCapsChannelManager *caps_manager,
-    GabbleConnection *conn,
-    TpHandle handle,
-    GHashTable *cap)
+    GHashTable *cap,
+    GabbleCapabilitySet *cap_set)
 {
   GabbleCapsChannelManagerIface *iface =
     GABBLE_CAPS_CHANNEL_MANAGER_GET_INTERFACE (caps_manager);
@@ -190,7 +198,7 @@ gabble_caps_channel_manager_add_capability (
 
   if (method != NULL)
     {
-      method (caps_manager, conn, handle, cap);
+      method (caps_manager, cap, cap_set);
     }
   /* ... else, nothing to do */
 }
diff --git a/src/caps-channel-manager.h b/src/caps-channel-manager.h
index 80298be..340cf7e 100644
--- a/src/caps-channel-manager.h
+++ b/src/caps-channel-manager.h
@@ -62,8 +62,9 @@ typedef void (*GabbleCapsChannelManagerGetContactCapsFunc) (
     GPtrArray *arr);
 
 typedef void (*GabbleCapsChannelManagerAddCapFunc) (
-    GabbleCapsChannelManager *manager, GabbleConnection *conn, TpHandle handle,
-    GHashTable *cap);
+    GabbleCapsChannelManager *manager,
+    GHashTable *cap,
+    GabbleCapabilitySet *cap_set);
 
 /* Specific to Gabble */
 typedef void (*GabbleCapsChannelManagerGetFeatureListFunc) (
@@ -118,9 +119,9 @@ gboolean gabble_caps_channel_manager_capabilities_diff (
     gpointer specific_old_caps, gpointer specific_new_caps);
 
 void gabble_caps_channel_manager_add_capability (
-    GabbleCapsChannelManager *manager, GabbleConnection *conn, TpHandle handle,
-    GHashTable *cap);
-
+    GabbleCapsChannelManager *caps_manager,
+    GHashTable *cap,
+    GabbleCapabilitySet *cap_set);
 
 struct _GabbleCapsChannelManagerIface {
     GTypeInterface parent;
diff --git a/src/connection.c b/src/connection.c
index 6b7a0f4..bf83118 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -204,10 +204,13 @@ struct _GabbleConnectionPrivate
   gboolean dispose_has_run;
 };
 
-static void connection_capabilities_update_cb (GabblePresenceCache *,
-    TpHandle, GabblePresenceCapabilities, GabblePresenceCapabilities,
-    GHashTable *, GHashTable *, gpointer);
-
+static void connection_capabilities_update_cb (GabblePresenceCache *cache,
+    TpHandle handle,
+    GabblePresenceCapabilities old_caps,
+    GabblePresenceCapabilities new_caps,
+    const GabbleCapabilitySet *old_cap_set,
+    const GabbleCapabilitySet *new_cap_set,
+    gpointer user_data);
 
 static GPtrArray *
 _gabble_connection_create_channel_managers (TpBaseConnection *conn)
@@ -2377,50 +2380,27 @@ gabble_free_enhanced_contact_capabilities (GPtrArray *caps)
 
 static void
 _emit_contact_capabilities_changed (GabbleConnection *conn,
-                                    TpHandle handle,
-                                    GHashTable *old_caps,
-                                    GHashTable *new_caps)
+    TpHandle handle,
+    const GabbleCapabilitySet *old_caps,
+    const GabbleCapabilitySet *new_caps)
 {
-  TpBaseConnection *base_conn = TP_BASE_CONNECTION (conn);
-  TpChannelManagerIter iter;
-  TpChannelManager *manager;
   GPtrArray *ret;
   GHashTable *hash;
-  gboolean diff = FALSE;
 
-  tp_base_connection_channel_manager_iter_init (&iter, base_conn);
-  while (tp_base_connection_channel_manager_iter_next (&iter, &manager))
+  /* Don't emit the D-Bus signal if there is no change */
+  if (gabble_capability_set_equals (old_caps, new_caps))
     {
-      gpointer per_channel_manager_caps_old = NULL;
-      gpointer per_channel_manager_caps_new = NULL;
-
-      /* all channel managers must implement the capability interface */
-      g_assert (GABBLE_IS_CAPS_CHANNEL_MANAGER (manager));
-
-      if (old_caps != NULL)
-        per_channel_manager_caps_old = g_hash_table_lookup (old_caps, manager);
-      if (new_caps != NULL)
-        per_channel_manager_caps_new = g_hash_table_lookup (new_caps, manager);
-
-      if (gabble_caps_channel_manager_capabilities_diff (
-            GABBLE_CAPS_CHANNEL_MANAGER (manager), handle,
-            per_channel_manager_caps_old, per_channel_manager_caps_new))
-        {
-          diff = TRUE;
-          break;
-        }
+      DEBUG ("unchanged; not emitting ContactCapabilitiesChanged");
+      return;
     }
 
-  /* Don't emit the D-Bus signal if there is no change */
-  if (! diff)
-    return;
-
   ret = g_ptr_array_new ();
 
   gabble_connection_get_handle_contact_capabilities (conn, handle, ret);
 
   hash = g_hash_table_new (NULL, NULL);
   g_hash_table_insert (hash, GUINT_TO_POINTER (handle), ret);
+
   gabble_svc_connection_interface_contact_capabilities_emit_contact_capabilities_changed (
       conn, hash);
 
@@ -2430,21 +2410,19 @@ _emit_contact_capabilities_changed (GabbleConnection *conn,
 
 static void
 connection_capabilities_update_cb (GabblePresenceCache *cache,
-                                   TpHandle handle,
-                                   GabblePresenceCapabilities old_caps,
-                                   GabblePresenceCapabilities new_caps,
-                                   GHashTable *old_enhanced_caps,
-                                   GHashTable *new_enhanced_caps,
-                                   gpointer user_data)
+    TpHandle handle,
+    GabblePresenceCapabilities old_caps,
+    GabblePresenceCapabilities new_caps,
+    const GabbleCapabilitySet *old_cap_set,
+    const GabbleCapabilitySet *new_cap_set,
+    gpointer user_data)
 {
   GabbleConnection *conn = GABBLE_CONNECTION (user_data);
 
   if (old_caps != new_caps)
     _emit_capabilities_changed (conn, handle, old_caps, new_caps);
 
-  if (old_enhanced_caps != NULL || new_enhanced_caps != NULL)
-    _emit_contact_capabilities_changed (conn, handle,
-                                        old_enhanced_caps, new_enhanced_caps);
+  _emit_contact_capabilities_changed (conn, handle, old_cap_set, new_cap_set);
 }
 
 /**
@@ -2589,17 +2567,15 @@ gabble_connection_set_self_capabilities (
   GabbleConnection *self = GABBLE_CONNECTION (iface);
   TpBaseConnection *base = (TpBaseConnection *) self;
   GabbleConnectionPrivate *priv = self->priv;
+  GabbleCapabilitySet *old_caps, *new_caps;
   guint i;
   GabblePresence *pres = self->self_presence;
-  GHashTable *save_caps;
   GError *error = NULL;
 
   TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context);
 
-  /* reset the caps, and fill with the given parameter but keep a backup for
-   * diffing: we don't want to emit a signal if nothing has changed */
-  save_caps = pres->per_channel_manager_caps;
-  pres->per_channel_manager_caps = NULL;
+  old_caps = gabble_presence_get_caps (pres);
+  new_caps = gabble_capability_set_new ();
 
   for (i = 0; i < caps->len; i++)
     {
@@ -2614,28 +2590,28 @@ gabble_connection_set_self_capabilities (
           g_assert (GABBLE_IS_CAPS_CHANNEL_MANAGER (manager));
 
           gabble_caps_channel_manager_add_capability (
-              GABBLE_CAPS_CHANNEL_MANAGER (manager), self,
-              base->self_handle, cap_to_add);
+              GABBLE_CAPS_CHANNEL_MANAGER (manager), cap_to_add, new_caps);
         }
     }
 
-  priv->caps_serial++;
+  gabble_presence_set_capabilities (pres, priv->resource, new_caps,
+      pres->caps, NULL, priv->caps_serial++);
 
-  if (!_gabble_connection_signal_own_presence (self, &error))
+  if (_gabble_connection_signal_own_presence (self, &error))
+    {
+      _emit_contact_capabilities_changed (self, base->self_handle, old_caps,
+          new_caps);
+
+      gabble_svc_connection_interface_contact_capabilities_return_from_set_self_capabilities (
+          context);
+    }
+  else
     {
-      gabble_presence_cache_free_cache_entry (save_caps);
       dbus_g_method_return_error (context, error);
-      return;
     }
 
-  _emit_contact_capabilities_changed (self, base->self_handle,
-                                      save_caps,
-                                      pres->per_channel_manager_caps);
-  gabble_presence_cache_free_cache_entry (save_caps);
-
-
-  gabble_svc_connection_interface_contact_capabilities_return_from_set_self_capabilities
-      (context);
+  gabble_capability_set_free (old_caps);
+  gabble_capability_set_free (new_caps);
 }
 
 static const gchar *assumed_caps[] =
diff --git a/src/presence-cache.c b/src/presence-cache.c
index 4c2cbfc..4ab72ac 100644
--- a/src/presence-cache.c
+++ b/src/presence-cache.c
@@ -957,11 +957,11 @@ emit_capabilities_update (GabblePresenceCache *cache,
     TpHandle handle,
     GabblePresenceCapabilities old_caps,
     GabblePresenceCapabilities new_caps,
-    GHashTable *old_enhanced_caps,
-    GHashTable *new_enhanced_caps)
+    const GabbleCapabilitySet *old_cap_set,
+    const GabbleCapabilitySet *new_cap_set)
 {
   g_signal_emit (cache, signals[CAPABILITIES_UPDATE], 0,
-      handle, old_caps, new_caps, old_enhanced_caps, new_enhanced_caps);
+      handle, old_caps, new_caps, old_cap_set, new_cap_set);
 }
 
 /**
@@ -981,14 +981,14 @@ set_caps_for (DiscoWaiter *waiter,
 {
   GabblePresence *presence = gabble_presence_cache_get (cache, waiter->handle);
   GabblePresenceCapabilities save_caps;
-  GHashTable *save_enhanced_caps;
+  GabbleCapabilitySet *old_cap_set;
+  GabbleCapabilitySet *new_cap_set;
 
   if (presence == NULL)
     return;
 
   save_caps = presence->caps;
-  gabble_presence_cache_copy_cache_entry (&save_enhanced_caps,
-      presence->per_channel_manager_caps);
+  old_cap_set = gabble_presence_get_caps (presence);
 
   DEBUG ("setting caps for %d (thanks to %d %s) to %d (save_caps %d)",
       waiter->handle, responder_handle, responder_jid, caps, save_caps);
@@ -998,9 +998,13 @@ set_caps_for (DiscoWaiter *waiter,
 
   DEBUG ("caps for %d now %d", waiter->handle, presence->caps);
 
+  new_cap_set = gabble_presence_get_caps (presence);
+
   emit_capabilities_update (cache, waiter->handle, save_caps, presence->caps,
-      save_enhanced_caps, presence->per_channel_manager_caps);
-  gabble_presence_cache_free_cache_entry (save_enhanced_caps);
+      old_cap_set, new_cap_set);
+
+  gabble_capability_set_free (old_cap_set);
+  gabble_capability_set_free (new_cap_set);
 }
 
 static void
@@ -1277,7 +1281,7 @@ _process_caps (GabblePresenceCache *cache,
   GSList *uris, *i;
   GabblePresenceCachePrivate *priv;
   GabblePresenceCapabilities old_caps = 0;
-  GHashTable *old_enhanced_caps;
+  GabbleCapabilitySet *old_cap_set;
   guint serial;
   const gchar *hash, *ver;
 
@@ -1293,8 +1297,7 @@ _process_caps (GabblePresenceCache *cache,
   if (presence)
     {
       old_caps = presence->caps;
-      gabble_presence_cache_copy_cache_entry (&old_enhanced_caps,
-          presence->per_channel_manager_caps);
+      old_cap_set = gabble_presence_get_caps (presence);
     }
 
   for (i = uris; NULL != i; i = i->next)
@@ -1307,12 +1310,15 @@ _process_caps (GabblePresenceCache *cache,
 
   if (presence)
     {
+      GabbleCapabilitySet *new_cap_set = gabble_presence_get_caps (presence);
+
       DEBUG ("Emitting caps update: handle %u, old %u, new %u",
           handle, old_caps, presence->caps);
 
       emit_capabilities_update (cache, handle, old_caps, presence->caps,
-          old_enhanced_caps, presence->per_channel_manager_caps);
-      gabble_presence_cache_free_cache_entry (old_enhanced_caps);
+          old_cap_set, new_cap_set);
+
+      gabble_capability_set_free (new_cap_set);
     }
   else
     {
@@ -1320,6 +1326,7 @@ _process_caps (GabblePresenceCache *cache,
           presence->caps, handle);
     }
 
+  gabble_capability_set_free (old_cap_set);
   g_slist_free (uris);
 }
 
@@ -1584,7 +1591,7 @@ gabble_presence_cache_do_update (
   const gchar *jid;
   GabblePresence *presence;
   GabblePresenceCapabilities caps_before;
-  GHashTable *enhanced_caps_before;
+  GabbleCapabilitySet *old_cap_set, *new_cap_set;
   gboolean ret = FALSE;
 
   jid = tp_handle_inspect (contact_repo, handle);
@@ -1600,16 +1607,18 @@ gabble_presence_cache_do_update (
     presence = _cache_insert (cache, handle);
 
   caps_before = presence->caps;
-  enhanced_caps_before = presence->per_channel_manager_caps;
-  gabble_presence_cache_copy_cache_entry (&enhanced_caps_before,
-      presence->per_channel_manager_caps);
+  old_cap_set = gabble_presence_get_caps (presence);
 
   ret = gabble_presence_update (presence, resource, presence_id,
       status_message, priority);
 
+  new_cap_set = gabble_presence_get_caps (presence);
+
   emit_capabilities_update (cache, handle, caps_before, presence->caps,
-      enhanced_caps_before, presence->per_channel_manager_caps);
-  gabble_presence_cache_free_cache_entry (enhanced_caps_before);
+      old_cap_set, new_cap_set);
+
+  gabble_capability_set_free (old_cap_set);
+  gabble_capability_set_free (new_cap_set);
 
   return ret;
 }
diff --git a/src/private-tubes-factory.c b/src/private-tubes-factory.c
index c751100..c4e87bd 100644
--- a/src/private-tubes-factory.c
+++ b/src/private-tubes-factory.c
@@ -792,14 +792,11 @@ gabble_private_tubes_factory_caps_diff (
 
 static void
 gabble_private_tubes_factory_add_cap (GabbleCapsChannelManager *manager,
-                                      GabbleConnection *conn,
-                                      TpHandle handle,
-                                      GHashTable *cap)
+    GHashTable *cap,
+    GabbleCapabilitySet *cap_set)
 {
-  TpBaseConnection *base = (TpBaseConnection *) conn;
-  GabblePresence *presence;
-  TubesCapabilities *caps;
-  const gchar *channel_type;
+  const gchar *channel_type, *service;
+  gchar *ns = NULL;
 
   channel_type = tp_asv_get_string (cap,
             TP_IFACE_CHANNEL ".ChannelType");
@@ -814,50 +811,28 @@ gabble_private_tubes_factory_add_cap (GabbleCapsChannelManager *manager,
         TP_IFACE_CHANNEL ".TargetHandleType", NULL) != TP_HANDLE_TYPE_CONTACT)
     return;
 
-  if (handle == base->self_handle)
-    presence = conn->self_presence;
-  else
-    presence = gabble_presence_cache_get (conn->presence_cache, handle);
-
-  g_assert (presence != NULL);
-
-  if (presence->per_channel_manager_caps == NULL)
-    presence->per_channel_manager_caps = g_hash_table_new (NULL, NULL);
-
-  caps = g_hash_table_lookup (presence->per_channel_manager_caps, manager);
-  if (caps == NULL)
-    {
-      caps = g_new0 (TubesCapabilities, 1);
-      caps->stream_tube_caps = g_hash_table_new_full (g_str_hash, g_str_equal,
-          g_free, gabble_private_tubes_factory_free_feat);
-      caps->dbus_tube_caps = g_hash_table_new_full (g_str_hash, g_str_equal,
-          g_free, gabble_private_tubes_factory_free_feat);
-      g_hash_table_insert (presence->per_channel_manager_caps, manager, caps);
-
-      if (handle == base->self_handle)
-        /* We always support generic tubes caps */
-        caps->tubes_supported = TRUE;
-    }
-
   if (!tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_STREAM_TUBE))
     {
-      Feature *feat = g_new0 (Feature, 1);
-      gchar *service = g_strdup (tp_asv_get_string (cap,
-          TP_IFACE_CHANNEL_TYPE_STREAM_TUBE ".Service"));
-      feat->feature_type = FEATURE_OPTIONAL;
-      feat->ns = g_strdup_printf ("%s/stream#%s", NS_TUBES, service);
-      feat->caps = 0;
-      g_hash_table_insert (caps->stream_tube_caps, service, feat);
+      service = tp_asv_get_string (cap,
+          TP_IFACE_CHANNEL_TYPE_STREAM_TUBE ".Service");
+
+      if (service != NULL)
+        ns = g_strconcat (STREAM_CAP_PREFIX, service, NULL);
     }
   else if (!tp_strdiff (channel_type, TP_IFACE_CHANNEL_TYPE_DBUS_TUBE))
     {
-      Feature *feat = g_new0 (Feature, 1);
-      gchar *service = g_strdup (tp_asv_get_string (cap,
-          TP_IFACE_CHANNEL_TYPE_DBUS_TUBE ".ServiceName"));
-      feat->feature_type = FEATURE_OPTIONAL;
-      feat->ns = g_strdup_printf ("%s/dbus#%s", NS_TUBES, service);
-      feat->caps = 0;
-      g_hash_table_insert (caps->dbus_tube_caps, service, feat);
+      service = tp_asv_get_string (cap,
+          TP_IFACE_CHANNEL_TYPE_DBUS_TUBE ".ServiceName");
+
+      if (service != NULL)
+        ns = g_strconcat (DBUS_CAP_PREFIX, service, NULL);
+    }
+
+  if (ns != NULL)
+    {
+      DEBUG ("adding capability %s", ns);
+      gabble_capability_set_add (cap_set, ns);
+      g_free (ns);
     }
 }
 
-- 
1.5.6.5




More information about the telepathy-commits mailing list