[rygel-grilo] Add asynchonous function to get list of children
- From: Juan A. Suarez Romero <jasuarez src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [rygel-grilo] Add asynchonous function to get list of children
- Date: Thu, 20 May 2010 18:42:50 +0000 (UTC)
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]