diff options
author | Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> | 2011-01-18 15:09:14 +0100 |
---|---|---|
committer | Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> | 2011-05-12 12:30:41 +0200 |
commit | e3761c4c807b66b8e9a4408f51c81fd4fd4a8248 (patch) | |
tree | fbbfc80e5b961659f8195aef9b5eb97f316b3e63 | |
parent | 7b1fdf9783ffb9e6527c48257de56edc62c2dbcc (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.c | 31 | ||||
-rw-r--r-- | telepathy-glib/proxy-internal.h | 9 | ||||
-rw-r--r-- | telepathy-glib/proxy.c | 98 |
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) +} |