From 6adeea6009343402507f7d2c7d6c5d80c27d3cd1 Mon Sep 17 00:00:00 2001 From: Thomas Adamcik Date: Sun, 15 Mar 2015 11:29:07 +0100 Subject: [PATCH] core: Correctly handle missing duration in seek. Seeks will now fail when the duration is None, this is an approximation to if the track is seekable or not. This check is need as otherwise seeking a radio stream will trigger the next track. If the track truly isn't seekable despite having a duration we should still fail as GStreamer will reject the seek. --- mopidy/core/playback.py | 3 +++ mopidy/models.py | 2 +- mopidy/mpd/translator.py | 2 ++ tests/core/test_playback.py | 11 +++++++++++ tests/mpd/test_translator.py | 2 ++ 5 files changed, 19 insertions(+), 1 deletion(-) diff --git a/mopidy/core/playback.py b/mopidy/core/playback.py index e92563dd..84ffecb4 100644 --- a/mopidy/core/playback.py +++ b/mopidy/core/playback.py @@ -361,6 +361,9 @@ class PlaybackController(object): if not self.core.tracklist.tracks: return False + if self.current_track and self.current_track.length is None: + return False + if self.get_state() == PlaybackState.STOPPED: self.play() diff --git a/mopidy/models.py b/mopidy/models.py index 4d6ed27d..47f17b6b 100644 --- a/mopidy/models.py +++ b/mopidy/models.py @@ -325,7 +325,7 @@ class Track(ImmutableObject): :param date: track release date (YYYY or YYYY-MM-DD) :type date: string :param length: track length in milliseconds - :type length: integer + :type length: integer or :class:`None` if there is no duration :param bitrate: bitrate in kbit/s :type bitrate: integer :param comment: track comment diff --git a/mopidy/mpd/translator.py b/mopidy/mpd/translator.py index 77adecd0..8359f86b 100644 --- a/mopidy/mpd/translator.py +++ b/mopidy/mpd/translator.py @@ -34,6 +34,8 @@ def track_to_mpd_format(track, position=None, stream_title=None): result = [ ('file', track.uri or ''), + # TODO: only show length if not none, see: + # https://github.com/mopidy/mopidy/issues/923#issuecomment-79584110 ('Time', track.length and (track.length // 1000) or 0), ('Artist', artists_to_mpd_format(track.artists)), ('Title', track.name or ''), diff --git a/tests/core/test_playback.py b/tests/core/test_playback.py index 8911978a..2a28be4d 100644 --- a/tests/core/test_playback.py +++ b/tests/core/test_playback.py @@ -38,6 +38,7 @@ class CorePlaybackTest(unittest.TestCase): Track(uri='dummy2:a', length=40000), Track(uri='dummy3:a', length=40000), # Unplayable Track(uri='dummy1:b', length=40000), + Track(uri='dummy1:c', length=None), # No duration ] self.core = core.Core(mixer=None, backends=[ @@ -46,6 +47,7 @@ class CorePlaybackTest(unittest.TestCase): self.tl_tracks = self.core.tracklist.tl_tracks self.unplayable_tl_track = self.tl_tracks[2] + self.duration_less_tl_track = self.tl_tracks[4] def test_get_current_tl_track_none(self): self.core.playback.set_current_tl_track(None) @@ -478,6 +480,15 @@ class CorePlaybackTest(unittest.TestCase): self.assertFalse(self.playback1.seek.called) self.assertFalse(self.playback2.seek.called) + def test_seek_fails_for_track_without_duration(self): + self.core.playback.current_tl_track = self.duration_less_tl_track + self.core.playback.state = core.PlaybackState.PLAYING + success = self.core.playback.seek(1000) + + self.assertFalse(success) + self.assertFalse(self.playback1.seek.called) + self.assertFalse(self.playback2.seek.called) + def test_seek_play_stay_playing(self): self.core.playback.play(self.tl_tracks[0]) self.core.playback.state = core.PlaybackState.PLAYING diff --git a/tests/mpd/test_translator.py b/tests/mpd/test_translator.py index 027ce28f..527cfef8 100644 --- a/tests/mpd/test_translator.py +++ b/tests/mpd/test_translator.py @@ -34,6 +34,8 @@ class TrackMpdFormatTest(unittest.TestCase): mtime.undo_fake() def test_track_to_mpd_format_for_empty_track(self): + # TODO: this is likely wrong, see: + # https://github.com/mopidy/mopidy/issues/923#issuecomment-79584110 result = translator.track_to_mpd_format(Track()) self.assertIn(('file', ''), result) self.assertIn(('Time', 0), result)