]> git.0d.be Git - empathy.git/commitdiff
Add empathy_dispatcher_find_channel_class_async()
authorCosimo Cecchi <cosimoc@gnome.org>
Mon, 18 May 2009 14:59:00 +0000 (16:59 +0200)
committerCosimo Cecchi <cosimoc@gnome.org>
Mon, 1 Jun 2009 15:53:21 +0000 (17:53 +0200)
libempathy/empathy-dispatcher.c
libempathy/empathy-dispatcher.h

index 393c4a92d680e96c2f536e3f88be4d10aab0b2ed..6b465ecaea412c6b84064cb7ec486ced3fe7afd6 100644 (file)
@@ -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)
@@ -219,6 +229,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,
@@ -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);
+}
index fb7c6fe35cef867c6567331ed409bed7b8048bbf..c65da6c926ac61e1b60a0e42110627d71bc43349 100644 (file)
@@ -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);