[rygel] server: Use MediaResource for playlists



commit d50218a1ba52815a3601c67df4da130712bea501
Author: Jens Georg <mail jensge org>
Date:   Mon Nov 17 06:37:39 2014 +0100

    server: Use MediaResource for playlists
    
    Use the newly introduced MediaResource to serialize MediaContainer's
    playlist resources.
    
    Patch derived from Cablelabs's CVP-2 implementation
    
    Signed-off-by: Jens Georg <mail jensge org>

 src/librygel-server/filelist.am                    |    2 +-
 src/librygel-server/rygel-http-get.vala            |   13 +-
 src/librygel-server/rygel-http-item-uri.vala       |   12 +-
 .../rygel-http-playlist-handler.vala               |   81 --------
 src/librygel-server/rygel-http-request.vala        |    8 +-
 .../rygel-http-resource-handler.vala               |  102 ++++++++++
 src/librygel-server/rygel-http-server.vala         |    4 +-
 src/librygel-server/rygel-media-container.vala     |  199 ++++++++++++++------
 src/librygel-server/rygel-media-engine.vala        |    7 +
 src/librygel-server/rygel-media-file-item.vala     |    8 +
 src/librygel-server/rygel-media-object.vala        |    8 +-
 src/librygel-server/rygel-music-item.vala          |    1 -
 src/librygel-server/rygel-object-creator.vala      |    1 -
 src/librygel-server/rygel-transcode-manager.vala   |    1 -
 src/librygel-server/rygel-transcoder.vala          |    1 -
 src/librygel-server/rygel-video-item.vala          |    1 -
 src/librygel-server/rygel-visual-item.vala         |    1 -
 17 files changed, 277 insertions(+), 173 deletions(-)
---
diff --git a/src/librygel-server/filelist.am b/src/librygel-server/filelist.am
index 6364270..86c8bc3 100644
--- a/src/librygel-server/filelist.am
+++ b/src/librygel-server/filelist.am
@@ -44,7 +44,6 @@ LIBRYGEL_SERVER_NONVAPI_SOURCE_FILES = \
        rygel-http-get-handler.vala \
        rygel-http-get.vala \
        rygel-http-identity-handler.vala \
-       rygel-http-playlist-handler.vala \
        rygel-http-item-uri.vala \
        rygel-http-post.vala \
        rygel-http-request.vala \
@@ -52,6 +51,7 @@ LIBRYGEL_SERVER_NONVAPI_SOURCE_FILES = \
        rygel-http-server.vala \
        rygel-http-time-seek.vala \
        rygel-http-transcode-handler.vala \
+       rygel-http-resource-handler.vala \
        rygel-import-resource.vala \
        rygel-object-creator.vala \
        rygel-reference-creator.vala \
diff --git a/src/librygel-server/rygel-http-get.vala b/src/librygel-server/rygel-http-get.vala
index 19f587f..ede92a9 100644
--- a/src/librygel-server/rygel-http-get.vala
+++ b/src/librygel-server/rygel-http-get.vala
@@ -66,10 +66,10 @@ internal class Rygel.HTTPGet : HTTPRequest {
                                                      this.cancellable);
         }
 
