[rygel-grilo] Add asynchonous function to get list of children



commit 05f14b9dc96d8c563fff83fdcfcbf811a3399a05
Author: Juan A. Suarez Romero <jasuarez igalia com>
Date:   Wed May 19 21:27:15 2010 +0200

    Add asynchonous function to get list of children

 configure.ac               |    1 +
 lib/media-server1-client.c |  131 ++++++++++++++++++++++++++++++++++++++++++++
 lib/media-server1-client.h |   13 ++++
 src/test-client.c          |   85 +++++++++++++++++++++++++++-
 4 files changed, 226 insertions(+), 4 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index c7745a3..7f5be2c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -51,6 +51,7 @@ AM_CONDITIONAL([DEBUG], [test "x$enable_debug" = "xyes"])
 PKG_CHECK_MODULES(DEPS, 		\
 			glib-2.0	\
 			gobject-2.0	\
+                        gio-2.0         \
 			dbus-glib-1)
 
 AC_SUBST(DEPS_CFLAGS)
diff --git a/lib/media-server1-client.c b/lib/media-server1-client.c
index 5b12394..3bd9d99 100644
--- a/lib/media-server1-client.c
+++ b/lib/media-server1-client.c
@@ -33,6 +33,20 @@
 #define MS1_CLIENT_GET_PRIVATE(o)                                       \
   G_TYPE_INSTANCE_GET_PRIVATE((o), MS1_TYPE_CLIENT, MS1ClientPrivate)
 
+/*
+ * Structure to store data for asynchronous operations
+ *   gproxy: dbus proxy to invoke methods
+ *   error: operation error
+ *   properties: result of invoking get_properties
+ *   children: result of invoking list_children
+ */
+typedef struct {
+  DBusGProxy *gproxy;
+  GError *error;
+  GHashTable *properties;
+  GList *children;
+} AsyncData;
+
 enum {
   UPDATED,
   DESTROY,
@@ -71,6 +85,14 @@ free_gvalue (GValue *v)
   g_free (v);
 }
 
+/* Free AsyncData */
+static void
+free_async_data (AsyncData *adata)
+{
+  g_object_unref (adata->gproxy);
+  g_slice_free (AsyncData, adata);
+}
+
 /* Insert <key, value> in hashtable */
 static gboolean
 collect_value (gpointer key,
@@ -154,6 +176,30 @@ gptrarray_to_strv (GPtrArray *result)
   return strv;
 }
 
+/* Callback invoked when ListenChildren reply is received */
+static void
+list_children_reply (DBusGProxy *proxy,
+                     DBusGProxyCall *call,
+                     void *user_data)
+{
+  AsyncData *adata;
+  GPtrArray *result = NULL;
+  GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (user_data);
+
+  adata = g_simple_async_result_get_op_res_gpointer (res);
+  if (dbus_g_proxy_end_call (proxy, call, &(adata->error),
+                             dbus_g_type_get_collection ("GPtrArray",
+                                                         dbus_g_type_get_map ("GHashTable",
+                                                                              G_TYPE_STRING,
+                                                                              G_TYPE_VALUE)), &result,
+                             G_TYPE_INVALID)) {
+    adata->children = gptrarray_to_glist (result);
+    g_ptr_array_free (result, TRUE);
+  }
+
+  g_simple_async_result_complete (res);
+}
+
 /* Dispose function */
 static void
 ms1_client_dispose (GObject *object)
