[telepathy-mission-control/master] McdConnection: before calling Connect, try to set initial presence

Simon McVittie simon.mcvittie at collabora.co.uk
Thu Sep 3 11:03:27 PDT 2009


If this fails, it's no big deal - we'll set it again later anyway.

The infrastructure I've set up is fairly generic, so we can re-use it for
anything else that we want to try to set up before going online (to
include ContactCapabilities in 5.3, and perhaps Avatars and Aliasing
later).
---
 src/mcd-connection.c |  134 ++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 129 insertions(+), 5 deletions(-)

diff --git a/src/mcd-connection.c b/src/mcd-connection.c
index fd956c0..9612e70 100644
--- a/src/mcd-connection.c
+++ b/src/mcd-connection.c
@@ -100,6 +100,9 @@ struct _McdConnectionPrivate
     /* Telepathy connection */
     TpConnection *tp_conn;
 
+    /* Things to do before calling Connect */
+    guint tasks_before_connect;
+
     guint reconnect_timer; 	/* timer for reconnection */
     guint reconnect_interval;
 
@@ -351,7 +354,17 @@ presence_get_statuses_cb (TpProxy *proxy, const GValue *v_statuses,
 
     DEBUG ("account %s:", mcd_account_get_unique_name (priv->account));
     statuses = g_value_get_boxed (v_statuses);
+
+    g_return_if_fail (statuses != NULL);
+
+    /* This function can be called both before and after Connect() - before
+     * CONNECTED the Connection tells us the presences it believes it will
+     * probably support, and after CONNECTED it tells us the presences it
+     * *actually* supports (which might be less numerous). */
+    g_hash_table_remove_all (priv->recognized_presences);
+
     g_hash_table_iter_init (&iter, statuses);
+
     while (g_hash_table_iter_next (&iter, &ht_key, &ht_value))
     {
         GValueArray *va = ht_value;
@@ -1423,6 +1436,115 @@ _mcd_connection_start_dispatching (McdConnection *self)
     request_unrequested_channels (self);
 }
 
+static void
+mcd_connection_done_task_before_connect (McdConnection *self)
+{
+    if (--self->priv->tasks_before_connect == 0)
+    {
+        if (self->priv->tp_conn == NULL)
+        {
+            DEBUG ("TpConnection went away, not doing anything");
+        }
+
+        DEBUG ("%s: Calling Connect()",
+               tp_proxy_get_object_path (self->priv->tp_conn));
+        tp_cli_connection_call_connect (self->priv->tp_conn, -1, connect_cb,
+                                        self->priv, NULL, (GObject *) self);
+    }
+}
+
+static void
+mcd_connection_early_get_statuses_cb (TpProxy *proxy,
+                                      const GValue *v_statuses,
+                                      const GError *error,
+                                      gpointer user_data,
+                                      GObject *weak_object)
+{
+    McdConnection *self = MCD_CONNECTION (weak_object);
+
+    if (self->priv->tp_conn != (TpConnection *) proxy)
+    {
+        DEBUG ("Connection %p has been replaced with %p, stopping",
+               proxy, self->priv->tp_conn);
+        return;
+    }
+
+    /* This is before we called Connect(), and may or may not be before
+     * connection-ready has been signalled. */
+
+    if (error == NULL)
+    {
+        DEBUG ("%s: Early Get(Statuses) succeeded",
+               tp_proxy_get_object_path (proxy));
+
+        /* This will trigger a call to SetPresence, but don't wait for that to
+         * finish before calling Connect (there's no need to). */
+        presence_get_statuses_cb (proxy, v_statuses, error, self->priv,
+                                  weak_object);
+    }
+    else
+    {
+        DEBUG ("%s: Early Get(Statuses) failed (not a problem, will try "
+               "again later): %s #%d: %s",
+               tp_proxy_get_object_path (proxy),
+               g_quark_to_string (error->domain), error->code, error->message);
+    }
+
+    mcd_connection_done_task_before_connect (self);
+}
+
+static void
+mcd_connection_early_get_interfaces_cb (TpConnection *tp_conn,
+                                        const gchar **interfaces,
+                                        const GError *error,
+                                        gpointer user_data,
+                                        GObject *weak_object)
+{
+    McdConnection *self = MCD_CONNECTION (weak_object);
+    const gchar **iter;
+
+    if (self->priv->tp_conn != tp_conn)
+    {
+        DEBUG ("Connection %p has been replaced with %p, stopping",
+               tp_conn, self->priv->tp_conn);
+        return;
+    }
+
+    if (error != NULL)
+    {
+        DEBUG ("%s: Early GetInterfaces failed (not a problem, will try "
+               "again later): %s #%d: %s",
+               tp_proxy_get_object_path (tp_conn),
+               g_quark_to_string (error->domain), error->code, error->message);
+    }
+    else
+    {
+        for (iter = interfaces; *iter != NULL; iter++)
+        {
+            GQuark q = g_quark_try_string (*iter);
+
+            /* if the interface is not recognised, q will just be 0 */
+
+            if (q == TP_IFACE_QUARK_CONNECTION_INTERFACE_SIMPLE_PRESENCE)
+            {
+                /* nail on the interface (TpConnection will eventually know
+                 * how to do this for itself) */
+                tp_proxy_add_interface_by_id ((TpProxy *) tp_conn, q);
+                self->priv->has_presence_if = TRUE;
+
+                self->priv->tasks_before_connect++;
+
+                tp_cli_dbus_properties_call_get (tp_conn, -1,
+                    TP_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE, "Statuses",
+                    mcd_connection_early_get_statuses_cb, NULL, NULL,
+                    (GObject *) self);
+            }
+        }
+    }
+
+    mcd_connection_done_task_before_connect (self);
+}
+
 typedef struct {
     /* really a McdConnection *, but g_object_add_weak_pointer wants a
      * gpointer */
@@ -1520,11 +1642,13 @@ request_connection_cb (TpConnectionManager *proxy, const gchar *bus_name,
 	return;
     }
 
-    /* FIXME we don't know the status of the connection yet, but calling
-     * Connect shouldn't cause any harm
-     * https://bugs.freedesktop.org/show_bug.cgi?id=14620 */
-    tp_cli_connection_call_connect (priv->tp_conn, -1, connect_cb, priv, NULL,
-				    (GObject *)connection);
+    priv->tasks_before_connect = 1;
+
+    /* TpConnection doesn't yet know how to get this information before
+     * the Connection goes to CONNECTED, so we'll have to do it ourselves */
+    tp_cli_connection_call_get_interfaces (priv->tp_conn, -1,
+        mcd_connection_early_get_interfaces_cb, NULL, NULL,
+        (GObject *) connection);
 }
 
 static void
-- 
1.5.6.5




More information about the telepathy-commits mailing list