summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>2011-01-18 15:09:14 +0100
committerGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>2011-05-12 12:30:41 +0200
commite3761c4c807b66b8e9a4408f51c81fd4fd4a8248 (patch)
treefbbfc80e5b961659f8195aef9b5eb97f316b3e63
parent7b1fdf9783ffb9e6527c48257de56edc62c2dbcc (diff)
Add TpProxyFeature.prepare_before_signalling_connected_async
It allows a prepared feature to be notified to update itself before announcing that the connection is now CONNECTED.
-rw-r--r--telepathy-glib/connection.c31
-rw-r--r--telepathy-glib/proxy-internal.h9
-rw-r--r--telepathy-glib/proxy.c98
3 files changed, 137 insertions, 1 deletions
diff --git a/telepathy-glib/connection.c b/telepathy-glib/connection.c
index 9ef3e056..20af2f43 100644
--- a/telepathy-glib/connection.c
+++ b/telepathy-glib/connection.c
@@ -372,6 +372,32 @@ signal_connected (TpConnection *self)
}
static void
+will_announced_connected_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ TpConnection *self = (TpConnection *) source;
+ GError *error = NULL;
+
+ if (!_tp_proxy_will_announce_connected_finish ((TpProxy *) self, result,
+ &error))
+ {
+ DEBUG ("_tp_connection_prepare_contact_info_async failed: %s",
+ error->message);
+
+ g_error_free (error);
+ }
+
+ if (tp_proxy_get_invalidated (self) != NULL)
+ {
+ DEBUG ("Connection has been invalidated; we're done");
+ return;
+ }
+
+ signal_connected (self);
+}
+
+static void
tp_connection_continue_introspection (TpConnection *self)
{
if (tp_proxy_get_invalidated (self) != NULL)
@@ -391,7 +417,10 @@ tp_connection_continue_introspection (TpConnection *self)
return;
}
- signal_connected (self);
+ /* We'll announce CONNECTED state soon, but first give a chance to
+ * prepared feature to be updated, if needed */
+ _tp_proxy_will_announce_connected_async ((TpProxy *) self,
+ will_announced_connected_cb, NULL);
}
else
{
diff --git a/telepathy-glib/proxy-internal.h b/telepathy-glib/proxy-internal.h
index ade38d26..775779ff 100644
--- a/telepathy-glib/proxy-internal.h
+++ b/telepathy-glib/proxy-internal.h
@@ -40,6 +40,7 @@ struct _TpProxyFeature {
gboolean core;
TpProxyPrepareAsync prepare_async;
+ TpProxyPrepareAsync prepare_before_signalling_connected_async;
const GQuark *interfaces_needed;
/* Features we depend on */
@@ -60,4 +61,12 @@ void _tp_proxy_set_feature_prepared (TpProxy *self,
void _tp_proxy_set_features_failed (TpProxy *self,
const GError *error);
+void _tp_proxy_will_announce_connected_async (TpProxy *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean _tp_proxy_will_announce_connected_finish (TpProxy *self,
+ GAsyncResult *result,
+ GError **error);
+
#endif
diff --git a/telepathy-glib/proxy.c b/telepathy-glib/proxy.c
index 20e27b4f..0978c1c0 100644
--- a/telepathy-glib/proxy.c
+++ b/telepathy-glib/proxy.c
@@ -354,6 +354,11 @@ struct _TpProxyPrivate {
* until the super class features have been prepared. */
GList *prepare_requests;
+ GSimpleAsyncResult *will_announce_connected_result;
+ /* Number of pending calls blocking will_announce_connected_result to be
+ * completed */
+ guint pending_will_announce_calls;
+
gboolean dispose_has_run;
};
@@ -962,6 +967,11 @@ check_feature_validity (TpProxy *self,
/* Core features can't have depends, their depends are implicit */
if (feature->core)
g_assert (feature->depends_on == NULL || feature->depends_on[0] == 0);
+
+ /* prepare_before_signalling_connected_async only make sense for
+ * TpConnection subclasses */
+ if (feature->prepare_before_signalling_connected_async != NULL)
+ g_assert (TP_IS_CONNECTION (self));
}
static GObject *
@@ -2165,3 +2175,91 @@ _tp_proxy_set_features_failed (TpProxy *self,
g_return_if_fail (error != NULL);
tp_proxy_poll_features (self, error);
}
+
+static void
+check_announce_connected (TpProxy *self,
+ gboolean in_idle)
+{
+ if (self->priv->pending_will_announce_calls != 0)
+ return;
+
+ if (in_idle)
+ {
+ g_simple_async_result_complete_in_idle (
+ self->priv->will_announce_connected_result);
+ }
+ else
+ {
+ g_simple_async_result_complete (
+ self->priv->will_announce_connected_result);
+ }
+
+ tp_clear_object (&self->priv->will_announce_connected_result);
+}
+
+static void
+prepare_before_signalling_connected_cb (GObject *source,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ TpProxy *self = user_data;
+
+ /* We don't care if the call succeeded or not as it was already prepared */
+ self->priv->pending_will_announce_calls--;
+
+ check_announce_connected (self, FALSE);
+}
+
+static void foreach_feature (GQuark name,
+ gpointer data,
+ gpointer user_data)
+{
+ FeatureState state = GPOINTER_TO_INT (data);
+ TpProxy *self = user_data;
+ const TpProxyFeature *feature;
+
+ if (state != FEATURE_STATE_READY)
+ return;
+
+ feature = tp_proxy_subclass_get_feature (G_OBJECT_TYPE (self), name);
+
+ if (feature->prepare_before_signalling_connected_async == NULL)
+ return;
+
+ self->priv->pending_will_announce_calls++;
+
+ feature->prepare_before_signalling_connected_async (self, feature,
+ prepare_before_signalling_connected_cb, self);
+}
+
+/*
+ * _tp_proxy_will_announce_connected_async:
+ *
+ * Called by connection.c when the connection became connected and we're about
+ * to announce it. But before we have to wait for all the prepared features to
+ * process their prepare_before_signalling_connected_async, if any.
+ */
+void
+_tp_proxy_will_announce_connected_async (TpProxy *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_assert (TP_IS_CONNECTION (self));
+ g_assert (self->priv->will_announce_connected_result == NULL);
+
+ self->priv->will_announce_connected_result = g_simple_async_result_new (
+ (GObject *) self, callback, user_data,
+ _tp_proxy_will_announce_connected_async);
+
+ g_datalist_foreach (&self->priv->features, foreach_feature, self);
+
+ check_announce_connected (self, TRUE);
+}
+
+gboolean
+_tp_proxy_will_announce_connected_finish (TpProxy *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ _tp_implement_finish_void (self, _tp_proxy_will_announce_connected_async)
+}