[gnome-music/wip/jfelder/mpris-fix-seek: 2/7] mpris: Correctly handle position unit



commit fec49f413d676380ad6a3a5c3f02d137246cd006
Author: Jean Felder <jfelder src gnome org>
Date:   Tue Sep 25 10:34:29 2018 +0200

    mpris: Correctly handle position unit
    
    MPRIS position unit is in microseconds while Player position and
    duration unit is seconds.
    Correctly handle the conversion between the two objects.
    
    Simplify player set_position method: if the requested position is
    greater than the position, do nothing.
    
    Use the following syntax:
     * position means an absolute position
     * offset means a position relative to the current one
     * msecond means a position in microseconds
     * second means a position in seconds
    
    Closes: #227

 gnomemusic/mpris.py  | 49 ++++++++++++++++++++++++++++++++++++-------------
 gnomemusic/player.py | 33 +++++++++++++++------------------
 2 files changed, 51 insertions(+), 31 deletions(-)
---
diff --git a/gnomemusic/mpris.py b/gnomemusic/mpris.py
index d488d8c7..e34dac23 100644
--- a/gnomemusic/mpris.py
+++ b/gnomemusic/mpris.py
@@ -471,8 +471,8 @@ class MediaPlayer2Service(Server):
         self.player.play()
 
     @log
-    def _on_seeked(self, player, position, data=None):
-        self.Seeked(position)
+    def _on_seeked(self, player, position_second):
+        self.Seeked(int(position_second * 1e6))
 
     @log
     def _on_playlist_changed(self, player, data=None):
@@ -550,23 +550,45 @@ class MediaPlayer2Service(Server):
             else:
                 self.first_song_handler = model.connect('row-inserted', self._play_first_song)
 
-    def Seek(self, offset):
-        self.player.set_position(offset, True, True)
+    def Seek(self, offset_msecond):
+        """Seek forward in the current track.
 
-    def SetPosition(self, track_id, position):
+        Seek is relative to the current player position.
+        If the value passed in would mean seeking beyond the end of the track,
+        acts like a call to Next.
+        :param int offset_msecond: number of microseconds
+        """
+        current_position_second = self.player.get_position()
+        new_position_second = current_position_second + offset_msecond / 1e6
+
+        duration_second = self.player.props.duration
+        if new_position_second <= duration_second:
+            self.player.set_position(new_position_second)
+        else:
+            self.player.next()
+
+    def SetPosition(self, track_id, position_msecond):
+        """Set the current track position in microseconds.
+
+        :param str track_id: The currently playing track's identifier
+        :param int position_msecond: new position in microseconds
+        """
         if track_id != self._get_metadata().get('mpris:trackid').get_string():
             return
-        self.player.set_position(position)
+        self.player.set_position(position_msecond / 1e6)
 
     def OpenUri(self, uri):
         pass
 
-    def Seeked(self, position):
-        self.con.emit_signal(None,
-                             '/org/mpris/MediaPlayer2',
-                             MediaPlayer2Service.MEDIA_PLAYER2_PLAYER_IFACE,
-                             'Seeked',
-                             GLib.Variant.new_tuple(GLib.Variant('x', position)))
+    def Seeked(self, position_msecond):
+        """Indicate that the track position has changed.
+
+        :param int position_msecond: new position in microseconds.
+        """
+        variant = GLib.Variant.new_tuple(GLib.Variant('x', position_msecond))
+        self.con.emit_signal(
+            None, '/org/mpris/MediaPlayer2',
+            MediaPlayer2Service.MEDIA_PLAYER2_PLAYER_IFACE, 'Seeked', variant)
 
     def GetTracksMetadata(self, track_ids):
         metadata = []
@@ -661,6 +683,7 @@ class MediaPlayer2Service(Server):
                 ]),
             }
         elif interface_name == MediaPlayer2Service.MEDIA_PLAYER2_PLAYER_IFACE:
+            position_msecond = int(self.player.get_position() * 1e6)
             return {
                 'PlaybackStatus': GLib.Variant('s', self._get_playback_status()),
                 'LoopStatus': GLib.Variant('s', self._get_loop_status()),
@@ -668,7 +691,7 @@ class MediaPlayer2Service(Server):
                 'Shuffle': GLib.Variant('b', self.player.props.repeat_mode == RepeatMode.SHUFFLE),
                 'Metadata': GLib.Variant('a{sv}', self._get_metadata()),
                 'Volume': GLib.Variant('d', self.player.get_volume()),
-                'Position': GLib.Variant('x', self.player.get_position()),
+                'Position': GLib.Variant('x', position_msecond),
                 'MinimumRate': GLib.Variant('d', 1.0),
                 'MaximumRate': GLib.Variant('d', 1.0),
                 'CanGoNext': GLib.Variant('b', self.player.props.has_next),
diff --git a/gnomemusic/player.py b/gnomemusic/player.py
index f2dffcfc..821f721d 100644
--- a/gnomemusic/player.py
+++ b/gnomemusic/player.py
@@ -804,32 +804,29 @@ class Player(GObject.GObject):
 
     @log
     def get_position(self):
+        """Get player position.
+
+        Player position in seconds.
+        :returns: position
+        :rtype: float
+        """
         return self._player.position
 
     # TODO: used by MPRIS
     @log
-    def set_position(self, offset, start_if_ne=False, next_on_overflow=False):
+    def set_position(self, position_second):
         """Change GstPlayer position.
 
-        :param int offset: requested position in second
-        :param bool start_if_ne: if position is negative, set it to zero
-        :param bool next_on_overflow: next song if position is greater than
-                                      duration
+        If the position if negative, set it to zero.
+        If the position if greater than song duration, do nothing
+        :param float position_second: requested position in second
         """
-        if offset < 0:
-            if start_if_ne:
-                offset = 0
-            else:
-                return
+        if position_second < 0.0:
+            position_second = 0.0
 
-        if self.props.duration == -1.:
-            return
-
-        if self.props.duration >= offset:
-            self._player.seek(offset)
-            self.emit('seeked', offset)
-        elif next_on_overflow:
-            self.next()
+        duration_second = self._player.props.duration
+        if position_second <= duration_second:
+            self._player.seek(position_second)
 
     @log
     def get_volume(self):


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