rygel r293 - in trunk: data/xml src/media-providers/tracker src/media-server



Author: zeeshanak
Date: Tue Nov 25 14:43:12 2008
New Revision: 293
URL: http://svn.gnome.org/viewvc/rygel?rev=293&view=rev

Log:
Complete Redesign: More power to the plugins.

List of changes:
* Plugins now loaded into separate Media Servers.
* Plugins can now implement any kind of resources (only services atm).
* Service classes are now exposed to plugins so they can inherit from them.
* MediaTracker now inherits from ContentDirectory rather than ContentProvider.
* ContentProvider is removed.

Added:
   trunk/src/media-server/rygel-main.vala
   trunk/src/media-server/rygel-media-server-factory.vala
      - copied, changed from r292, /trunk/src/media-server/rygel-media-server.vala
   trunk/src/media-server/rygel-plugin-loader.vala
   trunk/src/media-server/rygel-plugin.vala
   trunk/src/media-server/rygel-resource-info.vala
      - copied, changed from r292, /trunk/src/media-providers/tracker/rygel-tracker-plugin.vala
Removed:
   trunk/src/media-server/rygel-media-manager.vala
   trunk/src/media-server/rygel-media-provider.vala
Modified:
   trunk/data/xml/description-xbox360.xml
   trunk/data/xml/description.xml
   trunk/src/media-providers/tracker/rygel-media-tracker.vala
   trunk/src/media-providers/tracker/rygel-tracker-container.vala
   trunk/src/media-providers/tracker/rygel-tracker-plugin.vala
   trunk/src/media-server/Makefile.am
   trunk/src/media-server/rygel-connection-manager.vala
   trunk/src/media-server/rygel-content-directory.vala
   trunk/src/media-server/rygel-media-receiver-registrar.vala
   trunk/src/media-server/rygel-media-server.vala

Modified: trunk/data/xml/description-xbox360.xml
==============================================================================
--- trunk/data/xml/description-xbox360.xml	(original)
+++ trunk/data/xml/description-xbox360.xml	Tue Nov 25 14:43:12 2008
@@ -16,30 +16,6 @@
 <UPC></UPC>
 <presentationURL></presentationURL>
 <serviceList>
-<service>
-<serviceType>urn:schemas-upnp-org:service:ContentDirectory:1</serviceType>
-<serviceId>urn:upnp-org:serviceId:ContentDirectory</serviceId>
-<SCPDURL>xml/ContentDirectory.xml</SCPDURL>
-<eventSubURL>/ContentDirectory/Event</eventSubURL>
-<controlURL>/ContentDirectory/Control</controlURL>
-</service>
-<!-- FIXME: Implement the service, uncomment these lines and enable the
-            distribution of the SCPD in the build.
-<service>
-<serviceType>urn:schemas-upnp-org:service:ConnectionManager:1</serviceType>
-<serviceId>urn:upnp-org:serviceId:ConnectionManager</serviceId>
-<SCPDURL>xml/ConnectionManager.xml</SCPDURL>
-<eventSubURL>/ConnectionManager/Event</eventSubURL>
-<controlURL>/ConnectionManager/Control</controlURL>
-</service>
--->
-<service>
-<serviceType>urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1</serviceType>
-<serviceId>urn:microsoft.com:serviceId:X_MS_MediaReceiverRegistrar</serviceId>
-<SCPDURL>xml/X_MS_MediaReceiverRegistrar1.xml</SCPDURL>
-<eventSubURL>/X_MS_MediaReceiverRegistrar/Event</eventSubURL>
-<controlURL>/X_MS_MediaReceiverRegistrar/Control</controlURL>
-</service>
 </serviceList>
 <dlna:X_DLNADOC>DMS-1.50</dlna:X_DLNADOC>
 <dlna:X_DLNADOC>M-DMS-1.50</dlna:X_DLNADOC>

Modified: trunk/data/xml/description.xml
==============================================================================
--- trunk/data/xml/description.xml	(original)
+++ trunk/data/xml/description.xml	Tue Nov 25 14:43:12 2008
@@ -16,27 +16,6 @@
 <UPC></UPC>
 <presentationURL></presentationURL>
 <serviceList>
-<service>
-<serviceType>urn:schemas-upnp-org:service:ContentDirectory:2</serviceType>
-<serviceId>urn:upnp-org:serviceId:ContentDirectory</serviceId>
-<SCPDURL>xml/ContentDirectory.xml</SCPDURL>
-<eventSubURL>/ContentDirectory/Event</eventSubURL>
-<controlURL>/ContentDirectory/Control</controlURL>
-</service>
-<service>
-<serviceType>urn:schemas-upnp-org:service:ConnectionManager:2</serviceType>
-<serviceId>urn:upnp-org:serviceId:ConnectionManager</serviceId>
-<SCPDURL>xml/ConnectionManager.xml</SCPDURL>
-<eventSubURL>/ConnectionManager/Event</eventSubURL>
-<controlURL>/ConnectionManager/Control</controlURL>
-</service>
-<service>
-<serviceType>urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1</serviceType>
-<serviceId>urn:microsoft.com:serviceId:X_MS_MediaReceiverRegistrar</serviceId>
-<SCPDURL>xml/X_MS_MediaReceiverRegistrar1.xml</SCPDURL>
-<eventSubURL>/X_MS_MediaReceiverRegistrar/Event</eventSubURL>
-<controlURL>/X_MS_MediaReceiverRegistrar/Control</controlURL>
-</service>
 </serviceList>
 <dlna:X_DLNADOC>DMS-1.50</dlna:X_DLNADOC>
 <dlna:X_DLNADOC>M-DMS-1.50</dlna:X_DLNADOC>

Modified: trunk/src/media-providers/tracker/rygel-media-tracker.vala
==============================================================================
--- trunk/src/media-providers/tracker/rygel-media-tracker.vala	(original)
+++ trunk/src/media-providers/tracker/rygel-media-tracker.vala	Tue Nov 25 14:43:12 2008
@@ -23,10 +23,11 @@
  * version 2 of the License, or (at your option) any later version.
  */
 
+using Rygel;
 using GUPnP;
 using DBus;
 
