[rygel] core: Append extensions to served files
- From: Jens Georg <jensgeorg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [rygel] core: Append extensions to served files
- Date: Thu, 19 Jan 2012 18:50:27 +0000 (UTC)
commit 674800ee11e09c8477c69f6bb76decae06496c37
Author: Krzesimir Nowak <qdlacz gmail com>
Date: Mon Dec 12 16:02:01 2011 +0100
core: Append extensions to served files
src/rygel/rygel-aac-transcoder.vala | 2 +-
src/rygel/rygel-audio-transcoder.vala | 10 ++-
src/rygel/rygel-avc-transcoder.vala | 1 +
src/rygel/rygel-http-item-uri.vala | 125 ++++++++++++++++++++++++++++++++-
src/rygel/rygel-http-server.vala | 2 +-
src/rygel/rygel-l16-transcoder.vala | 3 +-
src/rygel/rygel-mp2ts-transcoder.vala | 1 +
src/rygel/rygel-mp3-transcoder.vala | 3 +-
src/rygel/rygel-transcoder.vala | 5 +-
src/rygel/rygel-video-transcoder.vala | 4 +-
src/rygel/rygel-wmv-transcoder.vala | 3 +-
tests/rygel-http-get-test.vala | 32 +++++++--
tests/rygel-http-item-uri-test.vala | 60 ++++++++++++++--
tests/rygel-http-post-test.vala | 46 ++++++++++++-
14 files changed, 268 insertions(+), 29 deletions(-)
---
diff --git a/src/rygel/rygel-aac-transcoder.vala b/src/rygel/rygel-aac-transcoder.vala
index 805ad18..71f74fa 100644
--- a/src/rygel/rygel-aac-transcoder.vala
+++ b/src/rygel/rygel-aac-transcoder.vala
@@ -33,6 +33,6 @@ internal class Rygel.AACTranscoder : Rygel.AudioTranscoder {
"channels=1";
public AACTranscoder () {
- base ("audio/3gpp", "AAC_ISO_320", BITRATE, CONTAINER, CODEC);
+ base ("audio/3gpp", "AAC_ISO_320", BITRATE, CONTAINER, CODEC, "3gp");
}
}
diff --git a/src/rygel/rygel-audio-transcoder.vala b/src/rygel/rygel-audio-transcoder.vala
index 0b45be5..eead824 100644
--- a/src/rygel/rygel-audio-transcoder.vala
+++ b/src/rygel/rygel-audio-transcoder.vala
@@ -36,8 +36,9 @@ internal class Rygel.AudioTranscoder : Rygel.Transcoder {
string dlna_profile,
int audio_bitrate,
string? container_caps,
- string audio_codec_caps) {
- base (content_type, dlna_profile, AudioItem.UPNP_CLASS);
+ string audio_codec_caps,
+ string extension) {
+ base (content_type, dlna_profile, AudioItem.UPNP_CLASS, extension);
this.audio_bitrate = audio_bitrate;
if (container_caps != null) {
@@ -52,8 +53,9 @@ internal class Rygel.AudioTranscoder : Rygel.Transcoder {
string upnp_class,
int audio_bitrate,
string? container_caps,
- string audio_codec_caps) {
- base (content_type, dlna_profile, upnp_class);
+ string audio_codec_caps,
+ string extension) {
+ base (content_type, dlna_profile, upnp_class, extension);
this.audio_bitrate = audio_bitrate;
if (container_caps != null) {
diff --git a/src/rygel/rygel-avc-transcoder.vala b/src/rygel/rygel-avc-transcoder.vala
index d2651df..cb4dbe8 100644
--- a/src/rygel/rygel-avc-transcoder.vala
+++ b/src/rygel/rygel-avc-transcoder.vala
@@ -45,6 +45,7 @@ internal class Rygel.AVCTranscoder : Rygel.VideoTranscoder {
CONTAINER,
AUDIO_CAPS,
VIDEO_CAPS,
+ "mp4",
RESTRICTIONS);
}
diff --git a/src/rygel/rygel-http-item-uri.vala b/src/rygel/rygel-http-item-uri.vala
index 861a6ea..0e48b8d 100644
--- a/src/rygel/rygel-http-item-uri.vala
+++ b/src/rygel/rygel-http-item-uri.vala
@@ -23,23 +23,97 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+using Gee;
+
internal class Rygel.HTTPItemURI : Object {
public string item_id;
public int thumbnail_index;
public int subtitle_index;
public string? transcode_target;
public unowned HTTPServer http_server;
+ private string real_extension;
+ public string extension {
+ owned get {
+ if (this.real_extension != "") {
+ return "." + this.real_extension;
+ }
+ return "";
+ }
+ set {
+ this.real_extension = value;
+ }
+ }
- public HTTPItemURI (string item_id,
+ public static HashMap<string, string> mime_to_ext;
+
+ public HTTPItemURI (MediaItem item,
HTTPServer http_server,
int thumbnail_index = -1,
int subtitle_index = -1,
string? transcode_target = null) {
- this.item_id = item_id;
+ this.item_id = item.id;
this.thumbnail_index = thumbnail_index;
this.subtitle_index = subtitle_index;
this.transcode_target = transcode_target;
this.http_server = http_server;
+ this.extension = "";
+
+ if (thumbnail_index > -1) {
+ if (item is VisualItem) {
+ var thumbnails = (item as VisualItem).thumbnails;
+
+ if (thumbnails.size > thumbnail_index) {
+ this.extension = thumbnails[thumbnail_index].file_extension;
+ } else {
+ this.extension = "jpg";
+ // what now? throw an error?
+ }
+ } else {
+ this.extension = "jpg";
+ // what now? throw an error?
+ }
+ }
+ else if (subtitle_index > -1) {
+ if (item is VideoItem) {
+ var subtitles = (item as VideoItem).subtitles;
+
+ if (subtitles.size > subtitle_index) {
+ this.extension = subtitles[subtitle_index].caption_type;
+ } else {
+ // what now? throw an error?
+ this.extension = "srt";
+ }
+ } else {
+ // what now? throw an error?
+ this.extension = "srt";
+ }
+ }
+ else if (transcode_target != null) {
+ try {
+ var tc = this.http_server.get_transcoder (transcode_target);
+
+ this.extension = tc.extension;
+ } catch (Error err) {}
+ }
+ if (this.extension == "") {
+ string uri_extension = "";
+
+ foreach (string uri_string in item.uris) {
+ string basename = Path.get_basename (uri_string);
+ int dot_index = basename.last_index_of(".");
+
+ if (dot_index > -1) {
+ uri_extension = basename.substring (dot_index + 1);
+ break;
+ }
+ }
+
+ if (uri_extension == "") {
+ this.extension = ext_from_mime_type (item.mime_type);
+ } else {
+ this.extension = uri_extension;
+ }
+ }
}
public HTTPItemURI.from_string (string uri,
@@ -50,6 +124,7 @@ internal class Rygel.HTTPItemURI : Object {
this.subtitle_index = -1;
this.transcode_target = null;
this.http_server = http_server;
+ this.extension = "";
var request_uri = uri.replace (http_server.path_root, "");
var parts = request_uri.split ("/");
@@ -59,6 +134,14 @@ internal class Rygel.HTTPItemURI : Object {
request_uri);
}
+ string last_part = parts[parts.length - 1];
+ int dot_index = last_part.last_index_of (".");
+
+ if (dot_index > -1) {
+ this.extension = last_part.substring (dot_index + 1);
+ parts[parts.length - 1] = last_part.substring (0, dot_index);
+ }
+
for (int i = 1; i < parts.length - 1; i += 2) {
switch (parts[i]) {
case "i":
@@ -108,7 +191,7 @@ internal class Rygel.HTTPItemURI : Object {
} else if (this.subtitle_index >= 0) {
path += "/sub/" + this.subtitle_index.to_string ();
}
-
+ path += this.extension;
return this.create_uri_for_path (path);
}
@@ -118,4 +201,40 @@ internal class Rygel.HTTPItemURI : Object {
this.http_server.path_root,
path);
}
+
+ private string ext_from_mime_type (string mime_type) {
+ if (mime_to_ext == null) {
+ mime_to_ext = new HashMap<string, string> ();
+ // videos
+ string[] videos = {"mpeg", "webm", "ogg"};
+
+ foreach (string video in videos) {
+ mime_to_ext.set ("video/" + video, video);
+ }
+ mime_to_ext.set("video/x-matroska", "mkv");
+
+ // audios
+ mime_to_ext.set ("audio/x-wav", "wav");
+ mime_to_ext.set ("audio/x-matroska", "mka");
+
+ // images
+ string[] images = {"jpeg", "png"};
+
+ foreach (string image in images) {
+ mime_to_ext.set ("image/" + image, image);
+ }
+
+ // texts
+ mime_to_ext.set ("text/srt", "srt");
+
+ // applications? (can be either video or audio?);
+ mime_to_ext.set ("application/ogg", "ogg");
+ }
+
+ if (this.mime_to_ext.has_key (mime_type)) {
+ return mime_to_ext.get (mime_type);
+ }
+
+ return "";
+ }
}
diff --git a/src/rygel/rygel-http-server.vala b/src/rygel/rygel-http-server.vala
index 1b49b5f..bbfa083 100644
--- a/src/rygel/rygel-http-server.vala
+++ b/src/rygel/rygel-http-server.vala
@@ -100,7 +100,7 @@ internal class Rygel.HTTPServer : Rygel.TranscodeManager, Rygel.StateMachine {
int thumbnail_index,
int subtitle_index,
string? transcode_target) {
- var uri = new HTTPItemURI (item.id,
+ var uri = new HTTPItemURI (item,
this,
thumbnail_index,
subtitle_index,
diff --git a/src/rygel/rygel-l16-transcoder.vala b/src/rygel/rygel-l16-transcoder.vala
index e9e0c77..54516f5 100644
--- a/src/rygel/rygel-l16-transcoder.vala
+++ b/src/rygel/rygel-l16-transcoder.vala
@@ -52,7 +52,8 @@ internal class Rygel.L16Transcoder : Rygel.AudioTranscoder {
"LPCM",
0,
AudioTranscoder.NO_CONTAINER,
- caps_str);
+ caps_str,
+ "lpcm");
}
public override DIDLLiteResource? add_resource (DIDLLiteItem didl_item,
diff --git a/src/rygel/rygel-mp2ts-transcoder.vala b/src/rygel/rygel-mp2ts-transcoder.vala
index a0609e1..06708fd 100644
--- a/src/rygel/rygel-mp2ts-transcoder.vala
+++ b/src/rygel/rygel-mp2ts-transcoder.vala
@@ -63,6 +63,7 @@ internal class Rygel.MP2TSTranscoder : Rygel.VideoTranscoder {
CONTAINER,
AUDIO_FORMAT,
BASE_VIDEO_FORMAT,
+ "mpg",
RESTRICTION_TEMPLATE.printf (FRAME_RATE[profile],
WIDTH[profile],
HEIGHT[profile]));
diff --git a/src/rygel/rygel-mp3-transcoder.vala b/src/rygel/rygel-mp3-transcoder.vala
index 6eb7206..ad14a3b 100644
--- a/src/rygel/rygel-mp3-transcoder.vala
+++ b/src/rygel/rygel-mp3-transcoder.vala
@@ -36,6 +36,7 @@ internal class Rygel.MP3Transcoder : Rygel.AudioTranscoder {
"MP3",
BITRATE,
AudioTranscoder.NO_CONTAINER,
- FORMAT);
+ FORMAT,
+ "mp3");
}
}
diff --git a/src/rygel/rygel-transcoder.vala b/src/rygel/rygel-transcoder.vala
index 2e7b28e..63a71b2 100644
--- a/src/rygel/rygel-transcoder.vala
+++ b/src/rygel/rygel-transcoder.vala
@@ -31,6 +31,7 @@ using GUPnP;
internal abstract class Rygel.Transcoder : GLib.Object {
public string mime_type { get; protected set; }
public string dlna_profile { get; protected set; }
+ public string extension { get; protected set; }
private const string DECODE_BIN = "decodebin2";
private const string ENCODE_BIN = "encodebin";
@@ -46,11 +47,13 @@ internal abstract class Rygel.Transcoder : GLib.Object {
public Transcoder (string mime_type,
string dlna_profile,
- string upnp_class) {
+ string upnp_class,
+ string extension) {
this.mime_type = mime_type;
this.dlna_profile = dlna_profile;
this.upnp_class = upnp_class;
this.link_failed = true;
+ this.extension = extension;
}
/**
diff --git a/src/rygel/rygel-video-transcoder.vala b/src/rygel/rygel-video-transcoder.vala
index 0639cab..15f1928 100644
--- a/src/rygel/rygel-video-transcoder.vala
+++ b/src/rygel/rygel-video-transcoder.vala
@@ -37,6 +37,7 @@ internal class Rygel.VideoTranscoder : Rygel.AudioTranscoder {
string container_caps,
string audio_codec_caps,
string video_codec_caps,
+ string extension,
string? restrictions = null) {
base.with_class (content_type,
@@ -44,7 +45,8 @@ internal class Rygel.VideoTranscoder : Rygel.AudioTranscoder {
VideoItem.UPNP_CLASS,
audio_bitrate,
container_caps,
- audio_codec_caps);
+ audio_codec_caps,
+ extension);
this.video_bitrate = video_bitrate;
this.video_codec_format = Caps.from_string (video_codec_caps);
diff --git a/src/rygel/rygel-wmv-transcoder.vala b/src/rygel/rygel-wmv-transcoder.vala
index a601ddc..947ee04 100644
--- a/src/rygel/rygel-wmv-transcoder.vala
+++ b/src/rygel/rygel-wmv-transcoder.vala
@@ -33,6 +33,7 @@ internal class Rygel.WMVTranscoder : Rygel.VideoTranscoder {
VIDEO_BITRATE,
"video/x-ms-asf,parsed=true",
"audio/x-wma,channels=2,wmaversion=1",
- "video/x-wmv,wmvversion=1");
+ "video/x-wmv,wmvversion=1",
+ "wmv");
}
}
diff --git a/tests/rygel-http-get-test.vala b/tests/rygel-http-get-test.vala
index 9b5912c..f9632ff 100644
--- a/tests/rygel-http-get-test.vala
+++ b/tests/rygel-http-get-test.vala
@@ -132,7 +132,7 @@ public class Rygel.HTTPGetTest : GLib.Object {
requests.add (new TestRequestFactory (request, Soup.KnownStatusCode.OK));
string uri = this.server.create_uri ("VideoItem");
- uri = uri + "/tr/MPEG";
+ uri = uri + "/tr/MP3";
request = new Soup.Message ("HEAD", uri);
requests.add (new TestRequestFactory (request, Soup.KnownStatusCode.OK));
@@ -261,10 +261,13 @@ public class Rygel.HTTPServer : GLib.Object {
}
}
- public string create_uri(string item_id) {
- var item_uri = new HTTPItemURI (item_id,
- this);
- return item_uri.to_string ();
+ public string create_uri (string item_id) {
+ var item = new VideoItem ();
+ item.id = item_id;
+
+ var item_uri = new HTTPItemURI (item, this);
+
+ return item_uri.to_string ();
}
public signal void message_received (Soup.Message message);
@@ -295,7 +298,12 @@ public class Rygel.HTTPServer : GLib.Object {
}
public Transcoder get_transcoder (string target) throws Error {
- return new Transcoder ();
+ if (target == "MP3") {
+ return new Transcoder ("mp3");
+ }
+ throw new HTTPRequestError.NOT_FOUND (
+ "No transcoder available for target format '%s'",
+ target);
}
}
@@ -368,6 +376,7 @@ public abstract class Rygel.MediaItem : Rygel.MediaObject {
public long size = 1024;
public ArrayList<Subtitle> subtitles = new ArrayList<Subtitle> ();
public ArrayList<Thumbnail> thumbnails = new ArrayList<Thumbnail> ();
+ public ArrayList<string> uris = new ArrayList<string> ();
public bool place_holder = false;
@@ -441,10 +450,12 @@ private class Rygel.MusicItem : AudioItem {
public class Rygel.Thumbnail {
public long size = 1024;
+ public string file_extension;
}
public class Rygel.Subtitle {
public long size = 1024;
+ public string caption_type;
}
internal class Rygel.HTTPResponse : Rygel.StateMachine, GLib.Object {
@@ -479,6 +490,13 @@ internal class Rygel.HTTPResponse : Rygel.StateMachine, GLib.Object {
public class Rygel.MediaObject {
public string id;
+ public string mime_type = "";
}
-public class Rygel.Transcoder {}
+public class Rygel.Transcoder : GLib.Object {
+ public string extension { get; protected set; }
+
+ public Transcoder (string extension) {
+ this.extension = extension;
+ }
+}
diff --git a/tests/rygel-http-item-uri-test.vala b/tests/rygel-http-item-uri-test.vala
index f79295a..e527156 100644
--- a/tests/rygel-http-item-uri-test.vala
+++ b/tests/rygel-http-item-uri-test.vala
@@ -21,6 +21,8 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+using Gee;
+
private errordomain Rygel.HTTPRequestError {
UNACCEPTABLE = Soup.KnownStatusCode.NOT_ACCEPTABLE,
BAD_REQUEST = Soup.KnownStatusCode.BAD_REQUEST,
@@ -31,6 +33,14 @@ private errordomain Rygel.TestError {
SKIP
}
+private class Rygel.Transcoder : GLib.Object {
+ public string extension { get; protected set; }
+
+ public Transcoder (string extension) {
+ this.extension = extension;
+ }
+}
+
private class Rygel.HTTPServer : GLib.Object {
private const string SERVER_PATH = "/Test";
@@ -51,14 +61,44 @@ private class Rygel.HTTPServer : GLib.Object {
assert (this.context.host_ip != null);
assert (this.context.port > 0);
}
+
+ public Transcoder get_transcoder (string target) throws Error {
+ if (target == "MP3") {
+ return new Transcoder ("mp3");
+ }
+ throw new HTTPRequestError.NOT_FOUND (
+ "No transcoder available for target format '%s'",
+ target);
+ }
+}
+
+private class Rygel.MediaItem : GLib.Object {
+ public string id;
+ public ArrayList<string> uris = new ArrayList<string> ();
+ public string mime_type;
+}
+
+private class Rygel.Thumbnail {
+ public string file_extension;
+}
+
+private class Rygel.VisualItem : MediaItem {
+ public ArrayList<Thumbnail> thumbnails = new ArrayList<Thumbnail> ();
+}
+
+private class Rygel.Subtitle : GLib.Object {
+ public string caption_type;
+}
+
+private class Rygel.VideoItem : VisualItem {
+ public ArrayList<Subtitle> subtitles = new ArrayList<Subtitle> ();
}
private class Rygel.HTTPItemURITest : GLib.Object {
- private const string ITEM_ID = "HELLO";
private const int THUMBNAIL_INDEX = 1;
private const int SUBTITLE_INDEX = 1;
private const string TRANSCODE_TARGET = "MP3";
-
+ private VisualItem item = new VisualItem ();
private HTTPServer server;
public static int main (string[] args) {
@@ -78,6 +118,14 @@ private class Rygel.HTTPItemURITest : GLib.Object {
}
public void run () throws Error {
+ Thumbnail thumb = new Thumbnail ();
+
+ thumb.file_extension = "png";
+ this.item.thumbnails.add (thumb);
+ this.item.id = "HELLO";
+ this.item.uris.add ("foo.mp3");
+ this.item.mime_type = "audio/mp3";
+
var uris = new HTTPItemURI[] {
this.test_construction (),
this.test_construction_with_thumbnail (),
@@ -96,14 +144,14 @@ private class Rygel.HTTPItemURITest : GLib.Object {
}
private HTTPItemURI test_construction () {
- var uri = new HTTPItemURI (ITEM_ID, this.server);
+ var uri = new HTTPItemURI (this.item, this.server);
assert (uri != null);
return uri;
}
private HTTPItemURI test_construction_with_subtitle () {
- var uri = new HTTPItemURI (ITEM_ID,
+ var uri = new HTTPItemURI (this.item,
this.server,
-1,
SUBTITLE_INDEX);
@@ -113,7 +161,7 @@ private class Rygel.HTTPItemURITest : GLib.Object {
}
private HTTPItemURI test_construction_with_thumbnail () {
- var uri = new HTTPItemURI (ITEM_ID,
+ var uri = new HTTPItemURI (this.item,
this.server,
THUMBNAIL_INDEX);
assert (uri != null);
@@ -122,7 +170,7 @@ private class Rygel.HTTPItemURITest : GLib.Object {
}
private HTTPItemURI test_construction_with_transcoder () {
- var uri = new HTTPItemURI (ITEM_ID,
+ var uri = new HTTPItemURI (this.item,
this.server,
THUMBNAIL_INDEX,
-1,
diff --git a/tests/rygel-http-post-test.vala b/tests/rygel-http-post-test.vala
index 7abdf87..531f3a4 100644
--- a/tests/rygel-http-post-test.vala
+++ b/tests/rygel-http-post-test.vala
@@ -170,7 +170,7 @@ public class Rygel.HTTPServer : GLib.Object {
public string uri {
owned get {
- var item_uri = new HTTPItemURI (this.root_container.ITEM_ID,
+ var item_uri = new HTTPItemURI (this.root_container.item,
this);
return item_uri.to_string ();
@@ -204,6 +204,15 @@ public class Rygel.HTTPServer : GLib.Object {
private void on_got_headers (Soup.Message msg) {
this.message_received (msg);
}
+
+ public Transcoder get_transcoder (string target) throws Error {
+ if (target == "MP3") {
+ return new Transcoder ("mp3");
+ }
+ throw new HTTPRequestError.NOT_FOUND (
+ "No transcoder available for target format '%s'",
+ target);
+ }
}
public class Rygel.HTTPClient : GLib.Object, StateMachine {
@@ -293,11 +302,14 @@ public class Rygel.MediaItem : Rygel.MediaObject {
public string id;
public long size = 1024;
public long duration = 1024;
+ public ArrayList<string> uris = new ArrayList<string> ();
public bool place_holder = true;
public File file;
+ public MediaItem.for_visual_item () {}
+
public MediaItem (string id, MediaContainer parent) {
this.id = id;
this.parent = parent;
@@ -373,8 +385,38 @@ public class Rygel.ItemRemovalQueue: GLib.Object {
}
}
-public class Rygel.MediaObject : GLib.Object {}
+public class Rygel.MediaObject : GLib.Object {
+ public string mime_type = "";
+}
+
+public class Rygel.Thumbnail : GLib.Object {
+ public string file_extension;
+}
+
+public class Rygel.VisualItem : Rygel.MediaItem {
+ public ArrayList<Thumbnail> thumbnails = new ArrayList<Thumbnail> ();
+
+ public VisualItem () {
+ base.for_visual_item();
+ }
+}
+
+private class Rygel.Subtitle : GLib.Object {
+ public string caption_type;
+}
+
+private class Rygel.VideoItem : Rygel.VisualItem {
+ public ArrayList<Subtitle> subtitles = new ArrayList<Subtitle> ();
+}
public errordomain Rygel.ContentDirectoryError {
INVALID_ARGS = 402
}
+
+public class Rygel.Transcoder : GLib.Object {
+ public string extension { get; protected set; }
+
+ public Transcoder (string extension) {
+ this.extension = extension;
+ }
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]