[Telepathy-commits] [telepathy-glib/master] Only listen to one of MembersChanged[Detailed]

Will Thompson will.thompson at collabora.co.uk
Mon Jan 5 16:10:11 PST 2009


based on whether the Members_Changed_Detailed group flag is set.
---
 telepathy-glib/channel-group.c    |   64 +++++++++++++++++++++++++++----------
 telepathy-glib/channel-internal.h |    6 +++
 2 files changed, 53 insertions(+), 17 deletions(-)

diff --git a/telepathy-glib/channel-group.c b/telepathy-glib/channel-group.c
index e2e7455..401503f 100644
--- a/telepathy-glib/channel-group.c
+++ b/telepathy-glib/channel-group.c
@@ -309,6 +309,43 @@ tp_channel_group_get_handle_owner (TpChannel *self,
 }
 
 
+/* This must be called before the local group members lists are created.  Until
+ * this is called, the proxy is listening to both MembersChanged and
+ * MembersChangedDetailed, but they are ignored until priv->group_members
+ * exists.  If that list is created before one signal is disconnected, the
+ * proxy will react to state changes twice and madness will ensue.
+ */
+static void
+_got_initial_group_flags (TpChannel *self,
+                          TpChannelGroupFlags flags)
+{
+  TpChannelPrivate *priv = self->priv;
+
+  g_assert (priv->group_flags == 0);
+  g_assert (self->priv->group_members == NULL);
+
+  priv->group_flags = flags;
+  DEBUG ("Initial GroupFlags: %u", flags);
+  priv->have_group_flags = TRUE;
+
+  if (flags != 0)
+    g_object_notify ((GObject *) self, "group-flags");
+
+  /* If the channel claims to support MembersChangedDetailed, disconnect from
+   * MembersChanged. Otherwise, disconnect from MembersChangedDetailed in case
+   * it secretly emits it anyway, so we're only listening to one change
+   * notification.
+   */
+  if (flags & TP_CHANNEL_GROUP_FLAG_MEMBERS_CHANGED_DETAILED)
+    tp_proxy_signal_connection_disconnect (priv->members_changed_sig);
+  else
+    tp_proxy_signal_connection_disconnect (priv->members_changed_detailed_sig);
+
+  priv->members_changed_sig = NULL;
+  priv->members_changed_detailed_sig = NULL;
+}
+
+
 static void
 tp_channel_got_group_flags_0_16_cb (TpChannel *self,
                                     guint flags,
@@ -322,6 +359,7 @@ tp_channel_got_group_flags_0_16_cb (TpChannel *self,
     {
       DEBUG ("%p GetGroupFlags() failed, assuming initial flags 0: %s", self,
           error->message);
+      flags = 0;
     }
   else
     {
@@ -332,15 +370,9 @@ tp_channel_got_group_flags_0_16_cb (TpChannel *self,
               "properties, but GetAll didn't work");
           flags &= ~TP_CHANNEL_GROUP_FLAG_PROPERTIES;
         }
-
-      self->priv->group_flags = flags;
-      DEBUG ("Initial GroupFlags: %u", flags);
-
-      if (flags != 0)
-        g_object_notify ((GObject *) self, "group-flags");
     }
 
-  self->priv->have_group_flags = 1;
+  _got_initial_group_flags (self, flags);
   _tp_channel_continue_introspection (self);
 }
 
@@ -652,12 +684,8 @@ tp_channel_got_group_properties_cb (TpProxy *proxy,
 
       DEBUG ("Received %u group properties", g_hash_table_size (asv));
 
-      self->priv->group_flags = tp_asv_get_uint32 (asv, "GroupFlags", NULL);
-      DEBUG ("Initial GroupFlags: %u", self->priv->group_flags);
-      self->priv->have_group_flags = 1;
-
-      if (self->priv->group_flags != 0)
-        g_object_notify ((GObject *) self, "group-flags");
+      _got_initial_group_flags (self,
+          tp_asv_get_uint32 (asv, "GroupFlags", NULL));
 
       tp_channel_group_self_handle_changed_cb (self,
           tp_asv_get_uint32 (asv, "SelfHandle", NULL), NULL, NULL);
@@ -978,11 +1006,13 @@ _tp_channel_get_group_properties (TpChannel *self)
 
   DEBUG ("%p", self);
 
-  tp_cli_channel_interface_group_connect_to_members_changed (self,
-      tp_channel_group_members_changed_cb, NULL, NULL, NULL, NULL);
+  self->priv->members_changed_sig =
+      tp_cli_channel_interface_group_connect_to_members_changed (self,
+          tp_channel_group_members_changed_cb, NULL, NULL, NULL, NULL);
 
-  tp_cli_channel_interface_group_connect_to_members_changed_detailed (self,
-      tp_channel_group_members_changed_detailed_cb, NULL, NULL, NULL, NULL);
+  self->priv->members_changed_detailed_sig =
+      tp_cli_channel_interface_group_connect_to_members_changed_detailed (self,
+          tp_channel_group_members_changed_detailed_cb, NULL, NULL, NULL, NULL);
 
   tp_cli_channel_interface_group_connect_to_group_flags_changed (self,
       tp_channel_group_flags_changed_cb, NULL, NULL, NULL, NULL);
diff --git a/telepathy-glib/channel-internal.h b/telepathy-glib/channel-internal.h
index e856d7c..1d1fb0b 100644
--- a/telepathy-glib/channel-internal.h
+++ b/telepathy-glib/channel-internal.h
@@ -49,6 +49,12 @@ struct _TpChannelPrivate {
     /* owned string (iface + "." + prop) => slice-allocated GValue */
     GHashTable *channel_properties;
 
+    /* Set until introspection discovers which to use; both NULL after one has
+     * been disconnected.
+     */
+    TpProxySignalConnection *members_changed_sig;
+    TpProxySignalConnection *members_changed_detailed_sig;
+
     TpHandle group_self_handle;
     TpChannelGroupFlags group_flags;
     /* NULL if members not discovered yet */
-- 
1.5.6.5




More information about the Telepathy-commits mailing list