@@ -475,6 +521,91 @@ ms1_client_get_properties (MS1Client *client,
 }
 
 /**
+ * ms1_client_list_children_async:
+ * @client: a #MS1Client
+ * @object_path: container identifier to get children from
+ * @offset: number of children to skip
+ * @max_count: maximum number of children to return, or 0 for no limit
+ * @properties: @NULL-terminated array of properties to request for each child
+ * @callback: a #GAsyncReadyCallback to call when request is satisfied
+ * @user_data: the data to pass to callback function
+ *
+ * Starts an asynchronous list children.
+ *
+ * For more details, see ms1_client_list_children(), which is the synchronous
+ * version of this call.
+ *
+ * When the children have been obtained, @callback will be called with
+ * @user_data. To finish the operation, call ms1_client_list_children_finish()
+ * with the #GAsyncResult returned by the @callback.
+ **/
+void
+ms1_client_list_children_async (MS1Client *client,
+                                const gchar *object_path,
+                                guint offset,
+                                guint max_count,
+                                gchar **properties,
+                                GAsyncReadyCallback callback,
+                                gpointer user_data)
+{
+  AsyncData *adata;
+  GSimpleAsyncResult *res;
+
+  g_return_if_fail (MS1_IS_CLIENT (client));
+
+  res = g_simple_async_result_new (G_OBJECT (client),
+                                   callback,
+                                   user_data,
+                                   ms1_client_list_children_async);
+  adata = g_slice_new0 (AsyncData);
+  g_simple_async_result_set_op_res_gpointer (res,
+                                             adata,
+                                             (GDestroyNotify) free_async_data);
+  adata->gproxy = dbus_g_proxy_new_for_name (client->priv->bus,
+                                             client->priv->fullname,
+                                             object_path,
+                                             "org.gnome.UPnP.MediaContainer1");
+
+  dbus_g_proxy_begin_call (adata->gproxy,
+                           "ListChildren", list_children_reply,
+                           res, g_object_unref,
+                           G_TYPE_UINT, offset,
+                           G_TYPE_UINT, max_count,
+                           G_TYPE_STRV, properties,
+                           G_TYPE_INVALID);
+}
+
+/**
+ * ms1_client_list_children_finish:
+ * @client: a #MS1Client
+ * @res: a #GAsyncResult
+ * @error: a #GError location to store the error ocurring, or @NULL to ignore
+ *
+ * Finishes an asynchronous listing children operation.
+ *
+ * Returns: a new #GList of #GHashTAble. To free it, free first each element
+ * (g_hash_table_unref()) and finally the list itself (g_list_free())
+ **/
+GList *
+ms1_client_list_children_finish (MS1Client *client,
+                                 GAsyncResult *res,
+                                 GError **error)
+{
+  AsyncData *adata;
+
+  g_return_val_if_fail (g_simple_async_result_get_source_tag (G_SIMPLE_ASYNC_RESULT (res)) ==
+                        ms1_client_list_children_async, NULL);
+
+  adata = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (res));
+
+  if (error) {
+    *error = adata->error;
+  }
+
+  return adata->children;
+}
+
+/**
  * ms1_client_list_children:
  * @client: a #MS1Client
  * @object_path: container identifier to get children from
diff --git a/lib/media-server1-client.h b/lib/media-server1-client.h
index 290b298..86a1bab 100644
--- a/lib/media-server1-client.h
+++ b/lib/media-server1-client.h
@@ -25,6 +25,7 @@
 
 #include <glib-object.h>
 #include <glib.h>
+#include <gio/gio.h>
 
 #include "media-server1-common.h"
 
@@ -90,6 +91,18 @@ GHashTable *ms1_client_get_properties (MS1Client *client,
                                        gchar **properties,
                                        GError **error);
 
+void ms1_client_list_children_async (MS1Client *client,
+                                     const gchar *object_path,
+                                     guint offset,
+                                     guint max_count,
+                                     gchar **properties,
+                                     GAsyncReadyCallback callback,
+                                     gpointer user_data);
+
+GList *ms1_client_list_children_finish (MS1Client *client,
+                                        GAsyncResult *res,
+                                        GError **error);
+
 GList *ms1_client_list_children (MS1Client *client,
                                  const gchar *object_path,
                                  guint offset,
diff --git a/src/test-client.c b/src/test-client.c
index f87c70b..a8ee223 100644
--- a/src/test-client.c
+++ b/src/test-client.c
@@ -4,8 +4,13 @@
 #include <string.h>
 
 static gchar *properties[] = { MS1_PROP_PATH,
-                               MS1_PROP_DISPLAY_NAME,
-                               MS1_PROP_PARENT,
+                               /* MS1_PROP_DISPLAY_NAME, */
+                               /* MS1_PROP_PARENT, */
+                               /* MS1_PROP_CHILD_COUNT, */
+                               MS1_PROP_CONTAINERS,
+                               /* MS1_PROP_ITEMS, */
+                               /* MS1_PROP_URLS, */
+                               /* MS1_PROP_ARTIST, */
                                NULL };
 
 static void
@@ -35,7 +40,7 @@ test_properties ()
     }
 
     result = ms1_client_get_properties (client,
-                                        ms1_client_get_root_path (client),
+                                        "/org/gnome/UPnP/MediaServer1/grl_shoutcast",
                                         (gchar **) properties,
                                         &error);
 
@@ -45,6 +50,15 @@ test_properties ()
       return;
     }
 
+    gchar **urls = ms1_client_get_urls (result);
+    g_print ("We got %d urls\n", urls? g_strv_length (urls): 0);
+
+    gchar **items = ms1_client_get_items (result);
+    g_print ("We got %d items\n", items? g_strv_length (items): 0);
+
+    gchar **containers = ms1_client_get_containers (result);
+    g_print ("We got %d containers\n", containers? g_strv_length (containers): 0);
+
     for (p = properties; *p; p++) {
       v = g_hash_table_lookup (result, *p);
       if (v && G_VALUE_HOLDS_INT (v)) {
@@ -115,6 +129,68 @@ test_children ()
 }
 
 static void
+children_reply (GObject *source,
+                GAsyncResult *res,
+                gpointer user_data)
+{
+  GList *children;
+  GList *child;
+  GError *error = NULL;
+
+  children =
+    ms1_client_list_children_finish (MS1_CLIENT (source), res, &error);
+
+  if (!children) {
+      g_print ("\tDid not get any child, %s\n", error? error->message: "no error");
+      return;
+  }
+
+  for (child = children; child; child = g_list_next (child)) {
+    g_print ("\t* '%s', '%s'\n",
+             ms1_client_get_path (child->data),
+             ms1_client_get_display_name(child->data));
+  }
+
+  g_list_foreach (children, (GFunc) g_hash_table_unref, NULL);
+  g_list_free (children);
+  g_object_unref (source);
+}
+
+static void
+test_children_async ()
+{
+  gchar **providers;
+  gchar **provider;
+  MS1Client *client;
+
+  providers = ms1_client_get_providers ();
+
+  if (!providers) {
+    g_print ("There is no MediaServer1 provider\n");
+    return;
+  }
+
+  for (provider = providers; *provider; provider ++) {
+    client = ms1_client_new (*provider);
+
+    if (!client) {
+      g_printerr ("Unable to create a client\n");
+      return;
+    }
+
+    ms1_client_list_children_async (client,
+                                    ms1_client_get_root_path (client),
+                                    0,
+                                    10,
+                                    properties,
+                                    children_reply,
+                                    NULL);
+  }
+
+  g_strfreev (providers);
+}
+
+static void
 test_search ()
 {
   GList *child;
@@ -295,9 +371,10 @@ int main (int argc, char **argv)
 
   if (0) test_properties ();
   if (0) test_children ();
+  if (1) test_children_async ();
   if (0) test_search ();
   if (0) test_provider_free ();
-  if (1) test_updated ();
+  if (0) test_updated ();
   if (0) test_dynamic_providers ();
 
   mainloop = g_main_loop_new (NULL, FALSE);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]