core: Refactor previous() to use pending_track for state changes

This commit is contained in:
Thomas Adamcik 2015-09-04 17:16:39 +02:00
parent 2cd9903a54
commit 592b728e32
3 changed files with 90 additions and 85 deletions

View File

@ -395,28 +395,19 @@ class PlaybackController(object):
The current playback state will be kept. If it was playing, playing
will continue. If it was paused, it will still be paused, etc.
"""
original_tl_track = self.get_current_tl_track()
prev_tl_track = self.core.tracklist.previous_track(original_tl_track)
state = self.get_state()
current = self._pending_tl_track or self._current_tl_track
backend = self._get_backend(prev_tl_track)
self._set_current_tl_track(prev_tl_track)
if backend:
backend.playback.prepare_change()
# TODO: check return values of change track
backend.playback.change_track(prev_tl_track.track)
if self.get_state() == PlaybackState.PLAYING:
result = backend.playback.play().get()
elif self.get_state() == PlaybackState.PAUSED:
result = backend.playback.pause().get()
while current:
pending = self.core.tracklist.previous_track(current)
if self._change(pending, state):
break
else:
result = True
if result and self.get_state() != PlaybackState.PAUSED:
self._trigger_track_playback_started()
elif not result:
self.core.tracklist._mark_unplayable(prev_tl_track)
self.previous()
self.core.tracklist._mark_unplayable(pending)
# TODO: this could be needed to prevent a loop in rare cases
# if current == pending:
# break
current = pending
# TODO: no return value?

View File

@ -13,6 +13,7 @@ from mopidy.models import Track
from tests import dummy_audio
# TODO: Replace this with dummy_backend no that it uses a real playbackprovider
# Since we rely on our DummyAudio to actually emit events we need a "real"
# backend and not a mock so the right calls make it through to audio.
class TestBackend(pykka.ThreadingActor, backend.Backend):
@ -99,6 +100,76 @@ class TestNextHandling(PlaybackBaseTest):
self.assertEqual(current_track, self.tracks[1])
class TestPreviousHandling(PlaybackBaseTest):
# TODO Test previous() more
def test_get_current_tl_track_prev(self):
tl_tracks = self.core.tracklist.get_tl_tracks()
self.core.playback.play(tl_tracks[1])
self.core.playback.previous()
self.replay_events()
self.assertEqual(
self.core.playback.get_current_tl_track(), tl_tracks[0])
def test_get_current_track_prev(self):
tl_tracks = self.core.tracklist.get_tl_tracks()
self.core.playback.play(tl_tracks[1])
self.core.playback.previous()
self.replay_events()
self.assertEqual(
self.core.playback.get_current_track(), self.tracks[0])
def test_previous_keeps_finished_track_in_tracklist(self):
tl_tracks = self.core.tracklist.get_tl_tracks()
self.core.playback.play(tl_tracks[1])
self.core.playback.previous()
self.replay_events()
self.assertIn(tl_tracks[1], self.core.tracklist.tl_tracks)
def test_previous_keeps_finished_track_even_in_consume_mode(self):
tl_tracks = self.core.tracklist.get_tl_tracks()
self.core.playback.play(tl_tracks[1])
self.core.tracklist.consume = True
self.core.playback.previous()
self.replay_events()
self.assertIn(tl_tracks[1], self.core.tracklist.tl_tracks)
@unittest.skip('Currently tests wrong events, and nothing generates them.')
@mock.patch(
'mopidy.core.playback.listener.CoreListener', spec=core.CoreListener)
def test_previous_emits_events(self, listener_mock):
self.core.playback.play(self.tl_tracks[1])
listener_mock.reset_mock()
self.core.playback.previous()
self.assertListEqual(
listener_mock.send.mock_calls,
[
mock.call(
'playback_state_changed',
old_state='playing', new_state='stopped'),
mock.call(
'track_playback_ended',
tl_track=self.tl_tracks[1], time_position=mock.ANY),
mock.call(
'playback_state_changed',
old_state='stopped', new_state='playing'),
mock.call(
'track_playback_started', tl_track=self.tl_tracks[0]),
])
class TestPlayUnknownHanlding(PlaybackBaseTest):
tracks = [Track(uri='unknown:a', length=1234),
@ -286,26 +357,12 @@ class CorePlaybackTest(unittest.TestCase):
self.assertEqual(
self.core.playback.get_current_tl_track(), self.tl_tracks[0])
def test_get_current_tl_track_prev(self):
self.core.playback.play(self.tl_tracks[1])
self.core.playback.previous()
self.assertEqual(
self.core.playback.get_current_tl_track(), self.tl_tracks[0])
def test_get_current_track_play(self):
self.core.playback.play(self.tl_tracks[0])
self.assertEqual(
self.core.playback.get_current_track(), self.tracks[0])
def test_get_current_track_prev(self):
self.core.playback.play(self.tl_tracks[1])
self.core.playback.previous()
self.assertEqual(
self.core.playback.get_current_track(), self.tracks[0])
def test_get_current_tlid_none(self):
self.set_current_tl_track(None)
@ -572,50 +629,6 @@ class CorePlaybackTest(unittest.TestCase):
'track_playback_started', tl_track=self.tl_tracks[1]),
])
# TODO Test previous() more
def test_previous_keeps_finished_track_in_tracklist(self):
tl_track = self.tl_tracks[1]
self.core.playback.play(tl_track)
self.core.playback.previous()
self.assertIn(tl_track, self.core.tracklist.tl_tracks)
def test_previous_keeps_finished_track_even_in_consume_mode(self):
tl_track = self.tl_tracks[1]
self.core.playback.play(tl_track)
self.core.tracklist.consume = True
self.core.playback.previous()
self.assertIn(tl_track, self.core.tracklist.tl_tracks)
@unittest.skip('Currently tests wrong events, and nothing generates them.')
@mock.patch(
'mopidy.core.playback.listener.CoreListener', spec=core.CoreListener)
def test_previous_emits_events(self, listener_mock):
self.core.playback.play(self.tl_tracks[1])
listener_mock.reset_mock()
self.core.playback.previous()
self.assertListEqual(
listener_mock.send.mock_calls,
[
mock.call(
'playback_state_changed',
old_state='playing', new_state='stopped'),
mock.call(
'track_playback_ended',
tl_track=self.tl_tracks[1], time_position=mock.ANY),
mock.call(
'playback_state_changed',
old_state='stopped', new_state='playing'),
mock.call(
'track_playback_started', tl_track=self.tl_tracks[0]),
])
def test_on_about_to_finish_keeps_finished_track_in_tracklist(self):
tl_track = self.tl_tracks[0]
self.core.playback.play(tl_track)

View File

@ -227,7 +227,7 @@ class LocalPlaybackProviderTest(unittest.TestCase):
def test_previous(self):
self.playback.play()
self.playback.next().get()
self.playback.previous()
self.playback.previous().get()
self.assert_current_track_is(self.tracks[0])
@populate_tracklist
@ -235,7 +235,7 @@ class LocalPlaybackProviderTest(unittest.TestCase):
self.playback.play() # At track 0
self.playback.next().get() # At track 1
self.playback.next().get() # At track 2
self.playback.previous() # At track 1
self.playback.previous().get() # At track 1
self.assert_current_track_is(self.tracks[1])
@populate_tracklist
@ -266,11 +266,12 @@ class LocalPlaybackProviderTest(unittest.TestCase):
@populate_tracklist
def test_previous_skips_to_previous_track_on_failure(self):
# If backend's play() returns False, it is a failure.
return_values = [True, False, True]
self.backend.playback.play = lambda: return_values.pop()
uri = self.backend.playback.translate_uri(self.tracks[1].uri).get()
self.audio.trigger_fake_playback_failure(uri)
self.playback.play(self.tl_tracks.get()[2])
self.assert_current_track_is(self.tracks[2])
self.playback.previous()
self.playback.previous().get()
self.assert_current_track_is_not(self.tracks[1])
self.assert_current_track_is(self.tracks[0])
@ -352,7 +353,7 @@ class LocalPlaybackProviderTest(unittest.TestCase):
def test_next_track_after_previous(self):
self.playback.play()
self.playback.next().get()
self.playback.previous()
self.playback.previous().get()
self.assert_next_tl_track_is(self.tl_tracks.get()[1])
def test_next_track_empty_playlist(self):
@ -610,7 +611,7 @@ class LocalPlaybackProviderTest(unittest.TestCase):
self.playback.play() # At track 0
self.playback.next().get() # At track 1
self.playback.next().get() # At track 2
self.playback.previous() # At track 1
self.playback.previous().get() # At track 1
self.assert_previous_tl_track_is(self.tl_tracks.get()[0])
def test_previous_track_empty_playlist(self):