"channels=1";
public AACTranscoder () {
- base ("audio/3gpp", "AAC_ISO_320", BITRATE, CONTAINER, CODEC);
+ base ("audio/3gpp", "AAC_ISO_320", BITRATE, CONTAINER, CODEC, "3gp");
}
}
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) {
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) {
CONTAINER,
AUDIO_CAPS,
VIDEO_CAPS,
+ "mp4",
RESTRICTIONS);
}
* 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,
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 ("/");
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":
} else if (this.subtitle_index >= 0) {
path += "/sub/" + this.subtitle_index.to_string ();
}
-
+ path += this.extension;
return this.create_uri_for_path (path);
}
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 "";
+ }
}
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,
"LPCM",
0,
AudioTranscoder.NO_CONTAINER,
- caps_str);
+ caps_str,
+ "lpcm");
}
public override DIDLLiteResource? add_resource (DIDLLiteItem didl_item,
CONTAINER,
AUDIO_FORMAT,
BASE_VIDEO_FORMAT,
+ "mpg",
RESTRICTION_TEMPLATE.printf (FRAME_RATE[profile],
WIDTH[profile],
HEIGHT[profile]));
"MP3",
BITRATE,
AudioTranscoder.NO_CONTAINER,
- FORMAT);
+ FORMAT,
+ "mp3");
}
}
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";
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;
}
/**
string container_caps,
string audio_codec_caps,
string video_codec_caps,
+ string extension,
string? restrictions = null) {
base.with_class (content_type,
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);
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");
}
}
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));
}
}
- 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);
}
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);
}
}
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;
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 {
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;
+ }
+}
* 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,
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";
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) {
}
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 (),
}
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);
}
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);
}
private HTTPItemURI test_construction_with_transcoder () {
- var uri = new HTTPItemURI (ITEM_ID,
+ var uri = new HTTPItemURI (this.item,
this.server,
THUMBNAIL_INDEX,
-1,
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 ();
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 {
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;
}
}
-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;
+ }
+}