From a7022e27e4df91388170481f0d51d16473aa20e9 Mon Sep 17 00:00:00 2001 From: "Zeeshan Ali (Khattak)" Date: Mon, 9 Feb 2009 22:27:38 +0000 Subject: [PATCH] Separate class for serializing the media objects. svn path=/trunk/; revision=538 --- src/rygel/Makefile.am | 7 +- src/rygel/rygel-browse.vala | 9 +- src/rygel/rygel-didl-lite-writer.vala | 225 ++++++++++++++++++++++++++++++++++ src/rygel/rygel-media-container.vala | 27 ---- src/rygel/rygel-media-item.vala | 159 +----------------------- src/rygel/rygel-media-object.vala | 5 +- 6 files changed, 238 insertions(+), 194 deletions(-) create mode 100644 src/rygel/rygel-didl-lite-writer.vala diff --git a/src/rygel/Makefile.am b/src/rygel/Makefile.am index c7ac2d5..0c89b96 100644 --- a/src/rygel/Makefile.am +++ b/src/rygel/Makefile.am @@ -34,6 +34,8 @@ BUILT_SOURCES = rygel-1.0.vapi \ rygel-content-directory.c \ rygel-browse.h \ rygel-browse.c \ + rygel-didl-lite-writer.h \ + rygel-didl-lite-writer.c \ rygel-plugin.h \ rygel-plugin.c \ rygel-plugin-loader.h \ @@ -77,6 +79,8 @@ rygel_SOURCES = rygel-1.0.vapi \ rygel-content-directory.c \ rygel-browse.h \ rygel-browse.c \ + rygel-didl-lite-writer.h \ + rygel-didl-lite-writer.c \ rygel-plugin.h \ rygel-plugin.c \ rygel-plugin-loader.h \ @@ -135,7 +139,8 @@ VAPI_SOURCE_FILES = rygel-content-directory.vala \ rygel-media-object.vala \ rygel-media-container.vala \ rygel-media-item.vala \ - rygel-browse.vala + rygel-browse.vala \ + rygel-didl-lite-writer.vala rygel-1.0.vapi: $(VAPI_SOURCE_FILES) $(VALAC) -C --library=rygel-1.0 \ diff --git a/src/rygel/rygel-browse.vala b/src/rygel/rygel-browse.vala index 9d32d47..f25391f 100644 --- a/src/rygel/rygel-browse.vala +++ b/src/rygel/rygel-browse.vala @@ -52,7 +52,7 @@ public class Browse: GLib.Object { private unowned ContentDirectory content_dir; private ServiceAction action; - private DIDLLiteWriter didl_writer; + private Rygel.DIDLLiteWriter didl_writer; // Signals public signal void completed (); @@ -62,7 +62,8 @@ public class Browse: GLib.Object { this.content_dir = content_dir; this.action = (owned) action; - this.didl_writer = new DIDLLiteWriter (); + this.didl_writer = + new Rygel.DIDLLiteWriter (this.content_dir.http_server); } public void start () { @@ -105,7 +106,7 @@ public class Browse: GLib.Object { } try { - this.media_object.serialize (didl_writer); + this.didl_writer.serialize (this.media_object); } catch (Error err) { this.handle_error (err); return; @@ -229,7 +230,7 @@ public class Browse: GLib.Object { /* serialize all children */ for (int i = 0; i < children.size; i++) { try { - children[i].serialize (didl_writer); + this.didl_writer.serialize (children[i]); } catch (Error err) { this.handle_error (err); return false; diff --git a/src/rygel/rygel-didl-lite-writer.vala b/src/rygel/rygel-didl-lite-writer.vala new file mode 100644 index 0000000..1d3e750 --- /dev/null +++ b/src/rygel/rygel-didl-lite-writer.vala @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2009 Nokia Corporation, all rights reserved. + * + * Author: Zeeshan Ali (Khattak) + * + * + * 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; +using Gee; + +public errordomain Rygel.DIDLLiteWriterError { + UNKNOWN_URI_TYPE, + UNSUPPORTED_OBJECT +} + +/** + * Responsible for serializing media objects. + */ +public class Rygel.DIDLLiteWriter : GUPnP.DIDLLiteWriter { + private Rygel.HTTPServer http_server; + + public DIDLLiteWriter (HTTPServer http_server) { + this.http_server = http_server; + } + + public void serialize (MediaObject media_object) throws Error { + if (media_object is MediaItem) { + this.serialize_item ((MediaItem) media_object); + } else if (media_object is MediaContainer) { + this.serialize_container ((MediaContainer) media_object); + } else { + throw new DIDLLiteWriterError.UNSUPPORTED_OBJECT ( + "Unable to serialize unsupported object"); + } + } + + private void serialize_item (MediaItem item) throws Error { + this.start_item (item.id, + item.parent_id, + null, + false); + + /* Add fields */ + this.add_string ("title", + GUPnP.DIDLLiteWriter.NAMESPACE_DC, + null, + item.title); + + this.add_string ("class", + GUPnP.DIDLLiteWriter.NAMESPACE_UPNP, + null, + item.upnp_class); + + if (item.author != null && item.author != "") { + this.add_string ("creator", + GUPnP.DIDLLiteWriter.NAMESPACE_DC, + null, + item.author); + + if (item.upnp_class.has_prefix (MediaItem.VIDEO_CLASS)) { + this.add_string ("author", + GUPnP.DIDLLiteWriter.NAMESPACE_UPNP, + null, + item.author); + } else if (item.upnp_class.has_prefix (MediaItem.MUSIC_CLASS)) { + this.add_string ("artist", + GUPnP.DIDLLiteWriter.NAMESPACE_UPNP, + null, + item.author); + } + } + + if (item.track_number >= 0) { + this.add_int ("originalTrackNumber", + GUPnP.DIDLLiteWriter.NAMESPACE_UPNP, + null, + item.track_number); + } + + if (item.album != null && item.album != "") { + this.add_string ("album", + GUPnP.DIDLLiteWriter.NAMESPACE_UPNP, + null, + item.album); + } + + if (item.date != null && item.date != "") { + this.add_string ("date", + GUPnP.DIDLLiteWriter.NAMESPACE_DC, + null, + item.date); + } + + /* Add resource data */ + DIDLLiteResource res = this.get_original_res (item); + + /* Now get the transcoded/proxy URIs */ + var res_list = this.get_transcoded_resources (item, res); + foreach (DIDLLiteResource trans_res in res_list) { + this.add_res (trans_res); + } + + /* Add the original res in the end */ + if (res.uri != null) { + this.add_res (res); + } + + /* End of item */ + this.end_item (); + } + + private void serialize_container (MediaContainer container) throws Error { + this.start_container (container.id, + container.parent_id, + (int) container.child_count, + false, + false); + + this.add_string ("class", + GUPnP.DIDLLiteWriter.NAMESPACE_UPNP, + null, + "object.container.storageFolder"); + + this.add_string ("title", + GUPnP.DIDLLiteWriter.NAMESPACE_DC, + null, + container.title); + + /* End of Container */ + this.end_container (); + } + + private string get_protocol_for_uri (string uri) throws Error { + if (uri.has_prefix ("http")) { + return "http-get"; + } else if (uri.has_prefix ("file")) { + return "internal"; + } else if (uri.has_prefix ("rtsp")) { + // FIXME: Assuming that RTSP is always accompanied with RTP over UDP + return "rtsp-rtp-udp"; + } else { + throw new DIDLLiteWriterError.UNKNOWN_URI_TYPE + ("Failed to probe protocol for URI %s", uri); + } + } + + // FIXME: We only proxy URIs through our HTTP server for now + private ArrayList? get_transcoded_resources + (MediaItem item, + DIDLLiteResource orig_res) { + if (orig_res.protocol == "http-get") + return null; + + var resources = new ArrayList (); + + // Copy the original res first + DIDLLiteResource res = orig_res; + + // Then modify the URI and protocol + res.uri = this.http_server.create_http_uri_for_item (item); + res.protocol = "http-get"; + + resources.add (res); + + return resources; + } + + private DIDLLiteResource get_original_res (MediaItem item) throws Error { + DIDLLiteResource res = DIDLLiteResource (); + res.reset (); + + res.uri = item.uri; + res.mime_type = item.mime_type; + + res.size = item.size; + res.duration = item.duration; + res.bitrate = item.bitrate; + + res.sample_freq = item.sample_freq; + res.bits_per_sample = item.bits_per_sample; + res.n_audio_channels = item.n_audio_channels; + + res.width = item.width; + res.height = item.height; + res.color_depth = item.color_depth; + + /* Protocol info */ + if (res.uri != null) { + string protocol = get_protocol_for_uri (res.uri); + res.protocol = protocol; + } + + /* DLNA related fields */ + res.dlna_profile = "MP3"; /* FIXME */ + + if (item.upnp_class.has_prefix (MediaItem.IMAGE_CLASS)) { + res.dlna_flags |= DLNAFlags.INTERACTIVE_TRANSFER_MODE; + } else { + res.dlna_flags |= DLNAFlags.STREAMING_TRANSFER_MODE; + } + + if (res.size > 0) { + res.dlna_operation = DLNAOperation.RANGE; + res.dlna_flags |= DLNAFlags.BACKGROUND_TRANSFER_MODE; + } + + return res; + } +} diff --git a/src/rygel/rygel-media-container.vala b/src/rygel/rygel-media-container.vala index c5ddc74..2be7ad9 100644 --- a/src/rygel/rygel-media-container.vala +++ b/src/rygel/rygel-media-container.vala @@ -50,33 +50,6 @@ public abstract class Rygel.MediaContainer : MediaObject { } /** - * Serializes this container to the specified DIDLLiteWriter object - * - * @param didl_writer the DIDLLiteWriter object to serialize to. - * - */ - public override void serialize (DIDLLiteWriter didl_writer) throws Error { - didl_writer.start_container (this.id, - this.parent_id, - (int) this.child_count, - false, - false); - - didl_writer.add_string ("class", - DIDLLiteWriter.NAMESPACE_UPNP, - null, - "object.container.storageFolder"); - - didl_writer.add_string ("title", - DIDLLiteWriter.NAMESPACE_DC, - null, - this.title); - - /* End of Container */ - didl_writer.end_container (); - } - - /** * Fetches the list of media objects directly under this container. * * @param offet zero-based index of the first item to return diff --git a/src/rygel/rygel-media-item.vala b/src/rygel/rygel-media-item.vala index bcf81fc..2d85847 100644 --- a/src/rygel/rygel-media-item.vala +++ b/src/rygel/rygel-media-item.vala @@ -21,15 +21,9 @@ */ using GUPnP; -using Gee; - -public errordomain Rygel.MediaItemError { - UNKNOWN_URI_TYPE -} /** - * Represents a media (Music, Video and Image) item. Provides basic - * serialization (to DIDLLiteWriter) implementation. + * Represents a media (Music, Video and Image) item. */ public class Rygel.MediaItem : MediaObject { public static const string IMAGE_CLASS = "object.item.imageItem"; @@ -75,160 +69,9 @@ public class Rygel.MediaItem : MediaObject { this.http_server = http_server; } - public override void serialize (DIDLLiteWriter didl_writer) throws Error { - didl_writer.start_item (this.id, - this.parent_id, - null, - false); - - /* Add fields */ - didl_writer.add_string ("title", - DIDLLiteWriter.NAMESPACE_DC, - null, - this.title); - - didl_writer.add_string ("class", - DIDLLiteWriter.NAMESPACE_UPNP, - null, - this.upnp_class); - - if (this.author != null && this.author != "") { - didl_writer.add_string ("creator", - DIDLLiteWriter.NAMESPACE_DC, - null, - this.author); - - if (this.upnp_class.has_prefix (VIDEO_CLASS)) { - didl_writer.add_string ("author", - DIDLLiteWriter.NAMESPACE_UPNP, - null, - this.author); - } else if (this.upnp_class.has_prefix (MUSIC_CLASS)) { - didl_writer.add_string ("artist", - DIDLLiteWriter.NAMESPACE_UPNP, - null, - this.author); - } - } - - if (this.track_number >= 0) { - didl_writer.add_int ("originalTrackNumber", - DIDLLiteWriter.NAMESPACE_UPNP, - null, - this.track_number); - } - - if (this.album != null && this.album != "") { - didl_writer.add_string ("album", - DIDLLiteWriter.NAMESPACE_UPNP, - null, - this.album); - } - - if (this.date != null && this.date != "") { - didl_writer.add_string ("date", - DIDLLiteWriter.NAMESPACE_DC, - null, - this.date); - } - - /* Add resource data */ - DIDLLiteResource res = this.get_original_res (); - - /* Now get the transcoded/proxy URIs */ - var res_list = this.get_transcoded_resources (res); - foreach (DIDLLiteResource trans_res in res_list) { - didl_writer.add_res (trans_res); - } - - /* Add the original res in the end */ - if (res.uri != null) { - didl_writer.add_res (res); - } - - /* End of item */ - didl_writer.end_item (); - } - // Live media items need to provide a nice working implementation of this // method if they can/do no provide a valid URI public virtual Gst.Element? create_stream_source () { return null; } - - private string get_protocol_for_uri (string uri) throws Error { - if (uri.has_prefix ("http")) { - return "http-get"; - } else if (uri.has_prefix ("file")) { - return "internal"; - } else if (uri.has_prefix ("rtsp")) { - // FIXME: Assuming that RTSP is always accompanied with RTP over UDP - return "rtsp-rtp-udp"; - } else { - throw new MediaItemError.UNKNOWN_URI_TYPE - ("Failed to probe protocol for URI %s", uri); - } - } - - // FIXME: We only proxy URIs through our HTTP server for now - private ArrayList? get_transcoded_resources - (DIDLLiteResource orig_res) { - if (orig_res.protocol == "http-get") - return null; - - var resources = new ArrayList (); - - // Copy the original res first - DIDLLiteResource res = orig_res; - - // Then modify the URI and protocol - res.uri = this.http_server.create_http_uri_for_item (this); - res.protocol = "http-get"; - - resources.add (res); - - return resources; - } - - private DIDLLiteResource get_original_res () throws Error { - DIDLLiteResource res = DIDLLiteResource (); - res.reset (); - - res.uri = this.uri; - res.mime_type = this.mime_type; - - res.size = this.size; - res.duration = this.duration; - res.bitrate = this.bitrate; - - res.sample_freq = this.sample_freq; - res.bits_per_sample = this.bits_per_sample; - res.n_audio_channels = this.n_audio_channels; - - res.width = this.width; - res.height = this.height; - res.color_depth = this.color_depth; - - /* Protocol info */ - if (res.uri != null) { - string protocol = get_protocol_for_uri (res.uri); - res.protocol = protocol; - } - - /* DLNA related fields */ - res.dlna_profile = "MP3"; /* FIXME */ - - if (this.upnp_class.has_prefix (MediaItem.IMAGE_CLASS)) { - res.dlna_flags |= DLNAFlags.INTERACTIVE_TRANSFER_MODE; - } else { - res.dlna_flags |= DLNAFlags.STREAMING_TRANSFER_MODE; - } - - if (res.size > 0) { - res.dlna_operation = DLNAOperation.RANGE; - res.dlna_flags |= DLNAFlags.BACKGROUND_TRANSFER_MODE; - } - - return res; - } } diff --git a/src/rygel/rygel-media-object.vala b/src/rygel/rygel-media-object.vala index 5972509..cd89e80 100644 --- a/src/rygel/rygel-media-object.vala +++ b/src/rygel/rygel-media-object.vala @@ -23,13 +23,10 @@ using GUPnP; /** - * Represents a media object (container and item). Subclasses should implement - * the abstract serialize method. + * Represents a media object (container and item). */ public abstract class Rygel.MediaObject { public string id; public string parent_id; public string title; - - public abstract void serialize (DIDLLiteWriter didl_writer) throws Error; } -- 2.7.4