-public class Rygel.MediaTracker : MediaProvider {
+public class Rygel.MediaTracker : ContentDirectory {
     public static const int MAX_REQUESTED_COUNT = 128;
 
     private MediaContainer root_container;
@@ -37,50 +38,44 @@
     private SearchCriteriaParser search_parser;
 
     /* Pubic methods */
-    public MediaTracker (string        root_id,
-                         string        root_parent_id,
-                         GUPnP.Context context) {
+    public override void constructed () {
+        // Chain-up to base first
+        base.constructed ();
+
+        this.root_container = new MediaContainer ("0",
+                                                  "-1",
+                                                  "MediaTracker",
+                                                  this.containers.length ());
+
         this.containers = new List<TrackerContainer> ();
         this.containers.append
-                        (new TrackerContainer (this.root_id + ":" + "16",
-                                               this.root_id,
-                                               this.root_id,
+                        (new TrackerContainer ("16",
+                                               this.root_container.id,
                                                "All Images",
                                                "Images",
                                                MediaItem.IMAGE_CLASS,
                                                context));
         this.containers.append
-                        (new TrackerContainer (this.root_id + ":" + "14",
-                                               this.root_id,
-                                               this.root_id,
+                        (new TrackerContainer ("14",
+                                               this.root_container.id,
                                                "All Music",
                                                "Music",
                                                MediaItem.MUSIC_CLASS,
                                                context));
         this.containers.append
-                        (new TrackerContainer (this.root_id + ":" + "15",
-                                               this.root_id,
-                                               this.root_id,
+                        (new TrackerContainer ("15",
+                                               this.root_container.id,
                                                "All Videos",
                                                "Videos",
                                                MediaItem.VIDEO_CLASS,
                                                context));
 
-        this.root_container = new MediaContainer (this.root_id,
-                                                  this.root_parent_id,
-                                                  this.title,
-                                                  this.containers.length ());
-
         this.search_parser = new SearchCriteriaParser ();
 
         weak string home_dir = Environment.get_home_dir ();
 
         /* Host the home dir of the user */
         this.context.host_path (home_dir, home_dir);
-        this.root_id = root_id;
-        this.root_parent_id = root_parent_id;
-        this.title = "Tracker";
-        this.context = context;
     }
 
     public override void add_children_metadata
@@ -93,7 +88,7 @@
                              out uint       number_returned,
                              out uint       total_matches,
                              out uint       update_id) throws GLib.Error {
-        if (container_id == this.root_id) {
+        if (container_id == this.root_container.id) {
             number_returned = this.add_root_container_children (didl_writer);
             total_matches = number_returned;
         } else {
@@ -117,7 +112,7 @@
         if (number_returned > 0) {
             update_id = uint32.MAX;
         } else {
-            throw new MediaProviderError.NO_SUCH_OBJECT ("No such object");
+            throw new ContentDirectoryError.NO_SUCH_OBJECT ("No such object");
         }
     }
 
@@ -129,7 +124,7 @@
                              out uint       update_id) throws GLib.Error {
         bool found = false;
 
-        if (object_id == this.root_id) {
+        if (object_id == this.root_container.id) {
             this.root_container.serialize (didl_writer);
 
             found = true;
@@ -144,18 +139,16 @@
 
                 found = true;
             } else {
-                string id = this.remove_root_id_prefix (object_id);
-
                 /* Now try items */
-                container = get_item_parent (id);
+                container = get_item_parent (object_id);
 
                 if (container != null)
-                    found = container.add_item_from_db (didl_writer, id);
+                    found = container.add_item_from_db (didl_writer, object_id);
             }
         }
 
         if (!found) {
-            throw new MediaProviderError.NO_SUCH_OBJECT ("No such object");
+            throw new ContentDirectoryError.NO_SUCH_OBJECT ("No such object");
         }
 
         update_id = uint32.MAX;
@@ -208,16 +201,5 @@
 
         return container;
     }
-
-    string remove_root_id_prefix (string id) {
-        string[] tokens;
-
-        tokens = id.split (":", 2);
-
-        if (tokens[1] != null)
-            return tokens[1];
-        else
-            return tokens[0];
-    }
 }
 

Modified: trunk/src/media-providers/tracker/rygel-tracker-container.vala
==============================================================================
--- trunk/src/media-providers/tracker/rygel-tracker-container.vala	(original)
+++ trunk/src/media-providers/tracker/rygel-tracker-container.vala	Tue Nov 25 14:43:12 2008
@@ -45,9 +45,6 @@
     /* UPnP class of items under this container */
     public string child_class;
 
-    // FIXME: We should not need this
-    private string root_id;
-
     // Class constructor
     static construct {
         DBus.Connection connection;
@@ -74,14 +71,12 @@
 
     public TrackerContainer (string  id,
                              string  parent_id,
-                             string  root_id,
                              string  title,
                              string  category,
                              string  child_class,
                              Context context) {
         this.id = id;
         this.parent_id = parent_id;
-        this.root_id = root_id;
         this.title = title;
         this.category = category;
         this.child_class = child_class;
@@ -161,15 +156,15 @@
         MediaItem item;
 
         if (this.child_class == MediaItem.VIDEO_CLASS) {
-            item = new TrackerVideoItem (this.root_id + ":" + path,
+            item = new TrackerVideoItem (path,
                                          path,
                                          this);
         } else if (this.child_class == MediaItem.IMAGE_CLASS) {
-            item = new TrackerImageItem (this.root_id + ":" + path,
+            item = new TrackerImageItem (path,
                                          path,
                                          this);
         } else {
-            item = new TrackerMusicItem (this.root_id + ":" + path,
+            item = new TrackerMusicItem (path,
                                          path,
                                          this);
         }
@@ -179,14 +174,6 @@
         return true;
     }
 
-    private string uri_from_path (string path) {
-        string escaped_path = Uri.escape_string (path, "/", true);
-
-        return "http://%s:%u%s".printf (this.context.host_ip,
-                                        this.context.port,
-                                        escaped_path);
-    }
-
     public static string get_file_category (string uri) throws GLib.Error {
         string category;
 

Modified: trunk/src/media-providers/tracker/rygel-tracker-plugin.vala
==============================================================================
--- trunk/src/media-providers/tracker/rygel-tracker-plugin.vala	(original)
+++ trunk/src/media-providers/tracker/rygel-tracker-plugin.vala	Tue Nov 25 14:43:12 2008
@@ -23,13 +23,19 @@
  */
 
 using Rygel;
+using Gee;
 
 [ModuleInit]
-public MediaProvider register_media_provider (string        root_id,
-                                              string        root_parent_id,
-                                              GUPnP.Context context) {
-    return new MediaTracker (root_id,
-                             root_parent_id,
-                             context);
+public Plugin load_plugin () {
+    Plugin plugin = new Plugin ("Tracker");
+
+    // We only implement a ContentDirectory service
+    var resource_info = new ResourceInfo (ContentDirectory.UPNP_ID,
+                                          ContentDirectory.UPNP_CLASS,
+                                          ContentDirectory.DESCRIPTION_PATH,
+                                          typeof (MediaTracker));
+    plugin.add_resource (resource_info);
+
+    return plugin;
 }
 

Modified: trunk/src/media-server/Makefile.am
==============================================================================
--- trunk/src/media-server/Makefile.am	(original)
+++ trunk/src/media-server/Makefile.am	Tue Nov 25 14:43:12 2008
@@ -24,22 +24,28 @@
 		rygel.stamp \
 		rygel-media-server.h \
 		rygel-media-server.c \
+		rygel-media-server-factory.h \
+		rygel-media-server-factory.c \
+		rygel-main.h \
+		rygel-main.c \
 		rygel-content-directory.h \
 		rygel-content-directory.c \
+		rygel-plugin.h \
+		rygel-plugin.c \
+		rygel-plugin-loader.h \
+		rygel-plugin-loader.c \
+		rygel-resource-info.h \
+		rygel-resource-info.c \
 		rygel-connection-manager.h \
 		rygel-connection-manager.c \
 		rygel-media-receiver-registrar.h \
 		rygel-media-receiver-registrar.c \
-		rygel-media-provider.h \
-		rygel-media-provider.c \
 		rygel-media-object.c \
 		rygel-media-object.h \
 		rygel-media-container.c \
 		rygel-media-container.h \
 		rygel-media-item.c \
-		rygel-media-item.h \
-		rygel-media-manager.h \
-		rygel-media-manager.c
+		rygel-media-item.h
 
 rygel_SOURCES = rygel-1.0.vapi \
 		cstuff.c \
@@ -47,26 +53,31 @@
 		rygel-media-server.h \
 		rygel-media-server.c \
 		rygel-media-server.vala \
+		rygel-media-server-factory.h \
+		rygel-media-server-factory.c \
+		rygel-media-server-factory.vala \
+		rygel-main.h \
+		rygel-main.c \
+		rygel-main.vala \
 		rygel-content-directory.h \
 		rygel-content-directory.c \
-		rygel-content-directory.vala \
+		rygel-plugin.h \
+		rygel-plugin.c \
+		rygel-plugin-loader.h \
+		rygel-plugin-loader.c \
+		rygel-plugin-loader.vala \
+		rygel-resource-info.h \
+		rygel-resource-info.c \
 		rygel-connection-manager.h \
 		rygel-connection-manager.c \
-		rygel-connection-manager.vala \
 		rygel-media-receiver-registrar.h \
 		rygel-media-receiver-registrar.c \
-		rygel-media-receiver-registrar.vala \
-		rygel-media-provider.h \
-		rygel-media-provider.c \
 		rygel-media-object.c \
 		rygel-media-object.h \
 		rygel-media-container.c \
 		rygel-media-container.h \
 		rygel-media-item.c \
 		rygel-media-item.h \
-		rygel-media-manager.h \
-		rygel-media-manager.c \
-		rygel-media-manager.vala \
 		rygel-metadata-extractor.c \
 		rygel-metadata-extractor.h \
 		rygel-metadata-extractor.vala
@@ -86,7 +97,11 @@
 
 VAPI_FILES = rygel-1.0.vapi
 
-rygel-1.0.vapi: rygel-media-provider.vala \
+rygel-1.0.vapi: rygel-content-directory.vala \
+		rygel-connection-manager.vala \
+		rygel-media-receiver-registrar.vala \
+		rygel-resource-info.vala \
+		rygel-plugin.vala \
 		rygel-media-object.vala \
 		rygel-media-container.vala \
 		rygel-media-item.vala

Modified: trunk/src/media-server/rygel-connection-manager.vala
==============================================================================
--- trunk/src/media-server/rygel-connection-manager.vala	(original)
+++ trunk/src/media-server/rygel-connection-manager.vala	Tue Nov 25 14:43:12 2008
@@ -28,8 +28,10 @@
 using GUPnP;
 
 public class Rygel.ConnectionManager : Service {
+    public const string UPNP_ID = "urn:upnp-org:serviceId:ConnectionManager";
     public const string UPNP_CLASS =
-                        "urn:schemas-upnp-org:service:ConnectionManager";
+                    "urn:schemas-upnp-org:service:ConnectionManager:2";
+    public const string DESCRIPTION_PATH = "xml/ConnectionManager.xml";
 
     private string source_protocol_info;
     private string sink_protocol_info;

Modified: trunk/src/media-server/rygel-content-directory.vala
==============================================================================
--- trunk/src/media-server/rygel-content-directory.vala	(original)
+++ trunk/src/media-server/rygel-content-directory.vala	Tue Nov 25 14:43:12 2008
@@ -26,20 +26,49 @@
 
 using GUPnP;
 
+public errordomain Rygel.ContentDirectoryError {
+    NO_SUCH_OBJECT = 701
+}
+
 public class Rygel.ContentDirectory: Service {
+    public const string UPNP_ID = "urn:upnp-org:serviceId:ContentDirectory";
     public const string UPNP_CLASS =
-            "urn:schemas-upnp-org:service:ContentDirectory";
+                    "urn:schemas-upnp-org:service:ContentDirectory:2";
+    public const string DESCRIPTION_PATH = "xml/ContentDirectory.xml";
+
+    protected uint32 system_update_id;
+
     string feature_list;
 
     DIDLLiteWriter didl_writer;
 
-    MediaManager media_manager;
+    // Public abstract methods derived classes need to implement
+    public virtual void add_children_metadata
+                            (DIDLLiteWriter didl_writer,
+                             string         container_id,
+                             string         filter,
+                             uint           starting_index,
+                             uint           requested_count,
+                             string         sort_criteria,
+                             out uint       number_returned,
+                             out uint       total_matches,
+                             out uint       update_id) throws Error {
+        throw new ServerError.NOT_IMPLEMENTED ("Not Implemented\n");
+    }
+
+    public virtual void add_metadata (DIDLLiteWriter didl_writer,
+                                       string         object_id,
+                                       string         filter,
+                                       string         sort_criteria,
+                                       out uint       update_id) throws Error {
+        throw new ServerError.NOT_IMPLEMENTED ("Not Implemented\n");
+    }
 
     public override void constructed () {
-        this.media_manager = new MediaManager (this.context);
-
         this.didl_writer = new DIDLLiteWriter ();
 
+        this.system_update_id = 0;
+
         this.feature_list =
             "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
             "<Features xmlns=\"urn:schemas-upnp-org:av:avs\" " +
@@ -116,24 +145,24 @@
 
         try {
             if (browse_metadata) {
-                this.media_manager.add_metadata (this.didl_writer,
-                                                 object_id,
-                                                 filter,
-                                                 sort_criteria,
-                                                 out update_id);
+                this.add_metadata (this.didl_writer,
+                                   object_id,
+                                   filter,
+                                   sort_criteria,
+                                   out update_id);
 
                 num_returned = 1;
                 total_matches = 1;
             } else {
-                this.media_manager.add_children_metadata (this.didl_writer,
-                                                          object_id,
-                                                          filter,
-                                                          starting_index,
-                                                          requested_count,
-                                                          sort_criteria,
-                                                          out num_returned,
-                                                          out total_matches,
-                                                          out update_id);
+                this.add_children_metadata (this.didl_writer,
+                                            object_id,
+                                            filter,
+                                            starting_index,
+                                            requested_count,
+                                            sort_criteria,
+                                            out num_returned,
+                                            out total_matches,
+                                            out update_id);
             }
 
             /* End DIDL-Lite fragment */
@@ -142,6 +171,10 @@
             /* Retrieve generated string */
             string didl = this.didl_writer.get_string ();
 
+            if (update_id == uint32.MAX) {
+                update_id = this.system_update_id;
+            }
+
             /* Set action return arguments */
             action.set ("Result", typeof (string), didl,
                         "NumberReturned", typeof (uint), num_returned,
@@ -161,7 +194,7 @@
     private void get_system_update_id_cb (ContentDirectory content_dir,
                                           ServiceAction    action) {
         /* Set action return arguments */
-        action.set ("Id", typeof (uint32), this.media_manager.system_update_id);
+        action.set ("Id", typeof (uint32), this.system_update_id);
 
         action.return ();
     }
@@ -172,7 +205,7 @@
                                          ref GLib.Value value) {
         /* Set action return arguments */
         value.init (typeof (uint32));
-        value.set_uint (this.media_manager.system_update_id);
+        value.set_uint (this.system_update_id);
     }
 
     /* action GetSearchCapabilities implementation */

Added: trunk/src/media-server/rygel-main.vala
==============================================================================
--- (empty file)
+++ trunk/src/media-server/rygel-main.vala	Tue Nov 25 14:43:12 2008
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation, all rights reserved.
+ * Copyright (C) 2008 Zeeshan Ali (Khattak) <zeeshanak gnome org>.
+ *
+ * Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ */
+
+using GUPnP;
+using GConf;
+using CStuff;
+
+public class Rygel.Main : Object {
+    private PluginLoader plugin_loader;
+    private MediaServerFactory ms_factory;
+    private List<MediaServer> media_servers;
+
+    public Main () {
+        this.media_servers = new List<MediaServer> ();
+        this.plugin_loader = new PluginLoader ();
+        this.ms_factory = new MediaServerFactory ();
+
+        this.plugin_loader.plugin_available += this.on_plugin_loaded;
+    }
+
+    public void run () {
+        this.plugin_loader.load_plugins ();
+
+        var main_loop = new GLib.MainLoop (null, false);
+        main_loop.run ();
+    }
+
+    private void on_plugin_loaded (PluginLoader plugin_loader,
+                                   Plugin       plugin) {
+        var server = this.ms_factory.create_media_server (plugin);
+
+        /* Make our device available */
+        server.available = true;
+
+        media_servers.append (server);
+    }
+
+    public static int main (string[] args) {
+        Main main;
+
+        main = new Main ();
+        main.run ();
+
+        return 0;
+    }
+}
+

Modified: trunk/src/media-server/rygel-media-receiver-registrar.vala
==============================================================================
--- trunk/src/media-server/rygel-media-receiver-registrar.vala	(original)
+++ trunk/src/media-server/rygel-media-receiver-registrar.vala	Tue Nov 25 14:43:12 2008
@@ -25,8 +25,12 @@
 using GUPnP;
 
 public class Rygel.MediaReceiverRegistrar: Service {
+    public const string UPNP_ID =
+                    "urn:microsoft.com:serviceId:X_MS_MediaReceiverRegistrar";
     public const string UPNP_CLASS =
-                        "urn:microsoft.com:service:X_MS_MediaReceiverRegistrar";
+                    "urn:microsoft.com:service:X_MS_MediaReceiverRegistrar:1";
+    public const string DESCRIPTION_PATH =
+                    "xml/X_MS_MediaReceiverRegistrar1.xml";
 
     public override void constructed () {
         this.action_invoked["IsAuthorized"] += this.is_authorized_cb;

Copied: trunk/src/media-server/rygel-media-server-factory.vala (from r292, /trunk/src/media-server/rygel-media-server.vala)
==============================================================================
--- /trunk/src/media-server/rygel-media-server.vala	(original)
+++ trunk/src/media-server/rygel-media-server-factory.vala	Tue Nov 25 14:43:12 2008
@@ -1,9 +1,9 @@
 /*
- * Copyright (C) 2008 Zeeshan Ali <zeenix gmail com>.
- * Copyright (C) 2007 OpenedHand Ltd.
+ * Copyright (C) 2008 Nokia Corporation, all rights reserved.
+ * Copyright (C) 2008 Zeeshan Ali (Khattak) <zeeshanak gnome org>.
  *
- * Author: Zeeshan Ali <zeenix gmail com>
- *         Jorn Baayen <jorn openedhand com>
+ * Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
+ *                               <zeeshan ali nokia com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -28,72 +28,29 @@
 using GConf;
 using CStuff;
 
-public class Rygel.MediaServer: RootDevice {
+public class Rygel.MediaServerFactory {
     public static const string DESC_DOC = "xml/description.xml";
     public static const string XBOX_DESC_DOC = "xml/description-xbox360.xml";
-    public static const string MODIFIED_DESC_DOC = "gupnp-media-server.xml";
+    public static const string DESC_PREFIX = "Rygel";
     public static const string GCONF_PATH = "/apps/gupnp-media-server/";
 
-    private List<ServiceInfo> services;   /* Services we implement */
+    private GConf.Client gconf;
+    private GUPnP.Context context;
 
-    public MediaServer (GUPnP.Context context,
-                        Xml.Doc       description_doc,
-                        string        relative_location) {
-        this.context = context;
-        this.resource_factory = GUPnP.ResourceFactory.get_default ();
-        this.root_device = null;
-        this.description_doc = description_doc;
-        this.relative_location = relative_location;
-
-        ResourceFactory factory = this.resource_factory;
-
-        /* Register Rygel.ContentDirectory */
-        factory.register_resource_type (ContentDirectory.UPNP_CLASS + ":1",
-                                        typeof (ContentDirectory));
-        factory.register_resource_type (ContentDirectory.UPNP_CLASS + ":2",
-                                        typeof (ContentDirectory));
-
-        /* Register Rygel.ConnectionManager */
-        factory.register_resource_type (ConnectionManager.UPNP_CLASS + ":1",
-                                        typeof (ConnectionManager));
-        factory.register_resource_type (ConnectionManager.UPNP_CLASS + ":2",
-                                        typeof (ConnectionManager));
-
-        /* Register Rygel.MediaReceiverRegistrar */
-        factory.register_resource_type
-                        (MediaReceiverRegistrar.UPNP_CLASS + ":1",
-                         typeof (MediaReceiverRegistrar));
-        factory.register_resource_type
-                        (MediaReceiverRegistrar.UPNP_CLASS + ":2",
-                         typeof (MediaReceiverRegistrar));
-
-        /* Now create the sevice objects */
-        services.append (this.get_service (ContentDirectory.UPNP_CLASS));
-        services.append (this.get_service (ConnectionManager.UPNP_CLASS));
-        services.append (this.get_service (MediaReceiverRegistrar.UPNP_CLASS));
-    }
-
-    public static int main (string[] args) {
-        MediaServer server;
-        MainLoop main_loop;
-
-        server = create_default ();
-        if (server == null) {
-            return -1;
-        }
-
-        main_loop = new GLib.MainLoop (null, false);
-        main_loop.run ();
+    public MediaServerFactory () {
+        this.gconf = GConf.Client.get_default ();
 
-        return 0;
+        /* Set up GUPnP context */
+        this.context = create_upnp_context ();
     }
 
-    private static MediaServer? create_default () {
-        GConf.Client gconf_client = GConf.Client.get_default ();
+    public MediaServer? create_media_server (Plugin plugin) {
+        string gconf_path = GCONF_PATH + plugin.name + "/";
+        string modified_desc = DESC_PREFIX + "-" + plugin.name + ".xml";
 
         bool enable_xbox;
         try {
-            enable_xbox = gconf_client.get_bool (GCONF_PATH + "enable-xbox");
+            enable_xbox = this.gconf.get_bool (gconf_path + "enable-xbox");
         } catch (GLib.Error error) {
             warning ("%s", error.message);
         }
@@ -101,7 +58,7 @@
         /* We store a modified description.xml in the user's config dir */
         string desc_path = Path.build_filename
                                     (Environment.get_user_config_dir (),
-                                     MODIFIED_DESC_DOC);
+                                     modified_desc);
 
         string orig_desc_path;
 
@@ -117,8 +74,8 @@
         if (doc == null)
             return null;
 
-        /* Modify description.xml to include a UDN and a friendy name */
-        set_friendly_name_and_udn (doc, gconf_client);
+        /* Modify description to include Plugin-specific stuff */
+        this.prepare_desc_for_plugin (doc, plugin, gconf_path);
 
         if (enable_xbox)
             /* Put/Set XboX specific stuff to description */
@@ -142,38 +99,21 @@
             return null;
         }
 
-        /* Set up GUPnP context */
-        GUPnP.Context context = create_default_context (gconf_client,
-                                                        desc_path);
-        if (context == null) {
-            delete doc;
-
-            return null;
-        }
-
-        /* Set up the root device */
-        MediaServer server = new MediaServer (context,
-                                              doc,
-                                              MODIFIED_DESC_DOC);
-
-        server.weak_ref ((WeakNotify) xml_doc_free, doc);
+        /* Host our modified file */
+        this.context.host_path (desc_path, "/" + modified_desc);
 
-        /* Make our device available */
-        server.available = true;
+        var server = new MediaServer (this.context,
+                                      plugin,
+                                      doc,
+                                      modified_desc);
 
         return server;
     }
 
-    private static void xml_doc_free (Xml.Doc* doc, MediaServer server) {
-        delete doc;
-    }
-
-    private static GUPnP.Context? create_default_context
-                                    (GConf.Client gconf_client,
-                                     string      desc_path) {
+    private GUPnP.Context? create_upnp_context () {
         string host_ip;
         try {
-            host_ip = gconf_client.get_string (GCONF_PATH + "host-ip");
+            host_ip = this.gconf.get_string (GCONF_PATH + "host-ip");
         } catch (GLib.Error error) {
             warning ("%s", error.message);
 
@@ -182,7 +122,7 @@
 
         int port;
         try {
-            port = gconf_client.get_int (GCONF_PATH + "port");
+            port = this.gconf.get_int (GCONF_PATH + "port");
         } catch (GLib.Error error) {
             warning ("%s", error.message);
 
@@ -201,22 +141,18 @@
         /* Host UPnP dir */
         context.host_path (BuildConfig.DATA_DIR, "");
 
-        /* Host our modified file */
-        context.host_path (desc_path, "/" + MODIFIED_DESC_DOC);
-
         return context;
     }
 
-    private static string? get_str_from_gconf (GConf.Client gconf_client,
-                                               string       key,
-                                               string       default_value) {
+    private string? get_str_from_gconf (string key,
+                                        string default_value) {
         string str;
 
         try {
-            str = gconf_client.get_string (key);
+            str = this.gconf.get_string (key);
         } catch (GLib.Error error) {
             try {
-                gconf_client.set_string (key, str);
+                this.gconf.set_string (key, str);
             } catch (GLib.Error error) {
                 warning ("Error setting gconf key '%s': %s.",
                         key,
@@ -232,7 +168,7 @@
                 return default_value;
     }
 
-    private static void add_xbox_specifics (Xml.Doc doc) {
+    private void add_xbox_specifics (Xml.Doc doc) {
         Xml.Node *element;
 
         element = Utils.get_xml_element ((Xml.Node *) doc,
@@ -249,27 +185,38 @@
         element->add_content (": 1 : Windows Media Connect");
     }
 
-    /* Fills the description doc @doc with a friendly name, and UDN from gconf.
-     * If these keys are not present in gconf, they are set with default values.
-     */
-    static void set_friendly_name_and_udn (Xml.Doc      doc,
-                                           GConf.Client gconf_client) {
+    private void prepare_desc_for_plugin (Xml.Doc doc,
+                                          Plugin  plugin,
+                                          string  gconf_path) {
         Xml.Node *device_element;
-        Xml.Node *element;
-        string str, default_value;
 
         device_element = Utils.get_xml_element ((Xml.Node *) doc,
-                                               "root",
-                                               "device",
-                                               null);
+                                                "root",
+                                                "device",
+                                                null);
         if (device_element == null) {
             warning ("Element /root/device not found.");
 
             return;
         }
 
+        /* First, set the Friendly name and UDN */
+        this.set_friendly_name_and_udn (device_element,
+                                        plugin.name,
+                                        gconf_path);
+
+        /* Then list each service */
+        this.add_services_to_desc (device_element, plugin);
+    }
+
+    /* Fills the description doc @doc with a friendly name, and UDN from gconf.
+     * If these keys are not present in gconf, they are set with default values.
+     */
+    private void set_friendly_name_and_udn (Xml.Node *device_element,
+                                            string    plugin_name,
+                                            string    gconf_path) {
         /* friendlyName */
-        element = Utils.get_xml_element (device_element,
+        Xml.Node *element = Utils.get_xml_element (device_element,
                                          "friendlyName",
                                          null);
         if (element == null) {
@@ -278,11 +225,8 @@
             return;
         }
 
-        string user_name = Environment.get_real_name();
-        default_value = "%s's MediaServer".printf (user_name);
-        str = get_str_from_gconf (gconf_client,
-                                  GCONF_PATH + "friendly-name",
-                                  default_value);
+        string str = get_str_from_gconf (gconf_path + "friendly-name",
+                                         plugin_name);
         if (str == null)
             return;
 
@@ -297,15 +241,54 @@
         }
 
         /* Generate new UUID */
-        default_value = Utils.generate_random_udn ();
+        string default_value = Utils.generate_random_udn ();
 
-        str = get_str_from_gconf (gconf_client,
-                                  GCONF_PATH + "UDN",
-                                  default_value);
+        str = get_str_from_gconf (gconf_path + "UDN", default_value);
         if (str == null)
             return;
 
         element->set_content (str);
     }
+
+    private void add_services_to_desc (Xml.Node *device_element,
+                                       Plugin    plugin) {
+        Xml.Node *service_list_node = Utils.get_xml_element (device_element,
+                                                             "serviceList",
+                                                             null);
+        if (service_list_node == null) {
+            warning ("Element /root/device/serviceList not found.");
+
+            return;
+        }
+
+        foreach (ResourceInfo resource_info in plugin.resource_infos) {
+            // FIXME: We only support plugable services for now
+            if (resource_info.type.is_a (typeof (Service))) {
+                    this.add_service_to_desc (service_list_node,
+                                              plugin.name,
+                                              resource_info);
+            }
+        }
+    }
+
+    private void add_service_to_desc (Xml.Node    *service_list_node,
+                                      string       plugin_name,
+                                      ResourceInfo resource_info) {
+        // Create the service node
+        Xml.Node *service_node = service_list_node->new_child (null, "service");
+
+        service_node->new_child (null, "serviceType", resource_info.upnp_type);
+        service_node->new_child (null, "serviceId", resource_info.upnp_id);
+
+        /* Now the relative (to base URL) URLs*/
+        string url = resource_info.description_path;
+        service_node->new_child (null, "SCPDURL", url);
+
+        url = plugin_name + "/" + resource_info.type.name () + "/Event";
+        service_node->new_child (null, "eventSubURL", url);
+
+        url = plugin_name + "/" + resource_info.type.name () + "/Control";
+        service_node->new_child (null, "controlURL", url);
+    }
 }
 

Modified: trunk/src/media-server/rygel-media-server.vala
==============================================================================
--- trunk/src/media-server/rygel-media-server.vala	(original)
+++ trunk/src/media-server/rygel-media-server.vala	Tue Nov 25 14:43:12 2008
@@ -1,9 +1,8 @@
 /*
- * Copyright (C) 2008 Zeeshan Ali <zeenix gmail com>.
- * Copyright (C) 2007 OpenedHand Ltd.
+ * Copyright (C) 2008 Nokia Corporation, all rights reserved.
+ * Copyright (C) 2008 Zeeshan Ali (Khattak) <zeeshanak gnome org>.
  *
- * Author: Zeeshan Ali <zeenix gmail com>
- *         Jorn Baayen <jorn openedhand com>
+ * Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -29,283 +28,33 @@
 using CStuff;
 
 public class Rygel.MediaServer: RootDevice {
-    public static const string DESC_DOC = "xml/description.xml";
-    public static const string XBOX_DESC_DOC = "xml/description-xbox360.xml";
-    public static const string MODIFIED_DESC_DOC = "gupnp-media-server.xml";
-    public static const string GCONF_PATH = "/apps/gupnp-media-server/";
-
     private List<ServiceInfo> services;   /* Services we implement */
 
     public MediaServer (GUPnP.Context context,
-                        Xml.Doc       description_doc,
+                        Plugin        plugin,
+                        Xml.Doc      *description_doc,
                         string        relative_location) {
-        this.context = context;
-        this.resource_factory = GUPnP.ResourceFactory.get_default ();
+        this.resource_factory = plugin;
         this.root_device = null;
+        this.context = context;
+
         this.description_doc = description_doc;
+        this.weak_ref ((WeakNotify) xml_doc_free, description_doc);
         this.relative_location = relative_location;
 
-        ResourceFactory factory = this.resource_factory;
-
-        /* Register Rygel.ContentDirectory */
-        factory.register_resource_type (ContentDirectory.UPNP_CLASS + ":1",
-                                        typeof (ContentDirectory));
-        factory.register_resource_type (ContentDirectory.UPNP_CLASS + ":2",
-                                        typeof (ContentDirectory));
-
-        /* Register Rygel.ConnectionManager */
-        factory.register_resource_type (ConnectionManager.UPNP_CLASS + ":1",
-                                        typeof (ConnectionManager));
-        factory.register_resource_type (ConnectionManager.UPNP_CLASS + ":2",
-                                        typeof (ConnectionManager));
-
-        /* Register Rygel.MediaReceiverRegistrar */
-        factory.register_resource_type
-                        (MediaReceiverRegistrar.UPNP_CLASS + ":1",
-                         typeof (MediaReceiverRegistrar));
-        factory.register_resource_type
-                        (MediaReceiverRegistrar.UPNP_CLASS + ":2",
-                         typeof (MediaReceiverRegistrar));
-
-        /* Now create the sevice objects */
-        services.append (this.get_service (ContentDirectory.UPNP_CLASS));
-        services.append (this.get_service (ConnectionManager.UPNP_CLASS));
-        services.append (this.get_service (MediaReceiverRegistrar.UPNP_CLASS));
-    }
-
-    public static int main (string[] args) {
-        MediaServer server;
-        MainLoop main_loop;
-
-        server = create_default ();
-        if (server == null) {
-            return -1;
-        }
-
-        main_loop = new GLib.MainLoop (null, false);
-        main_loop.run ();
-
-        return 0;
-    }
-
-    private static MediaServer? create_default () {
-        GConf.Client gconf_client = GConf.Client.get_default ();
-
-        bool enable_xbox;
-        try {
-            enable_xbox = gconf_client.get_bool (GCONF_PATH + "enable-xbox");
-        } catch (GLib.Error error) {
-            warning ("%s", error.message);
-        }
-
-        /* We store a modified description.xml in the user's config dir */
-        string desc_path = Path.build_filename
-                                    (Environment.get_user_config_dir (),
-                                     MODIFIED_DESC_DOC);
-
-        string orig_desc_path;
+        // Now create the sevice objects
+        foreach (ResourceInfo info in plugin.resource_infos) {
+            // FIXME: We only support plugable services for now
+            if (info.type.is_a (typeof (Service))) {
+                var service = this.get_service (info.upnp_type);
 
-        if (enable_xbox)
-            /* Use Xbox 360 specific description */
-            orig_desc_path = Path.build_filename (BuildConfig.DATA_DIR,
-                                                  XBOX_DESC_DOC);
-        else
-            orig_desc_path = Path.build_filename (BuildConfig.DATA_DIR,
-                                                  DESC_DOC);
-
-        Xml.Doc *doc = Xml.Parser.parse_file (orig_desc_path);
-        if (doc == null)
-            return null;
-
-        /* Modify description.xml to include a UDN and a friendy name */
-        set_friendly_name_and_udn (doc, gconf_client);
-
-        if (enable_xbox)
-            /* Put/Set XboX specific stuff to description */
-            add_xbox_specifics (doc);
-
-        /* Save the modified description.xml into the user's config dir.
-         * We do this so that we can host the modified file, and also to
-         * make sure the generated UDN stays the same between sessions. */
-        FileStream f = FileStream.open (desc_path, "w+");
-        int res = -1;
-
-        if (f != null)
-            res = Xml.Doc.dump (f, doc);
-
-        if (f == null || res == -1) {
-            critical ("Failed to write modified description.xml to %s.\n",
-                      desc_path);
-
-            delete doc;
-
-            return null;
-        }
-
-        /* Set up GUPnP context */
-        GUPnP.Context context = create_default_context (gconf_client,
-                                                        desc_path);
-        if (context == null) {
-            delete doc;
-
-            return null;
+                this.services.append (service);
+            }
         }
-
-        /* Set up the root device */
-        MediaServer server = new MediaServer (context,
-                                              doc,
-                                              MODIFIED_DESC_DOC);
-
-        server.weak_ref ((WeakNotify) xml_doc_free, doc);
-
-        /* Make our device available */
-        server.available = true;
-
-        return server;
     }
 
     private static void xml_doc_free (Xml.Doc* doc, MediaServer server) {
         delete doc;
     }
-
-    private static GUPnP.Context? create_default_context
-                                    (GConf.Client gconf_client,
-                                     string      desc_path) {
-        string host_ip;
-        try {
-            host_ip = gconf_client.get_string (GCONF_PATH + "host-ip");
-        } catch (GLib.Error error) {
-            warning ("%s", error.message);
-
-            host_ip = null;
-        }
-
-        int port;
-        try {
-            port = gconf_client.get_int (GCONF_PATH + "port");
-        } catch (GLib.Error error) {
-            warning ("%s", error.message);
-
-            port = 0;
-        }
-
-        GUPnP.Context context;
-        try {
-            context = new GUPnP.Context (null, host_ip, port);
-        } catch (GLib.Error error) {
-            warning ("Error setting up GUPnP context: %s", error.message);
-
-            return null;
-        }
-
-        /* Host UPnP dir */
-        context.host_path (BuildConfig.DATA_DIR, "");
-
-        /* Host our modified file */
-        context.host_path (desc_path, "/" + MODIFIED_DESC_DOC);
-
-        return context;
-    }
-
-    private static string? get_str_from_gconf (GConf.Client gconf_client,
-                                               string       key,
-                                               string       default_value) {
-        string str;
-
-        try {
-            str = gconf_client.get_string (key);
-        } catch (GLib.Error error) {
-            try {
-                gconf_client.set_string (key, str);
-            } catch (GLib.Error error) {
-                warning ("Error setting gconf key '%s': %s.",
-                        key,
-                        error.message);
-
-                str = null;
-            }
-        }
-
-        if (str != null)
-                return str;
-        else
-                return default_value;
-    }
-
-    private static void add_xbox_specifics (Xml.Doc doc) {
-        Xml.Node *element;
-
-        element = Utils.get_xml_element ((Xml.Node *) doc,
-                                         "root",
-                                         "device",
-                                         "friendlyName");
-        /* friendlyName */
-        if (element == null) {
-            warning ("Element /root/device/friendlyName not found.");
-
-            return;
-        }
-
-        element->add_content (": 1 : Windows Media Connect");
-    }
-
-    /* Fills the description doc @doc with a friendly name, and UDN from gconf.
-     * If these keys are not present in gconf, they are set with default values.
-     */
-    static void set_friendly_name_and_udn (Xml.Doc      doc,
-                                           GConf.Client gconf_client) {
-        Xml.Node *device_element;
-        Xml.Node *element;
-        string str, default_value;
-
-        device_element = Utils.get_xml_element ((Xml.Node *) doc,
-                                               "root",
-                                               "device",
-                                               null);
-        if (device_element == null) {
-            warning ("Element /root/device not found.");
-
-            return;
-        }
-
-        /* friendlyName */
-        element = Utils.get_xml_element (device_element,
-                                         "friendlyName",
-                                         null);
-        if (element == null) {
-            warning ("Element /root/device/friendlyName not found.");
-
-            return;
-        }
-
-        string user_name = Environment.get_real_name();
-        default_value = "%s's MediaServer".printf (user_name);
-        str = get_str_from_gconf (gconf_client,
-                                  GCONF_PATH + "friendly-name",
-                                  default_value);
-        if (str == null)
-            return;
-
-        element->set_content (str);
-
-        /* UDN */
-        element = Utils.get_xml_element (device_element, "UDN");
-        if (element == null) {
-            warning ("Element /root/device/UDN not found.");
-
-            return;
-        }
-
-        /* Generate new UUID */
-        default_value = Utils.generate_random_udn ();
-
-        str = get_str_from_gconf (gconf_client,
-                                  GCONF_PATH + "UDN",
-                                  default_value);
-        if (str == null)
-            return;
-
-        element->set_content (str);
-    }
 }
 

Added: trunk/src/media-server/rygel-plugin-loader.vala
==============================================================================
--- (empty file)
+++ trunk/src/media-server/rygel-plugin-loader.vala	Tue Nov 25 14:43:12 2008
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation, all rights reserved.
+ * Copyright (C) 2008 Zeeshan Ali (Khattak) <zeeshanak gnome org>.
+ *
+ * Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ */
+
+using CStuff;
+using GUPnP;
+
+public class Rygel.PluginLoader : Object {
+    /* We need to keep the modules somewhere */
+    private List<Module> modules;
+
+    private delegate Plugin LoadPluginFunc ();
+
+    // Signals
+    public signal void plugin_available (Plugin plugin);
+
+    /* Pubic methods */
+    public PluginLoader () {
+        this.modules = new List<Module> ();
+    }
+
+    // Plugin loading functions
+    public void load_plugins () {
+        assert (Module.supported());
+
+        File dir = File.new_for_path (BuildConfig.PLUGIN_DIR);
+        assert (dir != null && is_dir (dir));
+
+        this.load_plugins_from_dir (dir);
+    }
+
+    private void load_plugins_from_dir (File dir) {
+        FileEnumerator enumerator;
+
+        try {
+            string attributes = FILE_ATTRIBUTE_STANDARD_NAME + "," +
+                                FILE_ATTRIBUTE_STANDARD_TYPE + "," +
+                                FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE;
+            enumerator = dir.enumerate_children (attributes,
+                                                 FileQueryInfoFlags.NONE,
+                                                 null);
+        } catch (Error error) {
+            critical ("Error listing contents of directory '%s': %s\n",
+                      dir.get_path (),
+                      error.message);
+
+            return;
+        }
+
+        FileInfo info;
+
+        while ((info = enumerator.next_file (null)) != null) {
+            string file_name = info.get_name ();
+            string file_path = Path.build_filename (dir.get_path (),
+                                                        file_name);
+            File file = File.new_for_path (file_path);
+            FileType file_type = info.get_file_type ();
+            string content_type = info.get_content_type ();
+            weak string mime = g_content_type_get_mime_type (content_type);
+
+            if (file_type == FileType.DIRECTORY) {
+                // Recurse into directories
+                this.load_plugins_from_dir (file);
+            } else if (mime == "application/x-sharedlib") {
+                // Seems like we found a plugin
+                this.load_plugin_from_file (file_path);
+            }
+        }
+    }
+
+    private void load_plugin_from_file (string file_path) {
+        Plugin plugin;
+        Module module;
+
+        plugin = this.load_media_provider_from_file (file_path, out module);
+        if (plugin != null) {
+            this.plugin_available (plugin);
+            this.modules.append (#module);
+        }
+    }
+
+    private Plugin? load_media_provider_from_file (string     file_path,
+                                                   out Module module) {
+        module = Module.open (file_path, ModuleFlags.BIND_LOCAL);
+        if (module == null) {
+            debug ("Failed to load plugin from path: '%s'\n", file_path);
+
+            return null;
+        }
+
+        void* function;
+
+        module.symbol("load_plugin", out function);
+
+        LoadPluginFunc load_plugin = (LoadPluginFunc) function;
+
+        if (load_plugin == null) {
+            warning ("Failed to load plugin from path: '%s'\n", file_path);
+
+            return null;
+        }
+
+        debug ("Loaded plugin: '%s'\n", module.name());
+
+        return load_plugin ();
+    }
+
+    private static bool is_dir (File file) {
+        FileInfo file_info;
+
+        try {
+            file_info = file.query_info (FILE_ATTRIBUTE_STANDARD_TYPE,
+                                         FileQueryInfoFlags.NONE,
+                                         null);
+        } catch (Error error) {
+            critical ("Failed to query content type for '%s'\n",
+                      file.get_path ());
+
+            return false;
+        }
+
+        return file_info.get_file_type () == FileType.DIRECTORY;
+    }
+}
+

Added: trunk/src/media-server/rygel-plugin.vala
==============================================================================
--- (empty file)
+++ trunk/src/media-server/rygel-plugin.vala	Tue Nov 25 14:43:12 2008
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation, all rights reserved.
+ *
+ * Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
+ *                               <zeeshan ali nokia com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU 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.
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ */
+
+using Gee;
+using GUPnP;
+
+public class Rygel.Plugin : GUPnP.ResourceFactory {
+    public string name;
+
+    public ArrayList<ResourceInfo> resource_infos;
+
+    public Plugin (string name) {
+        this.name = name;
+
+        this.resource_infos = new ArrayList<ResourceInfo> ();
+
+        /* Register Rygel.ConnectionManager */
+        var resource_info = new ResourceInfo
+                                (ConnectionManager.UPNP_ID,
+                                 ConnectionManager.UPNP_CLASS,
+                                 ConnectionManager.DESCRIPTION_PATH,
+                                 typeof (ConnectionManager));
+        this.add_resource (resource_info);
+
+        /* Register Rygel.MediaReceiverRegistrar */
+        resource_info = new ResourceInfo
+                                (MediaReceiverRegistrar.UPNP_ID,
+                                 MediaReceiverRegistrar.UPNP_CLASS,
+                                 MediaReceiverRegistrar.DESCRIPTION_PATH,
+                                 typeof (MediaReceiverRegistrar));
+        this.add_resource (resource_info);
+    }
+
+    public void add_resource (ResourceInfo resource_info) {
+        this.resource_infos.add (resource_info);
+        this.register_resource_type (resource_info.upnp_type,
+                                     resource_info.type);
+    }
+}
+

Copied: trunk/src/media-server/rygel-resource-info.vala (from r292, /trunk/src/media-providers/tracker/rygel-tracker-plugin.vala)
==============================================================================
--- /trunk/src/media-providers/tracker/rygel-tracker-plugin.vala	(original)
+++ trunk/src/media-server/rygel-resource-info.vala	Tue Nov 25 14:43:12 2008
@@ -1,7 +1,8 @@
 /*
- * Copyright (C) 2008 Zeeshan Ali <zeenix gmail com>.
+ * Copyright (C) 2008 Nokia Corporation, all rights reserved.
  *
- * Author: Zeeshan Ali <zeenix gmail com>
+ * Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
+ *                               <zeeshan ali nokia com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -22,14 +23,25 @@
  * version 2 of the License, or (at your option) any later version.
  */
 
-using Rygel;
+using Gee;
+using GUPnP;
 
-[ModuleInit]
-public MediaProvider register_media_provider (string        root_id,
-                                              string        root_parent_id,
-                                              GUPnP.Context context) {
-    return new MediaTracker (root_id,
-                             root_parent_id,
-                             context);
+public class Rygel.ResourceInfo {
+    public string upnp_type;
+    public string upnp_id;
+    public string description_path;
+
+    // The GLib.Type of the class implementing this service
+    public Type type;
+
+    public ResourceInfo (string upnp_id,
+                         string upnp_type,
+                         string description_path,
+                         Type   type) {
+        this.upnp_type = upnp_type;
+        this.upnp_id = upnp_id;
+        this.description_path = description_path;
+        this.type = type;
+    }
 }
 



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