diff options
author | Jens Georg <mail@jensge.org> | 2015-02-08 11:27:28 +0100 |
---|---|---|
committer | Jens Georg <mail@jensge.org> | 2015-02-08 13:21:12 +0100 |
commit | 3d777ecc385d38c6c6787314058b2f076a174f1e (patch) | |
tree | 07f0c32d7aa39f346e13c4a2318d4d206e21ffd2 | |
parent | 9c6aad4bf0b5d69809a7393f8da18e95c7bbf2d6 (diff) | |
download | rygel-3d777ecc385d38c6c6787314058b2f076a174f1e.tar.gz |
server: Refactor subtitle handling
Based on Cablelabs's CVP-2 implementation.
Signed-off-by: Jens Georg <mail@jensge.org>
-rw-r--r-- | src/librygel-server/filelist.am | 1 | ||||
-rw-r--r-- | src/librygel-server/rygel-http-byte-seek.vala | 2 | ||||
-rw-r--r-- | src/librygel-server/rygel-http-get.vala | 8 | ||||
-rw-r--r-- | src/librygel-server/rygel-http-identity-handler.vala | 18 | ||||
-rw-r--r-- | src/librygel-server/rygel-http-subtitle-handler.vala | 102 | ||||
-rw-r--r-- | src/librygel-server/rygel-http-time-seek.vala | 2 | ||||
-rw-r--r-- | src/librygel-server/rygel-video-item.vala | 79 |
7 files changed, 153 insertions, 59 deletions
diff --git a/src/librygel-server/filelist.am b/src/librygel-server/filelist.am index 29ce50a7..395f826c 100644 --- a/src/librygel-server/filelist.am +++ b/src/librygel-server/filelist.am @@ -44,6 +44,7 @@ LIBRYGEL_SERVER_NONVAPI_SOURCE_FILES = \ rygel-http-get-handler.vala \ rygel-http-get.vala \ rygel-http-thumbnail-handler.vala \ + rygel-http-subtitle-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 76cb3614..df1f2cc2 100644 --- a/src/librygel-server/rygel-http-byte-seek.vala +++ b/src/librygel-server/rygel-http-byte-seek.vala @@ -72,7 +72,7 @@ internal class Rygel.HTTPByteSeek : Rygel.HTTPSeek { ((request.object as MediaFileItem).size > 0 && request.handler is HTTPIdentityHandler) || (request.handler is HTTPThumbnailHandler) || - (request.subtitle != null && request.subtitle.size > 0)); + (request.handler is HTTPSubtitleHandler)); } public static bool requested (HTTPGet request) { diff --git a/src/librygel-server/rygel-http-get.vala b/src/librygel-server/rygel-http-get.vala index 0e7f6020..60a2c74c 100644 --- a/src/librygel-server/rygel-http-get.vala +++ b/src/librygel-server/rygel-http-get.vala @@ -70,12 +70,14 @@ internal class Rygel.HTTPGet : HTTPRequest { this.handler = new HTTPMediaResourceHandler (this.object, uri.resource_name, this.cancellable); - } - - if (uri.thumbnail_index >= 0) { + } else if (uri.thumbnail_index >= 0) { this.handler = new HTTPThumbnailHandler (this.object as MediaFileItem, uri.thumbnail_index, this.cancellable); + } else if (uri.subtitle_index >= 0) { + this.handler = new HTTPSubtitleHandler (this.object as MediaFileItem, + uri.subtitle_index, + this.cancellable); } if (this.handler == null) { diff --git a/src/librygel-server/rygel-http-identity-handler.vala b/src/librygel-server/rygel-http-identity-handler.vala index 383f057f..8563c285 100644 --- a/src/librygel-server/rygel-http-identity-handler.vala +++ b/src/librygel-server/rygel-http-identity-handler.vala @@ -34,10 +34,7 @@ internal class Rygel.HTTPIdentityHandler : Rygel.HTTPGetHandler { public override void add_response_headers (HTTPGet request) throws HTTPRequestError { - if (request.subtitle != null) { - request.msg.response_headers.append ("Content-Type", - request.subtitle.mime_type); - } else { + { request.msg.response_headers.append ("Content-Type", (request.object as MediaFileItem).mime_type); } @@ -90,15 +87,8 @@ internal class Rygel.HTTPIdentityHandler : Rygel.HTTPGetHandler { } private HTTPResponse render_body_real (HTTPGet request) throws Error { - DataSource src; - var engine = MediaEngine.get_default (); - - if (request.subtitle != null) { - src = engine.create_data_source (request.subtitle.uri); - } else { - src = (request.object as MediaFileItem).create_stream_source + var src = (request.object as MediaFileItem).create_stream_source (request.http_server.context.host_ip); - } if (src == null) { throw new HTTPRequestError.NOT_FOUND (_("Not found")); @@ -108,10 +98,6 @@ internal class Rygel.HTTPIdentityHandler : Rygel.HTTPGetHandler { } private int64 get_size (HTTPGet request) { - if (request.subtitle != null) { - return request.subtitle.size; - } - return (request.object as MediaFileItem).size; } } diff --git a/src/librygel-server/rygel-http-subtitle-handler.vala b/src/librygel-server/rygel-http-subtitle-handler.vala new file mode 100644 index 00000000..383b4689 --- /dev/null +++ b/src/librygel-server/rygel-http-subtitle-handler.vala @@ -0,0 +1,102 @@ +/* + * 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.HTTPSubtitleHandler : Rygel.HTTPGetHandler { + private MediaFileItem media_item; + private int subtitle_index; + public Subtitle subtitle; + + public HTTPSubtitleHandler (MediaFileItem media_item, + int subtitle_index, + Cancellable? cancellable) throws HTTPRequestError { + this.media_item = media_item; + this.subtitle_index = subtitle_index; + this.cancellable = cancellable; + + if (subtitle_index >= 0 && media_item is VideoItem) { + var video_item = media_item as VideoItem; + + if (subtitle_index < video_item.subtitles.size) { + this.subtitle = video_item.subtitles.get (subtitle_index); + } + } + + if (this.subtitle == null) { + throw new HTTPRequestError.NOT_FOUND ("Subtitle index %d not found for item '%s", + subtitle_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", subtitle.mime_type); + + // Add contentFeatures.dlna.org + + // This is functionally equivalent to how contentFeatures was formed via the + // (deprecated) HTTPIdentityHandler + MediaResource res = this.media_item.get_resource_list ().get (0); + 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.subtitle.uri); + + return new HTTPResponse (request, this, src); + } catch (Error err) { + throw new HTTPRequestError.NOT_FOUND (err.message); + } + } + + public override int64 get_resource_size () { + return subtitle.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 a8290795..7967bf51 100644 --- a/src/librygel-server/rygel-http-time-seek.vala +++ b/src/librygel-server/rygel-http-time-seek.vala @@ -101,7 +101,7 @@ internal class Rygel.HTTPTimeSeek : Rygel.HTTPSeek { (request.object as AudioItem).duration > 0 && (request.handler is HTTPTranscodeHandler || (!(request.handler is HTTPThumbnailHandler) && - request.subtitle == null && + !(request.handler is HTTPSubtitleHandler) && (request.object as MediaFileItem).is_live_stream ()))); } diff --git a/src/librygel-server/rygel-video-item.vala b/src/librygel-server/rygel-video-item.vala index e59eb85c..ad625e59 100644 --- a/src/librygel-server/rygel-video-item.vala +++ b/src/librygel-server/rygel-video-item.vala @@ -142,62 +142,65 @@ public class Rygel.VideoItem : AudioItem, VisualItem { internal override DIDLLiteObject? serialize (Serializer serializer, HTTPServer http_server) throws Error { - var didl_item = base.serialize (serializer, http_server); + var didl_item = base.serialize (serializer, http_server) as DIDLLiteItem; if (this.author != null && this.author != "") { var contributor = didl_item.add_author (); contributor.name = this.author; } - return didl_item; - } - - internal override void add_proxy_resources (HTTPServer server, - DIDLLiteItem didl_item) - throws Error { - var main_subtitle = null as Subtitle; if (!this.place_holder) { - // Subtitles first + var main_subtitle = null as Subtitle; foreach (var subtitle in this.subtitles) { - if (!server.need_proxy (subtitle.uri)) { - if (main_subtitle == null) { - main_subtitle = subtitle; - } - + string protocol; + try { + protocol = this.get_protocol_for_uri (subtitle.uri); + } catch (Error e) { + message ("Could not determine protocol for " + subtitle.uri); continue; } - var uri = subtitle.uri; // Save the original URI - var index = this.subtitles.index_of (subtitle); + if (http_server.need_proxy (subtitle.uri)) { + var uri = subtitle.uri; // Save the original URI + var index = this.subtitles.index_of (subtitle); - subtitle.uri = server.create_uri_for_object (this, - -1, - index, - null, - null); - subtitle.add_didl_node (didl_item); + subtitle.uri = http_server.create_uri_for_object (this, + -1, + index, + null, + null); + subtitle.add_didl_node (didl_item); + subtitle.uri = uri; // Now restore the original URI - if (main_subtitle == null) { - main_subtitle = new Subtitle (subtitle.mime_type, - subtitle.caption_type); - main_subtitle.uri = subtitle.uri; + if (main_subtitle == null) { + main_subtitle = new Subtitle (subtitle.mime_type, + subtitle.caption_type); + main_subtitle.uri = uri; + } + } else if (main_subtitle == null) { + main_subtitle = subtitle; } - // Now restore the original URI - subtitle.uri = uri; + if (http_server.is_local () || protocol != "internal") { + subtitle.add_didl_node (didl_item); + } } - } - - base.add_proxy_resources (server, didl_item); - - if (main_subtitle != null) { - var resources = didl_item.get_resources (); - foreach (var resource in resources) { - resource.subtitle_file_type = - main_subtitle.caption_type.up (); - resource.subtitle_file_uri = main_subtitle.uri; + if (main_subtitle != null) { + // Add resource-level subtitle metadata to all streamable video resources + // Note: All resources have already been serialized by the base + var resources = didl_item.get_resources (); + foreach (var resource in resources) { + if ( (resource.protocol_info.dlna_flags + & DLNAFlags.STREAMING_TRANSFER_MODE) != 0) { + resource.subtitle_file_type = + main_subtitle.caption_type.up (); + resource.subtitle_file_uri = main_subtitle.uri; + } + } } } + + return didl_item; } internal override void add_additional_resources (HTTPServer server) { |