[rygel-grilo] Handle Get call



commit 22cd6bb5c26849fa2b8a119ad7a254167a3aa4f6
Author: Juan A. Suarez Romero <jasuarez igalia com>
Date:   Tue Apr 27 23:56:51 2010 +0200

    Handle Get call

 data/media-server2.xml     |   18 ++--
 lib/media-server2-common.h |   58 +++++------
 lib/media-server2-server.c |  226 +++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 258 insertions(+), 44 deletions(-)
---
diff --git a/data/media-server2.xml b/data/media-server2.xml
index 011f937..22f2f10 100644
--- a/data/media-server2.xml
+++ b/data/media-server2.xml
@@ -13,24 +13,20 @@
   </interface>
 
   <interface name="org.gnome.UPnP.MediaItem2">
-    <property name="URLs"     type="as" access="read"/>
-    <property name="MIMEType" type="s"  access="read"/>
-    <property name="Type"     type="s"  access="read"/>
-    <property name="Artist"   type="s"  access="read"/>
     <property name="Album"    type="s"  access="read"/>
-    <property name="Genre"    type="s"  access="read"/>
-    <property name="Duration" type="i"  access="read"/>
+    <property name="Artist"   type="s"  access="read"/>
     <property name="Bitrate"  type="i"  access="read"/>
-    <property name="Width"    type="i"  access="read"/>
+    <property name="Duration" type="i"  access="read"/>
+    <property name="Genre"    type="s"  access="read"/>
     <property name="Height"   type="i"  access="read"/>
+    <property name="MIMEType" type="s"  access="read"/>
+    <property name="Type"     type="s"  access="read"/>
+    <property name="URLs"     type="as" access="read"/>
+    <property name="Width"    type="i"  access="read"/>
   </interface>
 
   <interface name="org.gnome.UPnP.MediaContainer2">
     <property name="CanSearch"      type="b"  access="read"/>
-    <property name="ContainerCount" type="u"  access="read"/>
-    <property name="Containers"     type="ao" access="read"/>
-    <property name="ItemCount"      type="u"  access="read"/>
-    <property name="Items"          type="ao" access="read"/>
 
     <method name="ListObjects">
       <arg name="offset"  direction="in"  type="u"/>
diff --git a/lib/media-server2-common.h b/lib/media-server2-common.h
index d791253..a3ff9b9 100644
--- a/lib/media-server2-common.h
+++ b/lib/media-server2-common.h
@@ -26,41 +26,35 @@
 #define MS2_ERROR                                       \
   g_quark_from_static_string("media_server2_error")
 
-/* Common properties */
-#define MS2_PROP_ID           "id"
-#define MS2_PROP_PARENT       "parent"
-#define MS2_PROP_DISPLAY_NAME "display-name"
-#define MS2_PROP_TYPE         "type"
+/* MediaObject2 properties */
+#define MS2_PROP_DISPLAY_NAME "DisplayName"
+#define MS2_PROP_PARENT       "Parent"
+#define MS2_PROP_ID           "Path"
 
-/* Container properties */
-#define MS2_PROP_CHILD_COUNT "child-count"
-#define MS2_PROP_ICON        "icon"
+/* MediaItem2 properties */
+#define MS2_PROP_ALBUM     "Album"
+#define MS2_PROP_ARTIST    "Artist"
+#define MS2_PROP_BITRATE   "Bitrate"
+#define MS2_PROP_DURATION  "Duration"
+#define MS2_PROP_GENRE     "Genre"
+#define MS2_PROP_HEIGHT    "Height"
+#define MS2_PROP_MIME_TYPE "MIMEType"
+#define MS2_PROP_TYPE      "Type"
+#define MS2_PROP_URLS      "URLs"
+#define MS2_PROP_WIDTH     "Width"
 
-/* Item properties */
-#define MS2_PROP_URLS         "URLs"
-#define MS2_PROP_MIME_TYPE    "mime-type"
-#define MS2_PROP_SIZE         "size"
-#define MS2_PROP_ARTIST       "artist"
-#define MS2_PROP_ALBUM        "album"
-#define MS2_PROP_DATE         "date"
-#define MS2_PROP_DLNA_PROFILE "dlna-profile"
-
-/* Audio/Video items properties */
-#define MS2_PROP_DURATION        "duration"
-#define MS2_PROP_BITRATE         "bitrate"
+/* Other undefined properties; pending to add to spec */
+#define MS2_PROP_CHILD_COUNT     "child-count"
+#define MS2_PROP_ICON            "icon"
+#define MS2_PROP_SIZE            "size"
+#define MS2_PROP_DATE            "date"
+#define MS2_PROP_DLNA_PROFILE    "dlna-profile"
 #define MS2_PROP_SAMPLE_RATE     "sample-rate"
 #define MS2_PROP_BITS_PER_SAMPLE "bits-per-sample"
