[Telepathy-commits] [telepathy-glib/master] TpConnectionManager: add API to become "ready"
Simon McVittie
simon.mcvittie at collabora.co.uk
Thu Feb 12 09:56:02 PST 2009
---
docs/reference/telepathy-glib-sections.txt | 2 +
telepathy-glib/connection-manager.c | 148 +++++++++++++++++++++++++++-
telepathy-glib/connection-manager.h | 7 ++
3 files changed, 153 insertions(+), 4 deletions(-)
diff --git a/docs/reference/telepathy-glib-sections.txt b/docs/reference/telepathy-glib-sections.txt
index 95ffa36..d419c3f 100644
--- a/docs/reference/telepathy-glib-sections.txt
+++ b/docs/reference/telepathy-glib-sections.txt
@@ -2450,6 +2450,8 @@ TpConnectionManagerParam
TpConnectionManagerClass
TpCMInfoSource
tp_connection_manager_new
+TpConnectionManagerWhenReadyCb
+tp_connection_manager_call_when_ready
tp_connection_manager_activate
tp_connection_manager_check_valid_name
tp_connection_manager_check_valid_protocol_name
diff --git a/telepathy-glib/connection-manager.c b/telepathy-glib/connection-manager.c
index 12b7b02..fc210b6 100644
--- a/telepathy-glib/connection-manager.c
+++ b/telepathy-glib/connection-manager.c
@@ -209,12 +209,143 @@ struct _TpConnectionManagerPrivate {
* progress (will replace ->protocols when finished).
* Otherwise NULL */
GPtrArray *found_protocols;
+
+ /* list of WhenReadyContext */
+ GList *waiting_for_ready;
};
G_DEFINE_TYPE (TpConnectionManager,
tp_connection_manager,
TP_TYPE_PROXY);
+typedef struct {
+ TpConnectionManager *cm;
+ TpConnectionManagerWhenReadyCb callback;
+ gpointer user_data;
+ GDestroyNotify destroy;
+ GObject *weak_object;
+} WhenReadyContext;
+
+static void
+when_ready_context_free (gpointer d)
+{
+ WhenReadyContext *c = d;
+
+ if (c->cm != NULL)
+ {
+ g_object_unref (c->cm);
+ c->cm = NULL;
+ }
+
+ if (c->destroy != NULL)
+ c->destroy (c->user_data);
+
+ g_slice_free (WhenReadyContext, c);
+}
+
+static void
+when_ready_context_cancel (gpointer d,
+ GObject *corpse)
+{
+ WhenReadyContext *c = d;
+
+ g_assert (c->weak_object == corpse);
+ c->weak_object = NULL;
+ c->callback = NULL;
+
+ if (c->destroy != NULL)
+ {
+ c->destroy (c->user_data);
+ c->destroy = NULL;
+ }
+
+ if (c->cm != NULL)
+ {
+ g_object_unref (c->cm);
+ c->cm = NULL;
+ }
+}
+
+static gboolean
+when_ready_context_complete (gpointer d)
+{
+ WhenReadyContext *c = d;
+
+ if (c->callback != NULL)
+ c->callback (c->cm, NULL, c->user_data, c->weak_object);
+
+ return FALSE;
+}
+
+static void
+tp_connection_manager_ready_or_failed (TpConnectionManager *self,
+ const GError *error)
+{
+ GList *waiters = self->priv->waiting_for_ready;
+ GList *link;
+
+ self->priv->waiting_for_ready = NULL;
+
+ if (self->info_source > TP_CM_INFO_SOURCE_NONE)
+ {
+ /* we have info already, so suppress any error and return the old info */
+ error = NULL;
+ }
+ else
+ {
+ g_assert (error != NULL);
+ }
+
+ for (link = waiters; link != NULL; link = g_list_next (link))
+ {
+ WhenReadyContext *c = link->data;
+
+ if (c->callback != NULL)
+ c->callback (c->cm, error, c->user_data, c->weak_object);
+
+ when_ready_context_free (c);
+ link->data = NULL;
+ }
+
+ g_list_free (waiters);
+}
+
+void
+tp_connection_manager_call_when_ready (TpConnectionManager *self,
+ TpConnectionManagerWhenReadyCb callback,
+ gpointer user_data,
+ GDestroyNotify destroy,
+ GObject *weak_object)
+{
+ WhenReadyContext *c;
+
+ g_return_if_fail (TP_IS_CONNECTION_MANAGER (self));
+ g_return_if_fail (callback != NULL);
+
+ c = g_slice_new0 (WhenReadyContext);
+
+ c->cm = g_object_ref (self);
+ c->callback = callback;
+ c->user_data = user_data;
+ c->destroy = destroy;
+ c->weak_object = weak_object;
+
+ if (weak_object != NULL)
+ {
+ g_object_weak_ref (weak_object, when_ready_context_cancel, c);
+ }
+
+ if (self->info_source != TP_CM_INFO_SOURCE_NONE)
+ {
+ g_idle_add_full (G_PRIORITY_HIGH, when_ready_context_complete,
+ c, when_ready_context_free);
+ return;
+ }
+
+ self->priv->waiting_for_ready = g_list_append (self->priv->waiting_for_ready,
+ c);
+}
+
static void tp_connection_manager_continue_introspection
(TpConnectionManager *self);
@@ -331,8 +462,12 @@ tp_connection_manager_free_protocols (GPtrArray *protocols)
g_ptr_array_free (protocols, TRUE);
}
+static void tp_connection_manager_ready_or_failed (TpConnectionManager *self,
+ const GError *error);
+
static void
-tp_connection_manager_end_introspection (TpConnectionManager *self)
+tp_connection_manager_end_introspection (TpConnectionManager *self,
+ const GError *error)
{
guint i;
@@ -354,6 +489,7 @@ tp_connection_manager_end_introspection (TpConnectionManager *self)
}
g_signal_emit (self, signals[SIGNAL_GOT_INFO], 0, self->info_source);
+ tp_connection_manager_ready_or_failed (self, error);
}
static void
@@ -378,7 +514,7 @@ tp_connection_manager_continue_introspection (TpConnectionManager *self)
self->priv->protocols->pdata;
self->info_source = TP_CM_INFO_SOURCE_LIVE;
- tp_connection_manager_end_introspection (self);
+ tp_connection_manager_end_introspection (self, NULL);
return;
}
@@ -413,7 +549,7 @@ tp_connection_manager_got_protocols (TpConnectionManager *self,
g_signal_emit (self, signals[SIGNAL_EXITED], 0);
}
- tp_connection_manager_end_introspection (self);
+ tp_connection_manager_end_introspection (self, error);
return;
}
@@ -471,10 +607,13 @@ tp_connection_manager_name_owner_changed_cb (TpDBusDaemon *bus,
if (new_owner[0] == '\0')
{
+ GError e = { TP_DBUS_ERRORS, TP_DBUS_ERROR_NAME_OWNER_LOST,
+ "Connection manager process exited during introspection" };
+
self->running = FALSE;
/* cancel pending introspection, if any */
- tp_connection_manager_end_introspection (self);
+ tp_connection_manager_end_introspection (self, &e);
g_signal_emit (self, signals[SIGNAL_EXITED], 0);
}
@@ -973,6 +1112,7 @@ tp_connection_manager_idle_read_manager_file (gpointer data)
g_signal_emit (self, signals[SIGNAL_GOT_INFO], 0,
self->info_source);
+ tp_connection_manager_ready_or_failed (self, NULL);
}
}
diff --git a/telepathy-glib/connection-manager.h b/telepathy-glib/connection-manager.h
index 85d1581..cc2a357 100644
--- a/telepathy-glib/connection-manager.h
+++ b/telepathy-glib/connection-manager.h
@@ -116,6 +116,13 @@ void tp_list_connection_managers (TpDBusDaemon *bus_daemon,
gpointer user_data, GDestroyNotify destroy,
GObject *weak_object);
+typedef void (*TpConnectionManagerWhenReadyCb) (TpConnectionManager *self,
+ const GError *error, gpointer user_data, GObject *weak_object);
+
+void tp_connection_manager_call_when_ready (TpConnectionManager *self,
+ TpConnectionManagerWhenReadyCb callback,
+ gpointer user_data, GDestroyNotify destroy, GObject *weak_object);
+
gboolean tp_connection_manager_check_valid_name (const gchar *name,
GError **error);
--
1.5.6.5
More information about the telepathy-commits
mailing list