[rygel-grilo] Handle ListObjects message



commit c12e85731e9d127549f4e53ba9d75cbc8e2176c8
Author: Juan A. Suarez Romero <jasuarez igalia com>
Date:   Tue May 4 11:47:11 2010 +0200

    Handle ListObjects message

 lib/media-server2-introspection.h |    1 -
 lib/media-server2-server-table.c  |   46 ++++++++++-----
 lib/media-server2-server.c        |  110 +++++++++++++++++++++++++++++++++----
 lib/media-server2-server.h        |    9 ++-
 src/rygel-grilo.c                 |   78 +++++++++++++++-----------
 5 files changed, 179 insertions(+), 65 deletions(-)
---
diff --git a/lib/media-server2-introspection.h b/lib/media-server2-introspection.h
index 5736ddd..1a1d593 100644
--- a/lib/media-server2-introspection.h
+++ b/lib/media-server2-introspection.h
@@ -106,4 +106,3 @@
   INTROSPECTION_CLOSE
 
 #endif /* _MEDIA_SERVER2_INTROSPECTION_H_ */
-
diff --git a/lib/media-server2-server-table.c b/lib/media-server2-server-table.c
index 8eb3fc9..28e216d 100644
--- a/lib/media-server2-server-table.c
+++ b/lib/media-server2-server-table.c
@@ -111,40 +111,54 @@ id_to_object_path (MS2Server *server,
 
 /**
  * ms2_server_new_properties_hashtable:
- * @server: a #MS2Server
- * @id: identifier of item which properties will be stored in the table
- * @is_container: @TRUE if the item is a container, or @FALSE if it is an item.
  *
  * Creates a new #GHashTable suitable to store items properties.
  *
- * @id will be transformed in an object path.
- *
  * Returns: a new #GHashTable
  **/
 GHashTable *
-ms2_server_new_properties_hashtable (MS2Server *server,
-                                     const gchar *id,
-                                     gboolean is_container)
+ms2_server_new_properties_hashtable ()
 {
   GHashTable *properties;
-  gchar *object_path;
-
-  g_return_val_if_fail (MS2_IS_SERVER (server), NULL);
-  g_return_val_if_fail (id, NULL);
 
   properties = g_hash_table_new_full (g_str_hash,
                                       g_str_equal,
                                       NULL,
                                       (GDestroyNotify) free_value);
 
-  object_path = id_to_object_path (server, id, is_container);
-  g_hash_table_insert (properties, MS2_PROP_ID, str_to_value (object_path));
-  g_free (object_path);
-
   return properties;
 }
 
 /**
+ * ms2_server_set_id:
+ * @server: a #MS2Server
+ * @properties: a #GHashTable
+ * @id: identifier value
+ * @is_container: @TRUE if the @id identifies a a container
+ *
+ * Sets the "id" property. Mandatory property
+ *
+ * @id will be transformed in an object path
+ **/
+void
+ms2_server_set_id (MS2Server *server,
+                   GHashTable *properties,
+                   const gchar *id,
+                   gboolean is_container)
+{
+  gchar *object_path;
+
+  g_return_if_fail (MS2_IS_SERVER (server));
+  g_return_if_fail (properties);
+
+  if (id) {
+    object_path = id_to_object_path (server, id, is_container);
+    g_hash_table_insert (properties, MS2_PROP_ID, str_to_value (object_path));
+    g_free (object_path);
+  }
+}
+
+/**
  * ms2_server_set_parent:
  * @server: a #MS2Server
  * @properties: a #GHashTable
diff --git a/lib/media-server2-server.c b/lib/media-server2-server.c
index c56ec5c..8187640 100644
--- a/lib/media-server2-server.c
+++ b/lib/media-server2-server.c
@@ -63,6 +63,7 @@ struct _MS2ServerPrivate {
 static const gchar introspect_sgn[] = { DBUS_TYPE_INVALID };
 static const gchar get_sgn[]  = { DBUS_TYPE_STRING, DBUS_TYPE_STRING, DBUS_TYPE_INVALID };
 static const gchar getall_sgn[] = { DBUS_TYPE_STRING, DBUS_TYPE_INVALID };
+static const gchar listobjects_sgn[] = { DBUS_TYPE_UINT32, DBUS_TYPE_UINT32, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, DBUS_TYPE_INVALID };
 
 static const gchar *mediaobject2_properties[] = { MS2_PROP_DISPLAY_NAME,
                                                   MS2_PROP_PARENT,
@@ -466,9 +467,9 @@ get_id_from_message (DBusMessage *m)
 }
 
 static void
-append_variant_arg (DBusMessage *m,
-                    DBusMessageIter *iter,
-                    const GValue *v)
+add_variant (DBusMessage *m,
+             DBusMessageIter *iter,
+             const GValue *v)
 {
   DBusMessageIter iternew;
   DBusMessageIter sub;
@@ -494,19 +495,24 @@ append_variant_arg (DBusMessage *m,
 }
 
 static void
-append_hashtable_arg (DBusMessage *m,
-                      GHashTable *t)
+add_hashtable_as_dict (DBusMessage *m,
+                       DBusMessageIter *iter,
+                       GHashTable *t)
 {
-  DBusMessageIter iter;
+  DBusMessageIter iternew;
   DBusMessageIter sub_array;
   DBusMessageIter sub_dict;
   GList *key;
   GList *keys;
   GValue *v;
 
-  dbus_message_iter_init_append (m, &iter);
+  if (!iter) {
+    dbus_message_iter_init_append (m, &iternew);
+    iter = &iternew;
+  }
+
   /* Add an array of dict */
-  dbus_message_iter_open_container (&iter, DBUS_TYPE_ARRAY, "{sv}", &sub_array);
+  dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, "{sv}", &sub_array);
   /* Add hashtable */
   if (t) {
     keys = g_hash_table_get_keys (t);
@@ -520,12 +526,35 @@ append_hashtable_arg (DBusMessage *m,
       dbus_message_iter_open_container (&sub_array, DBUS_TYPE_DICT_ENTRY, NULL, &sub_dict);
       /* Add key & value */
       dbus_message_iter_append_basic (&sub_dict, DBUS_TYPE_STRING, &key->data);
-      append_variant_arg (m, &sub_dict, v);
+      add_variant (m, &sub_dict, v);
       dbus_message_iter_close_container (&sub_array, &sub_dict);
     }
     g_list_free (keys);
   }
