[rygel-grilo] Use MediaServer2 class
- From: Juan A. Suarez Romero <jasuarez src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [rygel-grilo] Use MediaServer2 class
- Date: Thu, 8 Apr 2010 18:25:08 +0000 (UTC)
commit e8459b97dae4d7499da5fe17f2817101ec8c919d
Author: Juan A. Suarez Romero <jasuarez igalia com>
Date: Thu Apr 8 19:58:00 2010 +0200
Use MediaServer2 class
Use the new MediaServer2 class to re-implement rygel-grilo.
src/Makefile.am | 16 +-
src/rygel-grilo-media-server-glue.h | 170 --------
src/rygel-grilo-media-server.c | 749 -----------------------------------
src/rygel-grilo-media-server.h | 100 -----
src/rygel-grilo.c | 512 +++++++++++++++++++-----
5 files changed, 422 insertions(+), 1125 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 0f5192a..d9afcd1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -16,18 +16,18 @@ rygel-grilo-%-glue.h: $(top_srcdir)/data/%2.xml
bin_PROGRAMS = rygel-grilo
-rygel_grilo_SOURCES = \
- rygel-grilo.c \
- rygel-grilo-media-server-glue.h \
- rygel-grilo-media-server.h \
- rygel-grilo-media-server.c
+rygel_grilo_SOURCES = \
+ rygel-grilo.c
-rygel_grilo_CFLAGS = \
- -DPREFIX=$(prefix)
+
+rygel_grilo_CFLAGS = \
+ -DPREFIX=$(prefix) \
+ -I$(top_srcdir)/lib
rygel_grilo_LDADD = \
-ldl -lpthread \
- @DEPS_LIBS@
+ @DEPS_LIBS@ \
+ $(top_builddir)/lib/libmediaserver2.la
MAINTAINERCLEANFILES = \
*.in
diff --git a/src/rygel-grilo.c b/src/rygel-grilo.c
index d2095a3..0ef9549 100644
--- a/src/rygel-grilo.c
+++ b/src/rygel-grilo.c
@@ -20,18 +20,21 @@
*
*/
-#include <stdio.h>
-#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-bindings.h>
+#include <dbus/dbus-glib.h>
+#include <grilo.h>
+#include <stdio.h>
-#include "rygel-grilo-media-server.h"
+#include "media-server2.h"
-#define ENTRY_POINT_SERVICE "org.gnome.UPnP.MediaServer2"
-#define ENTRY_POINT_PATH "/org/gnome/UPnP/MediaServer2"
+#define ID_PREFIX_AUDIO "gra://"
+#define ID_PREFIX_CONTAINER "grc://"
+#define ID_PREFIX_IMAGE "gri://"
+#define ID_PREFIX_VIDEO "grv://"
+#define ID_ROOT "0"
+#define ID_SEPARATOR "/"
static gchar **args;
-static DBusGProxy *gproxy = NULL;
-static GHashTable *registered_sources = NULL;
static GOptionEntry entries[] = {
{ G_OPTION_REMAINING, '\0', 0,
@@ -41,42 +44,15 @@ static GOptionEntry entries[] = {
{ NULL }
};
-/* Request and register a name in dbus */
-static void
-dbus_register_name (const gchar *name)
-{
- GError *error = NULL;
- guint request_name_result;
-
- if (!org_freedesktop_DBus_request_name (gproxy,
- name,
- DBUS_NAME_FLAG_DO_NOT_QUEUE,
- &request_name_result,
- &error)) {
- g_warning ("Unable to register \"%s\" name in dbus: %s",
- name,
- error->message);
- g_error_free (error);
- }
-}
-
-/* Release a name in dbus */
-static void
-dbus_unregister_name (const gchar *name)
-{
- GError *error = NULL;
- guint request_name_result;
-
- if(!org_freedesktop_DBus_release_name (gproxy,
- name,
- &request_name_result,
- &error)) {
- g_debug ("Unable to unregister \"%s\" name in dbus: %s",
- name,
- error->message);
- g_error_free (error);
- }
-}
+typedef struct {
+ GError *error;
+ GHashTable *properties;
+ GList *children;
+ GList *keys;
+ GrlMediaSource *source;
+ gboolean updated;
+ gchar *parent_id;
+} RygelGriloData;
/* Fix invalid characters so string can be used in a dbus name */
static void
@@ -97,14 +73,400 @@ sanitize (gchar *string)
}
}
+/* Returns the rygel-grilo parent id of the child */
+static gchar *
+get_parent_id (const gchar *child_id)
+{
+ gchar *parent_end;
+ gchar *parent_id;
+ gsize bytes_to_copy;
+
+ if (g_strcmp0 (child_id, ID_ROOT) == 0) {
+ return NULL;
+ }
+
+ parent_end = g_strrstr (child_id, ID_SEPARATOR);
+ bytes_to_copy = parent_end - child_id;
+
+ /* Check if parent is a root */
+ if (bytes_to_copy < 6) {
+ return g_strdup (ID_ROOT);
+ }
+
+ /* Save parent id */
+ parent_id = g_strndup (child_id, bytes_to_copy);
+
+ /* Parent should be always a container */
+ parent_id[2] = 'c';
+
+ return parent_id;
+}
+
+static gchar *
+get_grl_id (const gchar *ms_id)
+{
+ gchar **offspring;
+ gchar *grl_id;
+
+ if (g_strcmp0 (ms_id, ID_ROOT) == 0) {
+ return NULL;
+ }
+
+ /* Skip gr?:// prefix */
+ ms_id += 6;
+
+ offspring = g_strsplit (ms_id, ID_SEPARATOR, -1);
+
+ /* Last token is the searched id; first tokens are the family */
+ grl_id = g_uri_unescape_string (offspring[g_strv_length (offspring) - 1],
+ NULL);
+
+ g_strfreev (offspring);
+
+ return grl_id;
+}
+
+static gchar *
+serialize_media (const gchar *parent_id,
+ GrlMedia *media)
+{
+ gchar *escaped_id;
+ gchar *ms_id;
+
+ escaped_id = g_uri_escape_string (grl_media_get_id (media), NULL, TRUE);
+
+ if (g_strcmp0 (parent_id, ID_ROOT) == 0) {
+ ms_id = g_strconcat (ID_PREFIX_CONTAINER, escaped_id, NULL);
+ } else {
+ ms_id = g_strconcat (parent_id, ID_SEPARATOR, escaped_id, NULL);
+ }
+
+ g_free (escaped_id);
+
+ /* Parent id should be of grc:// type; adjust the prefix to the new content */
+ if (GRL_IS_MEDIA_AUDIO (media)) {
+ ms_id[2] = 'a';
+ } else if (GRL_IS_MEDIA_VIDEO (media)) {
+ ms_id[2] = 'v';
+ } else if (GRL_IS_MEDIA_IMAGE (media)) {
+ ms_id[2] = 'i';
+ }
+
+ return ms_id;
+}
+
+static GrlMedia *
+unserialize_media (GrlMetadataSource *source, const gchar *id)
+{
+ GrlMedia *media = NULL;
+ gchar *grl_id;
+
+ if (g_strcmp0 (id, ID_ROOT) == 0 ||
+ g_str_has_prefix (id, ID_PREFIX_CONTAINER)) {
+ media = grl_media_box_new ();
+ } else if (g_str_has_prefix (id, ID_PREFIX_AUDIO)) {
+ media = grl_media_audio_new ();
+ } else if (g_str_has_prefix (id, ID_PREFIX_VIDEO)) {
+ media = grl_media_video_new ();
+ } else if (g_str_has_prefix (id, ID_PREFIX_IMAGE)) {
+ media = grl_media_image_new ();
+ }
+
+ grl_media_set_source (media, grl_metadata_source_get_id (source));
+ grl_id = get_grl_id (id);
+ if (grl_id) {
+ grl_media_set_id (media, grl_id);
+ g_free (grl_id);
+ }
+
+ return media;
+}
+
+/* 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)
+{
+ GList *grl_keys = NULL;
+ gint i;
+
+ for (i = 0; ms_keys[i]; i++) {
+ 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) {
+ grl_keys = g_list_append (grl_keys,
+ GRLKEYID_TO_POINTER (GRL_METADATA_KEY_ALBUM));
+ } else if (g_strcmp0 (ms_keys[i], MS2_PROP_ARTIST) == 0) {
+ grl_keys = g_list_append (grl_keys,
+ GRLKEYID_TO_POINTER (GRL_METADATA_KEY_ARTIST));
+ } else if (g_strcmp0 (ms_keys[i], MS2_PROP_GENRE) == 0) {
+ grl_keys = g_list_append (grl_keys,
+ GRLKEYID_TO_POINTER (GRL_METADATA_KEY_GENRE));
+ } else if (g_strcmp0 (ms_keys[i], MS2_PROP_MIME_TYPE) == 0) {
+ grl_keys = g_list_append (grl_keys,
+ GRLKEYID_TO_POINTER (GRL_METADATA_KEY_MIME));
+ } else if (g_strcmp0 (ms_keys[i], MS2_PROP_CHILD_COUNT) == 0) {
+ grl_keys = g_list_append (grl_keys,
+ GRLKEYID_TO_POINTER (GRL_METADATA_KEY_CHILDCOUNT));
+ } else if (g_strcmp0 (ms_keys[i], MS2_PROP_URLS) == 0) {
+ grl_keys = g_list_append (grl_keys,
+ GRLKEYID_TO_POINTER (GRL_METADATA_KEY_URL));
+ } else if (g_strcmp0 (ms_keys[i], MS2_PROP_BITRATE) == 0) {
+ grl_keys = g_list_append (grl_keys,
+ GRLKEYID_TO_POINTER (GRL_METADATA_KEY_BITRATE));
+ } else if (g_strcmp0 (ms_keys[i], MS2_PROP_DURATION) == 0) {
+ grl_keys = g_list_append (grl_keys,
+ GRLKEYID_TO_POINTER (GRL_METADATA_KEY_DURATION));
+ } else if (g_strcmp0 (ms_keys[i], MS2_PROP_HEIGHT) == 0) {
+ grl_keys = g_list_append (grl_keys,
+ GRLKEYID_TO_POINTER (GRL_METADATA_KEY_HEIGHT));
+ } 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));
+ }
+ }
+
+ return grl_keys;
+}
+
+static void
+fill_properties_table (GHashTable *properties_table,
+ GList *keys,
+ GrlMedia *media,
+ const gchar *parent_id)
+{
+ GList *prop;
+ GrlKeyID key;
+ 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)) {
+ switch (key) {
+ case GRL_METADATA_KEY_TITLE:
+ media_server2_set_display_name (properties_table,
+ grl_media_get_title (media));
+ break;
+ case GRL_METADATA_KEY_ALBUM:
+ media_server2_set_album (properties_table,
+ grl_data_get_string (GRL_DATA (media),
+ GRL_METADATA_KEY_ALBUM));
+ break;
+ case GRL_METADATA_KEY_ARTIST:
+ media_server2_set_artist (properties_table,
+ grl_data_get_string (GRL_DATA (media),
+ GRL_METADATA_KEY_ARTIST));
+ break;
+ case GRL_METADATA_KEY_GENRE:
+ media_server2_set_genre (properties_table,
+ grl_data_get_string (GRL_DATA (media),
+ GRL_METADATA_KEY_GENRE));
+ break;
+ case GRL_METADATA_KEY_MIME:
+ media_server2_set_mime_type (properties_table,
+ grl_media_get_mime (media));
+ break;
+ case GRL_METADATA_KEY_CHILDCOUNT:
+ media_server2_set_child_count (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);
+ media_server2_set_urls (properties_table, urls);
+ break;
+ case GRL_METADATA_KEY_BITRATE:
+ media_server2_set_bitrate (properties_table,
+ grl_data_get_int (GRL_DATA (media),
+ GRL_METADATA_KEY_BITRATE));
+ break;
+ case GRL_METADATA_KEY_DURATION:
+ media_server2_set_duration (properties_table,
+ grl_media_get_duration (media));
+ break;
+ case GRL_METADATA_KEY_HEIGHT:
+ media_server2_set_height (properties_table,
+ grl_data_get_int (GRL_DATA (media),
+ GRL_METADATA_KEY_HEIGHT));
+ break;
+ case GRL_METADATA_KEY_WIDTH:
+ media_server2_set_width (properties_table,
+ grl_data_get_int (GRL_DATA (media),
+ GRL_METADATA_KEY_WIDTH));
+ break;
+ }
+ }
+ }
+
+ if (parent_id) {
+ media_server2_set_parent (properties_table, parent_id);
+ }
+}
+
+static void
+metadata_cb (GrlMediaSource *source,
+ GrlMedia *media,
+ gpointer user_data,
+ const GError *error)
+{
+ RygelGriloData *rgdata = (RygelGriloData *) user_data;
+
+ if (error) {
+ rgdata->error = g_error_copy (error);
+ rgdata->updated = TRUE;
+ return;
+ }
+
+ fill_properties_table (rgdata->properties, rgdata->keys, media, rgdata->parent_id);
+
+ rgdata->updated = TRUE;
+}
+
+static void
+browse_cb (GrlMediaSource *source,
+ guint browse_id,
+ GrlMedia *media,
+ guint remaining,
+ gpointer user_data,
+ const GError *error)
+{
+ GHashTable *prop_table;
+ RygelGriloData *rgdata = (RygelGriloData *) user_data;
+ gchar *id;
+
+ if (error) {
+ rgdata->error = g_error_copy (error);
+ rgdata->updated = TRUE;
+ return;
+ }
+
+ if (media) {
+ id = serialize_media (rgdata->parent_id, media);
+ if (id) {
+ prop_table = media_server2_new_properties_hashtable (id);
+ fill_properties_table (prop_table, rgdata->keys, media, rgdata->parent_id);
+ rgdata->children = g_list_prepend (rgdata->children, prop_table);
+ g_free (id);
+ }
+ }
+
+ if (!remaining) {
+ rgdata->children = g_list_reverse (rgdata->children);
+ rgdata->updated = TRUE;
+ }
+}
+
+static void
+wait_for_result (RygelGriloData *rgdata)
+{
+ GMainLoop *mainloop;
+ GMainContext *mainloop_context;
+
+ mainloop = g_main_loop_new (NULL, TRUE);
+ mainloop_context = g_main_loop_get_context (mainloop);
+ while (!rgdata->updated) {
+ g_main_context_iteration (mainloop_context, TRUE);
+ }
+}
+
+static GHashTable *
+get_properties_cb (const gchar *id,
+ const gchar **properties,
+ gpointer data,
+ GError **error)
+{
+ GHashTable *properties_table;
+ GrlMedia *media;
+ RygelGriloData *rgdata;
+
+ rgdata = g_slice_new0 (RygelGriloData);
+ rgdata->source = (GrlMediaSource *) data;
+ rgdata->properties = media_server2_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);
+
+ grl_media_source_metadata (rgdata->source,
+ media,
+ rgdata->keys,
+ GRL_RESOLVE_FULL | GRL_RESOLVE_IDLE_RELAY,
+ metadata_cb,
+ rgdata);
+
+ wait_for_result (rgdata);
+
+ if (rgdata->error) {
+ if (error) {
+ *error = rgdata->error;
+ }
+ g_hash_table_unref (rgdata->properties);
+ } else {
+ properties_table = rgdata->properties;
+ }
+
+ g_object_unref (media);
+ g_list_free (rgdata->keys);
+ g_free (rgdata->parent_id);
+ g_slice_free (RygelGriloData, rgdata);
+
+ return properties_table;
+}
+
+static GList *
+get_children_cb (const gchar *id,
+ guint offset,
+ gint max_count,
+ const gchar **properties,
+ gpointer data,
+ GError **error)
+{
+ GList *children;
+ GrlMedia *media;
+ RygelGriloData *rgdata;
+
+ rgdata = g_slice_new0 (RygelGriloData);
+ rgdata->source = (GrlMediaSource *) data;
+ rgdata->keys = get_grilo_keys (properties);
+ rgdata->parent_id = g_strdup (id);
+ media = unserialize_media (GRL_METADATA_SOURCE (rgdata->source), id);
+
+ grl_media_source_browse (rgdata->source,
+ media,
+ rgdata->keys,
+ offset,
+ max_count < 0? G_MAXINT: max_count,
+ GRL_RESOLVE_FULL | GRL_RESOLVE_IDLE_RELAY,
+ browse_cb,
+ rgdata);
+
+ wait_for_result (rgdata);
+
+ if (rgdata->error) {
+ if (error) {
+ *error = rgdata->error;
+ }
+ g_list_foreach (rgdata->children, (GFunc) g_hash_table_unref, NULL);
+ g_list_free (rgdata->children);
+ children = NULL;
+ } else {
+ children = rgdata->children;
+ }
+
+ g_object_unref (media);
+ g_list_free (rgdata->keys);
+ g_free (rgdata->parent_id);
+ g_slice_free (RygelGriloData, rgdata);
+
+ return children;
+}
+
/* Callback invoked whenever a new source comes up */
static void
source_added_cb (GrlPluginRegistry *registry, gpointer user_data)
{
GrlSupportedOps supported_ops;
- RygelGriloMediaServer *server;
- gchar *dbus_path;
- gchar *dbus_service;
+ MediaServer2 *server;
gchar *source_id;
/* Only sources that implement browse and metadata are of interest */
@@ -120,52 +482,26 @@ source_added_cb (GrlPluginRegistry *registry, gpointer user_data)
g_debug ("Registering %s source", source_id);
sanitize (source_id);
- dbus_service = g_strconcat (ENTRY_POINT_SERVICE ".", source_id, NULL);
- dbus_path = g_strconcat (ENTRY_POINT_PATH "/", source_id, NULL);
- g_free (source_id);
- dbus_register_name (dbus_service);
- g_free (dbus_service);
- server = rygel_grilo_media_server_new (dbus_path,
- GRL_MEDIA_SOURCE (user_data));
+ server = media_server2_new (source_id, GRL_MEDIA_SOURCE (user_data));
+
if (!server) {
g_warning ("Cannot register %s", source_id);
} else {
- g_hash_table_insert (registered_sources, dbus_path, server);
+ media_server2_set_get_properties_func (server, get_properties_cb);
+ media_server2_set_get_children_func (server, get_children_cb);
}
+ g_free (source_id);
} else {
g_debug ("%s source does not support either browse or metadata",
grl_metadata_source_get_id (GRL_METADATA_SOURCE (user_data)));
}
}
-/* Callback invoked whenever a new source goes away */
-static void
-source_removed_cb (GrlPluginRegistry *registry, gpointer user_data)
-{
- gchar *dbus_name;
- gchar *dbus_path;
- gchar *source_id;
-
- source_id =
- g_strdup (grl_metadata_source_get_id (GRL_METADATA_SOURCE (user_data)));
- sanitize (source_id);
-
- dbus_name = g_strconcat (ENTRY_POINT_SERVICE ".", source_id, NULL);
- dbus_unregister_name (dbus_name);
- g_free (dbus_name);
-
- /* Remove source */
- dbus_path = g_strconcat (ENTRY_POINT_PATH "/", source_id, NULL);
- g_hash_table_remove (registered_sources, dbus_path);
- g_free (dbus_path);
-}
-
/* Main program */
gint
main (gint argc, gchar **argv)
{
- DBusGConnection *connection;
GError *error = NULL;
GOptionContext *context = NULL;
GrlPluginRegistry *registry;
@@ -184,32 +520,11 @@ main (gint argc, gchar **argv)
return -1;
}
- /* Get DBus */
- connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
- if (!connection) {
- g_printerr ("Could not connect to session bus, %s\n", error->message);
- g_clear_error (&error);
- return -1;
- }
-
- gproxy = dbus_g_proxy_new_for_name (connection,
- DBUS_SERVICE_DBUS,
- DBUS_PATH_DBUS,
- DBUS_INTERFACE_DBUS);
-
- /* Initialize registered sources table */
- registered_sources = g_hash_table_new_full (g_str_hash,
- g_str_equal,
- g_free,
- g_object_unref);
-
/* Load grilo plugins */
registry = grl_plugin_registry_get_instance ();
g_signal_connect (registry, "source-added",
G_CALLBACK (source_added_cb), NULL);
- g_signal_connect (registry, "source-removed",
- G_CALLBACK (source_removed_cb), NULL);
if (!args || !args[0]) {
grl_plugin_registry_load_all (registry);
@@ -218,5 +533,6 @@ main (gint argc, gchar **argv)
grl_plugin_registry_load (registry, args[i]);
}
}
+
g_main_loop_run (g_main_loop_new (NULL, FALSE));
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]