[rygel] server: Refactor subtitle handling



commit 5c7579defe3d55de71f5328c2dde4f7586952b14
Author: Jens Georg <mail jensge org>
Date:   Sat Nov 29 14:51:04 2014 +0100

    server: Refactor subtitle handling
    
    Code based on Cablelabs's CVP-2 implementation.

 src/librygel-server/filelist.am                    |    1 +
 src/librygel-server/rygel-http-byte-seek.vala      |    3 +-
 src/librygel-server/rygel-http-get.vala            |    6 +
 .../rygel-http-identity-handler.vala               |   16 +---
 .../rygel-http-thumbnail-handler.vala              |  103 ++++++++++++++++++++
 src/librygel-server/rygel-http-time-seek.vala      |    2 +-
 src/librygel-server/rygel-image-item.vala          |   26 ++----
 src/librygel-server/rygel-thumbnail.vala           |   51 +++-------
 src/librygel-server/rygel-video-item.vala          |   11 +-
 src/librygel-server/rygel-visual-item.vala         |   56 ++++++-----
 10 files changed, 171 insertions(+), 104 deletions(-)
---
diff --git a/src/librygel-server/filelist.am b/src/librygel-server/filelist.am
index 86c8bc3..29ce50a 100644
--- a/src/librygel-server/filelist.am
+++ b/src/librygel-server/filelist.am
@@ -43,6 +43,7 @@ LIBRYGEL_SERVER_NONVAPI_SOURCE_FILES = \
        rygel-http-byte-seek.vala \
        rygel-http-get-handler.vala \
        rygel-http-get.vala \
+       rygel-http-thumbnail-handler.vala \
        rygel-http-identity-handler.vala \
        rygel-http-item-uri.vala \
        rygel-http-post.vala \
diff --git a/src/librygel-server/rygel-http-byte-seek.vala b/src/librygel-server/rygel-http-byte-seek.vala
index 5742e06..76cb361 100644
--- a/src/librygel-server/rygel-http-byte-seek.vala
+++ b/src/librygel-server/rygel-http-byte-seek.vala
@@ -71,8 +71,7 @@ internal class Rygel.HTTPByteSeek : Rygel.HTTPSeek {
         return force_seek || (!(request.object is MediaContainer) &&
                 ((request.object as MediaFileItem).size > 0 &&
                 request.handler is HTTPIdentityHandler) ||
-               (request.thumbnail != null &&
-                request.thumbnail.size > 0) ||
+                (request.handler is HTTPThumbnailHandler) ||
                (request.subtitle != null && request.subtitle.size > 0));
     }
 
diff --git a/src/librygel-server/rygel-http-get.vala b/src/librygel-server/rygel-http-get.vala
index 3a4e229..b3fd5b9 100644
--- a/src/librygel-server/rygel-http-get.vala
+++ b/src/librygel-server/rygel-http-get.vala
@@ -72,6 +72,12 @@ internal class Rygel.HTTPGet : HTTPRequest {
                                                          this.cancellable);
         }
 
+        if (uri.thumbnail_index >= 0) {
+            this.handler = new HTTPThumbnailHandler (this.object as MediaFileItem,
+                                                     uri.thumbnail_index,
+                                                     this.cancellable);
+        }
+
         if (this.handler == null) {
             this.handler = new HTTPIdentityHandler (this.cancellable);
         }
