From: Jussi Kukkonen Date: Tue, 22 Oct 2013 11:05:49 +0000 (+0300) Subject: renderer: Implement DLNA byte seeking X-Git-Tag: RYGEL_0_21_1~6 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=0347a67d128438dcce66b9ae8785c543c8ef6b1b;p=profile%2Fivi%2Frygel.git renderer: Implement DLNA byte seeking Adds X_DLNA_GetBytePositionInfo() method, the required state variables and the missing SeekModes for Seek() to AVTransport2 implementation. https://bugzilla.gnome.org/show_bug.cgi?id=710368 https://bugzilla.gnome.org/show_bug.cgi?id=707058 https://bugzilla.gnome.org/show_bug.cgi?id=707059 https://bugzilla.gnome.org/show_bug.cgi?id=707541 --- diff --git a/data/xml/AVTransport2.xml.in b/data/xml/AVTransport2.xml.in index 1b799fd..e9d929b 100644 --- a/data/xml/AVTransport2.xml.in +++ b/data/xml/AVTransport2.xml.in @@ -364,6 +364,32 @@ + + + X_DLNA_GetBytePositionInfo + + + InstanceID + in + A_ARG_TYPE_InstanceID + + + TrackSize + out + X_DLNA_CurrentTrackSize + + + RelByte + out + X_DLNA_RelativeBytePosition + + + AbsByte + out + X_DLNA_AbsoluteBytePosition + + + @@ -650,6 +676,9 @@ ABS_TIME REL_TIME TRACK_NR + ABS_COUNT + REL_COUNT + X_DLNA_REL_BYTE @@ -662,6 +691,21 @@ A_ARG_TYPE_InstanceID ui4 + + + X_DLNA_RelativeBytePosition + string + + + + X_DLNA_AbsoluteBytePosition + string + + + + X_DLNA_CurrentTrackSize + string + diff --git a/examples/renderer-plugins/vala/example-player-vala.vala b/examples/renderer-plugins/vala/example-player-vala.vala index 6771e43..660e956 100644 --- a/examples/renderer-plugins/vala/example-player-vala.vala +++ b/examples/renderer-plugins/vala/example-player-vala.vala @@ -1,5 +1,6 @@ /* * Copyright (C) 2012 Intel Corporation + * Copyright (C) 2013 Cable Television Laboratories, Inc. * * This file is part of Rygel. * @@ -140,6 +141,7 @@ public class Rygel.Example.PlayerVala : GLib.Object, Rygel.MediaPlayer { } public bool can_seek { get { return false; } } + public bool can_seek_bytes { get { return false; } } private string _content_features = ""; public string? content_features { @@ -171,6 +173,12 @@ public class Rygel.Example.PlayerVala : GLib.Object, Rygel.MediaPlayer { } } + public int64 size { + get { + return 0; + } + } + private int64 _position = 0; public int64 position { get { @@ -178,10 +186,20 @@ public class Rygel.Example.PlayerVala : GLib.Object, Rygel.MediaPlayer { } } + public int64 byte_position { + get { + return 0; + } + } + public bool seek (int64 time) { return false; } + public bool seek_bytes (int64 bytes) { + return false; + } + public string[] get_protocols () { return PROTOCOLS; } diff --git a/src/librygel-renderer-gst/rygel-playbin-player.vala b/src/librygel-renderer-gst/rygel-playbin-player.vala index cd35041..3a9cf4b 100644 --- a/src/librygel-renderer-gst/rygel-playbin-player.vala +++ b/src/librygel-renderer-gst/rygel-playbin-player.vala @@ -3,11 +3,14 @@ * Copyright (C) 2009,2010,2011,2012 Nokia Corporation. * Copyright (C) 2012 Openismus GmbH * Copyright (C) 2012,2013 Intel Corporation. + * Copyright (C) 2013 Cable Television Laboratories, Inc. * * Author: Jorn Baayen * Zeeshan Ali (Khattak) * * Jens Georg + * Neha Shanbhag + * Sivakumar Mani * * 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 @@ -233,6 +236,13 @@ public class Rygel.Playbin.Player : GLib.Object, Rygel.MediaPlayer { } } + public bool can_seek_bytes { + get { + return this.transfer_mode != TRANSFER_MODE_INTERACTIVE && + ! this.mime_type.has_prefix ("image/"); + } + } + private string _content_features = ""; private ProtocolInfo protocol_info; public string? content_features { @@ -284,6 +294,18 @@ public class Rygel.Playbin.Player : GLib.Object, Rygel.MediaPlayer { } } + public int64 size { + get { + int64 dur; + + if (this.playbin.source.query_duration (Format.BYTES, out dur)) { + return dur; + } else { + return 0; + } + } + } + public int64 position { get { int64 pos; @@ -296,6 +318,18 @@ public class Rygel.Playbin.Player : GLib.Object, Rygel.MediaPlayer { } } + public int64 byte_position { + get { + int64 pos; + + if (this.playbin.source.query_position (Format.BYTES, out pos)) { + return pos; + } else { + return 0; + } + } + } + private Player () { this.playbin = ElementFactory.make ("playbin", null); this.foreign = false; @@ -320,20 +354,52 @@ public class Rygel.Playbin.Player : GLib.Object, Rygel.MediaPlayer { return player; } + private bool seek_with_format (Format format, int64 target) { + bool seeked; + + var speed = this.play_speed_to_double (this._playback_speed); + if (speed > 0) { + seeked = this.playbin.seek (speed, + format, + SeekFlags.FLUSH | SeekFlags.SKIP | SeekFlags.ACCURATE, + Gst.SeekType.SET, + target, + Gst.SeekType.NONE, + -1); + } else { + seeked = this.playbin.seek (speed, + format, + SeekFlags.FLUSH | SeekFlags.SKIP | SeekFlags.ACCURATE, + Gst.SeekType.SET, + 0, + Gst.SeekType.SET, + target); + } + + return seeked; + } + public bool seek (int64 time) { + debug ("Seeking %lld usec, play speed %s", time, this._new_playback_speed); + // Playbin doesn't return false when seeking beyond the end of the // file if (time > this.duration) { return false; } - return this.playbin.seek (1.0, - Format.TIME, - SeekFlags.FLUSH, - Gst.SeekType.SET, - time * Gst.USECOND, - Gst.SeekType.NONE, - -1); + return this.seek_with_format (Format.TIME, time * Gst.USECOND); + } + + public bool seek_bytes (int64 bytes) { + debug ("Seeking %lld bytes, play speed %s", bytes, this._new_playback_speed); + + int64 size = this.size; + if (size > 0 && bytes > size) { + return false; + } + + return this.seek_with_format (Format.BYTES, bytes); } public string[] get_protocols () { diff --git a/src/librygel-renderer/rygel-av-transport.vala b/src/librygel-renderer/rygel-av-transport.vala index d534d91..a423067 100644 --- a/src/librygel-renderer/rygel-av-transport.vala +++ b/src/librygel-renderer/rygel-av-transport.vala @@ -2,11 +2,14 @@ * Copyright (C) 2008 OpenedHand Ltd. * Copyright (C) 2009,2010 Nokia Corporation. * Copyright (C) 2012 Openismus GmbH. + * Copyright (C) 2013 Cable Television Laboratories, Inc. * * Author: Jorn Baayen * Zeeshan Ali (Khattak) * * Jens Georg + * Neha Shanbhag + * Sivakumar Mani * * 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 @@ -135,6 +138,8 @@ internal class Rygel.AVTransport : Service { action_invoked["Seek"].connect (this.seek_cb); action_invoked["Next"].connect (this.next_cb); action_invoked["Previous"].connect (this.previous_cb); + action_invoked["X_DLNA_GetBytePositionInfo"].connect + (this.x_dlna_get_byte_position_info_cb); this.controller.notify["playback-state"].connect (this.notify_state_cb); this.controller.notify["n-tracks"].connect (this.notify_n_tracks_cb); @@ -558,8 +563,9 @@ internal class Rygel.AVTransport : Service { return; } - this.player.playback_state = "PLAYING"; + // Speed change will take effect when playback state is changed this.player.playback_speed = speed; + this.player.playback_state = "PLAYING"; action.return (); } @@ -596,12 +602,11 @@ internal class Rygel.AVTransport : Service { switch (unit) { case "ABS_TIME": case "REL_TIME": - debug ("Seeking %s to %s.", unit, target); - var seek_target = TimeUtils.time_from_string (target); - if (unit == "REL_TIME") { + if (unit != "ABS_TIME") { seek_target += this.player.position; } + debug ("Seeking to %lld sec", seek_target / TimeSpan.SECOND); if (!this.player.can_seek) { action.return_error (710, _("Seek mode not supported")); @@ -618,6 +623,31 @@ internal class Rygel.AVTransport : Service { action.return (); return; + case "REL_COUNT": + case "X_DLNA_REL_BYTE": + case "ABS_COUNT": + var seek_target = int64.parse (target); + + if (unit != "ABS_COUNT") { + seek_target += this.player.byte_position; + } + debug ("Seeking to %lld bytes.", seek_target); + + if (!this.player.can_seek_bytes) { + action.return_error (710, _("Seek mode not supported")); + + return; + } + + if (!this.player.seek_bytes (seek_target)) { + action.return_error (711, _("Illegal seek target")); + + return; + } + + action.return (); + + return; case "TRACK_NR": debug ("Setting track to %s.", target); var track = int.parse (target); @@ -656,6 +686,38 @@ internal class Rygel.AVTransport : Service { } } + private void x_dlna_get_byte_position_info_cb (Service service, + ServiceAction action) { + if (!this.check_instance_id (action)) { + return; + } + + if (this.controller.uri == "") { + action.set ("TrackSize", + typeof (string), + "", + "RelByte", + typeof (string), + "", + "AbsByte", + typeof (string), + ""); + } else { + var position = this.player.byte_position.to_string (); + action.set ("TrackSize", + typeof (string), + this.player.size.to_string (), + "RelByte", + typeof (string), + position, + "AbsByte", + typeof (string), + position); + } + + action.return (); + } + private void notify_state_cb (Object player, ParamSpec p) { var state = this.player.playback_state; this.changelog.log ("TransportState", state); diff --git a/src/librygel-renderer/rygel-media-player.vala b/src/librygel-renderer/rygel-media-player.vala index 181ffeb..1efcf05 100644 --- a/src/librygel-renderer/rygel-media-player.vala +++ b/src/librygel-renderer/rygel-media-player.vala @@ -1,11 +1,13 @@ /* * Copyright (C) 2008 OpenedHand Ltd. * Copyright (C) 2009,2010 Nokia Corporation. - * Copyright (C) 2012 Intel Corporation. + * Copyright (C) 2012,2013 Intel Corporation. + * Copyright (C) 2013 Cable Television Laboratories, Inc. * * Author: Jorn Baayen * Zeeshan Ali (Khattak) * + * Sivakumar Mani * * 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 @@ -51,6 +53,9 @@ public interface Rygel.MediaPlayer : GLib.Object { /// Duration of the current media in microseconds public abstract int64 duration { get; } + /// Size of the current media in bytes + public abstract int64 size { get; } + /** * A DIDLLite document describing the current media URI or null. * The document is either the one received from a UPnP control point or @@ -64,6 +69,9 @@ public interface Rygel.MediaPlayer : GLib.Object { /// The current media supports time-based seeking public abstract bool can_seek { get; } + /// The current media supports byte-based seeking + public abstract bool can_seek_bytes { get; } + /** * The contents of the contentFeatures.dlna.org HTTP header, * containing the 4th field of the protocol info for the current @@ -82,6 +90,9 @@ public interface Rygel.MediaPlayer : GLib.Object { /// Position in the current media in microseconds public abstract int64 position { get; } + ///Position in the current media in bytes + public abstract int64 byte_position { get; } + /// The position as a human-readable string, in HH:MM:SS format public string position_as_str { owned get { @@ -96,6 +107,11 @@ public interface Rygel.MediaPlayer : GLib.Object { public abstract bool seek (int64 time); /** + * Seek to a byte position in the current media. + */ + public abstract bool seek_bytes (int64 bytes); + + /** * Return the protocols supported by this renderer, * such as "http-get" and "rtsp". */ diff --git a/src/librygel-renderer/rygel-player-controller.vala b/src/librygel-renderer/rygel-player-controller.vala index d2fc496..0d91640 100644 --- a/src/librygel-renderer/rygel-player-controller.vala +++ b/src/librygel-renderer/rygel-player-controller.vala @@ -106,7 +106,13 @@ internal class Rygel.PlayerController : Object { if (this.player.can_seek) { actions += ",X_DLNA_SeekTime"; + } + if (actions != null && this.player.can_seek_bytes) { + actions += ",X_DLNA_SeekByte"; + } + if (actions != null && + this.player.allowed_playback_speeds.length > 1) { string play_speeds = ""; foreach (var speed in this.player.allowed_playback_speeds) { if (speed != "1") { diff --git a/src/plugins/mpris/rygel-mpris-player.vala b/src/plugins/mpris/rygel-mpris-player.vala index ba7afaf..8fab6e6 100644 --- a/src/plugins/mpris/rygel-mpris-player.vala +++ b/src/plugins/mpris/rygel-mpris-player.vala @@ -1,10 +1,12 @@ /* * Copyright (C) 2008 OpenedHand Ltd. * Copyright (C) 2009 Nokia Corporation. + * Copyright (C) 2013 Cable Television Laboratories, Inc. * * Author: Jorn Baayen * Zeeshan Ali (Khattak) * + * Sivakumar Mani * * 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 @@ -128,6 +130,12 @@ public class Rygel.MPRIS.Player : GLib.Object, Rygel.MediaPlayer { } } + public bool can_seek_bytes { + get { + return false; + } + } + public double volume { get { return this.actual_player.volume; @@ -151,12 +159,25 @@ public class Rygel.MPRIS.Player : GLib.Object, Rygel.MediaPlayer { } } + public int64 size { + get { + return 0; + } + } + public int64 position { get { return this.actual_player.position; } } + public int64 byte_position { + get { + return 0; + } + } + + public Player (Plugin plugin) { this.actual_player = plugin.actual_player; this.mime_types = plugin.mime_types; @@ -176,6 +197,10 @@ public class Rygel.MPRIS.Player : GLib.Object, Rygel.MediaPlayer { return ret; } + public bool seek_bytes (int64 bytes) { + return false; + } + public string[] get_protocols () { return this.protocols; }