-
-/* Video/Image items properties */
-#define MS2_PROP_WIDTH        "width"
-#define MS2_PROP_HEIGHT       "height"
-#define MS2_PROP_COLOR_DEPTH  "color-depth"
-#define MS2_PROP_PIXEL_WIDTH  "pixel-width"
-#define MS2_PROP_PIXEL_HEIGHT "pixel-height"
-#define MS2_PROP_THUMBNAIL    "thumbnail"
-
-/* Audio items properties */
-#define MS2_PROP_GENRE "genre"
+#define MS2_PROP_COLOR_DEPTH     "color-depth"
+#define MS2_PROP_PIXEL_WIDTH     "pixel-width"
+#define MS2_PROP_PIXEL_HEIGHT    "pixel-height"
+#define MS2_PROP_THUMBNAIL       "thumbnail"
 
 /* Type items */
 #define MS2_TYPE_CONTAINER "container"
@@ -76,7 +70,7 @@
 #define MS2_UNKNOWN_STR ""
 
 /* Root category */
-#define MS2_ROOT "0"
+#define MS2_ROOT ""
 
 typedef enum {
   MS2_ERROR_GENERAL = 1
diff --git a/lib/media-server2-server.c b/lib/media-server2-server.c
index 9490ff4..a607182 100644
--- a/lib/media-server2-server.c
+++ b/lib/media-server2-server.c
@@ -25,6 +25,7 @@
 #include <dbus/dbus-glib-lowlevel.h>
 #include <dbus/dbus.h>
 #include <string.h>
+#include <stdlib.h>
 
 #include "media-server2-private.h"
 #include "media-server2-server.h"
@@ -58,6 +59,24 @@ 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 *mediaobject2_properties[] = { MS2_PROP_DISPLAY_NAME,
+                                                  MS2_PROP_PARENT,
+                                                  MS2_PROP_ID,
+                                                  NULL };
+
+static const gchar *mediaitem2_properties[] = { MS2_PROP_ALBUM,
+                                                MS2_PROP_ARTIST,
+                                                MS2_PROP_BITRATE,
+                                                MS2_PROP_DURATION,
+                                                MS2_PROP_GENRE,
+                                                MS2_PROP_HEIGHT,
+                                                MS2_PROP_MIME_TYPE,
+                                                MS2_PROP_TYPE,
+                                                MS2_PROP_URLS,
+                                                MS2_PROP_WIDTH,
+                                                NULL };
 
 static guint32 signals[LAST_SIGNAL] = { 0 };
 
@@ -249,6 +268,167 @@ get_introspection ()
   return introspection;
 }
 
