diff options
author | Jens Georg <mail@jensge.org> | 2014-11-29 14:51:04 +0100 |
---|---|---|
committer | Jens Georg <mail@jensge.org> | 2015-02-08 13:19:26 +0100 |
commit | 5c7579defe3d55de71f5328c2dde4f7586952b14 (patch) | |
tree | f6c3f3824ce846ee01d309ac8c7dbaa9201d3a0b | |
parent | d0c9a4e5c2389b25c2c811e6fa666fed3626e644 (diff) | |
download | rygel-5c7579defe3d55de71f5328c2dde4f7586952b14.tar.gz |
server: Refactor subtitle handling
Code based on Cablelabs's CVP-2 implementation.
-rw-r--r-- | src/librygel-server/filelist.am | 1 | ||||
-rw-r--r-- | src/librygel-server/rygel-http-byte-seek.vala | 3 | ||||
-rw-r--r-- | src/librygel-server/rygel-http-get.vala | 6 | ||||
-rw-r--r-- | src/librygel-server/rygel-http-identity-handler.vala | 16 | ||||
-rw-r--r-- | src/librygel-server/rygel-http-thumbnail-handler.vala | 103 | ||||
-rw-r--r-- | src/librygel-server/rygel-http-time-seek.vala | 2 | ||||
-rw-r--r-- | src/librygel-server/rygel-image-item.vala | 26 | ||||
-rw-r--r-- | src/librygel-server/rygel-thumbnail.vala | 51 | ||||
-rw-r--r-- | src/librygel-server/rygel-video-item.vala | 11 | ||||
-rw-r--r-- | 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 86c8bc33..29ce50a7 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 5742e06d..76cb3614 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 3a4e229b..b3fd5b9e 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 f39e3612..6c8b126d 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 00000000..364d1278 --- /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 7b248a9a..a8290795 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 d81aca4d..83e136b2 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 42ed9201..9b38f314 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 6dc44a48..d0ca515c 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 85068e53..0c623762 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); + } } } } |