-  dbus_message_iter_close_container (&iter, &sub_array);
+  dbus_message_iter_close_container (iter, &sub_array);
+}
+
+static void
+add_glist_as_array (DBusMessage *m,
+                    DBusMessageIter *iter,
+                    GList *l)
+{
+  DBusMessageIter iternew;
+  DBusMessageIter sub_array;
+
+  if (!iter) {
+    dbus_message_iter_init_append (m, &iternew);
+    iter = &iternew;
+  }
+
+  /* Add an array */
+  dbus_message_iter_open_container (iter, DBUS_TYPE_ARRAY, "a{sv}", &sub_array);
+  while (l) {
+    add_hashtable_as_dict (m, &sub_array, l->data);
+    l = g_list_next (l);
+  }
+
+  dbus_message_iter_close_container (iter, &sub_array);
 }
 
 static DBusHandlerResult
@@ -575,7 +604,7 @@ handle_get_message (DBusConnection *c,
                   interface);
     } else {
       r = dbus_message_new_method_return (m);
-      append_variant_arg (r, NULL, value);
+      add_variant (r, NULL, value);
       dbus_connection_send (c, r, NULL);
       dbus_message_unref (r);
       free_value (value);
@@ -630,7 +659,7 @@ handle_get_all_message (DBusConnection *c,
       propresult = NULL;
     }
     r = dbus_message_new_method_return (m);
-    append_hashtable_arg (r, propresult);
+    add_hashtable_as_dict (r, NULL, propresult);
     dbus_connection_send (c, r, NULL);
     dbus_message_unref (r);
     if (propresult) {
@@ -643,6 +672,59 @@ handle_get_all_message (DBusConnection *c,
 }
 
 static DBusHandlerResult
+handle_list_objects_message (DBusConnection *c,
+                             DBusMessage *m,
+                             void *userdata)
+{
+  DBusMessage *r;
+  GList *children;
+  gchar **filter;
+  gchar *id;
+  guint max_count;
+  guint offset;
+  gint nitems;
+  MS2Server *server = MS2_SERVER (userdata);
+
+  /* Check signature */
+  if (dbus_message_has_signature (m, listobjects_sgn)) {
+    dbus_message_get_args (m, NULL,
+                           DBUS_TYPE_UINT32, &offset,
+                           DBUS_TYPE_UINT32, &max_count,
+                           DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &filter, &nitems,
+                           DBUS_TYPE_INVALID);
+    if (!server->priv->get_children || nitems == 0) {
+      children = NULL;
+    } else {
+      id = get_id_from_message (m);
+      if (!id) {
+        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+      }
+      children = server->priv->get_children (server,
+                                             id,
+                                             offset,
+                                             max_count? max_count: G_MAXUINT,
+                                             (const gchar **) filter,
+                                             server->priv->data,
+                                             NULL);
+      g_free (id);
+      dbus_free_string_array (filter);
+    }
+
+    r = dbus_message_new_method_return (m);
+    add_glist_as_array (r, NULL, children);
+    dbus_connection_send (c, r, NULL);
+    dbus_message_unref (r);
+    if (children) {
+      g_list_foreach (children, (GFunc) g_hash_table_unref, NULL);
+      g_list_free (children);
+    }
+    return DBUS_HANDLER_RESULT_HANDLED;
+  } else {
+    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+  }
+}
+
+static DBusHandlerResult
 items_handler (DBusConnection *c,
                DBusMessage *m,
                void *userdata)
@@ -683,6 +765,10 @@ containers_handler (DBusConnection *c,
                                           "org.freedesktop.DBus.Properties",
                                           "GetAll")) {
     return handle_get_all_message (c, m, userdata);
+  } else if (dbus_message_is_method_call (m,
+                                          "org.gnome.UPnP.MediaContainer2",
+                                          "ListObjects")) {
+    return handle_list_objects_message (c, m, userdata);
   } else {
     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
   }
diff --git a/lib/media-server2-server.h b/lib/media-server2-server.h
index 462ad7a..07323a2 100644
--- a/lib/media-server2-server.h
+++ b/lib/media-server2-server.h
@@ -105,9 +105,12 @@ void ms2_server_updated (MS2Server *server,
 
 const gchar *ms2_server_get_name (MS2Server *server);
 
-GHashTable *ms2_server_new_properties_hashtable (MS2Server *server,
-                                                 const gchar *id,
-                                                 gboolean is_container);
+GHashTable *ms2_server_new_properties_hashtable (void);
+
+void ms2_server_set_id (MS2Server *server,
+                        GHashTable *properties,
+                        const gchar *id,
+                        gboolean is_container);
 
 void ms2_server_set_parent (MS2Server *server,
                             GHashTable *properties,
diff --git a/src/rygel-grilo.c b/src/rygel-grilo.c
index 501ab15..3641bfb 100644
--- a/src/rygel-grilo.c
+++ b/src/rygel-grilo.c
@@ -67,6 +67,7 @@ typedef struct {
   GrlMediaSource *source;
   MS2Server *server;
   gboolean updated;
+  gboolean parent_requested;
   gchar *parent_id;
 } RygelGriloData;
 
@@ -209,13 +210,20 @@ unserialize_media (GrlMetadataSource *source, const gchar *id)
 /* Given a null-terminated array of MediaServerSpec2 properties, returns a list
    with the corresponding Grilo metadata keys */
 static GList *
-get_grilo_keys (const gchar **ms_keys)
+get_grilo_keys (const gchar **ms_keys, gboolean *contains_parent)
 {
   GList *grl_keys = NULL;
   gint i;
 
+  if (contains_parent) {
+    *contains_parent = FALSE;
+  }
+
   for (i = 0; ms_keys[i]; i++) {
-    if (g_strcmp0 (ms_keys[i], MS2_PROP_DISPLAY_NAME) == 0) {
+    if (g_strcmp0 (ms_keys[i], MS2_PROP_ID) == 0) {
+      grl_keys = g_list_append (grl_keys,
+                                GRLKEYID_TO_POINTER (GRL_METADATA_KEY_ID));
+    } else if (g_strcmp0 (ms_keys[i], MS2_PROP_DISPLAY_NAME) == 0) {
       grl_keys = g_list_append (grl_keys,
                                 GRLKEYID_TO_POINTER (GRL_METADATA_KEY_TITLE));
     } else if (g_strcmp0 (ms_keys[i], MS2_PROP_ALBUM) == 0) {
@@ -248,6 +256,8 @@ get_grilo_keys (const gchar **ms_keys)
     } else if (g_strcmp0 (ms_keys[i], MS2_PROP_WIDTH) == 0) {
       grl_keys = g_list_append (grl_keys,
                                 GRLKEYID_TO_POINTER (GRL_METADATA_KEY_WIDTH));
+    } else if (g_strcmp0 (ms_keys[i], MS2_PROP_PARENT) == 0 && contains_parent) {
+      *contains_parent = TRUE;
     }
   }
 
@@ -259,16 +269,29 @@ fill_properties_table (MS2Server *server,
                        GHashTable *properties_table,
                        GList *keys,
                        GrlMedia *media,
+                       gboolean parent_requested,
                        const gchar *parent_id)
 {
   GList *prop;
   GrlKeyID key;
+  gchar *id;
   gchar *urls[2] = { 0 };
 
   for (prop = keys; prop; prop = g_list_next (prop)) {
     key = POINTER_TO_GRLKEYID (prop->data);
-    if (grl_data_key_is_known (GRL_DATA (media), key)) {
+    if (key == GRL_METADATA_KEY_ID ||
+        grl_data_key_is_known (GRL_DATA (media), key)) {
       switch (key) {
+      case GRL_METADATA_KEY_ID:
+        id = serialize_media (parent_id, media);
+        if (id) {
+          ms2_server_set_id (server,
+                             properties_table,
+                             id,
+                             GRL_IS_MEDIA_BOX (media));
+          g_free (id);
+        }
+        break;
       case GRL_METADATA_KEY_TITLE:
         ms2_server_set_display_name (server,
                                      properties_table,
@@ -334,7 +357,7 @@ fill_properties_table (MS2Server *server,
     }
   }
 
-  if (parent_id) {
+  if (parent_requested && parent_id) {
     ms2_server_set_parent (server, properties_table, parent_id);
   }
 }
@@ -346,25 +369,20 @@ metadata_cb (GrlMediaSource *source,
              const GError *error)
 {
   RygelGriloData *rgdata = (RygelGriloData *) user_data;
-  gchar *id;
 
   if (error) {
     rgdata->error = g_error_copy (error);
     rgdata->updated = TRUE;
     return;
   }
-  id = serialize_media (rgdata->parent_id, media);
-  if (id) {
-    rgdata->properties = ms2_server_new_properties_hashtable (rgdata->server,
-                                                              id,
-                                                              GRL_IS_MEDIA_BOX (media));
-    fill_properties_table (rgdata->server,
-                           rgdata->properties,
-                           rgdata->keys,
-                           media,
-                           rgdata->parent_id);
-    g_free (id);
-  }
+
+  rgdata->properties = ms2_server_new_properties_hashtable ();
+  fill_properties_table (rgdata->server,
+                         rgdata->properties,
+                         rgdata->keys,
+                         media,
+                         rgdata->parent_requested,
+                         rgdata->parent_id);
 
   rgdata->updated = TRUE;
 }
@@ -379,7 +397,6 @@ browse_cb (GrlMediaSource *source,
 {
   GHashTable *prop_table;
   RygelGriloData *rgdata = (RygelGriloData *) user_data;
-  gchar *id;
 
   if (error) {
     rgdata->error = g_error_copy (error);
@@ -388,19 +405,14 @@ browse_cb (GrlMediaSource *source,
   }
 
   if (media) {
-    id = serialize_media (rgdata->parent_id, media);
-    if (id) {
-      prop_table = ms2_server_new_properties_hashtable (rgdata->server,
-                                                        id,
-                                                        GRL_IS_MEDIA_BOX (media));
-      fill_properties_table (rgdata->server,
-                             prop_table,
-                             rgdata->keys,
-                             media,
-                             rgdata->parent_id);
-      rgdata->children = g_list_prepend (rgdata->children, prop_table);
-      g_free (id);
-    }
+    prop_table = ms2_server_new_properties_hashtable ();
+    fill_properties_table (rgdata->server,
+                           prop_table,
+                           rgdata->keys,
+                           media,
+                           rgdata->parent_requested,
+                           rgdata->parent_id);
+    rgdata->children = g_list_prepend (rgdata->children, prop_table);
   }
 
   if (!remaining) {
@@ -438,7 +450,7 @@ get_properties_cb (MS2Server *server,
   rgdata = g_slice_new0 (RygelGriloData);
   rgdata->server = g_object_ref (server);
   rgdata->source = (GrlMediaSource *) data;
-  rgdata->keys = get_grilo_keys (properties);
+  rgdata->keys = get_grilo_keys (properties, &rgdata->parent_requested);
   rgdata->parent_id = get_parent_id (id);
   media = unserialize_media (GRL_METADATA_SOURCE (rgdata->source), id);
 
@@ -488,7 +500,7 @@ get_children_cb (MS2Server *server,
   rgdata = g_slice_new0 (RygelGriloData);
   rgdata->server = g_object_ref (server);
   rgdata->source = (GrlMediaSource *) data;
-  rgdata->keys = get_grilo_keys (properties);
+  rgdata->keys = get_grilo_keys (properties, &rgdata->parent_requested);
   rgdata->parent_id = g_strdup (id);
   media = unserialize_media (GRL_METADATA_SOURCE (rgdata->source), id);
 



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