aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libempathy/empathy-dispatcher.c97
-rw-r--r--libempathy/empathy-dispatcher.h6
2 files changed, 103 insertions, 0 deletions
diff --git a/libempathy/empathy-dispatcher.c b/libempathy/empathy-dispatcher.c
index 393c4a92d..6b465ecae 100644
--- a/libempathy/empathy-dispatcher.c
+++ b/libempathy/empathy-dispatcher.c
@@ -52,6 +52,7 @@ typedef struct
MissionControl *mc;
/* connection to connection data mapping */
GHashTable *connections;
+ GHashTable *outstanding_classes_requests;
gpointer token;
GSList *tubes;
@@ -110,6 +111,15 @@ typedef struct
GPtrArray *requestable_channels;
} ConnectionData;
+typedef struct
+{
+ EmpathyDispatcher *dispatcher;
+ char *channel_type;
+ guint handle_type;
+ EmpathyDispatcherFindChannelClassCb *callback;
+ gpointer user_data;
+} FindChannelRequest;
+
static DispatchData *
new_dispatch_data (TpChannel *channel,
GObject *channel_wrapper)
@@ -220,6 +230,14 @@ free_connection_data (ConnectionData *cd)
}
static void
+free_find_channel_request (FindChannelRequest *r)
+{
+ g_object_unref (r->dispatcher);
+ g_free (r->channel_type);
+ g_slice_free (FindChannelRequest, r);
+}
+
+static void
dispatcher_connection_invalidated_cb (TpConnection *connection,
guint domain,
gint code,
@@ -712,12 +730,32 @@ dispatcher_connection_got_all (TpProxy *proxy,
else
{
ConnectionData *cd;
+ GList *requests, *l;
+ FindChannelRequest *request;
+ GStrv retval;
cd = g_hash_table_lookup (priv->connections, proxy);
g_assert (cd != NULL);
cd->requestable_channels = g_boxed_copy (
TP_ARRAY_TYPE_REQUESTABLE_CHANNEL_CLASS_LIST, requestable_channels);
+
+ requests = g_hash_table_lookup (priv->outstanding_classes_requests,
+ proxy);
+
+ for (l = requests; l != NULL; l = l->next)
+ {
+ request = l->data;
+
+ retval = empathy_dispatcher_find_channel_class (dispatcher,
+ TP_CONNECTION (proxy), request->channel_type,
+ request->handle_type);
+ request->callback (retval, request->user_data);
+
+ free_find_channel_request (request);
+ }
+
+ g_hash_table_remove (priv->outstanding_classes_requests, proxy);
}
}
@@ -861,6 +899,7 @@ dispatcher_finalize (GObject *object)
GList *l;
GHashTableIter iter;
gpointer connection;
+ GList *list;
g_signal_handlers_disconnect_by_func (priv->account_manager,
dispatcher_new_connection_cb, object);
@@ -880,10 +919,17 @@ dispatcher_finalize (GObject *object)
dispatcher_connection_invalidated_cb, object);
}
+ g_hash_table_iter_init (&iter, priv->outstanding_classes_requests);
+ while (g_hash_table_iter_next (&iter, &connection, (gpointer *) &list))
+ {
+ g_list_foreach (list, (GFunc) free_find_channel_request, NULL);
+ }
+
g_object_unref (priv->account_manager);
g_object_unref (priv->mc);
g_hash_table_destroy (priv->connections);
+ g_hash_table_destroy (priv->outstanding_classes_requests);
}
static void
@@ -946,6 +992,9 @@ empathy_dispatcher_init (EmpathyDispatcher *dispatcher)
priv->connections = g_hash_table_new_full (g_direct_hash, g_direct_equal,
g_object_unref, (GDestroyNotify) free_connection_data);
+ priv->outstanding_classes_requests = g_hash_table_new_full (g_direct_hash,
+ g_direct_equal, g_object_unref, NULL);
+
priv->channels = NULL;
connections = empathy_account_manager_dup_connections (priv->account_manager);
@@ -1373,3 +1422,51 @@ empathy_dispatcher_find_channel_class (EmpathyDispatcher *dispatcher,
return NULL;
}
+void
+empathy_dispatcher_find_channel_class_async (EmpathyDispatcher *dispatcher,
+ TpConnection *connection,
+ const gchar *channel_type,
+ guint handle_type,
+ EmpathyDispatcherFindChannelClassCb callback,
+ gpointer user_data)
+{
+ GStrv retval;
+ EmpathyDispatcherPriv *priv;
+ GList *requests;
+ FindChannelRequest *request;
+
+ g_return_if_fail (EMPATHY_IS_DISPATCHER (dispatcher));
+ g_return_if_fail (TP_IS_CONNECTION (connection));
+ g_return_if_fail (channel_type != NULL);
+ g_return_if_fail (handle_type != 0);
+
+ /* own a reference to the object, so that clients can unref the singleton
+ * while waiting for the cb
+ */
+ priv = GET_PRIV (g_object_ref (dispatcher));
+ retval = empathy_dispatcher_find_channel_class (dispatcher, connection,
+ channel_type, handle_type);
+
+ if (retval != NULL)
+ {
+ g_object_unref (dispatcher);
+ callback (retval, user_data);
+ return;
+ }
+
+ requests = g_hash_table_lookup (priv->outstanding_classes_requests,
+ connection);
+
+ /* append another request for this connection */
+ request = g_slice_new0 (FindChannelRequest);
+ request->dispatcher = dispatcher;
+ request->channel_type = g_strdup (channel_type);
+ request->handle_type = handle_type;
+ request->callback = callback;
+ request->user_data = user_data;
+
+ requests = g_list_prepend (requests, request);
+
+ g_hash_table_insert (priv->outstanding_classes_requests,
+ connection, requests);
+}
diff --git a/libempathy/empathy-dispatcher.h b/libempathy/empathy-dispatcher.h
index fb7c6fe35..c65da6c92 100644
--- a/libempathy/empathy-dispatcher.h
+++ b/libempathy/empathy-dispatcher.h
@@ -58,6 +58,8 @@ struct _EmpathyDispatcherClass
typedef void (EmpathyDispatcherRequestCb) (
EmpathyDispatchOperation *dispatch, const GError *error,
gpointer user_data);
+typedef void (EmpathyDispatcherFindChannelClassCb) (
+ GStrv channel_class, gpointer user_data);
GType empathy_dispatcher_get_type (void) G_GNUC_CONST;
@@ -86,6 +88,10 @@ void empathy_dispatcher_join_muc (TpConnection *connection,
GStrv empathy_dispatcher_find_channel_class (EmpathyDispatcher *dispatcher,
TpConnection *connection, const gchar *channel_type, guint handle_type);
+void empathy_dispatcher_find_channel_class_async (EmpathyDispatcher *dispatcher,
+ TpConnection *connection, const gchar *channel_type, guint handle_type,
+ EmpathyDispatcherFindChannelClassCb callback, gpointer user_data);
+
/* Get the dispatcher singleton */
EmpathyDispatcher * empathy_dispatcher_dup_singleton (void);