[rygel] First implementation of External plugin



commit 15cdac0c7d9fd0667100c7eedd1a98bd40c6298b
Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
Date:   Thu May 7 00:40:42 2009 +0300

    First implementation of External plugin
    
    This is the implementation of external MediaServer spec Lennart wrote:
    http://live.gnome.org/Rygel/MediaServerSpec. It builds but it's totally
    untested and also currently specific to the PulseAudio implementation.
---
 configure.ac                                       |    7 +
 src/plugins/Makefile.am                            |   11 ++-
 src/plugins/external/rygel-external-container.vala |  164 ++++++++++++++++++++
 .../external/rygel-external-content-dir.vala       |   47 ++++++
 src/plugins/external/rygel-external-item.vala      |   79 ++++++++++
 src/plugins/external/rygel-external-plugin.vala    |   43 +++++
 6 files changed, 350 insertions(+), 1 deletions(-)

diff --git a/configure.ac b/configure.ac
index 270dcc4..2daf888 100644
--- a/configure.ac
+++ b/configure.ac
@@ -171,6 +171,11 @@ AC_ARG_ENABLE(folder-plugin,
 	[  --enable-folder-plugin          build Folder plugin],,
         enable_folder_plugin=yes)
 
+# Build External plugin
+AC_ARG_ENABLE(external-plugin,
+	[  --enable-external-plugin          build External plugin],,
+        enable_external_plugin=yes)
+
 # Build Mediathek plugin
 AC_ARG_ENABLE(mediathek-plugin,
 	[  --enable-mediathek-plugin          build Mediathek plugin],,
@@ -186,6 +191,7 @@ AM_CONDITIONAL([BUILD_TRACKER_PLUGIN],
 AM_CONDITIONAL([BUILD_DVB_PLUGIN], [test "x$enable_dvb_plugin" = "xyes"])
 AM_CONDITIONAL([BUILD_MEDIATHEK_PLUGIN], [test "x$enable_mediathek_plugin" = "xyes"])
 AM_CONDITIONAL([BUILD_FOLDER_PLUGIN], [test "x$enable_folder_plugin" = "xyes"])
+AM_CONDITIONAL([BUILD_EXTERNAL_PLUGIN], [test "x$enable_external_plugin" = "xyes"])
 
 # Gettext
 GETTEXT_PACKAGE=rygel
@@ -205,6 +211,7 @@ src/ui/Makefile
 src/plugins/Makefile
 src/plugins/dvb/Makefile
 src/plugins/folder/Makefile
+src/plugins/external/Makefile
 src/plugins/mediathek/Makefile
 src/plugins/tracker/Makefile
 src/plugins/test/Makefile
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index 3a5515a..91b3c81 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -18,6 +18,15 @@ if BUILD_FOLDER_PLUGIN
 FOLDER_PLUGIN = folder
 endif
 
-SUBDIRS = $(TEST_PLUGIN) $(TRACKER_PLUGIN) $(DVB_PLUGIN) $(MEDIATHEK_PLUGIN) $(FOLDER_PLUGIN)
+if BUILD_EXTERNAL_PLUGIN
+EXTERNAL_PLUGIN = external
+endif
+
+SUBDIRS = $(TEST_PLUGIN) \
+	  $(TRACKER_PLUGIN) \
+	  $(DVB_PLUGIN) \
+	  $(MEDIATHEK_PLUGIN) \
+	  $(FOLDER_PLUGIN) \
+	  $(EXTERNAL_PLUGIN)
 
 MAINTAINERCLEANFILES = Makefile.in
diff --git a/src/plugins/external/rygel-external-container.vala b/src/plugins/external/rygel-external-container.vala
new file mode 100644
index 0000000..97340fc
--- /dev/null
+++ b/src/plugins/external/rygel-external-container.vala
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2009 Zeeshan Ali (Khattak) <zeeshanak gnome org>.
+ * Copyright (C) 2009 Nokia Corporation, all rights reserved.
+ *
+ * Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
+ *                               <zeeshan ali nokia com>
+ *
+ * This file is part of Rygel.
+ *
+ * Rygel is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Rygel is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+using Rygel;
+using GUPnP;
+using DBus;
+using Gee;
+
+/**
+ * Represents and external container.
+ */
+public class Rygel.ExternalContainer : MediaContainer {
+    // class-wide constants
+    private static string PROPS_IFACE = "org.freedesktop.DBus.Properties";
+    private const string OBJECT_IFACE = "org.Rygel.MediaObject1";
+    private const string CONTAINER_IFACE = "org.Rygel.MediaContainer1";
+    private const string ITEM_IFACE = "org.Rygel.MediaItem1";
+
+    public dynamic DBus.Object actual_container;
+
+    private string service_path;
+    private string object_path;
+
+    private ArrayList<MediaObject> media_objects;
+
+    public ExternalContainer (string             id,
+                              string             service_path,
+                              string             object_path,
+                              ExternalContainer? parent) {
+        base (id, parent, "Uknown", 0);
+
+        this.service_path = service_path;
+        this.object_path = object_path;
+
+        this.media_objects = new ArrayList<MediaObject> ();
+
+        try {
+            DBus.Connection connection = DBus.Bus.get (DBus.BusType.SESSION);
+
+            // Create proxy to MediaObject iface to get the display name through
+            dynamic DBus.Object props = connection.get_object (service_path,
+                                                               object_path,
+                                                               PROPS_IFACE);
+            Value value;
+            props.Get (OBJECT_IFACE, "display-name", out value);
+            this.title = value.get_string ();
+
+            // Now proxy to MediaContainer iface for the rest of the stuff
+            this.actual_container = connection.get_object (service_path,
+                                                           object_path,
+                                                           CONTAINER_IFACE);
+
+            this.fetch_media_objects (connection);
+        } catch (DBus.Error error) {
+            critical ("Failed to fetch root media objects: %s\n",
+                      error.message);
+        }
+    }
+
+    public override void get_children (uint               offset,
+                                       uint               max_count,
+                                       Cancellable?       cancellable,
+                                       AsyncReadyCallback callback) {
+        uint stop = offset + max_count;
+
+        stop = stop.clamp (0, this.child_count);
+        var containers = this.media_objects.slice ((int) offset, (int) stop);
+
+        var res = new Rygel.SimpleAsyncResult<Gee.List<MediaObject>>
+                                                (this, callback);
+        res.data = containers;
+        res.complete_in_idle ();
+    }
+
+    public override Gee.List<MediaObject>? get_children_finish (
+                                                         AsyncResult res)
+                                                         throws GLib.Error {
+        var simple_res = (Rygel.SimpleAsyncResult<Gee.List<MediaObject>>) res;
+        return simple_res.data;
+    }
+
+    public override void find_object (string             id,
+                                      Cancellable?       cancellable,
+                                      AsyncReadyCallback callback) {
+        MediaObject media_object = find_object_sync (id);
+
+        var res = new Rygel.SimpleAsyncResult<MediaObject> (this, callback);
+
+        res.data = media_object;
+        res.complete_in_idle ();
+    }
+
+    public override MediaObject? find_object_finish (AsyncResult res)
+                                                     throws GLib.Error {
+        var simple_res = (Rygel.SimpleAsyncResult<MediaObject>) res;
+        return simple_res.data;
+    }
+
+    // Private methods
+    private MediaObject? find_object_sync (string id) {
+        MediaObject obj = null;
+
+        foreach (var tmp in this.media_objects) {
+            if (id == tmp.id) {
+                obj = tmp;
+            } else if (tmp is ExternalContainer) {
+                // Check it's children
+                var container = (ExternalContainer) tmp;
+
+                obj = container.find_object_sync (id);
+            }
+
+            if (obj != null) {
+                break;
+            }
+        }
+
+        return obj;
+    }
+
+    private void fetch_media_objects (DBus.Connection connection)
+                                      throws GLib.Error {
+        string[] object_paths = null;
+
+        object_paths = this.actual_container.GetContainers ();
+        foreach (var object_path in object_paths) {
+            this.media_objects.add (new ExternalContainer (object_path,
+                                                           this.service_path,
+                                                           object_path,
+                                                           this));
+        }
+
+        object_paths = this.actual_container.GetItems ();
+        foreach (var object_path in object_paths) {
+            this.media_objects.add (new ExternalItem (this.service_path,
+                                                      object_path,
+                                                      this));
+        }
+
+        this.child_count = this.media_objects.size;
+    }
+}
+
diff --git a/src/plugins/external/rygel-external-content-dir.vala b/src/plugins/external/rygel-external-content-dir.vala
new file mode 100644
index 0000000..73d4fef
--- /dev/null
+++ b/src/plugins/external/rygel-external-content-dir.vala
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2009 Zeeshan Ali (Khattak) <zeeshanak gnome org>.
+ * Copyright (C) 2009 Nokia Corporation, all rights reserved.
+ *
+ * Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
+ *                               <zeeshan ali nokia com>
+ *
+ * This file is part of Rygel.
+ *
+ * Rygel is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Rygel is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+using Rygel;
+using GUPnP;
+using DBus;
+using Gee;
+
+/**
+ * Implementation of External ContentDirectory service.
+ */
+public class Rygel.ExternalContentDir : ContentDirectory {
+    private const string EXTERNAL_SERVICE = "org.Rygel.MediaServer1.PulseAudio";
+    private const string EXTERNAL_PATH = "/org/Rygel/MediaServer1/PulseAudio";
+
+    // Pubic methods
+    public override MediaContainer? create_root_container () {
+        //string friendly_name = this.root_device.get_friendly_name ();
+
+        return new ExternalContainer ("0",
+                                      EXTERNAL_SERVICE,
+                                      EXTERNAL_PATH,
+                                      null);
+    }
+}
+
diff --git a/src/plugins/external/rygel-external-item.vala b/src/plugins/external/rygel-external-item.vala
new file mode 100644
index 0000000..b478928
--- /dev/null
+++ b/src/plugins/external/rygel-external-item.vala
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2009 Zeeshan Ali (Khattak) <zeeshanak gnome org>.
+ * Copyright (C) 2009 Nokia Corporation, all rights reserved.
+ *
+ * Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
+ *                               <zeeshan ali nokia com>
+ *
+ * This file is part of Rygel.
+ *
+ * Rygel is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Rygel is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+using Rygel;
+using GUPnP;
+using DBus;
+
+/**
+ * Represents External item.
+ */
+public class Rygel.ExternalItem : MediaItem {
+    private static string PROPS_IFACE = "org.freedesktop.DBus.Properties";
+    private static string OBJECT_IFACE = "org.Rygel.MediaObject1";
+    private static string ITEM_IFACE = "org.Rygel.MediaItem1";
+
+    public ExternalItem (string         service_path,
+                         string         object_path,
+                         MediaContainer parent)
+                         throws GLib.Error {
+        base (object_path,
+              parent,
+              "Unknown",        /* Title Unknown at this point */
+              "Unknown");       /* UPnP Class Unknown at this point */
+
+        DBus.Connection connection = DBus.Bus.get (DBus.BusType.SESSION);
+
+        dynamic DBus.Object props = connection.get_object (service_path,
+                                                           object_path,
+                                                           PROPS_IFACE);
+
+        Value value;
+        props.Get (OBJECT_IFACE, "display-name", out value);
+        this.title = value.get_string ();
+
+        props.Get (ITEM_IFACE, "type", out value);
+        string type = value.get_string ();
+        if (type == "audio") {
+            this.upnp_class = MediaItem.AUDIO_CLASS;
+        } else if (type == "music") {
+            this.upnp_class = MediaItem.MUSIC_CLASS;
+        } else if (type == "video") {
+            this.upnp_class = MediaItem.VIDEO_CLASS;
+        } else {
+            this.upnp_class = MediaItem.IMAGE_CLASS;
+        }
+
+        props.Get (ITEM_IFACE, "mime-type", out value);
+        this.mime_type = value.get_string ();
+
+        props.Get (ITEM_IFACE, "urls", out value);
+        string[] uris = (string[]) value.get_boxed ();
+
+        foreach (var uri in uris) {
+            this.uris.add (uri);
+        }
+    }
+}
+
diff --git a/src/plugins/external/rygel-external-plugin.vala b/src/plugins/external/rygel-external-plugin.vala
new file mode 100644
index 0000000..10850f9
--- /dev/null
+++ b/src/plugins/external/rygel-external-plugin.vala
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2009 Zeeshan Ali (Khattak) <zeeshanak gnome org>.
+ * Copyright (C) 2009 Nokia Corporation, all rights reserved.
+ *
+ * Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
+ *                               <zeeshan ali nokia com>
+ *
+ * This file is part of Rygel.
+ *
+ * Rygel is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Rygel is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+using Rygel;
+using Gee;
+using CStuff;
+
+[ModuleInit]
+public void load_plugin (PluginLoader loader) {
+    Plugin plugin = new Plugin ("PulseAudio");
+
+    // We only implement a ContentDirectory service
+    var resource_info = new ResourceInfo (ContentDirectory.UPNP_ID,
+                                          ContentDirectory.UPNP_TYPE,
+                                          ContentDirectory.DESCRIPTION_PATH,
+                                          typeof (ExternalContentDir));
+
+    plugin.add_resource (resource_info);
+
+    loader.add_plugin (plugin);
+}
+



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