[rygel-grilo] Handle Path property



commit 40f34d4cc2486f8c4758473bb40a78478c612b1e
Author: Juan A. Suarez Romero <jasuarez igalia com>
Date:   Wed Apr 28 14:19:40 2010 +0200

    Handle Path property
    
    Handle it in root category.

 lib/media-server2-server-table.c |  151 ++++++++++++++++++++-----
 lib/media-server2-server.c       |  229 ++++++++++++++++++++++++++++++--------
 lib/media-server2-server.h       |  101 +++++++++++------
 src/rygel-grilo.c                |   85 +++++++++++----
 4 files changed, 430 insertions(+), 136 deletions(-)
---
diff --git a/lib/media-server2-server-table.c b/lib/media-server2-server-table.c
index 35a932f..8eb3fc9 100644
--- a/lib/media-server2-server-table.c
+++ b/lib/media-server2-server-table.c
@@ -23,6 +23,7 @@
 #include <dbus/dbus-glib-bindings.h>
 
 #include "media-server2-server.h"
+#include "media-server2-private.h"
 
 #define DBUS_TYPE_G_ARRAY_OF_STRING                             \
   (dbus_g_type_get_collection ("GPtrArray", G_TYPE_STRING))
@@ -78,63 +79,111 @@ ptrarray_to_value (GPtrArray *array)
   return val;
 }
 
+/* Returns an object path from an id */
+static gchar *
+id_to_object_path (MS2Server *server,
+                   const gchar *id,
+                   gboolean is_container)
+{
+  gchar *object_path;
+
+  /* Root container */
+  if (g_strcmp0 (id, MS2_ROOT) == 0) {
+    object_path = g_strconcat (MS2_DBUS_PATH_PREFIX,
+                               ms2_server_get_name (server),
+                               NULL);
+  } else {
+    if (is_container) {
+      object_path = g_strdup_printf (MS2_DBUS_PATH_PREFIX "%s/containers/%d",
+                                     ms2_server_get_name (server),
+                                     g_quark_from_string (id));
+    } else {
+      object_path = g_strdup_printf (MS2_DBUS_PATH_PREFIX "%s/items/%d",
+                                     ms2_server_get_name (server),
+                                     g_quark_from_string (id));
+    }
+  }
+
+  return object_path;
+}
+
 /********************* PUBLIC API *********************/
 
 /**
  * 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.
  *
- * For root container, identifier should be "0".
+ * @id will be transformed in an object path.
  *
  * Returns: a new #GHashTable
  **/
 GHashTable *
-ms2_server_new_properties_hashtable (const gchar *id)
+ms2_server_new_properties_hashtable (MS2Server *server,
+                                     const gchar *id,
+                                     gboolean is_container)
 {
   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);
