[rygel] renderer: Implement DLNA byte seeking



commit 0347a67d128438dcce66b9ae8785c543c8ef6b1b
Author: Jussi Kukkonen <jussi kukkonen intel com>
Date:   Tue Oct 22 14:05:49 2013 +0300

    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

 data/xml/AVTransport2.xml.in                       |   44 +++++++++++
 .../renderer-plugins/vala/example-player-vala.vala |   18 +++++
 .../rygel-playbin-player.vala                      |   80 ++++++++++++++++++--
 src/librygel-renderer/rygel-av-transport.vala      |   70 ++++++++++++++++-
 src/librygel-renderer/rygel-media-player.vala      |   18 ++++-
 src/librygel-renderer/rygel-player-controller.vala |    6 ++
 src/plugins/mpris/rygel-mpris-player.vala          |   25 ++++++
 7 files changed, 249 insertions(+), 12 deletions(-)
---
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 @@
             </argument>
          </argumentList>
       </action>
+
+      <action>
+         <name>X_DLNA_GetBytePositionInfo</name>
+         <argumentList>
+            <argument>
+               <name>InstanceID</name>
+               <direction>in</direction>
+               <relatedStateVariable>A_ARG_TYPE_InstanceID</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>TrackSize</name>
+               <direction>out</direction>
+               <relatedStateVariable>X_DLNA_CurrentTrackSize</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>RelByte</name>
+               <direction>out</direction>
+               <relatedStateVariable>X_DLNA_RelativeBytePosition</relatedStateVariable>
+            </argument>
+            <argument>
+               <name>AbsByte</name>
+               <direction>out</direction>
+               <relatedStateVariable>X_DLNA_AbsoluteBytePosition</relatedStateVariable>
+            </argument>
+         </argumentList>
+      </action>
    </actionList>
 
    <serviceStateTable>
@@ -650,6 +676,9 @@
             <allowedValue>ABS_TIME</allowedValue>
             <allowedValue>REL_TIME</allowedValue>
             <allowedValue>TRACK_NR</allowedValue>
+            <allowedValue>ABS_COUNT</allowedValue>
+            <allowedValue>REL_COUNT</allowedValue>
+            <allowedValue>X_DLNA_REL_BYTE</allowedValue>
          </allowedValueList>
       </stateVariable>
 
@@ -662,6 +691,21 @@
          <name>A_ARG_TYPE_InstanceID</name>
          <dataType>ui4</dataType>
       </stateVariable>
+
+      <stateVariable sendEvents="no">
+         <name>X_DLNA_RelativeBytePosition</name>
+         <dataType>string</dataType>
+      </stateVariable>
+
+      <stateVariable sendEvents="no">
+         <name>X_DLNA_AbsoluteBytePosition</name>
+         <dataType>string</dataType>
+      </stateVariable>
+
+      <stateVariable sendEvents="no">
+         <name>X_DLNA_CurrentTrackSize</name>
+         <dataType>string</dataType>
+      </stateVariable>
    </serviceStateTable>
 </scpd>
 
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 <jorn openedhand com>
  *         Zeeshan Ali (Khattak) <zeeshanak gnome org>
  *                               <zeeshan ali nokia com>
  *         Jens Georg <jensg openismus com>
+ *         Neha Shanbhag <N Shanbhag cablelabs com>
+ *         Sivakumar Mani <siva orexel com>
  *
  * 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 <jorn openedhand com>
  *         Zeeshan Ali (Khattak) <zeeshanak gnome org>
  *                               <zeeshan ali nokia com>
  *         Jens Georg <jensg openismus com>
+ *         Neha Shanbhag <N Shanbhag cablelabs com>
+ *         Sivakumar Mani <siva orexel com>
  *
  * 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 <jorn openedhand com>
  *         Zeeshan Ali (Khattak) <zeeshanak gnome org>
  *                               <zeeshan ali nokia com>
+ *         Sivakumar Mani <siva orexel com>
  *
  * 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 <jorn openedhand com>
  *         Zeeshan Ali (Khattak) <zeeshanak gnome org>
  *                               <zeeshan ali nokia com>
+ *         Sivakumar Mani <siva orexel com>
  *
  * 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;
     }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]