+static gboolean
+is_property_valid (const gchar *interface,
+                   const gchar *property)
+{
+  const gchar *prop_intern;
+  gboolean found;
+  int i;
+  static gchar **mo2_properties_intern = NULL;
+  static gchar **mi2_properties_intern = NULL;
+
+  /* Initialize MediaObject2 properties interns */
+  if (!mo2_properties_intern) {
+    mo2_properties_intern = g_new (gchar *,
+                                   g_strv_length ((gchar **) mediaobject2_properties) + 1);
+    for (i = 0; mediaobject2_properties[i]; i++) {
+      mo2_properties_intern[i] =
+        (gchar *) g_intern_static_string (mediaobject2_properties[i]);
+    }
+    mo2_properties_intern[i] = NULL;
+  }
+
+  /* Initialize MediaItem2 properties interns */
+  if (!mi2_properties_intern) {
+    mi2_properties_intern = g_new (gchar *,
+                                   g_strv_length ((gchar **) mediaitem2_properties) + 1);
+    for (i = 0; mediaitem2_properties[i]; i++) {
+      mi2_properties_intern[i] =
+        (gchar *) g_intern_static_string (mediaitem2_properties[i]);
+    }
+    mi2_properties_intern[i] = NULL;
+  }
+
+  prop_intern = g_intern_string (property);
+
+  /* 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++;
+    }
+
+    if (found) {
+      return TRUE;
+    }
+
+    /* If not found, but interface is NULL, maybe property is in next interface */
+    if (!found && interface) {
+      return FALSE;
+    }
+  }
+
+  /* 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 FALSE;
+}
+
+static GValue *
+get_property_value (MS2Server *server,
+                    const gchar *id,
+                    const gchar *interface,
+                    const gchar *property)
+{
+  GHashTable *propresult;
+  GValue *propvalue;
+  GValue *v;
+  const gchar *prop[2] = { NULL };
+
+  /* Check everything is right */
+  if (!id ||
+      !property ||
+      !is_property_valid (interface, property) ||
+      !server->priv->get_properties) {
+    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 */
+    v = g_new0 (GValue, 1);
+    g_value_init (v, G_VALUE_TYPE (propvalue));
+    g_value_copy (propvalue, v);
+  }
+
+  g_hash_table_unref (propresult);
+
+  return v;
+}
+
+static gchar *
+get_id (DBusMessage *m)
+{
+  gchar **path;
+  gchar *id;
+  gint path_length;
+
+  dbus_message_get_path_decomposed (m, &path);
+
+  /* Path can of type:
+     /org/gnome/UPnP/MediaServer2/<name>
+     /org/gnome/UPnP/MediaServer2/<name>/items/<id>
+     /org/gnome/UPnP/MediaServer2/<name>/containers/<id>
+  */
+  path_length = g_strv_length (path);
+
+  if (path_length == 5) {
+    id = g_strdup (MS2_ROOT);
+  } else if (path_length == 7) {
+    id =  g_strdup (g_quark_to_string (atoi (path[6])));
+  } else {
+    id = NULL;
+  }
+
+  dbus_free_string_array (path);
+
+  return id;
+}
+
+static void
+append_variant_arg (DBusMessage *m, const GValue *v)
+{
+  DBusMessageIter iter;
+  DBusMessageIter sub;
+  const gchar *str_value;
+  gint int_value;
+
+  dbus_message_iter_init_append (m, &iter);
+  if (G_VALUE_HOLDS_STRING (v)) {
+    str_value = g_value_get_string (v);
+    dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT, "s", &sub);
+    dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING, &str_value);
+    dbus_message_iter_close_container (&iter, &sub);
+  } else if (G_VALUE_HOLDS_INT (v)) {
+    int_value = g_value_get_int (v);
+    dbus_message_iter_open_container (&iter, DBUS_TYPE_VARIANT, "i", &sub);
+    dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &int_value);
+    dbus_message_iter_close_container (&iter, &sub);
+  }
+}
+
 static DBusHandlerResult
 handle_introspect_message (DBusConnection *c,
                            DBusMessage *m,
@@ -271,6 +451,44 @@ handle_introspect_message (DBusConnection *c,
 }
 
 static DBusHandlerResult
+handle_get_message (DBusConnection *c,
+                    DBusMessage *m,
+                    void *userdata)
+{
+  GValue *value;
+  DBusMessage *r;
+  gchar *interface = NULL;
+  gchar *property = NULL;
+  gchar *id;
+  MS2Server *server = MS2_SERVER (userdata);
+
+  /* Check signature */
+  if (dbus_message_has_signature (m, get_sgn)) {
+    dbus_message_get_args (m, NULL,
+                           DBUS_TYPE_STRING, &interface,
+                           DBUS_TYPE_STRING, &property,
+                           DBUS_TYPE_INVALID);
+    id = get_id (m);
+    value = get_property_value (server, id, interface, property);
+    g_free (id);
+    if (!value) {
+      g_printerr ("Invalid property %s in interface %s\n",
+                  property,
+                  interface);
+    } else {
+      r = dbus_message_new_method_return (m);
+      append_variant_arg (r, value);
+      dbus_connection_send (c, r, NULL);
+      dbus_message_unref (r);
+      free_value (value);
+    }
+    return DBUS_HANDLER_RESULT_HANDLED;
+  } else {
+    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+  }
+}
+
+static DBusHandlerResult
 root_handler (DBusConnection *c,
               DBusMessage *m,
               void *userdata)
@@ -279,8 +497,14 @@ root_handler (DBusConnection *c,
 
   iface = dbus_message_get_interface (m);
 
-  if (dbus_message_is_method_call (m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
+  if (dbus_message_is_method_call (m,
+                                   "org.freedesktop.DBus.Introspectable",
+                                   "Introspect")) {
     return handle_introspect_message (c, m, userdata);
+  } 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;
   }



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