rygel r479 - in trunk: . src/plugins/dvb src/plugins/test src/plugins/tracker src/rygel



Author: zeeshanak
Date: Tue Jan 27 17:22:51 2009
New Revision: 479
URL: http://svn.gnome.org/viewvc/rygel?rev=479&view=rev

Log:
Merge branch 'easy-plugin'.

Conflicts:

	NEWS
	src/plugins/dvb/rygel-dvb-content-dir.vala
	src/plugins/test/rygel-test-content-dir.vala
	src/plugins/tracker/rygel-media-tracker.vala
	src/rygel/rygel-content-directory.vala
	src/rygel/rygel-seekable-response.vala

Added:
   trunk/src/plugins/dvb/rygel-dvb-root-container.vala
      - copied, changed from r478, /trunk/src/plugins/dvb/rygel-dvb-content-dir.vala
   trunk/src/plugins/test/rygel-test-root-container.vala
      - copied, changed from r478, /trunk/src/plugins/test/rygel-test-content-dir.vala
   trunk/src/plugins/tracker/rygel-tracker-root-container.vala
Modified:
   trunk/NEWS
   trunk/src/plugins/dvb/Makefile.am
   trunk/src/plugins/dvb/rygel-dvb-channel-group.vala
   trunk/src/plugins/dvb/rygel-dvb-channel.vala
   trunk/src/plugins/dvb/rygel-dvb-content-dir.vala
   trunk/src/plugins/test/Makefile.am
   trunk/src/plugins/test/rygel-test-content-dir.vala
   trunk/src/plugins/test/rygel-test-item.vala
   trunk/src/plugins/tracker/Makefile.am
   trunk/src/plugins/tracker/rygel-media-tracker.vala
   trunk/src/plugins/tracker/rygel-tracker-container.vala
   trunk/src/plugins/tracker/rygel-tracker-image-item.vala
   trunk/src/plugins/tracker/rygel-tracker-music-item.vala
   trunk/src/plugins/tracker/rygel-tracker-video-item.vala
   trunk/src/rygel/rygel-content-directory.vala
   trunk/src/rygel/rygel-http-server.vala
   trunk/src/rygel/rygel-media-container.vala
   trunk/src/rygel/rygel-media-item.vala
   trunk/src/rygel/rygel-seekable-response.vala

Modified: trunk/NEWS
==============================================================================
--- trunk/NEWS	(original)
+++ trunk/NEWS	Tue Jan 27 17:22:51 2009
@@ -2,7 +2,7 @@
 ===
 
 The major change after last release (as gupnp-media-server) is the introduction
-of a simple yet powerful plugin-based architecture/api: Everyone plugin:
+of a simple yet powerful plugin-based architecture/api: Every plugin:
 - is loaded into a separate MediaServer instance.
 - can implement any kind and number of resources (currently only services).
 - can export an icon file.

Modified: trunk/src/plugins/dvb/Makefile.am
==============================================================================
--- trunk/src/plugins/dvb/Makefile.am	(original)
+++ trunk/src/plugins/dvb/Makefile.am	Tue Jan 27 17:22:51 2009
@@ -12,6 +12,8 @@
 BUILT_SOURCES = rygel-dvb.stamp \
 		rygel-dvb-content-dir.h \
 		rygel-dvb-content-dir.c \
+                rygel-dvb-root-container.h \
+                rygel-dvb-root-container.c \
 		rygel-dvb-channel-group.h \
 		rygel-dvb-channel-group.c \
 		rygel-dvb-channel.h \
@@ -22,6 +24,9 @@
 librygel_dvb_la_SOURCES = rygel-dvb-content-dir.h \
 			  rygel-dvb-content-dir.c \
                           rygel-dvb-content-dir.vala \
+                          rygel-dvb-root-container.h \
+                          rygel-dvb-root-container.c \
+                          rygel-dvb-root-container.vala \
                           rygel-dvb-channel-group.h \
                           rygel-dvb-channel-group.c \
                           rygel-dvb-channel-group.vala \

Modified: trunk/src/plugins/dvb/rygel-dvb-channel-group.vala
==============================================================================
--- trunk/src/plugins/dvb/rygel-dvb-channel-group.vala	(original)
+++ trunk/src/plugins/dvb/rygel-dvb-channel-group.vala	Tue Jan 27 17:22:51 2009
@@ -38,8 +38,8 @@
 
     public static dynamic DBus.Object channel_list;
 
-    /* Hashmap of (UPnP) IDs to channels */
-    private HashMap<string, DVBChannel> channels;
+    /* List of channels */
+    private ArrayList<DVBChannel> channels;
 
     public HTTPServer http_server;
 
@@ -60,29 +60,32 @@
         this.http_server = http_server;
 
         this.fetch_channels ();
-
-        this.http_server.item_requested += this.on_item_requested;
     }
 
-    public uint add_channels (DIDLLiteWriter didl_writer,
-                              uint           index,
-                              uint           requested_count,
-                              out uint       total_matches) throws GLib.Error {
-        foreach (var channel in channels.get_values ()) {
-            channel.serialize (didl_writer);
-        }
-
-        total_matches = channels.size;
+    public override Gee.List<MediaObject>? get_children (uint offset,
+                                                         uint max_count)
+                                                         throws GLib.Error {
+        uint stop = offset + max_count;
+        stop = stop.clamp (0, this.child_count);
 
-        return total_matches;
+        return this.channels.slice ((int) offset, (int) stop);
     }
 
-    public DVBChannel find_channel (string id) {
-        return this.channels.get (id);
+    public override MediaObject? find_object_by_id (string id)
+                                                    throws GLib.Error {
+        MediaObject channel = null;
+        foreach (var tmp in this.channels) {
+            if (tmp.id == id) {
+                channel = tmp;
+                break;
+            }
+        }
+
+        return channel;
     }
 
     private void fetch_channels () {
-        this.channels = new HashMap<string, DVBChannel> (str_hash, str_equal);
+        this.channels = new ArrayList<DVBChannel> ();
 
         DBus.Connection connection;
         try {
@@ -109,7 +112,7 @@
                                               this.id,
                                               channel_list,
                                               http_server);
-                this.channels.set (channel.id, channel);
+                this.channels.add (channel);
             } catch (GLib.Error error) {
                 critical ("Failed to create DVB Channel object: %s",
                           error.message);
@@ -118,14 +121,5 @@
 
         this.child_count = this.channels.size;
     }
-
-    private void on_item_requested (HTTPServer    http_server,
-                                    string        item_id,
-                                    out MediaItem item) {
-        var channel = this.find_channel (item_id);
-        if (channel != null) {
-            item = channel;
-        }
-    }
 }
 

Modified: trunk/src/plugins/dvb/rygel-dvb-channel.vala
==============================================================================
--- trunk/src/plugins/dvb/rygel-dvb-channel.vala	(original)
+++ trunk/src/plugins/dvb/rygel-dvb-channel.vala	Tue Jan 27 17:22:51 2009
@@ -63,8 +63,8 @@
             this.upnp_class = "object.item.videoItem.videoBroadcast";
         }
 
-        this.res.mime_type = "video/mpeg";
-        this.res.uri = this.channel_list.GetChannelURL (cid);
+        this.mime_type = "video/mpeg";
+        this.uri = this.channel_list.GetChannelURL (cid);
     }
 }
 