-  if (id) {
-    g_hash_table_insert (properties, MS2_PROP_ID, str_to_value (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);
 
   return properties;
 }
 
 /**
  * ms2_server_set_parent:
+ * @server: a #MS2Server
  * @properties: a #GHashTable
  * @parent: parent value
  *
  * Sets the "parent" property. Mandatory property.
+ *
+ * @parent will be transformed in an object path.
  **/
 void
-ms2_server_set_parent (GHashTable *properties,
+ms2_server_set_parent (MS2Server *server,
+                       GHashTable *properties,
                        const gchar *parent)
 {
+  gchar *object_path;
+
+  g_return_if_fail (MS2_IS_SERVER (server));
   g_return_if_fail (properties);
 
   if (parent) {
+    object_path = id_to_object_path (server, parent, TRUE);
     g_hash_table_insert (properties,
                          MS2_PROP_PARENT,
-                         str_to_value (parent));
+                         str_to_value (object_path));
+    g_free (object_path);
   }
 }
 
 /**
  * ms2_server_set_display_name:
+ * @server: a #MS2Server
  * @properties: a #GHashTable
  * @display_name: display name value
  *
  * Sets the "display-name" property. Mandatory property.
  **/
 void
-ms2_server_set_display_name (GHashTable *properties,
+ms2_server_set_display_name (MS2Server *server,
+                             GHashTable *properties,
                              const gchar *display_name)
 {
   g_return_if_fail (properties);
@@ -148,6 +197,7 @@ ms2_server_set_display_name (GHashTable *properties,
 
 /**
  * ms2_server_set_item_type:
+ * @server: a #MS2Server
  * @properties: a #GHashTable
  * @type: type of item
  *
@@ -156,7 +206,8 @@ ms2_server_set_display_name (GHashTable *properties,
  * Tells what kind of object we are dealing with.
  **/
 void
-ms2_server_set_item_type (GHashTable *properties,
+ms2_server_set_item_type (MS2Server *server,
+                          GHashTable *properties,
                           MS2ItemType type)
 {
   g_return_if_fail (properties);
@@ -204,7 +255,8 @@ ms2_server_set_item_type (GHashTable *properties,
 }
 
 /**
- * ms2_server_set_icon:
+ * ms2_server_set_icon:ç
+ * @server: a #MS2Server
  * @properties: a #GHashTable
  * @icon: icon identifier value
  *
@@ -214,7 +266,8 @@ ms2_server_set_item_type (GHashTable *properties,
  * provider. This is only relevant to root container.
  **/
 void
-ms2_server_set_icon (GHashTable *properties,
+ms2_server_set_icon (MS2Server *server,
+                     GHashTable *properties,
                      const gchar *icon)
 {
   g_return_if_fail (properties);
@@ -228,13 +281,15 @@ ms2_server_set_icon (GHashTable *properties,
 
 /**
  * ms2_server_set_mime_type:
+ * @server: a #MS2Server
  * @properties: a #GHashTable
  * @mime_type: mime type value
  *
  * Sets the "mime-type" property. Mandatory property for items.
  **/
 void
-ms2_server_set_mime_type (GHashTable *properties,
+ms2_server_set_mime_type (MS2Server *server,
+                          GHashTable *properties,
                           const gchar *mime_type)
 {
   g_return_if_fail (properties);
@@ -248,13 +303,15 @@ ms2_server_set_mime_type (GHashTable *properties,
 
 /**
  * ms2_server_set_artist:
+ * @server: a #MS2Server
  * @properties: a #GHashTable
  * @artist: artist value
  *
  * Sets the "artist" property. Recommended property for items.
  **/
 void
-ms2_server_set_artist (GHashTable *properties,
+ms2_server_set_artist (MS2Server *server,
+                       GHashTable *properties,
                        const gchar *artist)
 {
   g_return_if_fail (properties);
@@ -268,13 +325,15 @@ ms2_server_set_artist (GHashTable *properties,
 
 /**
  * ms2_server_set_album:
+ * @server: a #MS2Server
  * @properties: a #GHashTable
  * @album: album value
  *
  * Sets the "album" property. Recommended property for items.
  **/
 void
-ms2_server_set_album (GHashTable *properties,
+ms2_server_set_album (MS2Server *server,
+                      GHashTable *properties,
                       const gchar *album)
 {
   g_return_if_fail (properties);
@@ -288,6 +347,7 @@ ms2_server_set_album (GHashTable *properties,
 
 /**
  * ms2_server_set_date:
+ * @server: a #MS2Server
  * @properties: a #GHashTable
  * @date: date value
  *
@@ -297,7 +357,8 @@ ms2_server_set_album (GHashTable *properties,
  * and RFC-3339.
  **/
 void
-ms2_server_set_date (GHashTable *properties,
+ms2_server_set_date (MS2Server *server,
+                     GHashTable *properties,
                      const gchar *date)
 {
   g_return_if_fail (properties);
@@ -311,6 +372,7 @@ ms2_server_set_date (GHashTable *properties,
 
 /**
  * ms2_server_set_dlna_profile:
+ * @server: a #MS2Server
  * @properties: a #GHashTable
  * @dlna_profile: DLNA value
  *
@@ -320,7 +382,8 @@ ms2_server_set_date (GHashTable *properties,
  * guessing of its value by UPnP consumers.
  **/
 void
-ms2_server_set_dlna_profile (GHashTable *properties,
+ms2_server_set_dlna_profile (MS2Server *server,
+                             GHashTable *properties,
                              const gchar *dlna_profile)
 {
   g_return_if_fail (properties);
@@ -334,13 +397,15 @@ ms2_server_set_dlna_profile (GHashTable *properties,
 
 /**
  * ms2_server_set_thumbnail:
+ * @server: a #MS2Server
  * @properties: a #GHashTable
  * @thumbnail: thumbnail identifier value
  *
  * Sets the "thumbnail" property. Optional property for video/image items.
  **/
 void
-ms2_server_set_thumbnail (GHashTable *properties,
+ms2_server_set_thumbnail (MS2Server *server,
+                          GHashTable *properties,
                           const gchar *thumbnail)
 {
   g_return_if_fail (properties);
@@ -354,13 +419,15 @@ ms2_server_set_thumbnail (GHashTable *properties,
 
 /**
  * ms2_server_set_genre:
+ * @server: a #MS2Server
  * @properties: a #GHashTable
  * @genre: genre value
  *
  * Sets the "genre" property. Optional property for audio/music items.
  **/
 void
-ms2_server_set_genre (GHashTable *properties,
+ms2_server_set_genre (MS2Server *server,
+                      GHashTable *properties,
                       const gchar *genre)
 {
   g_return_if_fail (properties);
@@ -374,6 +441,7 @@ ms2_server_set_genre (GHashTable *properties,
 
 /**
  * ms2_server_set_child_count:
+ * @server: a #MS2Server
  * @properties: a #GHashTable
  * @child_count: childcount value
  *
@@ -382,7 +450,8 @@ ms2_server_set_genre (GHashTable *properties,
  * It is the number of media objects directly under this container.
  **/
 void
-ms2_server_set_child_count (GHashTable *properties,
+ms2_server_set_child_count (MS2Server *server,
+                            GHashTable *properties,
                             gint child_count)
 {
   g_return_if_fail (properties);
@@ -394,6 +463,7 @@ ms2_server_set_child_count (GHashTable *properties,
 
 /**
  * ms2_server_set_size:
+ * @server: a #MS2Server
  * @properties: a #GHashTable
  * @size: size value
  *
@@ -402,7 +472,8 @@ ms2_server_set_child_count (GHashTable *properties,
  * It is the resource size in bytes.
  **/
 void
-ms2_server_set_size (GHashTable *properties,
+ms2_server_set_size (MS2Server *server,
+                     GHashTable *properties,
                      gint size)
 {
   g_return_if_fail (properties);
@@ -414,13 +485,15 @@ ms2_server_set_size (GHashTable *properties,
 
 /**
  * ms2_server_set_duration:
+ * @server: a #MS2Server
  * @properties: a #GHashTable
  * @duration: duration (in seconds) value
  *
  * Sets the "duration" property. Optional property for audio/video/music items.
  **/
 void
-ms2_server_set_duration (GHashTable *properties,
+ms2_server_set_duration (MS2Server *server,
+                         GHashTable *properties,
                          gint duration)
 {
   g_return_if_fail (properties);
@@ -432,13 +505,15 @@ ms2_server_set_duration (GHashTable *properties,
 
 /**
  * ms2_server_set_bitrate:
+ * @server: a #MS2Server
  * @properties: a #GHashTable
  * @bitrate: bitrate value
  *
  * Sets the "bitrate" property. Optional property for audio/video/music items.
  **/
 void
-ms2_server_set_bitrate (GHashTable *properties,
+ms2_server_set_bitrate (MS2Server *server,
+                        GHashTable *properties,
                         gint bitrate)
 {
   g_return_if_fail (properties);
@@ -450,6 +525,7 @@ ms2_server_set_bitrate (GHashTable *properties,
 
 /**
  * ms2_server_set_sample_rate:
+ * @server: a #MS2Server
  * @properties: a #GHashTable
  * @sample_rate: sample rate value
  *
@@ -457,7 +533,8 @@ ms2_server_set_bitrate (GHashTable *properties,
  * items.
  **/
 void
-ms2_server_set_sample_rate (GHashTable *properties,
+ms2_server_set_sample_rate (MS2Server *server,
+                            GHashTable *properties,
                             gint sample_rate)
 {
   g_return_if_fail (properties);
@@ -469,6 +546,7 @@ ms2_server_set_sample_rate (GHashTable *properties,
 
 /**
  * ms2_server_set_bits_per_sample:
+ * @server: a #MS2Server
  * @properties: a #GHashTable
  * @bits_per_sample: bits per sample value
  *
@@ -476,7 +554,8 @@ ms2_server_set_sample_rate (GHashTable *properties,
  * items.
  **/
 void
-ms2_server_set_bits_per_sample (GHashTable *properties,
+ms2_server_set_bits_per_sample (MS2Server *server,
+                                GHashTable *properties,
                                 gint bits_per_sample)
 {
   g_return_if_fail (properties);
@@ -488,13 +567,15 @@ ms2_server_set_bits_per_sample (GHashTable *properties,
 
 /**
  * ms2_server_set_width:
+ * @server: a #MS2Server
  * @properties: a #GHashTable
  * @width: width (in pixels) value
  *
  * Sets the "width" property. Recommended property for video/image items.
  **/
 void
-ms2_server_set_width (GHashTable *properties,
+ms2_server_set_width (MS2Server *server,
+                      GHashTable *properties,
                       gint width)
 {
   g_return_if_fail (properties);
@@ -506,13 +587,15 @@ ms2_server_set_width (GHashTable *properties,
 
 /**
  * ms2_server_set_height:
+ * @server: a #MS2Server
  * @properties: a #GHashTable
  * @height: height (in pixels) value
  *
  * Sets the "height" property. Recommended property for video/image items.
  **/
 void
-ms2_server_set_height (GHashTable *properties,
+ms2_server_set_height (MS2Server *server,
+                       GHashTable *properties,
                        gint height)
 {
   g_return_if_fail (properties);
@@ -524,13 +607,15 @@ ms2_server_set_height (GHashTable *properties,
 
 /**
  * ms2_server_set_color_depth:
+ * @server: a #MS2Server
  * @properties: a #GHashTable
  * @depth: color depth value
  *
  * Sets the "color-depth" property. Recommended property for video/image items.
  **/
 void
-ms2_server_set_color_depth (GHashTable *properties,
+ms2_server_set_color_depth (MS2Server *server,
+                            GHashTable *properties,
                             gint depth)
 {
   g_return_if_fail (properties);
@@ -542,13 +627,15 @@ ms2_server_set_color_depth (GHashTable *properties,
 
 /**
  * ms2_server_set_pixel_width:
+ * @server: a #MS2Server
  * @properties: a #GHashTable
  * @pixel_width: pixel width value
  *
  * Sets the "pixel-width" property. Optional property for video/image items.
  **/
 void
-ms2_server_set_pixel_width (GHashTable *properties,
+ms2_server_set_pixel_width (MS2Server *server,
+                            GHashTable *properties,
                             gint pixel_width)
 {
   g_return_if_fail (properties);
@@ -560,13 +647,15 @@ ms2_server_set_pixel_width (GHashTable *properties,
 
 /**
  * ms2_server_set_pixel_height:
+ * @server: a #MS2Server
  * @properties: a #GHashTable
  * @pixel_height: pixel height value
  *
  * Sets the "pixel-height" property. Optional property for video/image items.
  **/
 void
-ms2_server_set_pixel_height (GHashTable *properties,
+ms2_server_set_pixel_height (MS2Server *server,
+                             GHashTable *properties,
                              gint pixel_height)
 {
   g_return_if_fail (properties);
@@ -578,13 +667,15 @@ ms2_server_set_pixel_height (GHashTable *properties,
 
 /**
  * ms2_server_set_urls:
+ * @server: a #MS2Server
  * @properties: a #GHashTable
  * @urls: @NULL-terminated array of URLs values
  *
  * Sets the "URLs" property. Mandatory property for items.
  **/
 void
-ms2_server_set_urls (GHashTable *properties,
+ms2_server_set_urls (MS2Server *server,
+                     GHashTable *properties,
                      gchar **urls)
 {
   GPtrArray *url_array;
diff --git a/lib/media-server2-server.c b/lib/media-server2-server.c
index 509b4be..ed1738b 100644
--- a/lib/media-server2-server.c
+++ b/lib/media-server2-server.c
@@ -251,6 +251,78 @@ check_properties (const gchar **filter)
 }
 
 static gboolean
+lookup_in_strv (gchar **strv,
+                const gchar *needle)
+{
+  gint i;
+  if (!strv || !needle) {
+    return FALSE;
+  }
+
+  for (i = 0; strv[i] && strv[i] != needle; i++);
+  return (strv[i] != NULL);
+}
+
+static GValue *
+properties_lookup_with_default (GHashTable *properties,
+                                const gchar *property)
+{
+  GPtrArray *ptrarray;
+  GValue *ret_value;
+  GValue *propvalue;
+  const gchar *intern_property;
+  static gchar **int_type_properties = NULL;
+  static gchar **gptrarray_type_properties = NULL;
+
+  /* Initialize data */
+  if (!int_type_properties) {
+    int_type_properties = g_new (gchar *, 12);
+    int_type_properties[0] = (gchar *) g_intern_static_string (MS2_PROP_CHILD_COUNT);
+    int_type_properties[1] = (gchar *) g_intern_static_string (MS2_PROP_SIZE);
+    int_type_properties[2] = (gchar *) g_intern_static_string (MS2_PROP_DURATION);
+    int_type_properties[3] = (gchar *) g_intern_static_string (MS2_PROP_BITRATE);
+    int_type_properties[4] = (gchar *) g_intern_static_string (MS2_PROP_SAMPLE_RATE);
+    int_type_properties[5] = (gchar *) g_intern_static_string (MS2_PROP_BITS_PER_SAMPLE);
+    int_type_properties[6] = (gchar *) g_intern_static_string (MS2_PROP_WIDTH);
+    int_type_properties[7] = (gchar *) g_intern_static_string (MS2_PROP_HEIGHT);
+    int_type_properties[8] = (gchar *) g_intern_static_string (MS2_PROP_COLOR_DEPTH);
+    int_type_properties[9] = (gchar *) g_intern_static_string (MS2_PROP_PIXEL_WIDTH);
+    int_type_properties[10] = (gchar *) g_intern_static_string (MS2_PROP_PIXEL_HEIGHT);
+    int_type_properties[11] = NULL;
+  }
+
+  if (!gptrarray_type_properties) {
+    gptrarray_type_properties = g_new (gchar *, 2);
+    gptrarray_type_properties[0] = (gchar *) g_intern_static_string (MS2_PROP_URLS);
+    gptrarray_type_properties[1] = NULL;
+  }
+
+  propvalue = g_hash_table_lookup (properties, property);
+  if (propvalue) {
+    /* Make a copy and return it */
+    ret_value = g_new0 (GValue, 1);
+    g_value_init (ret_value, G_VALUE_TYPE (propvalue));
+    g_value_copy (propvalue, ret_value);
+
+    return ret_value;
+  }
+
+  /* Use a default value */
+  intern_property = g_intern_string (property);
+  if (lookup_in_strv (int_type_properties, intern_property)) {
+    ret_value = int_to_value (MS2_UNKNOWN_INT);
+  } else if (lookup_in_strv (gptrarray_type_properties, intern_property)) {
+    ptrarray = g_ptr_array_sized_new (1);
+    g_ptr_array_add (ptrarray, g_strdup (MS2_UNKNOWN_STR));
+    ret_value = ptrarray_to_value (ptrarray);
+  } else {
+    ret_value = str_to_value (MS2_UNKNOWN_STR);
+  }
+
+  return ret_value;
+}
+
+static gboolean
 is_property_valid (const gchar *interface,
                    const gchar *property)
 {
@@ -286,12 +358,7 @@ is_property_valid (const gchar *interface,
 
   /* Check MediaObject2 interface */
   if (!interface || g_strcmp0 (interface, "org.gnome.UPnP.MediaObject2") == 0) {
-    found = FALSE;
-    i = 0;
-    while (!found && mo2_properties_intern[i]) {
-      found = (prop_intern == mo2_properties_intern[i]);
-      i++;
-    }
+    found = lookup_in_strv (mo2_properties_intern, prop_intern);
 
     if (found) {
       return TRUE;
@@ -305,19 +372,25 @@ is_property_valid (const gchar *interface,
 
   /* Check MediaItem2 interface */
   if (!interface || g_strcmp0 (interface, "org.gnome.UPnP.MediaItem2") == 0) {
-    found = FALSE;
-    i = 0;
-    while (!found && mi2_properties_intern[i]) {
-      found = (prop_intern == mi2_properties_intern[i]);
-      i++;
-    }
-
-    return found;
+    return lookup_in_strv (mi2_properties_intern, prop_intern);
   }
 
   return FALSE;
 }
 
+static gchar *
+get_path_from_id (MS2Server *server,
+                  const gchar *id)
+{
+  gchar *path;
+
+  path = g_strconcat (MS2_DBUS_PATH_PREFIX,
+                      server->priv->name,
+                      NULL);
+
+  return path;
+}
+
 static GValue *
 get_property_value (MS2Server *server,
                     const gchar *id,
@@ -325,9 +398,9 @@ get_property_value (MS2Server *server,
                     const gchar *property)
 {
   GHashTable *propresult;
-  GValue *propvalue;
   GValue *v;
   const gchar *prop[2] = { NULL };
+  gchar *path;
 
   /* Check everything is right */
   if (!id ||
@@ -337,31 +410,31 @@ get_property_value (MS2Server *server,
     return NULL;
   }
 
-  prop[0] = property;
-  propresult = server->priv->get_properties (id,
-                                             prop,
-                                             server->priv->data,
-                                             NULL);
-  if (!propresult) {
-    return NULL;
-  }
-
-  propvalue = g_hash_table_lookup (propresult, property);
-
-  if (propvalue) {
-    /* Make a copy */
+  /* If asking for Path, we already can use id */
+  if (g_strcmp0 (property, MS2_PROP_ID) == 0) {
     v = g_new0 (GValue, 1);
-    g_value_init (v, G_VALUE_TYPE (propvalue));
-    g_value_copy (propvalue, v);
-  }
+    g_value_init (v, G_TYPE_STRING);
+    path = get_path_from_id (server, id);
+    g_value_take_string (v, path);
+  } else {
+    prop[0] = property;
+    propresult = server->priv->get_properties (server, id,
+                                               prop,
+                                               server->priv->data,
+                                               NULL);
+    if (!propresult) {
+      return NULL;
+    }
 
-  g_hash_table_unref (propresult);
+    v = properties_lookup_with_default (propresult, property);
+    g_hash_table_unref (propresult);
+  }
 
   return v;
 }
 
 static gchar *
-get_id (DBusMessage *m)
+get_id_from_message (DBusMessage *m)
 {
   gchar **path;
   gchar *id;
@@ -412,11 +485,11 @@ append_variant_arg (DBusMessage *m, const GValue *v)
 }
 
 static DBusHandlerResult
-handle_introspect_container_message (DBusConnection *c,
-                                     DBusMessage *m,
-                                     void *userdata)
+handle_introspect_message (DBusConnection *c,
+                           DBusMessage *m,
+                           void *userdata,
+                           const gchar *xml)
 {
-  static const gchar *xml = CONTAINER_INTROSPECTION;
   DBusMessage *r;
 
   /* Check signature */
@@ -449,7 +522,7 @@ handle_get_message (DBusConnection *c,
                            DBUS_TYPE_STRING, &interface,
                            DBUS_TYPE_STRING, &property,
                            DBUS_TYPE_INVALID);
-    id = get_id (m);
+    id = get_id_from_message (m);
     value = get_property_value (server, id, interface, property);
     g_free (id);
     if (!value) {
@@ -470,18 +543,34 @@ handle_get_message (DBusConnection *c,
 }
 
 static DBusHandlerResult
-root_handler (DBusConnection *c,
-              DBusMessage *m,
-              void *userdata)
+items_handler (DBusConnection *c,
+               DBusMessage *m,
+               void *userdata)
 {
-  const gchar *iface;
-
-  iface = dbus_message_get_interface (m);
+  if (dbus_message_is_method_call (m,
+                                   "org.freedesktop.DBus.Introspectable",
+                                   "Introspect")) {
+    return handle_introspect_message (c, m, userdata,
+                                      ITEM_INTROSPECTION);
+  } else if (dbus_message_is_method_call (m,
+                                          "org.freedesktop.DBus.Properties",
+                                          "Get")) {
+    return handle_get_message (c, m, userdata);
+  } else {
+    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+  }
+}
 
+static DBusHandlerResult
+containers_handler (DBusConnection *c,
+                    DBusMessage *m,
+                    void *userdata)
+{
   if (dbus_message_is_method_call (m,
                                    "org.freedesktop.DBus.Introspectable",
                                    "Introspect")) {
-    return handle_introspect_container_message (c, m, userdata);
+    return handle_introspect_message (c, m, userdata,
+                                      CONTAINER_INTROSPECTION);
   } else if (dbus_message_is_method_call (m,
                                           "org.freedesktop.DBus.Properties",
                                           "Get")) {
@@ -491,6 +580,14 @@ root_handler (DBusConnection *c,
   }
 }
 
+static DBusHandlerResult
+root_handler (DBusConnection *c,
+              DBusMessage *m,
+              void *userdata)
+{
+  return containers_handler (c, m, userdata);
+}
+
 /* Registers the MS2Server object in dbus */
 static gboolean
 ms2_server_dbus_register (MS2Server *server,
@@ -500,9 +597,17 @@ ms2_server_dbus_register (MS2Server *server,
   DBusError error;
   gchar *dbus_name;
   gchar *dbus_path;
+  gchar *dbus_path_items;
+  gchar *dbus_path_containers;
   static const DBusObjectPathVTable vtable_root = {
     .message_function = root_handler,
   };
+  static const DBusObjectPathVTable vtable_items = {
+    .message_function = items_handler,
+  };
+  static const DBusObjectPathVTable vtable_containers = {
+    .message_function = containers_handler
+  };
 
   dbus_error_init (&error);
 
@@ -525,9 +630,16 @@ ms2_server_dbus_register (MS2Server *server,
   g_free (dbus_name);
 
   dbus_path = g_strconcat (MS2_DBUS_PATH_PREFIX, name, NULL);
+  dbus_path_items = g_strconcat (dbus_path, "/items", NULL);
+  dbus_path_containers = g_strconcat (dbus_path, "/containers", NULL);
+
   dbus_connection_register_object_path (connection, dbus_path, &vtable_root, server);
+  dbus_connection_register_fallback (connection, dbus_path_items, &vtable_items, server);
+  dbus_connection_register_fallback (connection, dbus_path_containers, &vtable_containers, server);
 
   g_free (dbus_path);
+  g_free (dbus_path_items);
+  g_free (dbus_path_containers);
 
   dbus_connection_setup_with_g_main(connection, NULL);
 
@@ -557,7 +669,10 @@ ms2_server_dbus_unregister (MS2Server *server,
                                       DBUS_INTERFACE_DBUS);
 
   /* Release name */
-  dbus_name = g_strconcat (MS2_DBUS_SERVICE_PREFIX, name, NULL);
+  dbus_name = g_strconcat (MS2_DBUS_SERVICE_PREFIX,
+                           server->priv->name,
+                           NULL);
+
   org_freedesktop_DBus_release_name (gproxy,
                                      dbus_name,
                                      &request_name_result,
@@ -643,7 +758,8 @@ ms2_server_get_properties (MS2Server *server,
     wrong_prop = check_properties (filter);
 
     if (!wrong_prop) {
-      properties = server->priv->get_properties (id,
+      properties = server->priv->get_properties (server,
+                                                 id,
                                                  filter,
                                                  server->priv->data,
                                                  &prop_error);
@@ -729,7 +845,8 @@ ms2_server_get_children (MS2Server *server,
 
     if (!wrong_prop) {
       children =
-        server->priv->get_children (id,
+        server->priv->get_children (server,
+                                    id,
                                     offset,
                                     max_count < 0? G_MAXINT: max_count,
                                     filter,
@@ -865,3 +982,19 @@ ms2_server_updated (MS2Server *server,
 
   g_signal_emit (server, signals[UPDATED], 0, id);
 }
+
+/**
+ * ms2_server_get_name:
+ * @server: a #MS2Server
+ *
+ * Returns name used for this server.
+ *
+ * Returns: server name. Should not be freed.
+ **/
+const gchar *
+ms2_server_get_name (MS2Server *server)
+{
+  g_return_val_if_fail (MS2_IS_SERVER (server), NULL);
+
+  return server->priv->name;
+}
diff --git a/lib/media-server2-server.h b/lib/media-server2-server.h
index 7e277af..462ad7a 100644
--- a/lib/media-server2-server.h
+++ b/lib/media-server2-server.h
@@ -54,18 +54,6 @@
                               MS2_TYPE_SERVER,  \
                               MS2ServerClass))
 
-typedef GHashTable * (*GetPropertiesFunc) (const gchar *id,
-                                           const gchar **properties,
-                                           gpointer data,
-                                           GError **error);
-
-typedef GList * (*GetChildrenFunc) (const gchar *id,
-                                    guint offset,
-                                    gint max_count,
-                                    const gchar **properties,
-                                    gpointer data,
-                                    GError **error);
-
 typedef struct _MS2Server        MS2Server;
 typedef struct _MS2ServerPrivate MS2ServerPrivate;
 
@@ -87,6 +75,20 @@ struct _MS2ServerClass {
                    const gchar *id);
 };
 
+typedef GHashTable * (*GetPropertiesFunc) (MS2Server *server,
+                                           const gchar *id,
+                                           const gchar **properties,
+                                           gpointer data,
+                                           GError **error);
+
+typedef GList * (*GetChildrenFunc) (MS2Server *server,
+                                    const gchar *id,
+                                    guint offset,
+                                    gint max_count,
+                                    const gchar **properties,
+                                    gpointer data,
+                                    GError **error);
+
 GType ms2_server_get_type (void);
 
 MS2Server *ms2_server_new (const gchar *name,
@@ -101,75 +103,102 @@ void ms2_server_set_get_children_func (MS2Server *server,
 void ms2_server_updated (MS2Server *server,
                          const gchar *id);
 
-GHashTable *ms2_server_new_properties_hashtable (const gchar *id);
+const gchar *ms2_server_get_name (MS2Server *server);
+
+GHashTable *ms2_server_new_properties_hashtable (MS2Server *server,
+                                                 const gchar *id,
+                                                 gboolean is_container);
 
-void ms2_server_set_parent (GHashTable *properties,
+void ms2_server_set_parent (MS2Server *server,
+                            GHashTable *properties,
                             const gchar *parent);
 
-void ms2_server_set_display_name (GHashTable *properties,
+void ms2_server_set_display_name (MS2Server *server,
+                                  GHashTable *properties,
                                   const gchar *display_name);
 
-void ms2_server_set_item_type (GHashTable *properties,
+void ms2_server_set_item_type (MS2Server *server,
+                               GHashTable *properties,
                                MS2ItemType type);
 
-void ms2_server_set_icon (GHashTable *properties,
+void ms2_server_set_icon (MS2Server *server,
+                          GHashTable *properties,
                           const gchar *icon);
 
-void ms2_server_set_mime_type (GHashTable *properties,
+void ms2_server_set_mime_type (MS2Server *server,
+                               GHashTable *properties,
                                const gchar *mime_type);
 
-void ms2_server_set_artist (GHashTable *properties,
+void ms2_server_set_artist (MS2Server *server,
+                            GHashTable *properties,
                             const gchar *artist);
 
-void ms2_server_set_album (GHashTable *properties,
+void ms2_server_set_album (MS2Server *server,
+                           GHashTable *properties,
                            const gchar *album);
 
-void ms2_server_set_date (GHashTable *properties,
+void ms2_server_set_date (MS2Server *server,
+                          GHashTable *properties,
                           const gchar *date);
 
-void ms2_server_set_dlna_profile (GHashTable *properties,
+void ms2_server_set_dlna_profile (MS2Server *server,
+                                  GHashTable *properties,
                                   const gchar *dlna_profile);
 
-void ms2_server_set_thumbnail (GHashTable *properties,
+void ms2_server_set_thumbnail (MS2Server *server,
+                               GHashTable *properties,
                                const gchar *thumbnail);
 
-void ms2_server_set_genre (GHashTable *properties,
+void ms2_server_set_genre (MS2Server *server,
+                           GHashTable *properties,
                            const gchar *genre);
 
-void ms2_server_set_child_count (GHashTable *properties,
+void ms2_server_set_child_count (MS2Server *server,
+                                 GHashTable *properties,
                                  gint child_count);
 
-void ms2_server_set_size (GHashTable *properties,
+void ms2_server_set_size (MS2Server *server,
+                          GHashTable *properties,
                           gint size);
 
-void ms2_server_set_duration (GHashTable *properties,
+void ms2_server_set_duration (MS2Server *server,
+                              GHashTable *properties,
                               gint duration);
 
-void ms2_server_set_bitrate (GHashTable *properties,
+void ms2_server_set_bitrate (MS2Server *server,
+                             GHashTable *properties,
                              gint bitrate);
 
-void ms2_server_set_sample_rate (GHashTable *properties,
+void ms2_server_set_sample_rate (MS2Server *server,
+                                 GHashTable *properties,
                                  gint sample_rate);
 
-void ms2_server_set_bits_per_sample (GHashTable *properties,
+void ms2_server_set_bits_per_sample (MS2Server *server,
+                                     GHashTable *properties,
                                      gint bits_per_sample);
 
-void ms2_server_set_width (GHashTable *properties,
+void ms2_server_set_width (MS2Server *server,
+                           GHashTable *properties,
                            gint width);
 
-void ms2_server_set_height (GHashTable *properties,
+void ms2_server_set_height (MS2Server *server,
+                            GHashTable *properties,
                             gint height);
 
-void ms2_server_set_color_depth (GHashTable *properties,
+void ms2_server_set_color_depth (MS2Server *server,
+                                 GHashTable *properties,
                                  gint depth);
 
-void ms2_server_set_pixel_width (GHashTable *properties,
+void ms2_server_set_pixel_width (MS2Server *server,
+                                 GHashTable *properties,
                                  gint pixel_width);
 
-void ms2_server_set_pixel_height (GHashTable *properties,
+void ms2_server_set_pixel_height (MS2Server *server,
+                                  GHashTable *properties,
                                   gint pixel_height);
 
-void ms2_server_set_urls (GHashTable *properties,
+void ms2_server_set_urls (MS2Server *server,
+                          GHashTable *properties,
                           gchar **urls);
 
 #endif /* _MEDIA_SERVER2_SERVER_H_ */
diff --git a/src/rygel-grilo.c b/src/rygel-grilo.c
index b72b66c..1cb5f4a 100644
--- a/src/rygel-grilo.c
+++ b/src/rygel-grilo.c
@@ -65,6 +65,7 @@ typedef struct {
   GList *children;
   GList *keys;
   GrlMediaSource *source;
+  MS2Server *server;
   gboolean updated;
   gchar *parent_id;
 } RygelGriloData;
@@ -145,10 +146,18 @@ static gchar *
 serialize_media (const gchar *parent_id,
                  GrlMedia *media)
 {
+  const gchar *media_id;
   gchar *escaped_id;
   gchar *ms_id;
 
-  escaped_id = g_uri_escape_string (grl_media_get_id (media), NULL, TRUE);
+  media_id = grl_media_get_id (media);
+
+  /* Check if it is root media */
+  if (!media_id) {
+    return g_strdup (ID_PREFIX_CONTAINER);
+  }
+
+  escaped_id = g_uri_escape_string (media_id, NULL, TRUE);
 
   if (g_strcmp0 (parent_id, MS2_ROOT) == 0) {
     ms_id = g_strconcat (ID_PREFIX_CONTAINER, escaped_id, NULL);
@@ -246,7 +255,8 @@ get_grilo_keys (const gchar **ms_keys)
 }
 
 static void
-fill_properties_table (GHashTable *properties_table,
+fill_properties_table (MS2Server *server,
+                       GHashTable *properties_table,
                        GList *keys,
                        GrlMedia *media,
                        const gchar *parent_id)
@@ -260,53 +270,63 @@ fill_properties_table (GHashTable *properties_table,
     if (grl_data_key_is_known (GRL_DATA (media), key)) {
       switch (key) {
       case GRL_METADATA_KEY_TITLE:
-        ms2_server_set_display_name (properties_table,
+        ms2_server_set_display_name (server,
+                                     properties_table,
                                      grl_media_get_title (media));
         break;
       case GRL_METADATA_KEY_ALBUM:
-        ms2_server_set_album (properties_table,
+        ms2_server_set_album (server,
+                              properties_table,
                               grl_data_get_string (GRL_DATA (media),
                                                    GRL_METADATA_KEY_ALBUM));
         break;
       case GRL_METADATA_KEY_ARTIST:
-        ms2_server_set_artist (properties_table,
+        ms2_server_set_artist (server,
+                               properties_table,
                                grl_data_get_string (GRL_DATA (media),
                                                     GRL_METADATA_KEY_ARTIST));
         break;
       case GRL_METADATA_KEY_GENRE:
-        ms2_server_set_genre (properties_table,
+        ms2_server_set_genre (server,
+                              properties_table,
                               grl_data_get_string (GRL_DATA (media),
                                                    GRL_METADATA_KEY_GENRE));
         break;
       case GRL_METADATA_KEY_MIME:
-        ms2_server_set_mime_type (properties_table,
+        ms2_server_set_mime_type (server,
+                                  properties_table,
                                   grl_media_get_mime (media));
         break;
       case GRL_METADATA_KEY_CHILDCOUNT:
-        ms2_server_set_child_count (properties_table,
+        ms2_server_set_child_count (server,
+                                    properties_table,
                                     grl_data_get_int (GRL_DATA (media),
                                                       GRL_METADATA_KEY_CHILDCOUNT));
         break;
       case GRL_METADATA_KEY_URL:
         urls[0] = (gchar *) grl_media_get_url (media);
-        ms2_server_set_urls (properties_table, urls);
+        ms2_server_set_urls (server, properties_table, urls);
         break;
       case GRL_METADATA_KEY_BITRATE:
-        ms2_server_set_bitrate (properties_table,
+        ms2_server_set_bitrate (server,
+                                properties_table,
                                 grl_data_get_int (GRL_DATA (media),
                                                   GRL_METADATA_KEY_BITRATE));
         break;
       case GRL_METADATA_KEY_DURATION:
-        ms2_server_set_duration (properties_table,
+        ms2_server_set_duration (server,
+                                 properties_table,
                                  grl_media_get_duration (media));
         break;
       case GRL_METADATA_KEY_HEIGHT:
-        ms2_server_set_height (properties_table,
+        ms2_server_set_height (server,
+                               properties_table,
                                grl_data_get_int (GRL_DATA (media),
                                                  GRL_METADATA_KEY_HEIGHT));
         break;
       case GRL_METADATA_KEY_WIDTH:
-        ms2_server_set_width (properties_table,
+        ms2_server_set_width (server,
+                              properties_table,
                               grl_data_get_int (GRL_DATA (media),
                                                 GRL_METADATA_KEY_WIDTH));
         break;
@@ -315,7 +335,7 @@ fill_properties_table (GHashTable *properties_table,
   }
 
   if (parent_id) {
-    ms2_server_set_parent (properties_table, parent_id);
+    ms2_server_set_parent (server, properties_table, parent_id);
   }
 }
 
@@ -326,14 +346,25 @@ 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;
   }
-
-  fill_properties_table (rgdata->properties, rgdata->keys, media, rgdata->parent_id);
+  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->updated = TRUE;
 }
@@ -359,8 +390,14 @@ browse_cb (GrlMediaSource *source,
   if (media) {
     id = serialize_media (rgdata->parent_id, media);
     if (id) {
-      prop_table = ms2_server_new_properties_hashtable (id);
-      fill_properties_table (prop_table, rgdata->keys, media, rgdata->parent_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);
     }
@@ -388,7 +425,8 @@ wait_for_result (RygelGriloData *rgdata)
 }
 
 static GHashTable *
-get_properties_cb (const gchar *id,
+get_properties_cb (MS2Server *server,
+                   const gchar *id,
                    const gchar **properties,
                    gpointer data,
                    GError **error)
@@ -398,8 +436,8 @@ get_properties_cb (const gchar *id,
   RygelGriloData *rgdata;
 
   rgdata = g_slice_new0 (RygelGriloData);
+  rgdata->server = g_object_ref (server);
   rgdata->source = (GrlMediaSource *) data;
-  rgdata->properties = ms2_server_new_properties_hashtable (id);
   rgdata->keys = get_grilo_keys (properties);
   rgdata->parent_id = get_parent_id (id);
   media = unserialize_media (GRL_METADATA_SOURCE (rgdata->source), id);
@@ -421,7 +459,6 @@ get_properties_cb (const gchar *id,
     if (error) {
       *error = rgdata->error;
     }
-    g_hash_table_unref (rgdata->properties);
   } else {
     properties_table = rgdata->properties;
   }
@@ -429,13 +466,15 @@ get_properties_cb (const gchar *id,
   g_object_unref (media);
   g_list_free (rgdata->keys);
   g_free (rgdata->parent_id);
+  g_object_unref (rgdata->server);
   g_slice_free (RygelGriloData, rgdata);
 
   return properties_table;
 }
 
 static GList *
-get_children_cb (const gchar *id,
+get_children_cb (MS2Server *server,
+                 const gchar *id,
                  guint offset,
                  gint max_count,
                  const gchar **properties,
@@ -447,6 +486,7 @@ get_children_cb (const gchar *id,
   RygelGriloData *rgdata;
 
   rgdata = g_slice_new0 (RygelGriloData);
+  rgdata->server = g_object_ref (server);
   rgdata->source = (GrlMediaSource *) data;
   rgdata->keys = get_grilo_keys (properties);
   rgdata->parent_id = g_strdup (id);
@@ -477,6 +517,7 @@ get_children_cb (const gchar *id,
   g_object_unref (media);
   g_list_free (rgdata->keys);
   g_free (rgdata->parent_id);
+  g_object_unref (rgdata->server);
   g_slice_free (RygelGriloData, rgdata);
 
   return children;



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