diff --git a/mopidy/core/playback.py b/mopidy/core/playback.py index 3597f920..d6c470f2 100644 --- a/mopidy/core/playback.py +++ b/mopidy/core/playback.py @@ -254,13 +254,19 @@ class PlaybackController(object): pending = self.core.tracklist.eot_track(self._current_tl_track) while pending: # TODO: Avoid infinite loops if all tracks are unplayable. - # TODO: Wrap backend call in error handling. backend = self._get_backend(pending) - if backend and backend.playback.change_track(pending.track).get(): - self._pending_tl_track = pending - break - else: - self.core.tracklist._mark_unplayable(pending) + if not backend: + continue + + try: + if backend.playback.change_track(pending.track).get(): + self._pending_tl_track = pending + break + except Exception: + logger.exception('%s backend caused an exception.', + backend.actor_ref.actor_class.__name__) + + self.core.tracklist._mark_unplayable(pending) pending = self.core.tracklist.eot_track(pending) def _on_tracklist_change(self): diff --git a/tests/core/test_playback.py b/tests/core/test_playback.py index 860ce556..cfd58793 100644 --- a/tests/core/test_playback.py +++ b/tests/core/test_playback.py @@ -333,6 +333,34 @@ class TestOnAboutToFinish(BaseTest): self.assertIn(tl_track, self.core.tracklist.tl_tracks) + def test_on_about_to_finish_skips_over_change_track_error(self): + # Trigger an exception in translate_uri. + track = Track(uri='dummy:error', length=1234) + self.core.tracklist.add(tracks=[track], at_position=1) + + tl_tracks = self.core.tracklist.get_tl_tracks() + + self.core.playback.play(tl_tracks[0]) + self.replay_events() + + self.trigger_about_to_finish() + + assert self.core.playback.get_current_tl_track() == tl_tracks[2] + + def test_on_about_to_finish_skips_over_change_track_unplayable(self): + # Makes translate_uri return None. + track = Track(uri='dummy:unplayable', length=1234) + self.core.tracklist.add(tracks=[track], at_position=1) + + tl_tracks = self.core.tracklist.get_tl_tracks() + + self.core.playback.play(tl_tracks[0]) + self.replay_events() + + self.trigger_about_to_finish() + + assert self.core.playback.get_current_tl_track() == tl_tracks[2] + class TestConsumeHandling(BaseTest):