Modified: trunk/src/plugins/dvb/rygel-dvb-content-dir.vala
==============================================================================
--- trunk/src/plugins/dvb/rygel-dvb-content-dir.vala	(original)
+++ trunk/src/plugins/dvb/rygel-dvb-content-dir.vala	Tue Jan 27 17:22:51 2009
@@ -31,155 +31,10 @@
  * Implementation of DVB ContentDirectory service.
  */
 public class Rygel.DVBContentDir : ContentDirectory {
-    // class-wide constants
-    private const string DVB_SERVICE = "org.gnome.DVB";
-    private const string MANAGER_PATH = "/org/gnome/DVB/Manager";
-    private const string MANAGER_IFACE = "org.gnome.DVB.Manager";
-    private const string CHANNEL_LIST_IFACE = "org.gnome.DVB.ChannelList";
-
-    public dynamic DBus.Object manager;
-
-    private ArrayList<DVBChannelGroup> groups;
-
     // Pubic methods
-    public override void constructed () {
-        // Chain-up to base first
-        base.constructed ();
-
-        DBus.Connection connection;
-        try {
-            connection = DBus.Bus.get (DBus.BusType.SESSION);
-        } catch (DBus.Error error) {
-            critical ("Failed to connect to Session bus: %s\n",
-                      error.message);
-            return;
-        }
-
-        this.groups = new ArrayList<DVBChannelGroup> ();
-
-        // Get a proxy to DVB Manager object
-        this.manager = connection.get_object (DVBContentDir.DVB_SERVICE,
-                                              DVBContentDir.MANAGER_PATH,
-                                              DVBContentDir.MANAGER_IFACE);
-        uint[] dev_groups = null;
-
-        try {
-            dev_groups = this.manager.GetRegisteredDeviceGroups ();
-        } catch (GLib.Error error) {
-            critical ("error: %s", error.message);
-            return;
-        }
-
-        foreach (uint group_id in dev_groups) {
-            string channel_list_path = null;
-            string group_name =  null;
-
-            try {
-                channel_list_path = manager.GetChannelList (group_id);
-
-                // Get the name of the group
-                group_name = manager.GetDeviceGroupName (group_id);
-            } catch (GLib.Error error) {
-                critical ("error: %s", error.message);
-                return;
-            }
-
-            // Get a proxy to DVB ChannelList object
-            dynamic DBus.Object channel_list = connection.get_object
-                                        (DVBContentDir.DVB_SERVICE,
-                                         channel_list_path,
-                                         DVBContentDir.CHANNEL_LIST_IFACE);
-
-            // Create ChannelGroup for each registered device group
-            this.groups.add (new DVBChannelGroup (group_id,
-                                                  group_name,
-                                                  this.root_container.id,
-                                                  channel_list,
-                                                  this.http_server));
-        }
-    }
-
-    public override void add_children_metadata (DIDLLiteWriter didl_writer,
-                                                BrowseArgs     args)
-                                                throws GLib.Error {
-        DVBChannelGroup group;
-
-        group = this.find_group_by_id (args.object_id);
-        if (group == null) {
-            throw new ContentDirectoryError.NO_SUCH_OBJECT ("No such object");
-        }
-
-        args.number_returned = group.add_channels (didl_writer,
-                                                   args.index,
-                                                   args.requested_count,
-                                                   out args.total_matches);
-        args.update_id = uint32.MAX;
-    }
-
-    public override void add_metadata (DIDLLiteWriter didl_writer,
-                                       BrowseArgs     args) throws GLib.Error {
-        bool found = false;
-
-        DVBChannelGroup group;
-
-        // First try groups
-        group = find_group_by_id (args.object_id);
-
-        if (group != null) {
-            group.serialize (didl_writer);
-
-            found = true;
-        } else {
-            // Now try channels
-            found = this.add_channel (didl_writer, args.object_id);
-        }
-
-        if (!found) {
-            throw new ContentDirectoryError.NO_SUCH_OBJECT ("No such object");
-        }
-
-        args.update_id = uint32.MAX;
-    }
-
-    public override void add_root_children_metadata (DIDLLiteWriter didl_writer,
-                                                     BrowseArgs     args)
-                                                     throws GLib.Error {
-        foreach (DVBChannelGroup group in this.groups)
-            group.serialize (didl_writer);
-
-        args.total_matches = args.number_returned = this.groups.size;
-        args.update_id = uint32.MAX;
-    }
-
-    // Private methods
-    private DVBChannelGroup? find_group_by_id (string id) {
-        DVBChannelGroup group = null;
-
-        foreach (DVBChannelGroup tmp in this.groups) {
-            if (id == tmp.id) {
-                group = tmp;
-
-                break;
-            }
-        }
-
-        return group;
-    }
-
-    private bool add_channel (DIDLLiteWriter didl_writer,
-                              string         id) throws GLib.Error {
-        bool found = false;
-
-        foreach (DVBChannelGroup group in this.groups) {
-            var channel = group.find_channel (id);
-            if (channel != null) {
-                channel.serialize (didl_writer);
-                found = true;
-                break;
-            }
-        }
-
-        return found;
+    public override MediaContainer? create_root_container () {
+        string friendly_name = this.root_device.get_friendly_name ();
+        return new DVBRootContainer (friendly_name, this.http_server);
     }
 }
 

Copied: trunk/src/plugins/dvb/rygel-dvb-root-container.vala (from r478, /trunk/src/plugins/dvb/rygel-dvb-content-dir.vala)
==============================================================================
--- /trunk/src/plugins/dvb/rygel-dvb-content-dir.vala	(original)
+++ trunk/src/plugins/dvb/rygel-dvb-root-container.vala	Tue Jan 27 17:22:51 2009
@@ -28,9 +28,9 @@
 using Gee;
 
 /**
- * Implementation of DVB ContentDirectory service.
+ * Represents the root container for DVB media content hierarchy.
  */
-public class Rygel.DVBContentDir : ContentDirectory {
+public class Rygel.DVBRootContainer : MediaContainer {
     // class-wide constants
     private const string DVB_SERVICE = "org.gnome.DVB";
     private const string MANAGER_PATH = "/org/gnome/DVB/Manager";
@@ -41,10 +41,9 @@
 
     private ArrayList<DVBChannelGroup> groups;
 
-    // Pubic methods
-    public override void constructed () {
-        // Chain-up to base first
-        base.constructed ();
+    public DVBRootContainer (string     title,
+                             HTTPServer http_server) {
+        base.root (title, 0);
 
         DBus.Connection connection;
         try {
@@ -58,9 +57,9 @@
         this.groups = new ArrayList<DVBChannelGroup> ();
 
         // Get a proxy to DVB Manager object
-        this.manager = connection.get_object (DVBContentDir.DVB_SERVICE,
-                                              DVBContentDir.MANAGER_PATH,
-                                              DVBContentDir.MANAGER_IFACE);
+        this.manager = connection.get_object (DVBRootContainer.DVB_SERVICE,
+                                              DVBRootContainer.MANAGER_PATH,
+                                              DVBRootContainer.MANAGER_IFACE);
         uint[] dev_groups = null;
 
         try {
@@ -86,69 +85,40 @@
 
             // Get a proxy to DVB ChannelList object
             dynamic DBus.Object channel_list = connection.get_object
-                                        (DVBContentDir.DVB_SERVICE,
+                                        (DVBRootContainer.DVB_SERVICE,
                                          channel_list_path,
-                                         DVBContentDir.CHANNEL_LIST_IFACE);
+                                         DVBRootContainer.CHANNEL_LIST_IFACE);
 
             // Create ChannelGroup for each registered device group
             this.groups.add (new DVBChannelGroup (group_id,
                                                   group_name,
-                                                  this.root_container.id,
+                                                  this.id,
                                                   channel_list,
-                                                  this.http_server));
-        }
-    }
-
-    public override void add_children_metadata (DIDLLiteWriter didl_writer,
-                                                BrowseArgs     args)
-                                                throws GLib.Error {
-        DVBChannelGroup group;
-
-        group = this.find_group_by_id (args.object_id);
-        if (group == null) {
-            throw new ContentDirectoryError.NO_SUCH_OBJECT ("No such object");
+                                                  http_server));
         }
 
-        args.number_returned = group.add_channels (didl_writer,
-                                                   args.index,
-                                                   args.requested_count,
-                                                   out args.total_matches);
-        args.update_id = uint32.MAX;
+        this.child_count = this.groups.size;
     }
 
-    public override void add_metadata (DIDLLiteWriter didl_writer,
-                                       BrowseArgs     args) throws GLib.Error {
-        bool found = false;
+    public override Gee.List<MediaObject>? get_children (uint offset,
+                                                         uint max_count)
+                                                         throws GLib.Error {
+        uint stop = offset + max_count;
 
-        DVBChannelGroup group;
+        stop = stop.clamp (0, this.child_count);
+        return this.groups.slice ((int) offset, (int) stop);
+    }
 
+    public override MediaObject? find_object_by_id (string id)
+                                                    throws GLib.Error {
         // First try groups
-        group = find_group_by_id (args.object_id);
-
-        if (group != null) {
-            group.serialize (didl_writer);
+        MediaObject media_object = find_group_by_id (id);
 
-            found = true;
-        } else {
-            // Now try channels
-            found = this.add_channel (didl_writer, args.object_id);
+        if (media_object == null) {
+            media_object = find_channel_by_id (id);
         }
 
-        if (!found) {
-            throw new ContentDirectoryError.NO_SUCH_OBJECT ("No such object");
-        }
-
-        args.update_id = uint32.MAX;
-    }
-
-    public override void add_root_children_metadata (DIDLLiteWriter didl_writer,
-                                                     BrowseArgs     args)
-                                                     throws GLib.Error {
-        foreach (DVBChannelGroup group in this.groups)
-            group.serialize (didl_writer);
-
-        args.total_matches = args.number_returned = this.groups.size;
-        args.update_id = uint32.MAX;
+        return media_object;
     }
 
     // Private methods
@@ -166,20 +136,17 @@
         return group;
     }
 
-    private bool add_channel (DIDLLiteWriter didl_writer,
-                              string         id) throws GLib.Error {
-        bool found = false;
+    private MediaObject find_channel_by_id (string id) throws GLib.Error {
+        MediaObject channel = null;
 
         foreach (DVBChannelGroup group in this.groups) {
-            var channel = group.find_channel (id);
+            channel = group.find_object_by_id (id);
             if (channel != null) {
-                channel.serialize (didl_writer);
-                found = true;
                 break;
             }
         }
 
-        return found;
+        return channel;
     }
 }
 

Modified: trunk/src/plugins/test/Makefile.am
==============================================================================
--- trunk/src/plugins/test/Makefile.am	(original)
+++ trunk/src/plugins/test/Makefile.am	Tue Jan 27 17:22:51 2009
@@ -12,6 +12,8 @@
 BUILT_SOURCES = rygel-test.stamp \
 		rygel-test-content-dir.h \
 		rygel-test-content-dir.c \
+		rygel-test-root-container.h \
+		rygel-test-root-container.c \
                 rygel-test-item.h \
                 rygel-test-item.c \
 		rygel-test-audio-item.h \
@@ -24,6 +26,9 @@
 librygel_test_la_SOURCES = rygel-test-content-dir.h \
 			   rygel-test-content-dir.c \
                            rygel-test-content-dir.vala \
+			   rygel-test-root-container.h \
+			   rygel-test-root-container.c \
+			   rygel-test-root-container.vala \
                            rygel-test-item.h \
                            rygel-test-item.c \
                            rygel-test-item.vala \

Modified: trunk/src/plugins/test/rygel-test-content-dir.vala
==============================================================================
--- trunk/src/plugins/test/rygel-test-content-dir.vala	(original)
+++ trunk/src/plugins/test/rygel-test-content-dir.vala	Tue Jan 27 17:22:51 2009
@@ -24,91 +24,16 @@
 
 using Rygel;
 using GUPnP;
-using Gst;
 using Gee;
 
 /**
  * Implementation of ContentDirectory service, meant for testing purposes only.
  */
 public class Rygel.TestContentDir : ContentDirectory {
-    private ArrayList<MediaItem> items;
-
     /* Pubic methods */
-    public override void constructed () {
-        // Chain-up to base first
-        base.constructed ();
-
-        this.http_server.item_requested += this.on_item_requested;
-        this.http_server.need_stream_source += this.on_need_stream_source;
-
-        this.items = new ArrayList<MediaItem> ();
-        this.items.add (new TestAudioItem ("sinewave",
-                                           this.root_container.id,
-                                           "Sine Wave",
-                                           this.http_server));
-        this.items.add (new TestVideoItem ("smtpe",
-                                           this.root_container.id,
-                                           "SMTPE",
-                                           this.http_server));
-
-        // Now we know how many top-level items we have
-        this.root_container.child_count = this.items.size;
-    }
-
-    public override void add_metadata (DIDLLiteWriter didl_writer,
-                                       BrowseArgs     args) throws GLib.Error {
-        MediaItem item = find_item_by_id (args.object_id);
-        if (item == null) {
-            throw new ContentDirectoryError.NO_SUCH_OBJECT ("No such object");
-        }
-
-        item.serialize (didl_writer);
-        args.update_id = uint32.MAX;
-    }
-
-    public override void add_root_children_metadata (DIDLLiteWriter didl_writer,
-                                                     BrowseArgs     args)
-                                                     throws GLib.Error {
-        foreach (MediaItem item in this.items)
-            item.serialize (didl_writer);
-
-        args.total_matches = args.number_returned = this.items.size;
-        args.update_id = uint32.MAX;
-    }
-
-    /* Private methods */
-    private MediaItem? find_item_by_id (string item_id) {
-        MediaItem item = null;
-
-        foreach (MediaItem tmp in this.items) {
-            if (item_id == tmp.id) {
-                item = tmp;
-
-                break;
-            }
-        }
-
-        return item;
-    }
-
-    private void on_item_requested (HTTPServer    http_server,
-                                    string        item_id,
-                                    out MediaItem item) {
-        item = this.find_item_by_id (item_id);
-    }
-
-    private void on_need_stream_source (HTTPServer  http_server,
-                                        MediaItem   item,
-                                        out Element src) {
-        try {
-            src = ((TestItem) item).create_gst_source ();
-        } catch (Error error) {
-            critical ("Error creating Gst source element for item %s: %s",
-                      item.id,
-                      error.message);
-
-            return;
-        }
+    public override MediaContainer? create_root_container () {
+        string friendly_name = this.root_device.get_friendly_name ();
+        return new TestRootContainer (friendly_name, this.http_server);
     }
 }
 

Modified: trunk/src/plugins/test/rygel-test-item.vala
==============================================================================
--- trunk/src/plugins/test/rygel-test-item.vala	(original)
+++ trunk/src/plugins/test/rygel-test-item.vala	Tue Jan 27 17:22:51 2009
@@ -40,7 +40,7 @@
                      HTTPServer http_server) {
         base (id, parent_id, title, upnp_class, http_server);
 
-        this.res.mime_type = mime;
+        this.mime_type = mime;
         this.author = TEST_AUTHOR;
     }
 

Copied: trunk/src/plugins/test/rygel-test-root-container.vala (from r478, /trunk/src/plugins/test/rygel-test-content-dir.vala)
==============================================================================
--- /trunk/src/plugins/test/rygel-test-content-dir.vala	(original)
+++ trunk/src/plugins/test/rygel-test-root-container.vala	Tue Jan 27 17:22:51 2009
@@ -24,64 +24,53 @@
 
 using Rygel;
 using GUPnP;
-using Gst;
 using Gee;
+using Gst;
 
 /**
- * Implementation of ContentDirectory service, meant for testing purposes only.
+ * Represents the root container for Test media content hierarchy.
  */
-public class Rygel.TestContentDir : ContentDirectory {
+public class Rygel.TestRootContainer : MediaContainer {
     private ArrayList<MediaItem> items;
 
-    /* Pubic methods */
-    public override void constructed () {
-        // Chain-up to base first
-        base.constructed ();
+    private HTTPServer http_server;
+
+    public TestRootContainer (string     title,
+                             HTTPServer http_server) {
+        base.root (title, 0);
 
-        this.http_server.item_requested += this.on_item_requested;
+        this.http_server = http_server;
         this.http_server.need_stream_source += this.on_need_stream_source;
 
         this.items = new ArrayList<MediaItem> ();
         this.items.add (new TestAudioItem ("sinewave",
-                                           this.root_container.id,
+                                           this.id,
                                            "Sine Wave",
                                            this.http_server));
         this.items.add (new TestVideoItem ("smtpe",
-                                           this.root_container.id,
+                                           this.id,
                                            "SMTPE",
                                            this.http_server));
 
         // Now we know how many top-level items we have
-        this.root_container.child_count = this.items.size;
+        this.child_count = this.items.size;
     }
 
-    public override void add_metadata (DIDLLiteWriter didl_writer,
-                                       BrowseArgs     args) throws GLib.Error {
-        MediaItem item = find_item_by_id (args.object_id);
-        if (item == null) {
-            throw new ContentDirectoryError.NO_SUCH_OBJECT ("No such object");
-        }
+    public override Gee.List<MediaObject>? get_children (uint offset,
+                                                         uint max_count)
+                                                         throws GLib.Error {
+        uint stop = offset + max_count;
 
-        item.serialize (didl_writer);
-        args.update_id = uint32.MAX;
+        stop = stop.clamp (0, this.child_count);
+        return this.items.slice ((int) offset, (int) stop);
     }
 
-    public override void add_root_children_metadata (DIDLLiteWriter didl_writer,
-                                                     BrowseArgs     args)
-                                                     throws GLib.Error {
-        foreach (MediaItem item in this.items)
-            item.serialize (didl_writer);
-
-        args.total_matches = args.number_returned = this.items.size;
-        args.update_id = uint32.MAX;
-    }
-
-    /* Private methods */
-    private MediaItem? find_item_by_id (string item_id) {
+    public override MediaObject? find_object_by_id (string id)
+                                                    throws GLib.Error {
         MediaItem item = null;
 
         foreach (MediaItem tmp in this.items) {
-            if (item_id == tmp.id) {
+            if (id == tmp.id) {
                 item = tmp;
 
                 break;
@@ -91,12 +80,7 @@
         return item;
     }
 
-    private void on_item_requested (HTTPServer    http_server,
-                                    string        item_id,
-                                    out MediaItem item) {
-        item = this.find_item_by_id (item_id);
-    }
-
+    /* Private methods */
     private void on_need_stream_source (HTTPServer  http_server,
                                         MediaItem   item,
                                         out Element src) {

Modified: trunk/src/plugins/tracker/Makefile.am
==============================================================================
--- trunk/src/plugins/tracker/Makefile.am	(original)
+++ trunk/src/plugins/tracker/Makefile.am	Tue Jan 27 17:22:51 2009
@@ -12,6 +12,8 @@
 BUILT_SOURCES = rygel-media-tracker.stamp \
 		rygel-media-tracker.h \
 		rygel-media-tracker.c \
+		rygel-tracker-root-container.h \
+		rygel-tracker-root-container.c \
 		rygel-tracker-container.h \
 		rygel-tracker-container.c \
 		rygel-tracker-item.h \
@@ -28,6 +30,9 @@
 librygel_media_tracker_la_SOURCES = rygel-media-tracker.h \
 			            rygel-media-tracker.c \
 				    rygel-media-tracker.vala \
+				    rygel-tracker-root-container.h \
+				    rygel-tracker-root-container.c \
+				    rygel-tracker-root-container.vala \
 				    rygel-tracker-container.h \
 			            rygel-tracker-container.c \
 				    rygel-tracker-container.vala \

Modified: trunk/src/plugins/tracker/rygel-media-tracker.vala
==============================================================================
--- trunk/src/plugins/tracker/rygel-media-tracker.vala	(original)
+++ trunk/src/plugins/tracker/rygel-media-tracker.vala	Tue Jan 27 17:22:51 2009
@@ -30,162 +30,10 @@
  * Implementation of Tracker-based ContentDirectory service.
  */
 public class Rygel.MediaTracker : ContentDirectory {
-    public static const int MAX_REQUESTED_COUNT = 128;
-
-    /* FIXME: Make this a static if you know how to initize it */
-    private ArrayList<TrackerContainer> containers;
-
-    private SearchCriteriaParser search_parser;
-
     /* Pubic methods */
-    public override void constructed () {
-        // Chain-up to base first
-        base.constructed ();
-
-        this.http_server.item_requested += on_item_requested;
-
-        this.containers = new ArrayList<TrackerContainer> ();
-        this.containers.add
-                        (new TrackerContainer ("16",
-                                               this.root_container.id,
-                                               "All Images",
-                                               "Images",
-                                               MediaItem.IMAGE_CLASS,
-                                               this.http_server));
-        this.containers.add
-                        (new TrackerContainer ("14",
-                                               this.root_container.id,
-                                               "All Music",
-                                               "Music",
-                                               MediaItem.MUSIC_CLASS,
-                                               this.http_server));
-        this.containers.add
-                        (new TrackerContainer ("15",
-                                               this.root_container.id,
-                                               "All Videos",
-                                               "Videos",
-                                               MediaItem.VIDEO_CLASS,
-                                               this.http_server));
-
-        // Now we know how many top-level containers we have
-        this.root_container.child_count = this.containers.size;
-
-        this.search_parser = new SearchCriteriaParser ();
-    }
-
-    public override void add_children_metadata (DIDLLiteWriter didl_writer,
-                                                BrowseArgs     args)
-                                                throws GLib.Error {
-        TrackerContainer container;
-
-        if (args.requested_count == 0)
-            args.requested_count = MAX_REQUESTED_COUNT;
-
-        container = this.find_container_by_id (args.object_id);
-        if (container == null)
-            args.number_returned = 0;
-        else {
-            args.number_returned =
-                container.add_children_from_db (didl_writer,
-                                                args.index,
-                                                args.requested_count,
-                                                out args.total_matches);
-        }
-
-        if (args.number_returned > 0) {
-            args.update_id = uint32.MAX;
-        } else {
-            throw new ContentDirectoryError.NO_SUCH_OBJECT ("No such object");
-        }
-    }
-
-    public override void add_metadata (DIDLLiteWriter didl_writer,
-                                       BrowseArgs     args) throws GLib.Error {
-        bool found = false;
-
-        TrackerContainer container;
-
-        /* First try containers */
-        container = find_container_by_id (args.object_id);
-
-        if (container != null) {
-            container.serialize (didl_writer);
-
-            found = true;
-        } else {
-            /* Now try items */
-            container = get_item_parent (args.object_id);
-
-            if (container != null)
-                found = container.add_item_from_db (didl_writer,
-                                                    args.object_id);
-        }
-
-        if (!found) {
-            throw new ContentDirectoryError.NO_SUCH_OBJECT ("No such object");
-        }
-
-        args.update_id = uint32.MAX;
-    }
-
-    public override void add_root_children_metadata (DIDLLiteWriter didl_writer,
-                                                     BrowseArgs     args)
-                                                     throws GLib.Error {
-        foreach (TrackerContainer container in this.containers)
-            container.serialize (didl_writer);
-
-        args.total_matches = args.number_returned = this.containers.size;
-        args.update_id = uint32.MAX;
-    }
-
-    /* Private methods */
-    private TrackerContainer? find_container_by_id (string container_id) {
-        TrackerContainer container;
-
-        container = null;
-
-        foreach (TrackerContainer tmp in this.containers)
-            if (container_id == tmp.id) {
-                container = tmp;
-
-                break;
-            }
-
-        return container;
-    }
-
-    private TrackerContainer? get_item_parent (string uri) {
-        TrackerContainer container = null;
-        string category;
-
-        try {
-            category = TrackerContainer.get_file_category (uri);
-        } catch (GLib.Error error) {
-            critical ("failed to find service type for %s: %s",
-                      uri,
-                      error.message);
-
-            return null;
-        }
-
-        foreach (TrackerContainer tmp in this.containers) {
-            if (tmp.category == category) {
-                container = tmp;
-
-                break;
-            }
-        }
-
-        return container;
-    }
-
-    private void on_item_requested (HTTPServer    http_server,
-                                    string        item_id,
-                                    out MediaItem item) {
-        TrackerContainer container = get_item_parent (item_id);
-
-        if (container != null)
-            item = container.get_item_from_db (item_id);
+    public override MediaContainer? create_root_container () {
+        string friendly_name = this.root_device.get_friendly_name ();
+        return new TrackerRootContainer (friendly_name, this.http_server);
     }
 }
 

Modified: trunk/src/plugins/tracker/rygel-tracker-container.vala
==============================================================================
--- trunk/src/plugins/tracker/rygel-tracker-container.vala	(original)
+++ trunk/src/plugins/tracker/rygel-tracker-container.vala	Tue Jan 27 17:22:51 2009
@@ -24,6 +24,7 @@
 using Rygel;
 using GUPnP;
 using DBus;
+using Gee;
 
 /**
  * Represents Tracker category.
@@ -83,14 +84,11 @@
         this.category = category;
         this.child_class = child_class;
         this.http_server = http_server;
-    }
 
-    public override void serialize (DIDLLiteWriter didl_writer)
-                                    throws GLib.Error {
-        /* Update the child count */
+        /* FIXME: We need to hook to some tracker signals to keep
+         *        this field up2date at all times
+         */
         this.child_count = this.get_children_count ();
-
-        base.serialize (didl_writer);
     }
 
     private uint get_children_count () {
@@ -113,74 +111,26 @@
         return count;
     }
 
-    public uint add_children_from_db (DIDLLiteWriter didl_writer,
-                                       uint           offset,
-                                       uint           max_count,
-                                       out uint       child_count) {
-        string[] children;
-
-        children = this.get_children_from_db (offset,
-                                              max_count,
-                                              out child_count);
-        if (children == null)
-            return 0;
-
-        /* Iterate through all items */
-        for (uint i = 0; i < children.length; i++)
-            this.add_item_from_db (didl_writer, children[i]);
-
-        return children.length;
-    }
-
-    private string[]? get_children_from_db (uint     offset,
-                                            uint     max_count,
-                                            out uint child_count) {
-        string[] children = null;
-
-        child_count = this.get_children_count ();
+    public override Gee.List<MediaObject>? get_children (uint offset,
+                                                         uint max_count)
+                                                         throws GLib.Error {
+        ArrayList<MediaObject> children = new ArrayList<MediaObject> ();
 
-        try {
-            children =
+        string[] child_paths =
                 TrackerContainer.files.GetByServiceType (0,
                                                          this.category,
                                                          (int) offset,
                                                          (int) max_count);
-        } catch (GLib.Error error) {
-            critical ("error: %s", error.message);
 
-            return null;
+        /* Iterate through all items */
+        for (uint i = 0; i < child_paths.length; i++) {
+            MediaObject item = this.find_object_by_id (child_paths[i]);
+            children.add (item);
         }
 
         return children;
     }
 
-    public bool add_item_from_db (DIDLLiteWriter didl_writer,
-                                   string         path) {
-        MediaItem item = null;
-
-        try {
-            item = this.get_item_from_db (path);
-        } catch (GLib.Error error) {
-            critical ("Failed to fetch item %s. Reason: %s",
-                      item.id,
-                      error.message);
-
-            return false;
-        }
-
-        try {
-            item.serialize (didl_writer);
-        } catch (GLib.Error error) {
-            critical ("Failed to serialize item %s. Reason: %s",
-                      item.id,
-                      error.message);
-
-            return false;
-        }
-
-        return true;
-    }
-
     public static string get_file_category (string uri) throws GLib.Error {
         string category;
 
@@ -189,8 +139,10 @@
         return category;
     }
 
-    public MediaItem get_item_from_db (string path) throws GLib.Error {
-        MediaItem item;
+    public override MediaObject? find_object_by_id (string id)
+                                                    throws GLib.Error {
+        MediaObject item;
+        string path = id;
 
         if (this.child_class == MediaItem.VIDEO_CLASS) {
             item = new TrackerVideoItem (path, path, this);

Modified: trunk/src/plugins/tracker/rygel-tracker-image-item.vala
==============================================================================
--- trunk/src/plugins/tracker/rygel-tracker-image-item.vala	(original)
+++ trunk/src/plugins/tracker/rygel-tracker-image-item.vala	Tue Jan 27 17:22:51 2009
@@ -73,16 +73,16 @@
             this.title = values[Metadata.FILE_NAME];
 
         if (values[Metadata.SIZE] != "")
-            this.res.size = values[Metadata.SIZE].to_int ();
+            this.size = values[Metadata.SIZE].to_int ();
 
         if (values[Metadata.WIDTH] != "")
-            this.res.width = values[Metadata.WIDTH].to_int ();
+            this.width = values[Metadata.WIDTH].to_int ();
 
         if (values[Metadata.HEIGHT] != "")
-            this.res.height = values[Metadata.HEIGHT].to_int ();
+            this.height = values[Metadata.HEIGHT].to_int ();
 
         if (values[Metadata.SIZE] != "")
-            this.res.size = values[Metadata.SIZE].to_int ();
+            this.size = values[Metadata.SIZE].to_int ();
 
         if (values[Metadata.DATE] != "") {
             this.date = seconds_to_iso8601 (values[Metadata.DATE]);
@@ -90,10 +90,10 @@
             this.date = seconds_to_iso8601 (values[Metadata.IMAGE_DATE]);
         }
 
-        this.res.mime_type = values[Metadata.MIME];
+        this.mime_type = values[Metadata.MIME];
         this.author = values[Metadata.CREATOR];
         this.album = values[Metadata.ALBUM];
-        this.res.uri = this.uri_from_path (path);
+        this.uri = this.uri_from_path (path);
     }
 }
 

Modified: trunk/src/plugins/tracker/rygel-tracker-music-item.vala
==============================================================================
--- trunk/src/plugins/tracker/rygel-tracker-music-item.vala	(original)
+++ trunk/src/plugins/tracker/rygel-tracker-music-item.vala	Tue Jan 27 17:22:51 2009
@@ -73,7 +73,7 @@
             this.title = values[Metadata.FILE_NAME];
 
         if (values[Metadata.SIZE] != "")
-            this.res.size = values[Metadata.SIZE].to_int ();
+            this.size = values[Metadata.SIZE].to_int ();
 
         if (values[Metadata.TRACK_NUM] != "")
             this.track_number = values[Metadata.TRACK_NUM].to_int ();
@@ -86,10 +86,10 @@
             this.date = seconds_to_iso8601 (values[Metadata.DATE_ADDED]);
         }
 
-        this.res.mime_type = values[Metadata.MIME];
+        this.mime_type = values[Metadata.MIME];
         this.author = values[Metadata.ARTIST];
         this.album = values[Metadata.ALBUM];
-        this.res.uri = this.uri_from_path (path);
+        this.uri = this.uri_from_path (path);
     }
 }
 

Added: trunk/src/plugins/tracker/rygel-tracker-root-container.vala
==============================================================================
--- (empty file)
+++ trunk/src/plugins/tracker/rygel-tracker-root-container.vala	Tue Jan 27 17:22:51 2009
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2008 Zeeshan Ali (Khattak) <zeeshanak gnome org>.
+ * Copyright (C) 2008 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 the root container for Tracker media content hierarchy.
+ */
+public class Rygel.TrackerRootContainer : MediaContainer {
+    /* FIXME: Make this a static if you know how to initize it */
+    private ArrayList<TrackerContainer> containers;
+
+    public TrackerRootContainer (string title, HTTPServer http_server) {
+        base.root (title, 0);
+
+        this.containers = new ArrayList<TrackerContainer> ();
+        this.containers.add
+                        (new TrackerContainer ("16",
+                                               this.id,
+                                               "All Images",
+                                               "Images",
+                                               MediaItem.IMAGE_CLASS,
+                                               http_server));
+        this.containers.add
+                        (new TrackerContainer ("14",
+                                               this.id,
+                                               "All Music",
+                                               "Music",
+                                               MediaItem.MUSIC_CLASS,
+                                               http_server));
+        this.containers.add
+                        (new TrackerContainer ("15",
+                                               this.id,
+                                               "All Videos",
+                                               "Videos",
+                                               MediaItem.VIDEO_CLASS,
+                                               http_server));
+
+        // Now we know how many top-level containers we have
+        this.child_count = this.containers.size;
+    }
+
+    public override Gee.List<MediaObject>? get_children (uint offset,
+                                                         uint max_count)
+                                                         throws GLib.Error {
+        uint stop = offset + max_count;
+
+        stop = stop.clamp (0, this.child_count);
+        return this.containers.slice ((int) offset, (int) stop);
+    }
+
+    public override MediaObject? find_object_by_id (string id)
+                                                    throws GLib.Error {
+        /* First try containers */
+        MediaObject media_object = find_container_by_id (id);
+
+        if (media_object == null) {
+            /* Now try items */
+            var container = get_item_parent (id);
+
+            if (container != null)
+                media_object = container.find_object_by_id (id);
+        }
+
+        return media_object;
+    }
+
+    /* Private methods */
+    private TrackerContainer? find_container_by_id (string container_id) {
+        TrackerContainer container;
+
+        container = null;
+
+        foreach (TrackerContainer tmp in this.containers)
+            if (container_id == tmp.id) {
+                container = tmp;
+
+                break;
+            }
+
+        return container;
+    }
+
+    private TrackerContainer? get_item_parent (string uri) {
+        TrackerContainer container = null;
+        string category;
+
+        try {
+            category = TrackerContainer.get_file_category (uri);
+        } catch (GLib.Error error) {
+            critical ("failed to find service type for %s: %s",
+                      uri,
+                      error.message);
+
+            return null;
+        }
+
+        foreach (TrackerContainer tmp in this.containers) {
+            if (tmp.category == category) {
+                container = tmp;
+
+                break;
+            }
+        }
+
+        return container;
+    }
+}
+

Modified: trunk/src/plugins/tracker/rygel-tracker-video-item.vala
==============================================================================
--- trunk/src/plugins/tracker/rygel-tracker-video-item.vala	(original)
+++ trunk/src/plugins/tracker/rygel-tracker-video-item.vala	Tue Jan 27 17:22:51 2009
@@ -69,18 +69,18 @@
             this.title = values[Metadata.FILE_NAME];
 
         if (values[Metadata.SIZE] != "")
-            this.res.size = values[Metadata.SIZE].to_int ();
+            this.size = values[Metadata.SIZE].to_int ();
 
         if (values[Metadata.WIDTH] != "")
-            this.res.width = values[Metadata.WIDTH].to_int ();
+            this.width = values[Metadata.WIDTH].to_int ();
 
         if (values[Metadata.HEIGHT] != "")
-            this.res.height = values[Metadata.HEIGHT].to_int ();
+            this.height = values[Metadata.HEIGHT].to_int ();
 
         this.date = this.seconds_to_iso8601 (values[Metadata.DATE]);
-        this.res.mime_type = values[Metadata.MIME];
+        this.mime_type = values[Metadata.MIME];
         this.author = values[Metadata.AUTHOR];
-        this.res.uri = this.uri_from_path (path);
+        this.uri = this.uri_from_path (path);
     }
 }
 

Modified: trunk/src/rygel/rygel-content-directory.vala
==============================================================================
--- trunk/src/rygel/rygel-content-directory.vala	(original)
+++ trunk/src/rygel/rygel-content-directory.vala	Tue Jan 27 17:22:51 2009
@@ -23,6 +23,7 @@
  */
 
 using GUPnP;
+using Gee;
 
 /**
  * Errors used by ContentDirectory and deriving classes.
@@ -50,7 +51,7 @@
 /**
  * Basic implementation of UPnP ContentDirectory service version 2. Most often
  * plugins will provide a child of this class. The inheriting classes should
- * override add_children_metadata and add_metadata virtual methods.
+ * override create_root_container method.
  */
 public class Rygel.ContentDirectory: Service {
     public const string UPNP_ID = "urn:upnp-org:serviceId:ContentDirectory";
@@ -58,6 +59,8 @@
                     "urn:schemas-upnp-org:service:ContentDirectory:2";
     public const string DESCRIPTION_PATH = "xml/ContentDirectory.xml";
 
+    public const int MAX_REQUESTED_COUNT = 128;
+
     protected uint32 system_update_id;
     protected string feature_list;
     protected string search_caps;
@@ -70,27 +73,16 @@
     DIDLLiteWriter didl_writer;
 
     // Public abstract methods derived classes need to implement
-    public virtual void add_children_metadata (DIDLLiteWriter didl_writer,
-                                               BrowseArgs     args)
-                                               throws Error {
-        throw new ServerError.NOT_IMPLEMENTED ("Not Implemented\n");
-    }
-
-    public virtual void add_metadata (DIDLLiteWriter didl_writer,
-                                      BrowseArgs    args) throws Error {
-        throw new ServerError.NOT_IMPLEMENTED ("Not Implemented\n");
-    }
-
-    public virtual void add_root_children_metadata
-                                        (DIDLLiteWriter didl_writer,
-                                         BrowseArgs     args) throws Error {
-        throw new ServerError.NOT_IMPLEMENTED ("Not Implemented\n");
+    public virtual MediaContainer? create_root_container () {
+       return null;
     }
 
     public override void constructed () {
         this.didl_writer = new DIDLLiteWriter ();
-        this.setup_root_container ();
         this.http_server = new HTTPServer (context, this.get_type ().name ());
+        this.root_container = this.create_root_container ();
+
+        this.http_server.item_requested += this.on_item_requested;
 
         this.system_update_id = 0;
         this.feature_list =
@@ -241,11 +233,6 @@
         value.set_string (this.feature_list);
     }
 
-    private void setup_root_container () {
-        string friendly_name = this.root_device.get_friendly_name ();
-        this.root_container = new MediaContainer.root (friendly_name, 0);
-    }
-
     private void browse_metadata (BrowseArgs args) throws Error {
         if (args.object_id == this.root_container.id) {
             this.root_container.serialize (didl_writer);
@@ -316,5 +303,118 @@
 
         action.return ();
     }
+
+    private void add_children_metadata (DIDLLiteWriter didl_writer,
+                                                  BrowseArgs     args)
+                                                  throws GLib.Error {
+        if (args.requested_count == 0)
+            args.requested_count = MAX_REQUESTED_COUNT;
+
+        Gee.List<MediaObject> children;
+
+        children = this.get_children (args.object_id,
+                                      args.index,
+                                      args.requested_count,
+                                      out args.total_matches);
+        args.number_returned = children.size;
+
+        /* Iterate through all items */
+        for (int i = 0; i < children.size; i++) {
+            children[i].serialize (didl_writer);
+        }
+
+        args.update_id = uint32.MAX;
+    }
+
+    private void add_metadata (DIDLLiteWriter didl_writer,
+                                         BrowseArgs     args)
+                                         throws GLib.Error {
+        MediaObject media_object = this.find_object_by_id (args.object_id);
+        media_object.serialize (didl_writer);
+
+        args.update_id = uint32.MAX;
+    }
+
+    private void add_root_children_metadata (
+                                        DIDLLiteWriter didl_writer,
+                                        BrowseArgs     args)
+                                        throws GLib.Error {
+        var children = get_root_children (args.index,
+                                          args.requested_count,
+                                          out args.total_matches);
+        foreach (var child in children) {
+            child.serialize (didl_writer);
+        }
+
+        args.number_returned = children.size;
+        args.update_id = uint32.MAX;
+    }
+
+    private Gee.List<MediaObject> get_children (string   container_id,
+                                                uint     offset,
+                                                uint     max_count,
+                                                out uint child_count)
+                                                throws GLib.Error {
+        var media_object = this.find_object_by_id (container_id);
+        if (media_object == null || !(media_object is MediaContainer)) {
+            throw new ContentDirectoryError.NO_SUCH_OBJECT ("No such object");
+        }
+
+        var container = (MediaContainer) media_object;
+        child_count = container.child_count;
+        if (max_count == 0) {
+            // No max count requested, try to fetch all children
+            max_count = child_count;
+        }
+
+        var children = container.get_children (offset, max_count);
+        if (children == null) {
+            throw new ContentDirectoryError.NO_SUCH_OBJECT ("No such object");
+        }
+
+        return children;
+    }
+
+    private MediaObject find_object_by_id (string object_id) throws GLib.Error {
+        var media_object = this.root_container.find_object_by_id (object_id);
+        if (media_object == null) {
+            throw new ContentDirectoryError.NO_SUCH_OBJECT ("No such object");
+        }
+
+        return media_object;
+    }
+
+    private Gee.List<MediaObject> get_root_children (uint     offset,
+                                                     uint     max_count,
+                                                     out uint child_count)
+                                                     throws GLib.Error {
+        child_count = this.root_container.child_count;
+        if (max_count == 0) {
+            // No max count requested, try to fetch all children
+            max_count = child_count;
+        }
+
+        var children = this.root_container.get_children (offset, max_count);
+        if (children == null) {
+            throw new ContentDirectoryError.NO_SUCH_OBJECT ("No such object");
+        }
+
+        return children;
+    }
+
+    private void on_item_requested (HTTPServer    http_server,
+                                    string        item_id,
+                                    out MediaItem item) {
+        try {
+            var media_object = this.find_object_by_id (item_id);
+            if (media_object is MediaItem) {
+                item = (MediaItem) media_object;
+            }
+        } catch (Error err) {
+            warning ("Requested item '%s' not found: %s\n",
+                     item_id,
+                     err.message);
+        }
+    }
 }
 

Modified: trunk/src/rygel/rygel-http-server.vala
==============================================================================
--- trunk/src/rygel/rygel-http-server.vala	(original)
+++ trunk/src/rygel/rygel-http-server.vala	Tue Jan 27 17:22:51 2009
@@ -134,7 +134,6 @@
         // Signal the requestion for an item
         this.item_requested (item_id, out item);
         if (item == null) {
-            warning ("Requested item '%s' not found\n", item_id);
             msg.set_status (Soup.KnownStatusCode.NOT_FOUND);
             return;
         }
@@ -158,7 +157,7 @@
             return;
         }
 
-        if (item.res.size > 0) {
+        if (item.size > 0) {
             this.handle_interactive_item (msg, item, seek);
         } else {
             this.handle_streaming_item (msg, item);
@@ -168,20 +167,16 @@
     private void add_item_headers (Soup.Message msg,
                                    MediaItem    item,
                                    Seek?        seek) {
-        if (item.res.mime_type != null) {
-            msg.response_headers.append ("Content-Type", item.res.mime_type);
+        if (item.mime_type != null) {
+            msg.response_headers.append ("Content-Type", item.mime_type);
         }
 
-        if (item.res.size >= 0) {
+        if (item.size >= 0) {
             msg.response_headers.append ("Content-Length",
-                                         item.res.size.to_string ());
+                                         item.size.to_string ());
         }
 
-        if (DLNAOperation.RANGE in item.res.dlna_operation) {
-            msg.response_headers.append ("Accept-Ranges", "bytes");
-        }
-
-        if (item.res.size > 0) {
+        if (item.size > 0) {
             int64 first_byte;
             int64 last_byte;
 
@@ -190,21 +185,22 @@
                 last_byte = seek.stop;
             } else {
                 first_byte = 0;
-                last_byte = item.res.size - 1;
+                last_byte = item.size - 1;
             }
 
             // Content-Range: bytes START_BYTE-STOP_BYTE/TOTAL_LENGTH
             var content_range = "bytes " +
                                 first_byte.to_string () + "-" +
                                 last_byte.to_string () + "/" +
-                                item.res.size.to_string ();
+                                item.size.to_string ();
             msg.response_headers.append ("Content-Range", content_range);
+            msg.response_headers.append ("Accept-Ranges", "bytes");
         }
     }
 
     private void handle_streaming_item (Soup.Message msg,
                                         MediaItem    item) {
-        string uri = item.res.uri;
+        string uri = item.uri;
         dynamic Element src = null;
 
         if (uri != null) {
@@ -239,7 +235,7 @@
     private void handle_interactive_item (Soup.Message msg,
                                           MediaItem    item,
                                           Seek?        seek) {
-        string uri = item.res.uri;
+        string uri = item.uri;
 
         if (uri == null) {
             warning ("Requested item '%s' didn't provide a URI\n", item.id);
@@ -248,7 +244,7 @@
         }
 
         try {
-            this.serve_uri (uri, msg, seek, item.res.size);
+            this.serve_uri (uri, msg, seek, item.size);
         } catch (Error error) {
             warning ("Error in attempting to serve %s: %s",
                      uri,
@@ -291,7 +287,7 @@
                                                        range);
             }
 
-            seek = new Seek (Format.BYTES, 0, item.res.size - 1);
+            seek = new Seek (Format.BYTES, 0, item.size - 1);
 
             // Get first byte position
             string first_byte = range_tokens[0];
@@ -311,16 +307,16 @@
                                                        range);
             }
 
-            if (item.res.size > 0) {
+            if (item.size > 0) {
                 // shouldn't go beyond actual length of media
-                if (seek.start > item.res.size ||
-                    seek.length > item.res.size) {
+                if (seek.start > item.size ||
+                    seek.length > item.size) {
                     throw new HTTPServerError.OUT_OF_RANGE (
                             "Range '%s' not setsifiable", range);
                 }
 
                 // No need to seek if whole stream is requested
-                if (seek.start == 0 && seek.length == item.res.size) {
+                if (seek.start == 0 && seek.length == item.size) {
                     return null;
                 }
             } else if (seek.start == 0) {

Modified: trunk/src/rygel/rygel-media-container.vala
==============================================================================
--- trunk/src/rygel/rygel-media-container.vala	(original)
+++ trunk/src/rygel/rygel-media-container.vala	Tue Jan 27 17:22:51 2009
@@ -24,7 +24,9 @@
 
 /**
  * Represents a container (folder) for media items and containers. Provides
- * basic serialization (to DIDLLiteWriter) implementation.
+ * basic serialization (to DIDLLiteWriter) implementation. Deriving classes
+ * are supposed to provide working implementations of get_children and
+ * find_object_by_id.
  */
 public class Rygel.MediaContainer : MediaObject {
     public uint child_count;
@@ -44,6 +46,12 @@
         this ("0", "-1", title, child_count);
     }
 
+   /**
+     * Serializes this container to the specified DIDLLiteWriter object
+     *
+     * @param didl_writer the DIDLLiteWriter object to serialize to.
+     *
+     */
     public override void serialize (DIDLLiteWriter didl_writer) throws Error {
         didl_writer.start_container (this.id,
                                      this.parent_id,
@@ -64,4 +72,30 @@
         /* End of Container */
         didl_writer.end_container ();
     }
+
+   /**
+     * Fetches the list of media objects directly under this container.
+     *
+     * @param offet zero-based index of the first item to return
+     * @param max_count maximum number of objects to return
+     *
+     * return A list of media objects.
+     */
+    public virtual Gee.List<MediaObject>? get_children (uint offset,
+                                                        uint max_count)
+                                                        throws Error {
+        return null;
+    }
+
+   /**
+     * Recursively searches for media object with the given id in this
+     * container.
+     *
+     * @param id ID of the media object to search for.
+     *
+     * return the found media object.
+     */
+    public virtual MediaObject? find_object_by_id (string id) throws Error {
+        return null;
+    }
 }

Modified: trunk/src/rygel/rygel-media-item.vala
==============================================================================
--- trunk/src/rygel/rygel-media-item.vala	(original)
+++ trunk/src/rygel/rygel-media-item.vala	Tue Jan 27 17:22:51 2009
@@ -42,10 +42,25 @@
     public string date;
     public string upnp_class;
 
-    public DIDLLiteResource res;
-
+    // Resource info
+    public string uri;
+    public string mime_type;
+
+    public long size = -1;       // Size in bytes
+    public long duration = -1;   // Duration in seconds
+    public int bitrate = -1;     // Bytes/second
+
+    // Audio/Music
+    public int sample_freq = -1;
+    public int bits_per_sample = -1;
+    public int n_audio_channels = -1;
     public int track_number = -1;
 
+    // Image/Video
+    public int width = -1;
+    public int height = -1;
+    public int color_depth = -1;
+
     protected Rygel.HTTPServer http_server;
 
     public MediaItem (string     id,
@@ -58,9 +73,6 @@
         this.title = title;
         this.upnp_class = upnp_class;
         this.http_server = http_server;
-
-        this.res = DIDLLiteResource ();
-        this.res.reset ();
     }
 
     public override void serialize (DIDLLiteWriter didl_writer) throws Error {
@@ -121,24 +133,7 @@
         }
 
         /* Add resource data */
-        /* Protocol info */
-        if (this.res.uri != null) {
-            string protocol = get_protocol_for_uri (this.res.uri);
-            this.res.protocol = protocol;
-        }
-
-        this.res.dlna_profile = "MP3"; /* FIXME */
-
-        if (this.upnp_class.has_prefix (MediaItem.IMAGE_CLASS)) {
-            this.res.dlna_flags |= DLNAFlags.INTERACTIVE_TRANSFER_MODE;
-        } else {
-            this.res.dlna_flags |= DLNAFlags.STREAMING_TRANSFER_MODE;
-        }
-
-        if (this.res.size > 0) {
-            this.res.dlna_operation = DLNAOperation.RANGE;
-            this.res.dlna_flags |= DLNAFlags.BACKGROUND_TRANSFER_MODE;
-        }
+        DIDLLiteResource res = this.get_original_res ();
 
         /* Now get the transcoded/proxy URIs */
         var res_list = this.get_transcoded_resources (res);
@@ -147,7 +142,7 @@
         }
 
         /* Add the original res in the end */
-        if (this.res.uri != null) {
+        if (res.uri != null) {
             didl_writer.add_res (res);
         }
 
@@ -188,4 +183,46 @@
 
         return resources;
     }
+
+    private DIDLLiteResource get_original_res () throws Error {
+        DIDLLiteResource res = DIDLLiteResource ();
+        res.reset ();
+
+        res.uri = this.uri;
+        res.mime_type = this.mime_type;
+
+        res.size = this.size;
+        res.duration = this.duration;
+        res.bitrate = this.bitrate;
+
+        res.sample_freq = this.sample_freq;
+        res.bits_per_sample = this.bits_per_sample;
+        res.n_audio_channels = this.n_audio_channels;
+
+        res.width = this.width;
+        res.height = this.height;
+        res.color_depth = this.color_depth;
+
+        /* Protocol info */
+        if (res.uri != null) {
+            string protocol = get_protocol_for_uri (res.uri);
+            res.protocol = protocol;
+        }
+
+        /* DLNA related fields */
+        res.dlna_profile = "MP3"; /* FIXME */
+
+        if (this.upnp_class.has_prefix (MediaItem.IMAGE_CLASS)) {
+            res.dlna_flags |= DLNAFlags.INTERACTIVE_TRANSFER_MODE;
+        } else {
+            res.dlna_flags |= DLNAFlags.STREAMING_TRANSFER_MODE;
+        }
+
+        if (res.size > 0) {
+            res.dlna_operation = DLNAOperation.RANGE;
+            res.dlna_flags |= DLNAFlags.BACKGROUND_TRANSFER_MODE;
+        }
+
+        return res;
+    }
 }

Modified: trunk/src/rygel/rygel-seekable-response.vala
==============================================================================
--- trunk/src/rygel/rygel-seekable-response.vala	(original)
+++ trunk/src/rygel/rygel-seekable-response.vala	Tue Jan 27 17:22:51 2009
@@ -32,6 +32,8 @@
     private char[] buffer;
     private size_t length;
 
+    int priority;
+
     public SeekableResponse (Soup.Server  server,
                              Soup.Message msg,
                              string       uri,
@@ -41,6 +43,7 @@
 
         this.seek = seek;
         this.length = file_length;
+        this.priority = this.get_requested_priority ();
 
         if (seek != null) {
             this.length = (size_t) seek.length;
@@ -51,7 +54,7 @@
         this.buffer = new char[this.length];
         this.file = File.new_for_uri (uri);
 
-        this.file.read_async (Priority.DEFAULT, null, this.on_file_read);
+        this.file.read_async (this.priority, null, this.on_file_read);
     }
 
     private void on_file_read (GLib.Object      source_object,
@@ -85,7 +88,7 @@
 
         input_stream.read_async (this.buffer,
                                  this.length,
-                                 Priority.DEFAULT,
+                                 this.priority,
                                  null,
                                  on_contents_read);
     }
@@ -106,7 +109,7 @@
 
         this.push_data (this.buffer, this.length);
 
-        input_stream.close_async (Priority.DEFAULT,
+        input_stream.close_async (this.priority,
                                   null,
                                   on_input_stream_closed);
     }
@@ -125,5 +128,19 @@
 
         this.end (false, Soup.KnownStatusCode.NONE);
     }
+
+    private int get_requested_priority () {
+        var mode = this.msg.request_headers.get ("transferMode.dlna.org");
+
+        if (mode == null || mode == "Interactive") {
+            return Priority.DEFAULT;
+        } else if (mode == "Streaming") {
+            return Priority.HIGH;
+        } else if (mode == "Background") {
+            return Priority.LOW;
+        } else {
+            return Priority.DEFAULT;
+        }
+    }
 }
 



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