From e74eafb38a75b43bd1d7408339d255f4f5442fd9 Mon Sep 17 00:00:00 2001 From: Thomas Adamcik Date: Thu, 3 Dec 2015 22:27:22 +0100 Subject: [PATCH] core: Switch back to correct track if seek happens before stream changed Technically the seek still needs to be postponed for this to work right, but it's a step closer. --- mopidy/core/playback.py | 8 ++++---- tests/core/test_playback.py | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/mopidy/core/playback.py b/mopidy/core/playback.py index 45e1b4ba..96fac4d9 100644 --- a/mopidy/core/playback.py +++ b/mopidy/core/playback.py @@ -437,10 +437,10 @@ class PlaybackController(object): if self.get_state() == PlaybackState.STOPPED: self.play() - # TODO: uncomment once we have tests for this. Should fix seek after - # about to finish doing wrong track. - # if self._current_tl_track and self._pending_tl_track: - # self.play(self._current_tl_track) + # Make sure we switch back to previous track if we get a seek while we + # have a pending track. + if self._current_tl_track and self._pending_tl_track: + self._change(self._current_tl_track, self.get_state()) # We need to prefer the still playing track, but if nothing is playing # we fall back to the pending one. diff --git a/tests/core/test_playback.py b/tests/core/test_playback.py index 4ae3b4ef..6ea5313f 100644 --- a/tests/core/test_playback.py +++ b/tests/core/test_playback.py @@ -6,6 +6,8 @@ import mock import pykka +import pytest + from mopidy import backend, core from mopidy.internal import deprecation from mopidy.models import Track @@ -529,6 +531,25 @@ class EventEmissionTest(BaseTest): ], listener_mock.send.mock_calls) + @pytest.mark.xfail + def test_seek_race_condition_emits_events(self, listener_mock): + tl_tracks = self.core.tracklist.get_tl_tracks() + + self.core.playback.play(tl_tracks[0]) + self.trigger_about_to_finish(replay_until='stream_changed') + listener_mock.reset_mock() + + self.core.playback.seek(1000) + self.replay_events() + + # When we trigger seek after an about to finish the other code that + # emits track stopped/started and playback state changed events gets + # triggered as we have to switch back to the previous track. + # The correct behavior would be to only emit seeked. + self.assertListEqual( + [mock.call('seeked', time_position=1000)], + listener_mock.send.mock_calls) + def test_previous_emits_events(self, listener_mock): tl_tracks = self.core.tracklist.get_tl_tracks() @@ -632,6 +653,19 @@ class SeekTest(BaseTest): self.core.playback.seek(1000) self.assertEqual(self.core.playback.state, core.PlaybackState.PAUSED) + def test_seek_race_condition_after_about_to_finish(self): + tl_tracks = self.core.tracklist.get_tl_tracks() + + self.core.playback.play(tl_tracks[0]) + self.replay_events() + + self.trigger_about_to_finish(replay_until='stream_changed') + self.core.playback.seek(1000) + self.replay_events() + + current_tl_track = self.core.playback.get_current_tl_track() + self.assertEqual(current_tl_track, tl_tracks[0]) + class TestStream(BaseTest):