From b0aebaf99393bae51ee2a9effe33873002b72a66 Mon Sep 17 00:00:00 2001 From: Thomas Adamcik Date: Fri, 23 Jan 2015 00:14:30 +0100 Subject: [PATCH] core: Make sure current_tl_track changes on stream change - Adds stream changed handler to core - Moves playback started trigger to stream changed - Made about to finish store next track in _pending_tl_track - Set the pending track as current in stream changed - Adds tests for all of this and fixes existing tests --- mopidy/core/actor.py | 3 ++ mopidy/core/playback.py | 19 +++++---- tests/core/test_playback.py | 74 +++++++++++++++++++++++++++++++++++- tests/local/test_playback.py | 1 + 4 files changed, 89 insertions(+), 8 deletions(-) diff --git a/mopidy/core/actor.py b/mopidy/core/actor.py index da2daef2..0058d9b9 100644 --- a/mopidy/core/actor.py +++ b/mopidy/core/actor.py @@ -75,6 +75,9 @@ class Core( def reached_end_of_stream(self): self.playback.on_end_of_stream() + def stream_changed(self, uri): + self.playback.on_stream_changed(uri) + def state_changed(self, old_state, new_state, target_state): # XXX: This is a temporary fix for issue #232 while we wait for a more # permanent solution with the implementation of issue #234. When the diff --git a/mopidy/core/playback.py b/mopidy/core/playback.py index dbb841af..52278fbc 100644 --- a/mopidy/core/playback.py +++ b/mopidy/core/playback.py @@ -24,6 +24,7 @@ class PlaybackController(object): self._state = PlaybackState.STOPPED self._volume = None self._mute = False + self._pending_tl_track = None if self._audio: self._audio.set_about_to_finish_callback(self.on_about_to_finish) @@ -133,22 +134,26 @@ class PlaybackController(object): def on_end_of_stream(self): self.state = PlaybackState.STOPPED + self.current_tl_track = None + # TODO: self._trigger_track_playback_ended? + + def on_stream_changed(self, uri): + self.current_tl_track = self._pending_tl_track + self._pending_tl_track = None + self._trigger_track_playback_started() # TODO: self._trigger_track_playback_ended? def on_about_to_finish(self): + # TODO: check that we always have a current track + original_tl_track = self.current_tl_track + next_tl_track = self.core.tracklist.eot_track(original_tl_track) - next_tl_track = self.core.tracklist.eot_track(self.current_tl_track) - # TODO: this should be self.pending_tl_track and stream changed should - # make it current. - self.current_tl_track = next_tl_track - + self._pending_tl_track = next_tl_track backend = self._get_backend(next_tl_track) if backend: backend.playback.change_track(next_tl_track.track).get() - # TODO: this _really_ needs to be stream changed... - self._trigger_track_playback_started() self.core.tracklist.mark_played(original_tl_track) diff --git a/tests/core/test_playback.py b/tests/core/test_playback.py index c60e3d0c..443ace35 100644 --- a/tests/core/test_playback.py +++ b/tests/core/test_playback.py @@ -4,10 +4,82 @@ import unittest import mock -from mopidy import backend, core +import pykka + +from mopidy import audio, backend, core from mopidy.models import Track +class TestBackend(pykka.ThreadingActor, backend.Backend): + uri_schemes = ['dummy'] + + def __init__(self, config, audio): + super(TestBackend, self).__init__() + self.playback = backend.PlaybackProvider(audio=audio, backend=self) + + +class TestCurrentAndPendingTlTrack(unittest.TestCase): + def setUp(self): # noqa: N802 + self.audio = audio.DummyAudio.start().proxy() + self.backend = TestBackend.start(config={}, audio=self.audio).proxy() + self.core = core.Core(audio=self.audio, backends=[self.backend]) + self.playback = self.core.playback + + self.tracks = [Track(uri='dummy:a', length=1234), + Track(uri='dummy:b', length=1234)] + + self.core.tracklist.add(self.tracks) + + def tearDown(self): # noqa: N802 + pykka.ActorRegistry.stop_all() + + def trigger_about_to_finish(self): + self.audio.prepare_change() + # TODO: trigger via dummy audio? + self.playback.on_about_to_finish() + + def trigger_stream_changed(self): + # TODO: trigger via dummy audio? + self.playback.on_stream_changed(None) + + def trigger_end_of_stream(self): + # TODO: trigger via dummy audio? + self.playback.on_end_of_stream() + + def test_pending_tl_track_is_none(self): + self.core.playback.play() + self.assertEqual(self.playback._pending_tl_track, None) + + def test_pending_tl_track_after_about_to_finish(self): + self.core.playback.play() + self.trigger_about_to_finish() + self.assertEqual(self.playback._pending_tl_track.track.uri, 'dummy:b') + + def test_pending_tl_track_after_stream_changed(self): + self.trigger_about_to_finish() + self.trigger_stream_changed() + self.assertEqual(self.playback._pending_tl_track, None) + + def test_current_tl_track_after_about_to_finish(self): + self.core.playback.play() + self.trigger_about_to_finish() + self.assertEqual(self.playback.current_tl_track.track.uri, 'dummy:a') + + def test_current_tl_track_after_stream_changed(self): + self.core.playback.play() + self.trigger_about_to_finish() + self.trigger_stream_changed() + self.assertEqual(self.playback.current_tl_track.track.uri, 'dummy:b') + + def test_current_tl_track_after_end_of_stream(self): + self.core.playback.play() + self.trigger_about_to_finish() + self.trigger_stream_changed() + self.trigger_about_to_finish() + self.trigger_end_of_stream() + self.assertEqual(self.playback.current_tl_track, None) + + class CorePlaybackTest(unittest.TestCase): def setUp(self): # noqa: N802 self.backend1 = mock.Mock() diff --git a/tests/local/test_playback.py b/tests/local/test_playback.py index 98008590..ee002c1f 100644 --- a/tests/local/test_playback.py +++ b/tests/local/test_playback.py @@ -42,6 +42,7 @@ class LocalPlaybackProviderTest(unittest.TestCase): def trigger_about_to_finish(self): self.audio.prepare_change().get() self.playback.on_about_to_finish() + self.playback.on_stream_changed(None) def trigger_end_of_stream(self): self.playback.on_end_of_stream()