diff --git a/src/librygel-server/rygel-http-identity-handler.vala 
b/src/librygel-server/rygel-http-identity-handler.vala
index f39e361..6c8b126 100644
--- a/src/librygel-server/rygel-http-identity-handler.vala
+++ b/src/librygel-server/rygel-http-identity-handler.vala
@@ -37,9 +37,6 @@ internal class Rygel.HTTPIdentityHandler : Rygel.HTTPGetHandler {
         if (request.subtitle != null) {
            request.msg.response_headers.append ("Content-Type",
                                                 request.subtitle.mime_type);
-        } else if (request.thumbnail != null) {
-            request.msg.response_headers.append ("Content-Type",
-                                                 request.thumbnail.mime_type);
         } else {
             request.msg.response_headers.append ("Content-Type",
                                                  (request.object as MediaFileItem).mime_type);
@@ -85,12 +82,7 @@ internal class Rygel.HTTPIdentityHandler : Rygel.HTTPGetHandler {
                                         throws Error {
         var protocol = request.http_server.get_protocol ();
 
-        if (request.thumbnail != null) {
-            return request.thumbnail.add_resource (didl_object as DIDLLiteItem,
-                                                   protocol);
-        } else {
-            return request.object.add_resource (didl_object, null, protocol);
-        }
+        return request.object.add_resource (didl_object, null, protocol);
     }
 
     private HTTPResponse render_body_real (HTTPGet request) throws Error {
@@ -99,8 +91,6 @@ internal class Rygel.HTTPIdentityHandler : Rygel.HTTPGetHandler {
 
         if (request.subtitle != null) {
             src = engine.create_data_source (request.subtitle.uri);
-        } else if (request.thumbnail != null) {
-            src = engine.create_data_source (request.thumbnail.uri);
         } else {
             src = (request.object as MediaFileItem).create_stream_source
                                         (request.http_server.context.host_ip);
@@ -118,10 +108,6 @@ internal class Rygel.HTTPIdentityHandler : Rygel.HTTPGetHandler {
             return request.subtitle.size;
         }
 
-        if (request.thumbnail != null) {
-            return request.thumbnail.size;
-        }
-
         return (request.object as MediaFileItem).size;
     }
 }
diff --git a/src/librygel-server/rygel-http-thumbnail-handler.vala 
b/src/librygel-server/rygel-http-thumbnail-handler.vala
new file mode 100644
index 0000000..364d127
--- /dev/null
+++ b/src/librygel-server/rygel-http-thumbnail-handler.vala
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2008, 2009 Nokia Corporation.
+ * Copyright (C) 2012 Intel Corporation.
+ * Copyright (C) 2013  Cable Television Laboratories, Inc.
+ *
+ * Author: Zeeshan Ali (Khattak) <zeeshanak gnome org>
+ *                               <zeeshan ali nokia com>
+ *         Jens Georg <jensg openismus com>
+ *         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.
+ *
+ * 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 GUPnP;
+
+internal class Rygel.HTTPThumbnailHandler : Rygel.HTTPGetHandler {
+    private MediaFileItem media_item;
+    private int thumbnail_index;
+    private Thumbnail thumbnail;
+
+    public HTTPThumbnailHandler (MediaFileItem media_item,
+                                 int thumbnail_index,
+                                 Cancellable? cancellable) throws HTTPRequestError 
+    {
+
+        this.media_item = media_item;
+        this.thumbnail_index = thumbnail_index;
+        this.cancellable = cancellable;
+
+        if (media_item is MusicItem) {
+            var music_item = media_item as MusicItem;
+            this.thumbnail = music_item.album_art;
+        } else if (media_item is VisualItem) {
+            var visual_item = media_item as VisualItem;
+            if (thumbnail_index < visual_item.thumbnails.size) {
+                this.thumbnail = visual_item.thumbnails.get (thumbnail_index);
+            }
+        }
+        if (this.thumbnail == null) {
+            throw new HTTPRequestError.NOT_FOUND ("Thumbnail index %d not found for item '%s",
+                                                  thumbnail_index, media_item.id);
+        }
+    }
+
+    public override bool supports_transfer_mode (string mode) {
+        // Support interactive and background transfers only
+        return (mode != TRANSFER_MODE_STREAMING);
+    }
+
+    public override void add_response_headers (HTTPGet request)
+                                               throws HTTPRequestError {
+        // Add Content-Type
+        request.msg.response_headers.append ("Content-Type", thumbnail.mime_type);
+
+        // Add contentFeatures.dlna.org
+        MediaResource res = this.thumbnail.get_resource
+            (request.http_server.get_protocol (), this.thumbnail_index);
+        string protocol_info = res.get_protocol_info ().to_string ();
+        var pi_fields = protocol_info.split (":", 4);
+        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 {
+        DataSource src;
+        try {
+            var engine = MediaEngine.get_default ();
+            src = engine.create_data_source (this.thumbnail.uri);
+
+            return new HTTPResponse (request, this, src);
+        } catch (Error err) {
+            throw new HTTPRequestError.NOT_FOUND (err.message);
+        }
+    }
+
+    public override int64 get_resource_size () {
+        return thumbnail.size;
+    }
+
+    protected override DIDLLiteResource add_resource
+                                        (DIDLLiteObject didl_object,
+                                         HTTPGet        request)
+                                         throws Error {
+        return null as DIDLLiteResource;
+    }
+}
diff --git a/src/librygel-server/rygel-http-time-seek.vala b/src/librygel-server/rygel-http-time-seek.vala
index 7b248a9..a829079 100644
--- a/src/librygel-server/rygel-http-time-seek.vala
+++ b/src/librygel-server/rygel-http-time-seek.vala
@@ -100,7 +100,7 @@ internal class Rygel.HTTPTimeSeek : Rygel.HTTPSeek {
         return force_seek || (request.object is AudioItem &&
                (request.object as AudioItem).duration > 0 &&
                (request.handler is HTTPTranscodeHandler ||
-                (request.thumbnail == null &&
+                (!(request.handler is HTTPThumbnailHandler) &&
                  request.subtitle == null &&
                  (request.object as MediaFileItem).is_live_stream ())));
     }
diff --git a/src/librygel-server/rygel-image-item.vala b/src/librygel-server/rygel-image-item.vala
index d81aca4..83e136b 100644
--- a/src/librygel-server/rygel-image-item.vala
+++ b/src/librygel-server/rygel-image-item.vala
@@ -97,25 +97,6 @@ public class Rygel.ImageItem : MediaFileItem, VisualItem {
         return res;
     }
 
-    internal override void add_resources (DIDLLiteItem didl_item,
-                                          bool         allow_internal)
-                                          throws Error {
-        base.add_resources (didl_item, allow_internal);
-
-        this.add_thumbnail_resources (didl_item, allow_internal);
-    }
-
-    internal override void add_proxy_resources (HTTPServer   server,
-                                                DIDLLiteItem didl_item)
-                                                throws Error {
-        base.add_proxy_resources (server, didl_item);
-
-        if (!this.place_holder) {
-            // Thumbnails comes in the end
-            this.add_thumbnail_proxy_resources (server, didl_item);
-        }
-    }
-
     protected override ProtocolInfo get_protocol_info (string? uri,
                                                        string  protocol) {
         var protocol_info = base.get_protocol_info (uri, protocol);
@@ -124,4 +105,11 @@ public class Rygel.ImageItem : MediaFileItem, VisualItem {
 
         return protocol_info;
     }
+
+    internal override void add_additional_resources (HTTPServer server) {
+        base.add_additional_resources (server);
+
+        this.add_thumbnail_resources (server);
+    }
+
 }
diff --git a/src/librygel-server/rygel-thumbnail.vala b/src/librygel-server/rygel-thumbnail.vala
index 42ed920..9b38f31 100644
--- a/src/librygel-server/rygel-thumbnail.vala
+++ b/src/librygel-server/rygel-thumbnail.vala
@@ -36,45 +36,28 @@ public class Rygel.Thumbnail : Rygel.IconInfo {
         this.dlna_profile = dlna_profile;
     }
 
-    internal virtual DIDLLiteResource? add_resource (DIDLLiteItem didl_item,
-                                                     string       protocol) {
-        var res = didl_item.add_resource ();
-
-        /* We check for NULL because 
-         * gupnp_didl_lite_resource_set_uri(),
-         * used by the generated code,
-         * complains, with a critical warning, if the URI is NULL.
-         * It's already the default.
-         */
-        if (this.uri != null) {
-            res.uri = this.uri;
-        }
-
-        res.size64 = this.size;
+    internal virtual MediaResource get_resource (string protocol, int index) {
+        var name = "%s_thumbnail_%02d".printf (protocol, index);
+        MediaResource res = new MediaResource (name);
 
+        res.size = this.size;
         res.width = this.width;
         res.height = this.height;
         res.color_depth = this.depth;
-
-        /* Protocol info */
-        res.protocol_info = this.get_protocol_info (protocol);
+        res.mime_type = this.mime_type;
+        res.dlna_profile = this.dlna_profile;
+        res.protocol = protocol;
+        // Note: These represent best-case. The MediaServer/HTTPServer can dial these back
+        res.dlna_flags |= DLNAFlags.INTERACTIVE_TRANSFER_MODE |
+                          DLNAFlags.BACKGROUND_TRANSFER_MODE |
+                          DLNAFlags.CONNECTION_STALL |
+                          DLNAFlags.DLNA_V15;
+        res.dlna_operation = DLNAOperation.RANGE;
+        res.dlna_conversion = DLNAConversion.TRANSCODED;
+        res.extension = this.file_extension;
+
+        res.uri = this.uri;
 
         return res;
     }
-
-    private ProtocolInfo get_protocol_info (string protocol) {
-        var protocol_info = new ProtocolInfo ();
-
-        protocol_info.mime_type = this.mime_type;
-        protocol_info.dlna_profile = this.dlna_profile;
-        protocol_info.protocol = protocol;
-        protocol_info.dlna_flags |= DLNAFlags.INTERACTIVE_TRANSFER_MODE |
-                                    DLNAFlags.BACKGROUND_TRANSFER_MODE |
-                                    DLNAFlags.CONNECTION_STALL |
-                                    DLNAFlags.DLNA_V15;
-        protocol_info.dlna_operation = DLNAOperation.RANGE;
-        protocol_info.dlna_conversion = DLNAConversion.TRANSCODED;
-
-        return protocol_info;
-    }
 }
diff --git a/src/librygel-server/rygel-video-item.vala b/src/librygel-server/rygel-video-item.vala
index 6dc44a4..d0ca515 100644
--- a/src/librygel-server/rygel-video-item.vala
+++ b/src/librygel-server/rygel-video-item.vala
@@ -113,8 +113,6 @@ public class Rygel.VideoItem : AudioItem, VisualItem {
         }
 
         base.add_resources (didl_item, allow_internal);
-
-        this.add_thumbnail_resources (didl_item, allow_internal);
     }
 
     internal override MediaResource get_primary_resource () {
@@ -214,10 +212,11 @@ public class Rygel.VideoItem : AudioItem, VisualItem {
                 resource.subtitle_file_uri = main_subtitle.uri;
             }
         }
+    }
 
-        if (!this.place_holder) {
-            // Thumbnails comes in the end
-            this.add_thumbnail_proxy_resources (server, didl_item);
-        }
+    internal override void add_additional_resources (HTTPServer server) {
+        base.add_additional_resources (server);
+
+        this.add_thumbnail_resources (server);
     }
 }
diff --git a/src/librygel-server/rygel-visual-item.vala b/src/librygel-server/rygel-visual-item.vala
index 85068e5..0c62376 100644
--- a/src/librygel-server/rygel-visual-item.vala
+++ b/src/librygel-server/rygel-visual-item.vala
@@ -71,41 +71,43 @@ public interface Rygel.VisualItem : MediaFileItem {
         }
     }
 
-    internal void add_thumbnail_resources (DIDLLiteItem didl_item,
-                                           bool         allow_internal)
-                                           throws Error {
-        foreach (var thumbnail in this.thumbnails) {
-            var protocol = this.get_protocol_for_uri (thumbnail.uri);
-
-            if (allow_internal || protocol != "internal") {
-                thumbnail.add_resource (didl_item, protocol);
-            }
-        }
-    }
-
     internal void set_visual_resource_properties (MediaResource res) {
         res.width = this.width;
         res.height = this.height;
         res.color_depth = this.color_depth;
     }
 
-    internal void add_thumbnail_proxy_resources (HTTPServer   server,
-                                                 DIDLLiteItem didl_item)
-                                                 throws Error {
-        foreach (var thumbnail in this.thumbnails) {
-            if (server.need_proxy (thumbnail.uri)) {
-                var uri = thumbnail.uri; // Save the original URI
-                var index = this.thumbnails.index_of (thumbnail);
+    internal void add_thumbnail_resources (HTTPServer http_server) {
+        for (var i = 0; i < this.thumbnails.size; i++) {
+            if (!this.place_holder) {
+                var thumbnail = this.thumbnails.get (i);
+                // Add the defined thumbnail uri unconditionally
+                //  (it will be filtered out if the request is remote)
+                string protocol;
+                try {
+                    protocol = this.get_protocol_for_uri (thumbnail.uri);
+                } catch (Error e) {
+                    message ("Could not determine protocol for " + thumbnail.uri);
+                    continue;
+                }
 
-                thumbnail.uri = server.create_uri_for_object (this,
-                                                              index,
-                                                              -1,
-                                                              null,
-                                                              null);
-                thumbnail.add_resource (didl_item, server.get_protocol ());
+                var thumb_res = thumbnail.get_resource (protocol, i);
+                thumb_res.uri = thumbnail.uri;
+                this.get_resource_list ().add (thumb_res);
+                if (http_server.need_proxy (thumbnail.uri)) {
+                    var http_thumb_res = thumbnail.get_resource
+                                        (http_server.get_protocol (), i);
 
-                // Now restore the original URI
-                thumbnail.uri = uri;
+                    var index = this.thumbnails.index_of (thumbnail);
+                    // Make a http uri for the thumbnail
+                    http_thumb_res.uri = http_server.create_uri_for_object
+                                                 (this,
+                                                  index,
+                                                  -1,
+                                                  null,
+                                                  null);
+                    this.get_resource_list ().add (http_thumb_res);
+                }
             }
         }
     }


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