summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJens Georg <mail@jensge.org>2015-02-08 11:27:28 +0100
committerJens Georg <mail@jensge.org>2015-02-08 13:21:12 +0100
commit3d777ecc385d38c6c6787314058b2f076a174f1e (patch)
tree07f0c32d7aa39f346e13c4a2318d4d206e21ffd2
parent9c6aad4bf0b5d69809a7393f8da18e95c7bbf2d6 (diff)
downloadrygel-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.am1
-rw-r--r--src/librygel-server/rygel-http-byte-seek.vala2
-rw-r--r--src/librygel-server/rygel-http-get.vala8
-rw-r--r--src/librygel-server/rygel-http-identity-handler.vala18
-rw-r--r--src/librygel-server/rygel-http-subtitle-handler.vala102
-rw-r--r--src/librygel-server/rygel-http-time-seek.vala2
-rw-r--r--src/librygel-server/rygel-video-item.vala79
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) {