-        if (uri.playlist_format != null &&
-            HTTPPlaylistHandler.is_supported (uri.playlist_format)) {
-            this.handler = new HTTPPlaylistHandler (uri.playlist_format,
-                                                    this.cancellable);
+        if (uri.resource_name != null) {
+            this.handler = new HTTPMediaResourceHandler (this.object,
+                                                         uri.resource_name,
+                                                         this.cancellable);
         }
 
         if (this.handler == null) {
@@ -213,7 +213,7 @@ internal class Rygel.HTTPGet : HTTPRequest {
 
         switch (mode) {
         case "Streaming":
-            correct = (!(this.handler is HTTPPlaylistHandler)) && (
+            correct = (
                       (this.handler is HTTPTranscodeHandler ||
                       ((this.object as MediaFileItem).streamable () &&
                        this.subtitle == null &&
@@ -225,8 +225,7 @@ internal class Rygel.HTTPGet : HTTPRequest {
                       ((!(this.object as MediaFileItem).is_live_stream () &&
                        !(this.object as MediaFileItem).streamable ()) ||
                        (this.subtitle != null ||
-                        this.thumbnail != null))) ||
-                      this.handler is HTTPPlaylistHandler;
+                        this.thumbnail != null)));
 
             break;
         }
diff --git a/src/librygel-server/rygel-http-item-uri.vala b/src/librygel-server/rygel-http-item-uri.vala
index 99e81cb..ae03c34 100644
--- a/src/librygel-server/rygel-http-item-uri.vala
+++ b/src/librygel-server/rygel-http-item-uri.vala
@@ -25,12 +25,11 @@
 
 using Gee;
 
-internal class Rygel.HTTPItemURI : Object {
+public class Rygel.HTTPItemURI : Object {
     public string item_id { get; set; }
     public int thumbnail_index { get; set; default = -1; }
     public int subtitle_index { get; set; default = -1; }
     public string? transcode_target { get; set; default = null; }
-    public string? playlist_format { get; set; default = null; }
     public string? resource_name { get; set; default = null; }
     public unowned HTTPServer http_server { get; set; }
 
@@ -54,14 +53,12 @@ internal class Rygel.HTTPItemURI : Object {
                         int        thumbnail_index = -1,
                         int        subtitle_index = -1,
                         string?    transcode_target = null,
-                        string?    playlist_format = null,
                         string?    resource_name = null) {
         this.item_id = object.id;
         this.thumbnail_index = thumbnail_index;
         this.subtitle_index = subtitle_index;
         this.transcode_target = transcode_target;
         this.http_server = http_server;
-        this.playlist_format = playlist_format;
         this.resource_name = resource_name;
         this.extension = "";
 
@@ -196,10 +193,6 @@ internal class Rygel.HTTPItemURI : Object {
                     this.subtitle_index = int.parse (parts[i + 1]);
 
                     break;
-                case "pl":
-                    this.playlist_format = Soup.URI.decode (parts[i + 1]);
-
-                    break;
                 case "res":
                     this.resource_name = Soup.URI.decode (parts[i + 1]);
 
@@ -230,9 +223,6 @@ internal class Rygel.HTTPItemURI : Object {
             path += "/th/" + this.thumbnail_index.to_string ();
         } else if (this.subtitle_index >= 0) {
             path += "/sub/" + this.subtitle_index.to_string ();
-        } else if (this.playlist_format != null) {
-            path += "/pl/" + Uri.escape_string
-                                        (this.playlist_format, "", true);
         } else if (this.resource_name != null) {
             path += "/res/" + Uri.escape_string
                                         (this.resource_name, "", true);
diff --git a/src/librygel-server/rygel-http-playlist-handler.vala 
b/src/librygel-server/rygel-http-playlist-handler.vala
index 6a8d5aa..92a8907 100644
--- a/src/librygel-server/rygel-http-playlist-handler.vala
+++ b/src/librygel-server/rygel-http-playlist-handler.vala
@@ -21,87 +21,6 @@
  */
 using GUPnP;
 
-/**
- * Implementation of RygelDataSource to serve generated playlists to a client.
- */
-internal class Rygel.PlaylistDatasource : Rygel.DataSource, Object {
-    private MediaContainer container;
-    private uint8[] data;
-    private HTTPServer server;
-    private ClientHacks hacks;
-    private SerializerType playlist_type;
-
-    public PlaylistDatasource (SerializerType playlist_type,
-                               MediaContainer container,
-                               HTTPServer     server,
-                               ClientHacks?   hacks) {
-        this.playlist_type = playlist_type;
-        this.container = container;
-        this.server = server;
-        this.hacks = hacks;
-        this.generate_data.begin ();
-    }
-
-    public signal void data_ready ();
-
-    public void start (HTTPSeek? offsets) throws Error {
-        if (offsets != null) {
-            throw new DataSourceError.SEEK_FAILED
-                                        (_("Seeking not supported"));
-        }
-
-        if (this.data == null) {
-            this.data_ready.connect ( () => {
-                try {
-                    this.start (offsets);
-                } catch (Error error) { }
-            });
-
-            return;
-        }
-
-        Idle.add ( () => {
-            this.data_available (this.data);
-            this.done ();
-
-            return false;
-        });
-    }
-
-    public void freeze () { }
-
-    public void thaw () { }
-
-    public void stop () { }
-
-    public async void generate_data () {
-        try {
-            var sort_criteria = this.container.sort_criteria;
-            var count = this.container.child_count;
-
-            var children = yield this.container.get_children (0,
-                                                              count,
-                                                              sort_criteria,
-                                                              null);
-
-            if (children != null) {
-                var serializer = new Serializer (this.playlist_type);
-                children.serialize (serializer, this.server, this.hacks);
-
-                var xml = serializer.get_string ();
-
-                this.data = xml.data;
-                this.data_ready ();
-            } else {
-                this.error (new DataSourceError.GENERAL
-                                        (_("Failed to generate playlist")));
-            }
-        } catch (Error error) {
-            warning ("Could not generate playlist: %s", error.message);
-            this.error (error);
-        }
-    }
-}
 
 /**
  * RygelHTTPPlaylistHandler implements a special handler for generating XML
diff --git a/src/librygel-server/rygel-http-request.vala b/src/librygel-server/rygel-http-request.vala
index 2d3baef..389d3c0 100644
--- a/src/librygel-server/rygel-http-request.vala
+++ b/src/librygel-server/rygel-http-request.vala
@@ -25,7 +25,7 @@
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
-internal errordomain Rygel.HTTPRequestError {
+public errordomain Rygel.HTTPRequestError {
     UNACCEPTABLE = Soup.Status.NOT_ACCEPTABLE,
     BAD_REQUEST = Soup.Status.BAD_REQUEST,
     NOT_FOUND = Soup.Status.NOT_FOUND,
@@ -35,7 +35,7 @@ internal errordomain Rygel.HTTPRequestError {
 /**
  * Base class for HTTP client requests.
  */
-internal abstract class Rygel.HTTPRequest : GLib.Object, Rygel.StateMachine {
+public abstract class Rygel.HTTPRequest : GLib.Object, Rygel.StateMachine {
     public unowned HTTPServer http_server;
     private MediaContainer root_container;
     public unowned Soup.Server server;
@@ -89,8 +89,8 @@ internal abstract class Rygel.HTTPRequest : GLib.Object, Rygel.StateMachine {
 
         if (media_object == null ||
             !((media_object is MediaContainer &&
-               this.uri.playlist_format != null) ||
-              (media_object is MediaFileItem && this.uri.playlist_format == null))) {
+               this.uri.resource_name != null) ||
+              (media_object is MediaFileItem))) {
             throw new HTTPRequestError.NOT_FOUND
                                         (_("Requested item '%s' not found"),
                                          this.uri.item_id);
diff --git a/src/librygel-server/rygel-http-resource-handler.vala 
b/src/librygel-server/rygel-http-resource-handler.vala
new file mode 100644
index 0000000..dd87dc0
--- /dev/null
+++ b/src/librygel-server/rygel-http-resource-handler.vala
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2013  Cable Television Laboratories, Inc.
+ *
+ * Author: Craig Pratt <craig ecaspia 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.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CABLE TELEVISION LABORATORIES
+ * INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using GUPnP;
+
+/**
+ * The HTTP handler for HTTP ContentResource requests.
+ */
+internal class Rygel.HTTPMediaResourceHandler : HTTPGetHandler {
+    private MediaObject media_object;
+    private string media_resource_name;
+    public MediaResource media_resource;
+
+    public HTTPMediaResourceHandler (MediaObject media_object,
+                                     string media_resource_name,
+                                     Cancellable? cancellable) throws HTTPRequestError
+    {
+        this.media_object = media_object;
+        this.cancellable = cancellable;
+        this.media_resource_name = media_resource_name;
+        foreach (var resource in media_object.get_resource_list ()) {
+            if (resource.get_name () == media_resource_name) {
+                this.media_resource
+                    = new MediaResource.from_resource (resource.get_name (),
+                                                       resource);
+            }
+        }
+        if (this.media_resource == null) {
+            throw new HTTPRequestError.NOT_FOUND ("MediaResource %s not found",
+                                                  media_resource_name);
+        }
+    }
+
+    public override void add_response_headers (HTTPGet request)
+                                               throws HTTPRequestError {
+        request.http_server.set_resource_delivery_options (this.media_resource);
+        request.msg.response_headers.append ("Content-Type",
+                                             this.media_resource.mime_type);
+
+        // Add contentFeatures.dlna.org
+        var protocol_info = this.media_resource.get_protocol_info ();
+        if (protocol_info != null) {
+            var pi_fields = protocol_info.to_string ().split (":", 4);
+            if (pi_fields[3] != null) {
+                request.msg.response_headers.append ("contentFeatures.dlna.org",
+                                                     pi_fields[3]);
+            }
+        }
+
+        // Chain-up
+        base.add_response_headers (request);
+    }
+
+    public override HTTPResponse render_body (HTTPGet request)
+                                              throws HTTPRequestError {
+        try {
+            var src = request.object.create_stream_source_for_resource
+                                    (request, this.media_resource);
+            if (src == null) {
+                throw new HTTPRequestError.NOT_FOUND
+                              (_("Couldn't create data source for %s"),
+                               this.media_resource.get_name ());
+            }
+
+            return new HTTPResponse (request, this, src);
+        } catch (Error err) {
+            throw new HTTPRequestError.NOT_FOUND (err.message);
+        }
+    }
+
+    protected override DIDLLiteResource add_resource (DIDLLiteObject didl_object,
+                                                      HTTPGet      request)
+                                                      throws Error {
+        return null as DIDLLiteResource;
+    }
+}
diff --git a/src/librygel-server/rygel-http-server.vala b/src/librygel-server/rygel-http-server.vala
index cfe470a..daabf0b 100644
--- a/src/librygel-server/rygel-http-server.vala
+++ b/src/librygel-server/rygel-http-server.vala
@@ -84,7 +84,7 @@ public class Rygel.HTTPServer : Rygel.TranscodeManager, Rygel.StateMachine {
             return;
         }
 
-        var uri = this.create_uri_for_object (item, -1, -1, null, null, null);
+        var uri = this.create_uri_for_object (item, -1, -1, null, null);
 
         item.add_resource (didl_item, uri, this.get_protocol (), uri);
     }
@@ -120,14 +120,12 @@ public class Rygel.HTTPServer : Rygel.TranscodeManager, Rygel.StateMachine {
                                                     int         thumbnail_index,
                                                     int         subtitle_index,
                                                     string?     transcode_target,
-                                                    string?     playlist_target,
                                                     string?     resource_name) {
         var uri = new HTTPItemURI (object,
                                    this,
                                    thumbnail_index,
                                    subtitle_index,
                                    transcode_target,
-                                   playlist_target,
                                    resource_name);
 
         return uri.to_string ();
diff --git a/src/librygel-server/rygel-media-container.vala b/src/librygel-server/rygel-media-container.vala
index 5000084..e739ad3 100644
--- a/src/librygel-server/rygel-media-container.vala
+++ b/src/librygel-server/rygel-media-container.vala
@@ -36,6 +36,88 @@ public enum Rygel.ObjectEventType {
 }
 
 /**
+ * Implementation of RygelDataSource to serve generated playlists to a client.
+ */
+internal class Rygel.PlaylistDatasource : Rygel.DataSource, Object {
+    private MediaContainer container;
+    private uint8[] data;
+    private HTTPServer server;
+    private ClientHacks hacks;
+    private SerializerType playlist_type;
+
+    public PlaylistDatasource (SerializerType playlist_type,
+                               MediaContainer container,
+                               HTTPServer     server,
+                               ClientHacks?   hacks) {
+        this.playlist_type = playlist_type;
+        this.container = container;
+        this.server = server;
+        this.hacks = hacks;
+        this.generate_data.begin ();
+    }
+
+    public signal void data_ready ();
+
+    public void start (HTTPSeek? offsets) throws Error {
+        if (offsets != null) {
+            throw new DataSourceError.SEEK_FAILED
+                                        (_("Seeking not supported"));
+        }
+
+        if (this.data == null) {
+            this.data_ready.connect ( () => {
+                try {
+                    this.start (offsets);
+                } catch (Error error) { }
+            });
+
+            return;
+        }
+
+        Idle.add ( () => {
+            this.data_available (this.data);
+            this.done ();
+
+            return false;
+        });
+    }
+
+    public void freeze () { }
+
+    public void thaw () { }
+
+    public void stop () { }
+
+    public async void generate_data () {
+        try {
+            var sort_criteria = this.container.sort_criteria;
+            var count = this.container.child_count;
+
+            var children = yield this.container.get_children (0,
+                                                              count,
+                                                              sort_criteria,
+                                                              null);
+
+            if (children != null) {
+                var serializer = new Serializer (this.playlist_type);
+                children.serialize (serializer, this.server, this.hacks);
+
+                var xml = serializer.get_string ();
+
+                this.data = xml.data;
+                this.data_ready ();
+            } else {
+                this.error (new DataSourceError.GENERAL
+                                        (_("Failed to generate playlist")));
+            }
+        } catch (Error error) {
+            warning ("Could not generate playlist: %s", error.message);
+            this.error (error);
+        }
+    }
+}
+
+/**
  * This is a container (folder) for media items and child containers.
  *
  * It provides a basic serialization implementation (to DIDLLiteWriter).
@@ -77,6 +159,9 @@ public abstract class Rygel.MediaContainer : MediaObject {
                                               "+upnp:originalTrackNumber," +
                                               "+dc:title";
 
+    private const string DIDL_S_PLAYLIST_RESNAME = "didl_s_playlist";
+    private const string M3U_PLAYLIST_RESNAME = "m3u_playlist";
+
     public static bool equal_func (MediaContainer a, MediaContainer b) {
         return a.id == b.id;
     }
@@ -209,6 +294,7 @@ public abstract class Rygel.MediaContainer : MediaObject {
 
         this.container_updated.connect (on_container_updated);
         this.sub_tree_updates_finished.connect (on_sub_tree_updates_finished);
+        this.add_playlist_resources ();
     }
 
     /**
@@ -269,6 +355,36 @@ public abstract class Rygel.MediaContainer : MediaObject {
                                 sub_tree_update);
     }
 
+
+    /**
+     * Add playlist resources to the MediaObject resource list
+     */
+    internal void add_playlist_resources () {
+        { // Create the DIDL_S playlist resource
+            var didl_s_res = new MediaResource (DIDL_S_PLAYLIST_RESNAME);
+            didl_s_res.extension = "xml";
+            didl_s_res.mime_type = "text/xml";
+            didl_s_res.dlna_profile = "DIDL_S";
+            didl_s_res.dlna_flags = DLNAFlags.CONNECTION_STALL |
+                                    DLNAFlags.BACKGROUND_TRANSFER_MODE |
+                                    DLNAFlags.INTERACTIVE_TRANSFER_MODE;
+            didl_s_res.uri = ""; // Established during serialization
+            this.get_resource_list ().add (didl_s_res);
+        }
+
+        { // Create the M3U playlist resource
+            var m3u_res = new MediaResource (M3U_PLAYLIST_RESNAME);
+            m3u_res.extension = "m3u";
+            m3u_res.mime_type = "audio/x-mpegurl";
+            m3u_res.dlna_profile = null;
+            m3u_res.dlna_flags = DLNAFlags.CONNECTION_STALL |
+                                 DLNAFlags.BACKGROUND_TRANSFER_MODE |
+                                 DLNAFlags.INTERACTIVE_TRANSFER_MODE;
+            m3u_res.uri = ""; // Established during serialization
+            this.get_resource_list ().add (m3u_res);
+        }
+    }
+
     public override DIDLLiteObject? serialize (Serializer serializer,
                                                HTTPServer http_server)
                                                throws Error {
@@ -317,73 +433,38 @@ public abstract class Rygel.MediaContainer : MediaObject {
             didl_container.restricted = true;
         }
 
-        this.add_resources (http_server, didl_container);
+        if (this.child_count > 0) {
+            this.serialize_resource_list (didl_container, http_server);
+        }
 
         return didl_container;
     }
 
-    internal void add_resources (Rygel.HTTPServer http_server,
-                                 DIDLLiteContainer didl_container)
-                                 throws Error {
-        // Add resource with container contents serialized to DIDL_S playlist
-        var uri = new HTTPItemURI (this,
-                                   http_server,
-                                   -1,
-                                   -1,
-                                   null,
-                                   "DIDL_S");
-        uri.extension = "xml";
-
-        var res = this.add_resource (didl_container,
-                                     uri.to_string (),
-                                     http_server.get_protocol ());
-        if (res != null) {
-            res.protocol_info.mime_type = "text/xml";
-            res.protocol_info.dlna_profile = "DIDL_S";
+    public override DataSource? create_stream_source_for_resource
+                                         (HTTPRequest request,
+                                          MediaResource resource)
+                                          throws Error {
+        SerializerType playlist_type;
+
+        switch (resource.get_name ()) {
+            case DIDL_S_PLAYLIST_RESNAME:
+                playlist_type = SerializerType.DIDL_S;
+                break;
+            case M3U_PLAYLIST_RESNAME:
+                playlist_type = SerializerType.M3UEXT;
+                break;
+            default:
+                warning (_("Unknown MediaContainer resource: %s"), resource.get_name ());
+
+                return null;
         }
 
-        // Add resource with container contents serialized to M3U playlist
-        uri = new HTTPItemURI (this, http_server, -1, -1, null, "M3U");
-        uri.extension = "m3u";
-
-        res = this.add_resource (didl_container,
-                                 uri.to_string (),
-                                 http_server.get_protocol ());
-        if (res != null) {
-            res.protocol_info.mime_type = "audio/x-mpegurl";
-        }
+        return new PlaylistDatasource (playlist_type,
+                                       this,
+                                       request.http_server,
+                                       request.hack);
     }
 
-    internal override DIDLLiteResource add_resource
-                                        (DIDLLiteObject didl_object,
-                                         string?        uri,
-                                         string         protocol,
-                                         string?        import_uri = null)
-                                         throws Error {
-        if (this.child_count <= 0) {
-            return null as DIDLLiteResource;
-        }
-
-        var res = base.add_resource (didl_object,
-                                     uri,
-                                     protocol,
-                                     import_uri);
-
-        if (uri != null) {
-            res.uri = uri;
-        }
-
-        var protocol_info = new ProtocolInfo ();
-        protocol_info.mime_type = "";
-        protocol_info.protocol = protocol;
-        protocol_info.dlna_flags = DLNAFlags.DLNA_V15 |
-                                   DLNAFlags.CONNECTION_STALL |
-                                   DLNAFlags.BACKGROUND_TRANSFER_MODE |
-                                   DLNAFlags.INTERACTIVE_TRANSFER_MODE;
-        res.protocol_info = protocol_info;
-
-        return res;
-    }
 
     /**
      * The handler for the container_updated signal on this container. We only forward
diff --git a/src/librygel-server/rygel-media-engine.vala b/src/librygel-server/rygel-media-engine.vala
index 28d61b1..247475b 100644
--- a/src/librygel-server/rygel-media-engine.vala
+++ b/src/librygel-server/rygel-media-engine.vala
@@ -105,6 +105,13 @@ public abstract class Rygel.MediaEngine : GLib.Object {
      */
     public abstract unowned List<Transcoder>? get_transcoders ();
 
+    public virtual DataSource? create_data_source_for_resource
+                                        (MediaObject item,
+                                         MediaResource resource)
+                                         throws Error {
+        return this.create_data_source (resource.uri);
+    }
+
     /**
      * Get a data source for the URI.
      *
diff --git a/src/librygel-server/rygel-media-file-item.vala b/src/librygel-server/rygel-media-file-item.vala
index a410f04..249d285 100644
--- a/src/librygel-server/rygel-media-file-item.vala
+++ b/src/librygel-server/rygel-media-file-item.vala
@@ -141,6 +141,14 @@ public abstract class Rygel.MediaFileItem : MediaItem {
         return MediaEngine.get_default ().create_data_source (translated_uri);
     }
 
+    public override DataSource? create_stream_source_for_resource
+                                        (HTTPRequest request,
+                                         MediaResource resource)
+                                         throws Error {
+        return MediaEngine.get_default ().create_data_source_for_resource
+                                        (this, resource);
+    }
+
     public bool is_live_stream () {
         return this.streamable () && this.size <= 0;
     }
diff --git a/src/librygel-server/rygel-media-object.vala b/src/librygel-server/rygel-media-object.vala
index 2917c8a..179ee06 100644
--- a/src/librygel-server/rygel-media-object.vala
+++ b/src/librygel-server/rygel-media-object.vala
@@ -258,7 +258,6 @@ public abstract class Rygel.MediaObject : GLib.Object {
                                                              -1,
                                                              -1,
                                                              null,
-                                                             null,
                                                              res.get_name ());
                 var didl_resource = didl_object.add_resource ();
                 http_server.set_resource_delivery_options (res);
@@ -279,6 +278,13 @@ public abstract class Rygel.MediaObject : GLib.Object {
         }
     }
 
+    /**
+     * Create a stream source for the given resource
+     */
+    public abstract DataSource? create_stream_source_for_resource
+                                        (HTTPRequest request,
+                                         MediaResource resource) throws Error;
+
 
     internal virtual void apply_didl_lite (DIDLLiteObject didl_object) {
         this.title = didl_object.title;
diff --git a/src/librygel-server/rygel-music-item.vala b/src/librygel-server/rygel-music-item.vala
index 43678f8..9c48f5d 100644
--- a/src/librygel-server/rygel-music-item.vala
+++ b/src/librygel-server/rygel-music-item.vala
@@ -135,7 +135,6 @@ public class Rygel.MusicItem : AudioItem {
                                                                 0,
                                                                 -1,
                                                                 null,
-                                                                null,
                                                                 null);
         }
     }
diff --git a/src/librygel-server/rygel-object-creator.vala b/src/librygel-server/rygel-object-creator.vala
index 1922a49..a6372bd 100644
--- a/src/librygel-server/rygel-object-creator.vala
+++ b/src/librygel-server/rygel-object-creator.vala
@@ -79,7 +79,6 @@ private class Rygel.BaseMediaContainer : MediaContainer {
                                                     throws Error {
         return null;
     }
-
 }
 
 
diff --git a/src/librygel-server/rygel-transcode-manager.vala 
b/src/librygel-server/rygel-transcode-manager.vala
index 916ef04..baaf60b 100644
--- a/src/librygel-server/rygel-transcode-manager.vala
+++ b/src/librygel-server/rygel-transcode-manager.vala
@@ -45,7 +45,6 @@ public abstract class Rygel.TranscodeManager : GLib.Object {
                                                   int          thumbnail_index,
                                                   int          subtitle_index,
                                                   string?      transcode_target,
-                                                  string?      playlist_target,
                                                   string?      resource_name);
 
     public void add_resources (DIDLLiteItem didl_item, MediaFileItem item)
diff --git a/src/librygel-server/rygel-transcoder.vala b/src/librygel-server/rygel-transcoder.vala
index efa6152..fb48fd3 100644
--- a/src/librygel-server/rygel-transcoder.vala
+++ b/src/librygel-server/rygel-transcoder.vala
@@ -83,7 +83,6 @@ public abstract class Rygel.Transcoder : GLib.Object {
                                                  -1,
                                                  -1,
                                                  this.dlna_profile,
-                                                 null,
                                                  null);
         var res = item.add_resource (didl_item, uri, protocol);
         res.size = -1;
diff --git a/src/librygel-server/rygel-video-item.vala b/src/librygel-server/rygel-video-item.vala
index 514bbd1..c9d3a16 100644
--- a/src/librygel-server/rygel-video-item.vala
+++ b/src/librygel-server/rygel-video-item.vala
@@ -195,7 +195,6 @@ public class Rygel.VideoItem : AudioItem, VisualItem {
                                                              -1,
                                                              index,
                                                              null,
-                                                             null,
                                                              null);
                 subtitle.add_didl_node (didl_item);
 
diff --git a/src/librygel-server/rygel-visual-item.vala b/src/librygel-server/rygel-visual-item.vala
index 254d61d..2ab8897 100644
--- a/src/librygel-server/rygel-visual-item.vala
+++ b/src/librygel-server/rygel-visual-item.vala
@@ -101,7 +101,6 @@ public interface Rygel.VisualItem : MediaFileItem {
                                                               index,
                                                               -1,
                                                               null,
-                                                              null,
                                                               null);
                 thumbnail.add_resource (didl_item, server.get_protocol ());
 


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