[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