core: Remove on_end_of_track from playback
This has been replaced by on_about_to_finish and on_end_of_stream. Tests have been updated to reflect these changes.
This commit is contained in:
parent
edae29d769
commit
49f16704d8
@ -73,7 +73,7 @@ class Core(
|
||||
"""Version of the Mopidy core API"""
|
||||
|
||||
def reached_end_of_stream(self):
|
||||
self.playback.on_end_of_track()
|
||||
self.playback.on_end_of_stream()
|
||||
|
||||
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
|
||||
|
||||
@ -26,7 +26,7 @@ class PlaybackController(object):
|
||||
self._mute = False
|
||||
|
||||
if self._audio:
|
||||
self._audio.set_about_to_finish_callback(self._on_about_to_finish)
|
||||
self._audio.set_about_to_finish_callback(self.on_about_to_finish)
|
||||
|
||||
def _get_backend(self, tl_track):
|
||||
if tl_track is None:
|
||||
@ -34,23 +34,6 @@ class PlaybackController(object):
|
||||
uri_scheme = urlparse.urlparse(tl_track.track.uri).scheme
|
||||
return self.backends.with_playback.get(uri_scheme, None)
|
||||
|
||||
def _on_about_to_finish(self):
|
||||
original_tl_track = self.current_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
|
||||
|
||||
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)
|
||||
|
||||
# Properties
|
||||
|
||||
def get_current_tl_track(self):
|
||||
@ -148,38 +131,24 @@ class PlaybackController(object):
|
||||
|
||||
# Methods
|
||||
|
||||
# TODO: this is not really end of track, this is on_need_next_track
|
||||
def on_end_of_track(self):
|
||||
"""
|
||||
Tell the playback controller that end of track is reached.
|
||||
|
||||
Used by event handler in :class:`mopidy.core.Core`.
|
||||
"""
|
||||
if self.state == PlaybackState.STOPPED:
|
||||
return
|
||||
def on_end_of_stream(self):
|
||||
self.state = PlaybackState.STOPPED
|
||||
# TODO: self._trigger_track_playback_ended?
|
||||
|
||||
def on_about_to_finish(self):
|
||||
original_tl_track = self.current_tl_track
|
||||
next_tl_track = self.core.tracklist.eot_track(original_tl_track)
|
||||
|
||||
backend = self._get_backend(next_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
|
||||
|
||||
if backend:
|
||||
backend.playback.prepare_change()
|
||||
backend.playback.change_track(next_tl_track.track)
|
||||
result = backend.playback.play().get()
|
||||
backend = self._get_backend(next_tl_track)
|
||||
|
||||
if result:
|
||||
self.core.tracklist.mark_playing(next_tl_track)
|
||||
self.core.history.add(next_tl_track.track)
|
||||
# TODO: replace with stream-changed
|
||||
self._trigger_track_playback_started()
|
||||
else:
|
||||
self.core.tracklist.mark_unplayable(next_tl_track)
|
||||
# TODO: can cause an endless loop for single track repeat.
|
||||
self.next()
|
||||
else:
|
||||
self.stop()
|
||||
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)
|
||||
|
||||
|
||||
@ -331,22 +331,20 @@ class CorePlaybackTest(unittest.TestCase):
|
||||
'track_playback_started', tl_track=self.tl_tracks[0]),
|
||||
])
|
||||
|
||||
# TODO Test on_end_of_track() more
|
||||
|
||||
def test_on_end_of_track_keeps_finished_track_in_tracklist(self):
|
||||
def test_on_about_to_finish_keeps_finished_track_in_tracklist(self):
|
||||
tl_track = self.tl_tracks[0]
|
||||
self.core.playback.play(tl_track)
|
||||
|
||||
self.core.playback.on_end_of_track()
|
||||
self.core.playback.on_about_to_finish()
|
||||
|
||||
self.assertIn(tl_track, self.core.tracklist.tl_tracks)
|
||||
|
||||
def test_on_end_of_track_in_consume_mode_removes_finished_track(self):
|
||||
def test_on_about_to_finish_in_consume_mode_removes_finished_track(self):
|
||||
tl_track = self.tl_tracks[0]
|
||||
self.core.playback.play(tl_track)
|
||||
self.core.tracklist.consume = True
|
||||
|
||||
self.core.playback.on_end_of_track()
|
||||
self.core.playback.on_about_to_finish()
|
||||
|
||||
self.assertNotIn(tl_track, self.core.tracklist.tl_tracks)
|
||||
|
||||
|
||||
@ -39,6 +39,13 @@ class LocalPlaybackProviderTest(unittest.TestCase):
|
||||
track = Track(uri=uri, length=4464)
|
||||
self.tracklist.add([track])
|
||||
|
||||
def trigger_about_to_finish(self):
|
||||
self.audio.prepare_change().get()
|
||||
self.playback.on_about_to_finish()
|
||||
|
||||
def trigger_end_of_stream(self):
|
||||
self.playback.on_end_of_stream()
|
||||
|
||||
def setUp(self): # noqa: N802
|
||||
self.audio = audio.DummyAudio.start().proxy()
|
||||
self.backend = actor.LocalBackend.start(
|
||||
@ -163,7 +170,8 @@ class LocalPlaybackProviderTest(unittest.TestCase):
|
||||
@populate_tracklist
|
||||
def test_current_track_after_completed_playlist(self):
|
||||
self.playback.play(self.tracklist.tl_tracks[-1])
|
||||
self.playback.on_end_of_track()
|
||||
self.trigger_about_to_finish()
|
||||
self.trigger_end_of_stream()
|
||||
self.assertEqual(self.playback.state, PlaybackState.STOPPED)
|
||||
self.assertEqual(self.playback.current_track, None)
|
||||
|
||||
@ -322,6 +330,7 @@ class LocalPlaybackProviderTest(unittest.TestCase):
|
||||
self.playback.play()
|
||||
for _ in self.tracklist.tl_tracks[1:]:
|
||||
self.playback.next()
|
||||
|
||||
tl_track = self.playback.current_tl_track
|
||||
self.assertEqual(self.tracklist.next_track(tl_track), None)
|
||||
|
||||
@ -331,6 +340,7 @@ class LocalPlaybackProviderTest(unittest.TestCase):
|
||||
self.playback.play()
|
||||
for _ in self.tracks[1:]:
|
||||
self.playback.next()
|
||||
|
||||
tl_track = self.playback.current_tl_track
|
||||
self.assertEqual(
|
||||
self.tracklist.next_track(tl_track), self.tl_tracks[0])
|
||||
@ -399,14 +409,14 @@ class LocalPlaybackProviderTest(unittest.TestCase):
|
||||
self.assertNotEqual(next_tl_track, old_next_tl_track)
|
||||
|
||||
@populate_tracklist
|
||||
def test_end_of_track(self):
|
||||
def test_about_to_finish(self):
|
||||
self.playback.play()
|
||||
|
||||
tl_track = self.playback.current_tl_track
|
||||
old_position = self.tracklist.index(tl_track)
|
||||
old_uri = tl_track.track.uri
|
||||
|
||||
self.playback.on_end_of_track()
|
||||
self.trigger_about_to_finish()
|
||||
|
||||
tl_track = self.playback.current_tl_track
|
||||
self.assertEqual(
|
||||
@ -414,17 +424,7 @@ class LocalPlaybackProviderTest(unittest.TestCase):
|
||||
self.assertNotEqual(self.playback.current_track.uri, old_uri)
|
||||
|
||||
@populate_tracklist
|
||||
def test_end_of_track_return_value(self):
|
||||
self.playback.play()
|
||||
self.assertEqual(self.playback.on_end_of_track(), None)
|
||||
|
||||
@populate_tracklist
|
||||
def test_end_of_track_does_not_trigger_playback(self):
|
||||
self.playback.on_end_of_track()
|
||||
self.assertEqual(self.playback.state, PlaybackState.STOPPED)
|
||||
|
||||
@populate_tracklist
|
||||
def test_end_of_track_at_end_of_playlist(self):
|
||||
def test_about_to_finish_at_end_of_playlist(self):
|
||||
self.playback.play()
|
||||
|
||||
for i, track in enumerate(self.tracks):
|
||||
@ -433,16 +433,17 @@ class LocalPlaybackProviderTest(unittest.TestCase):
|
||||
tl_track = self.playback.current_tl_track
|
||||
self.assertEqual(self.tracklist.index(tl_track), i)
|
||||
|
||||
self.playback.on_end_of_track()
|
||||
self.trigger_about_to_finish()
|
||||
self.trigger_end_of_stream()
|
||||
|
||||
self.assertEqual(self.playback.state, PlaybackState.STOPPED)
|
||||
|
||||
@populate_tracklist
|
||||
def test_end_of_track_until_end_of_playlist_and_play_from_start(self):
|
||||
self.playback.play()
|
||||
|
||||
for _ in self.tracks:
|
||||
self.playback.on_end_of_track()
|
||||
self.trigger_about_to_finish()
|
||||
self.trigger_end_of_stream()
|
||||
|
||||
self.assertEqual(self.playback.current_track, None)
|
||||
self.assertEqual(self.playback.state, PlaybackState.STOPPED)
|
||||
@ -451,18 +452,20 @@ class LocalPlaybackProviderTest(unittest.TestCase):
|
||||
self.assertEqual(self.playback.state, PlaybackState.PLAYING)
|
||||
self.assertEqual(self.playback.current_track, self.tracks[0])
|
||||
|
||||
def test_end_of_track_for_empty_playlist(self):
|
||||
self.playback.on_end_of_track()
|
||||
self.assertEqual(self.playback.state, PlaybackState.STOPPED)
|
||||
|
||||
@unittest.skip('This is broken with gapless support')
|
||||
@populate_tracklist
|
||||
def test_end_of_track_skips_to_next_track_on_failure(self):
|
||||
# TODO: it is not obvious how to handle this now that we can only set
|
||||
# an uri and wait for a possible error some time later. Likely we need
|
||||
# to replace this with better error handling that ideally doesn't stop
|
||||
# the pipeline.
|
||||
|
||||
# If backend's play() returns False, it is a failure.
|
||||
return_values = [True, False, True]
|
||||
self.backend.playback.play = lambda: return_values.pop()
|
||||
self.playback.play()
|
||||
self.assertEqual(self.playback.current_track, self.tracks[0])
|
||||
self.playback.on_end_of_track()
|
||||
self.trigger_about_to_finish()
|
||||
self.assertNotEqual(self.playback.current_track, self.tracks[1])
|
||||
self.assertEqual(self.playback.current_track, self.tracks[2])
|
||||
|
||||
@ -480,9 +483,9 @@ class LocalPlaybackProviderTest(unittest.TestCase):
|
||||
self.tracklist.next_track(tl_track), self.tl_tracks[1])
|
||||
|
||||
@populate_tracklist
|
||||
def test_end_of_track_track_after_previous(self):
|
||||
def test_about_to_finish_after_previous(self):
|
||||
self.playback.play()
|
||||
self.playback.on_end_of_track()
|
||||
self.trigger_about_to_finish()
|
||||
self.playback.previous()
|
||||
tl_track = self.playback.current_tl_track
|
||||
self.assertEqual(
|
||||
@ -495,8 +498,9 @@ class LocalPlaybackProviderTest(unittest.TestCase):
|
||||
@populate_tracklist
|
||||
def test_end_of_track_track_at_end_of_playlist(self):
|
||||
self.playback.play()
|
||||
for _ in self.tracklist.tl_tracks[1:]:
|
||||
self.playback.on_end_of_track()
|
||||
for _ in self.tracks[1:]:
|
||||
self.trigger_about_to_finish()
|
||||
|
||||
tl_track = self.playback.current_tl_track
|
||||
self.assertEqual(self.tracklist.next_track(tl_track), None)
|
||||
|
||||
@ -505,37 +509,28 @@ class LocalPlaybackProviderTest(unittest.TestCase):
|
||||
self.tracklist.repeat = True
|
||||
self.playback.play()
|
||||
for _ in self.tracks[1:]:
|
||||
self.playback.on_end_of_track()
|
||||
self.trigger_about_to_finish()
|
||||
|
||||
tl_track = self.playback.current_tl_track
|
||||
self.assertEqual(
|
||||
self.tracklist.next_track(tl_track), self.tl_tracks[0])
|
||||
|
||||
@populate_tracklist
|
||||
@mock.patch('random.shuffle')
|
||||
def test_end_of_track_track_with_random(self, shuffle_mock):
|
||||
shuffle_mock.side_effect = lambda tracks: tracks.reverse()
|
||||
|
||||
self.tracklist.random = True
|
||||
tl_track = self.playback.current_tl_track
|
||||
self.assertEqual(
|
||||
self.tracklist.next_track(tl_track), self.tl_tracks[-1])
|
||||
|
||||
@populate_tracklist
|
||||
def test_end_of_track_with_consume(self):
|
||||
def test_on_about_to_finis_with_consume(self):
|
||||
self.tracklist.consume = True
|
||||
self.playback.play()
|
||||
self.playback.on_end_of_track()
|
||||
self.trigger_about_to_finish()
|
||||
self.assertNotIn(self.tracks[0], self.tracklist.tracks)
|
||||
|
||||
@populate_tracklist
|
||||
@mock.patch('random.shuffle')
|
||||
def test_end_of_track_with_random(self, shuffle_mock):
|
||||
def test_about_to_finish_with_random(self, shuffle_mock):
|
||||
shuffle_mock.side_effect = lambda tracks: tracks.reverse()
|
||||
|
||||
self.tracklist.random = True
|
||||
self.playback.play()
|
||||
self.assertEqual(self.playback.current_track, self.tracks[-1])
|
||||
self.playback.on_end_of_track()
|
||||
self.trigger_about_to_finish()
|
||||
self.assertEqual(self.playback.current_track, self.tracks[-2])
|
||||
|
||||
@populate_tracklist
|
||||
@ -654,7 +649,8 @@ class LocalPlaybackProviderTest(unittest.TestCase):
|
||||
@populate_tracklist
|
||||
def test_tracklist_position_at_end_of_playlist(self):
|
||||
self.playback.play(self.tracklist.tl_tracks[-1])
|
||||
self.playback.on_end_of_track()
|
||||
self.trigger_about_to_finish()
|
||||
self.trigger_end_of_stream()
|
||||
tl_track = self.playback.current_tl_track
|
||||
self.assertEqual(self.tracklist.index(tl_track), None)
|
||||
|
||||
@ -922,8 +918,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 range(len(self.tracklist.tracks)):
|
||||
self.playback.on_end_of_track()
|
||||
for _ in self.tracks:
|
||||
self.trigger_about_to_finish()
|
||||
self.trigger_end_of_stream()
|
||||
|
||||
self.assertEqual(len(self.tracklist.tracks), 0)
|
||||
|
||||
@populate_tracklist
|
||||
@ -950,7 +948,7 @@ class LocalPlaybackProviderTest(unittest.TestCase):
|
||||
@populate_tracklist
|
||||
def test_end_of_song_starts_next_track(self):
|
||||
self.playback.play()
|
||||
self.playback.on_end_of_track()
|
||||
self.trigger_about_to_finish()
|
||||
self.assertEqual(self.playback.current_track, self.tracks[1])
|
||||
|
||||
@populate_tracklist
|
||||
@ -959,7 +957,7 @@ class LocalPlaybackProviderTest(unittest.TestCase):
|
||||
self.tracklist.repeat = True
|
||||
self.playback.play()
|
||||
self.assertEqual(self.playback.current_track, self.tracks[0])
|
||||
self.playback.on_end_of_track()
|
||||
self.trigger_about_to_finish()
|
||||
self.assertEqual(self.playback.current_track, self.tracks[0])
|
||||
|
||||
@populate_tracklist
|
||||
@ -969,7 +967,7 @@ class LocalPlaybackProviderTest(unittest.TestCase):
|
||||
self.tracklist.random = True
|
||||
self.playback.play()
|
||||
current_track = self.playback.current_track
|
||||
self.playback.on_end_of_track()
|
||||
self.trigger_about_to_finish()
|
||||
self.assertEqual(self.playback.current_track, current_track)
|
||||
|
||||
@populate_tracklist
|
||||
@ -977,8 +975,9 @@ class LocalPlaybackProviderTest(unittest.TestCase):
|
||||
self.tracklist.single = True
|
||||
self.playback.play()
|
||||
self.assertEqual(self.playback.current_track, self.tracks[0])
|
||||
self.playback.on_end_of_track()
|
||||
self.trigger_about_to_finish()
|
||||
self.assertEqual(self.playback.current_track, None)
|
||||
self.trigger_end_of_stream()
|
||||
self.assertEqual(self.playback.state, PlaybackState.STOPPED)
|
||||
|
||||
@populate_tracklist
|
||||
@ -986,14 +985,16 @@ class LocalPlaybackProviderTest(unittest.TestCase):
|
||||
self.tracklist.single = True
|
||||
self.tracklist.random = True
|
||||
self.playback.play()
|
||||
self.playback.on_end_of_track()
|
||||
self.trigger_about_to_finish()
|
||||
self.assertEqual(self.playback.current_track, None)
|
||||
self.trigger_end_of_stream()
|
||||
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.playback.on_end_of_track()
|
||||
self.trigger_about_to_finish()
|
||||
self.trigger_end_of_stream()
|
||||
self.assertEqual(self.playback.state, PlaybackState.STOPPED)
|
||||
|
||||
def test_repeat_off_by_default(self):
|
||||
@ -1011,6 +1012,7 @@ class LocalPlaybackProviderTest(unittest.TestCase):
|
||||
self.playback.play()
|
||||
for _ in self.tracks[1:]:
|
||||
self.playback.next()
|
||||
|
||||
tl_track = self.playback.current_tl_track
|
||||
self.assertEqual(self.tracklist.next_track(tl_track), None)
|
||||
|
||||
@ -1019,7 +1021,8 @@ class LocalPlaybackProviderTest(unittest.TestCase):
|
||||
self.tracklist.random = True
|
||||
self.playback.play()
|
||||
for _ in self.tracks[1:]:
|
||||
self.playback.on_end_of_track()
|
||||
self.trigger_about_to_finish()
|
||||
|
||||
tl_track = self.playback.current_tl_track
|
||||
self.assertEqual(self.tracklist.eot_track(tl_track), None)
|
||||
|
||||
@ -1040,7 +1043,9 @@ class LocalPlaybackProviderTest(unittest.TestCase):
|
||||
self.tracklist.random = True
|
||||
self.playback.play()
|
||||
for _ in self.tracks:
|
||||
self.playback.on_end_of_track()
|
||||
self.trigger_about_to_finish()
|
||||
self.trigger_end_of_stream()
|
||||
|
||||
tl_track = self.playback.current_tl_track
|
||||
self.assertNotEqual(self.tracklist.eot_track(tl_track), None)
|
||||
self.assertEqual(self.playback.state, PlaybackState.STOPPED)
|
||||
@ -1054,6 +1059,7 @@ class LocalPlaybackProviderTest(unittest.TestCase):
|
||||
self.playback.play()
|
||||
for _ in self.tracks[1:]:
|
||||
self.playback.next()
|
||||
|
||||
tl_track = self.playback.current_tl_track
|
||||
self.assertNotEqual(self.tracklist.next_track(tl_track), None)
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user