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.
This commit is contained in:
Thomas Adamcik 2015-12-03 22:27:22 +01:00
parent 593f4e295b
commit e74eafb38a
2 changed files with 38 additions and 4 deletions

View File

@ -437,10 +437,10 @@ class PlaybackController(object):
if self.get_state() == PlaybackState.STOPPED: if self.get_state() == PlaybackState.STOPPED:
self.play() self.play()
# TODO: uncomment once we have tests for this. Should fix seek after # Make sure we switch back to previous track if we get a seek while we
# about to finish doing wrong track. # have a pending track.
# if self._current_tl_track and self._pending_tl_track: if self._current_tl_track and self._pending_tl_track:
# self.play(self._current_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 need to prefer the still playing track, but if nothing is playing
# we fall back to the pending one. # we fall back to the pending one.

View File

@ -6,6 +6,8 @@ import mock
import pykka import pykka
import pytest
from mopidy import backend, core from mopidy import backend, core
from mopidy.internal import deprecation from mopidy.internal import deprecation
from mopidy.models import Track from mopidy.models import Track
@ -529,6 +531,25 @@ class EventEmissionTest(BaseTest):
], ],
listener_mock.send.mock_calls) 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): def test_previous_emits_events(self, listener_mock):
tl_tracks = self.core.tracklist.get_tl_tracks() tl_tracks = self.core.tracklist.get_tl_tracks()
@ -632,6 +653,19 @@ class SeekTest(BaseTest):
self.core.playback.seek(1000) self.core.playback.seek(1000)
self.assertEqual(self.core.playback.state, core.PlaybackState.PAUSED) 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): class TestStream(BaseTest):