/* * Copyright (C) 2013 Cable Television Laboratories, Inc. * * Author: Craig Pratt * * 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.1 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 library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ using GUPnP; /** * The HTTP handler for HTTP ContentResource requests. */ internal class Rygel.HTTPMediaResourceHandler : HTTPGetHandler { private MediaObject media_object; private string media_resource_name; public MediaResource media_resource; public HTTPMediaResourceHandler (MediaObject media_object, string media_resource_name, Cancellable? cancellable) throws HTTPRequestError { this.media_object = media_object; this.cancellable = cancellable; this.media_resource_name = media_resource_name; var resource = media_object.get_resource_by_name (media_resource_name); if (resource == null) { throw new HTTPRequestError.NOT_FOUND ("MediaResource %s not found", media_resource_name); } // Handler modifies the resource, so we copy it. this.media_resource = resource.dup (); } public override void add_response_headers (HTTPGet request) throws HTTPRequestError { request.http_server.set_resource_delivery_options (this.media_resource); var replacements = request.http_server.get_replacements (); var mime_type = MediaObject.apply_replacements (replacements, this.media_resource.mime_type); request.msg.response_headers.append ("Content-Type", mime_type); // Add contentFeatures.dlna.org var protocol_info = media_resource.get_protocol_info (replacements); if (protocol_info != null) { var pi_fields = protocol_info.to_string ().split (":", 4); if (pi_fields != null && pi_fields[3] != null) { request.msg.response_headers.append ("contentFeatures.dlna.org", pi_fields[3]); } } // Chain-up base.add_response_headers (request); } public override string get_default_transfer_mode () { // Per DLNA 7.5.4.3.2.33.2, the assumed transfer mode is based on the content type // "Streaming" for AV content and "Interactive" for all others return media_resource.get_default_transfer_mode (); } public override bool supports_transfer_mode (string mode) { return media_resource.supports_transfer_mode (mode); } public override HTTPResponse render_body (HTTPGet request) throws HTTPRequestError { try { var src = request.object.create_stream_source_for_resource (request, this.media_resource); if (src == null) { throw new HTTPRequestError.NOT_FOUND (_("Couldn’t create data source for %s"), this.media_resource.get_name ()); } return new HTTPResponse (request, this, src); } catch (Error err) { throw new HTTPRequestError.NOT_FOUND (err.message); } } public override int64 get_resource_size () { return media_resource.size; } public override int64 get_resource_duration () { return media_resource.duration * TimeSpan.SECOND; } public override bool supports_byte_seek () { return media_resource.supports_arbitrary_byte_seek () || media_resource.supports_limited_byte_seek (); } public override bool supports_time_seek () { return media_resource.supports_arbitrary_time_seek () || media_resource.supports_limited_time_seek (); } public override bool supports_playspeed () { return media_resource.supports_playspeed (); } }