diff --git a/mopidy/core/playback.py b/mopidy/core/playback.py index 52278fbc..b33e098f 100644 --- a/mopidy/core/playback.py +++ b/mopidy/core/playback.py @@ -138,10 +138,10 @@ class PlaybackController(object): # 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? + if self._pending_tl_track: + self.current_tl_track = self._pending_tl_track + self._pending_tl_track = None + self._trigger_track_playback_started() def on_about_to_finish(self): # TODO: check that we always have a current track @@ -163,9 +163,12 @@ class PlaybackController(object): Used by :class:`mopidy.core.TracklistController`. """ - if self.current_tl_track not in self.core.tracklist.tl_tracks: + + if not self.core.tracklist.tl_tracks: self.stop() self.current_tl_track = None + elif self.current_tl_track not in self.core.tracklist.tl_tracks: + self.current_tl_track = None def next(self): """ diff --git a/tests/core/test_playback.py b/tests/core/test_playback.py index 443ace35..ae64eaef 100644 --- a/tests/core/test_playback.py +++ b/tests/core/test_playback.py @@ -30,21 +30,28 @@ class TestCurrentAndPendingTlTrack(unittest.TestCase): self.core.tracklist.add(self.tracks) + self.events = [] + self.patcher = mock.patch('mopidy.audio.listener.AudioListener.send') + self.send_mock = self.patcher.start() + + def send(event, **kwargs): + self.events.append((event, kwargs)) + + self.send_mock.side_effect = send + def tearDown(self): # noqa: N802 pykka.ActorRegistry.stop_all() + self.patcher.stop() - def trigger_about_to_finish(self): - self.audio.prepare_change() - # TODO: trigger via dummy audio? - self.playback.on_about_to_finish() + def trigger_about_to_finish(self, block_stream_changed=False): + callback = self.audio.get_about_to_finish_callback().get() + callback() - 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() + while self.events: + event, kwargs = self.events.pop(0) + if event == 'stream_changed' and block_stream_changed: + continue + self.core.on_event(event, **kwargs) def test_pending_tl_track_is_none(self): self.core.playback.play() @@ -52,31 +59,28 @@ class TestCurrentAndPendingTlTrack(unittest.TestCase): def test_pending_tl_track_after_about_to_finish(self): self.core.playback.play() - self.trigger_about_to_finish() + self.trigger_about_to_finish(block_stream_changed=True) + 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.trigger_about_to_finish(block_stream_changed=True) 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.trigger_about_to_finish() # EOS self.assertEqual(self.playback.current_tl_track, None) diff --git a/tests/local/test_playback.py b/tests/local/test_playback.py index ee002c1f..8fedb6a2 100644 --- a/tests/local/test_playback.py +++ b/tests/local/test_playback.py @@ -1,5 +1,6 @@ from __future__ import absolute_import, unicode_literals +import logging import time import unittest @@ -15,6 +16,7 @@ from mopidy.models import Track from tests import path_to_data_dir from tests.local import generate_song, populate_tracklist +logger = logging.getLogger(__name__) # TODO Test 'playlist repeat', e.g. repeat=1,single=0 @@ -40,18 +42,19 @@ class LocalPlaybackProviderTest(unittest.TestCase): self.tracklist.add([track]) def trigger_about_to_finish(self): - self.audio.prepare_change().get() - self.playback.on_about_to_finish() - self.playback.on_stream_changed(None) + callback = self.audio.get_about_to_finish_callback().get() + callback() - def trigger_end_of_stream(self): - self.playback.on_end_of_stream() + while self.events: + event, kwargs = self.events.pop(0) + logger.debug('Replaying: %s %s', event, kwargs) + self.core.on_event(event, **kwargs) def setUp(self): # noqa: N802 self.audio = audio.DummyAudio.start().proxy() self.backend = actor.LocalBackend.start( config=self.config, audio=self.audio).proxy() - self.core = core.Core(backends=[self.backend]) + self.core = core.Core(backends=[self.backend], audio=self.audio) self.playback = self.core.playback self.tracklist = self.core.tracklist @@ -60,8 +63,18 @@ class LocalPlaybackProviderTest(unittest.TestCase): assert self.tracks[0].length >= 2000, \ 'First song needs to be at least 2000 miliseconds' + self.events = [] + self.patcher = mock.patch('mopidy.audio.listener.AudioListener.send') + self.send_mock = self.patcher.start() + + def send(event, **kwargs): + self.events.append((event, kwargs)) + + self.send_mock.side_effect = send + def tearDown(self): # noqa: N802 pykka.ActorRegistry.stop_all() + self.patcher.stop() def test_uri_scheme(self): self.assertNotIn('file', self.core.uri_schemes) @@ -172,7 +185,7 @@ class LocalPlaybackProviderTest(unittest.TestCase): def test_current_track_after_completed_playlist(self): self.playback.play(self.tracklist.tl_tracks[-1]) self.trigger_about_to_finish() - self.trigger_end_of_stream() + # EOS should have triggered self.assertEqual(self.playback.state, PlaybackState.STOPPED) self.assertEqual(self.playback.current_track, None) @@ -435,7 +448,7 @@ class LocalPlaybackProviderTest(unittest.TestCase): self.assertEqual(self.tracklist.index(tl_track), i) self.trigger_about_to_finish() - self.trigger_end_of_stream() + # EOS should have triggered self.assertEqual(self.playback.state, PlaybackState.STOPPED) @@ -444,7 +457,7 @@ class LocalPlaybackProviderTest(unittest.TestCase): self.playback.play() for _ in self.tracks: self.trigger_about_to_finish() - self.trigger_end_of_stream() + # EOS should have triggered self.assertEqual(self.playback.current_track, None) self.assertEqual(self.playback.state, PlaybackState.STOPPED) @@ -517,7 +530,7 @@ class LocalPlaybackProviderTest(unittest.TestCase): self.tracklist.next_track(tl_track), self.tl_tracks[0]) @populate_tracklist - def test_on_about_to_finis_with_consume(self): + def test_on_about_to_finish_with_consume(self): self.tracklist.consume = True self.playback.play() self.trigger_about_to_finish() @@ -651,7 +664,7 @@ class LocalPlaybackProviderTest(unittest.TestCase): def test_tracklist_position_at_end_of_playlist(self): self.playback.play(self.tracklist.tl_tracks[-1]) self.trigger_about_to_finish() - self.trigger_end_of_stream() + # EOS should have triggered tl_track = self.playback.current_tl_track self.assertEqual(self.tracklist.index(tl_track), None) @@ -919,9 +932,10 @@ class LocalPlaybackProviderTest(unittest.TestCase): def test_playlist_is_empty_after_all_tracks_are_played_with_consume(self): self.tracklist.consume = True self.playback.play() - for _ in self.tracks: + + for t in self.tracks: self.trigger_about_to_finish() - self.trigger_end_of_stream() + # EOS should have trigger self.assertEqual(len(self.tracklist.tracks), 0) @@ -978,7 +992,7 @@ class LocalPlaybackProviderTest(unittest.TestCase): self.assertEqual(self.playback.current_track, self.tracks[0]) self.trigger_about_to_finish() self.assertEqual(self.playback.current_track, None) - self.trigger_end_of_stream() + # EOS should have triggered self.assertEqual(self.playback.state, PlaybackState.STOPPED) @populate_tracklist @@ -988,14 +1002,14 @@ class LocalPlaybackProviderTest(unittest.TestCase): self.playback.play() self.trigger_about_to_finish() self.assertEqual(self.playback.current_track, None) - self.trigger_end_of_stream() + # EOS should have triggered self.assertEqual(self.playback.state, PlaybackState.STOPPED) @populate_tracklist def test_end_of_playlist_stops(self): self.playback.play(self.tracklist.tl_tracks[-1]) self.trigger_about_to_finish() - self.trigger_end_of_stream() + # EOS should have triggered self.assertEqual(self.playback.state, PlaybackState.STOPPED) def test_repeat_off_by_default(self): @@ -1043,9 +1057,10 @@ class LocalPlaybackProviderTest(unittest.TestCase): def test_random_with_eot_until_end_of_playlist_and_play_from_start(self): self.tracklist.random = True self.playback.play() + for _ in self.tracks: self.trigger_about_to_finish() - self.trigger_end_of_stream() + # EOS should have triggered tl_track = self.playback.current_tl_track self.assertNotEqual(self.tracklist.eot_track(tl_track), None)