diff --git a/.gitignore b/.gitignore index 6ef1ff32..79230110 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,5 @@ docs/_build/ mopidy.log* node_modules/ nosetests.xml +*~ +*.orig diff --git a/docs/changelog.rst b/docs/changelog.rst index ef84c64f..1cbad579 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -39,6 +39,45 @@ of the following extensions as well: **Core** +- Parts of the functionality in :class:`mopidy.core.PlaybackController` have + been moved to :class:`mopidy.core.TracklistController`: + + =================================== ================================== + Old location New location + =================================== ================================== + playback.get_consume() tracklist.get_consume() + playback.set_consume(v) tracklist.set_consume(v) + playback.consume tracklist.consume + + playback.get_random() tracklist.get_random() + playback.set_random(v) tracklist.set_random(v) + playback.random tracklist.random + + playback.get_repeat() tracklist.get_repeat() + playback.set_repeat(v) tracklist.set_repeat(v) + playback.repeat tracklist.repeat + + playback.get_single() tracklist.get_single() + playback.set_single(v) tracklist.set_single(v) + playback.single tracklist.single + + playback.get_tracklist_position() tracklist.index(tl_track) + playback.tracklist_position tracklist.index(tl_track) + + playback.get_tl_track_at_eot() tracklist.eot_track(tl_track) + playback.tl_track_at_eot tracklist.eot_track(tl_track) + + playback.get_tl_track_at_next() tracklist.next_track(tl_track) + playback.tl_track_at_next tracklist.next_track(tl_track) + + playback.get_tl_track_at_previous() tracklist.previous_track(tl_track) + playback.tl_track_at_previous tracklist.previous_track(tl_track) + =================================== ================================== + + The ``tl_track`` argument to the last four new functions are used as the + reference ``tl_track`` in the tracklist to find e.g. the next track. Usually, + this will be :attr:`~mopidy.core.PlaybackController.current_tl_track`. + - Added :attr:`mopidy.core.PlaybackController.mute` for muting and unmuting audio. (Fixes: :issue:`186`) diff --git a/mopidy/core/playback.py b/mopidy/core/playback.py index 3dc6d0aa..d127fbbe 100644 --- a/mopidy/core/playback.py +++ b/mopidy/core/playback.py @@ -1,7 +1,6 @@ from __future__ import unicode_literals import logging -import random import urlparse from mopidy.audio import PlaybackState @@ -21,8 +20,6 @@ class PlaybackController(object): self.core = core self._state = PlaybackState.STOPPED - self._shuffled = [] - self._first_shuffle = True self._volume = None self._mute = False @@ -35,22 +32,6 @@ class PlaybackController(object): ### Properties - def get_consume(self): - return getattr(self, '_consume', False) - - def set_consume(self, value): - if self.get_consume() != value: - self._trigger_options_changed() - return setattr(self, '_consume', value) - - consume = property(get_consume, set_consume) - """ - :class:`True` - Tracks are removed from the playlist when they have been played. - :class:`False` - Tracks are not removed from the playlist. - """ - def get_current_tl_track(self): return self.current_tl_track @@ -70,56 +51,6 @@ class PlaybackController(object): Read-only. Extracted from :attr:`current_tl_track` for convenience. """ - def get_random(self): - return getattr(self, '_random', False) - - def set_random(self, value): - if self.get_random() != value: - self._trigger_options_changed() - return setattr(self, '_random', value) - - random = property(get_random, set_random) - """ - :class:`True` - Tracks are selected at random from the playlist. - :class:`False` - Tracks are played in the order of the playlist. - """ - - def get_repeat(self): - return getattr(self, '_repeat', False) - - def set_repeat(self, value): - if self.get_repeat() != value: - self._trigger_options_changed() - return setattr(self, '_repeat', value) - - repeat = property(get_repeat, set_repeat) - """ - :class:`True` - The current playlist is played repeatedly. To repeat a single track, - select both :attr:`repeat` and :attr:`single`. - :class:`False` - The current playlist is played once. - """ - - def get_single(self): - return getattr(self, '_single', False) - - def set_single(self, value): - if self.get_single() != value: - self._trigger_options_changed() - return setattr(self, '_single', value) - - single = property(get_single, set_single) - """ - :class:`True` - Playback is stopped after current song, unless in :attr:`repeat` - mode. - :class:`False` - Playback continues after current song. - """ - def get_state(self): return self._state @@ -157,119 +88,6 @@ class PlaybackController(object): time_position = property(get_time_position) """Time position in milliseconds.""" - def get_tracklist_position(self): - if self.current_tl_track is None: - return None - try: - return self.core.tracklist.tl_tracks.index(self.current_tl_track) - except ValueError: - return None - - tracklist_position = property(get_tracklist_position) - """ - The position of the current track in the tracklist. - - Read-only. - """ - - def get_tl_track_at_eot(self): - tl_tracks = self.core.tracklist.tl_tracks - - if not tl_tracks: - return None - - if self.random and not self._shuffled: - if self.repeat or self._first_shuffle: - logger.debug('Shuffling tracks') - self._shuffled = tl_tracks - random.shuffle(self._shuffled) - self._first_shuffle = False - - if self.random and self._shuffled: - return self._shuffled[0] - - if self.current_tl_track is None: - return tl_tracks[0] - - if self.repeat and self.single: - return tl_tracks[self.tracklist_position] - - if self.repeat and not self.single: - return tl_tracks[(self.tracklist_position + 1) % len(tl_tracks)] - - try: - return tl_tracks[self.tracklist_position + 1] - except IndexError: - return None - - tl_track_at_eot = property(get_tl_track_at_eot) - """ - The track that will be played at the end of the current track. - - Read-only. A :class:`mopidy.models.TlTrack`. - - Not necessarily the same track as :attr:`tl_track_at_next`. - """ - - def get_tl_track_at_next(self): - tl_tracks = self.core.tracklist.tl_tracks - - if not tl_tracks: - return None - - if self.random and not self._shuffled: - if self.repeat or self._first_shuffle: - logger.debug('Shuffling tracks') - self._shuffled = tl_tracks - random.shuffle(self._shuffled) - self._first_shuffle = False - - if self.random and self._shuffled: - return self._shuffled[0] - - if self.current_tl_track is None: - return tl_tracks[0] - - if self.repeat: - return tl_tracks[(self.tracklist_position + 1) % len(tl_tracks)] - - try: - return tl_tracks[self.tracklist_position + 1] - except IndexError: - return None - - tl_track_at_next = property(get_tl_track_at_next) - """ - The track that will be played if calling :meth:`next()`. - - Read-only. A :class:`mopidy.models.TlTrack`. - - For normal playback this is the next track in the playlist. If repeat - is enabled the next track can loop around the playlist. When random is - enabled this should be a random track, all tracks should be played once - before the list repeats. - """ - - def get_tl_track_at_previous(self): - if self.repeat or self.consume or self.random: - return self.current_tl_track - - if self.tracklist_position in (None, 0): - return None - - return self.core.tracklist.tl_tracks[self.tracklist_position - 1] - - tl_track_at_previous = property(get_tl_track_at_previous) - """ - The track that will be played if calling :meth:`previous()`. - - A :class:`mopidy.models.TlTrack`. - - For normal playback this is the previous track in the playlist. If - random and/or consume is enabled it should return the current track - instead. - """ - def get_volume(self): if self.audio: return self.audio.get_volume().get() @@ -339,15 +157,15 @@ class PlaybackController(object): return original_tl_track = self.current_tl_track + next_tl_track = self.core.tracklist.eot_track(original_tl_track) - if self.tl_track_at_eot: + if next_tl_track: self._trigger_track_playback_ended() - self.play(self.tl_track_at_eot) + self.play(next_tl_track) else: self.stop(clear_current_track=True) - if self.consume: - self.core.tracklist.remove(tlid=original_tl_track.tlid) + self.core.tracklist.mark_played(original_tl_track) def on_tracklist_change(self): """ @@ -355,12 +173,7 @@ class PlaybackController(object): Used by :class:`mopidy.core.TracklistController`. """ - self._first_shuffle = True - self._shuffled = [] - - if (not self.core.tracklist.tl_tracks or - self.current_tl_track not in - self.core.tracklist.tl_tracks): + if self.current_tl_track not in self.core.tracklist.tl_tracks: self.stop(clear_current_track=True) def next(self): @@ -370,9 +183,10 @@ 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. """ - if self.tl_track_at_next: + tl_track = self.core.tracklist.next_track(self.current_tl_track) + if tl_track: self._trigger_track_playback_ended() - self.change_track(self.tl_track_at_next) + self.change_track(tl_track) else: self.stop(clear_current_track=True) @@ -395,37 +209,40 @@ class PlaybackController(object): :type on_error_step: int, -1 or 1 """ - if tl_track is not None: - assert tl_track in self.core.tracklist.tl_tracks - elif tl_track is None: + assert on_error_step in (-1, 1) + + if tl_track is None: if self.state == PlaybackState.PAUSED: return self.resume() - elif self.current_tl_track is not None: - tl_track = self.current_tl_track - elif self.current_tl_track is None and on_error_step == 1: - tl_track = self.tl_track_at_next - elif self.current_tl_track is None and on_error_step == -1: - tl_track = self.tl_track_at_previous - if tl_track is not None: - self.current_tl_track = tl_track - self.state = PlaybackState.PLAYING - backend = self._get_backend() - if not backend or not backend.playback.play(tl_track.track).get(): - logger.warning('Track is not playable: %s', tl_track.track.uri) - if self.random and self._shuffled: - self._shuffled.remove(tl_track) + if self.current_tl_track is not None: + tl_track = self.current_tl_track + else: if on_error_step == 1: - # TODO: can cause an endless loop for single track repeat. - self.next() + tl_track = self.core.tracklist.next_track(tl_track) elif on_error_step == -1: - self.previous() + tl_track = self.core.tracklist.previous_track(tl_track) + + if tl_track is None: return - if self.random and self.current_tl_track in self._shuffled: - self._shuffled.remove(self.current_tl_track) + assert tl_track in self.core.tracklist.tl_tracks - self._trigger_track_playback_started() + self.current_tl_track = tl_track + self.state = PlaybackState.PLAYING + backend = self._get_backend() + success = backend and backend.playback.play(tl_track.track).get() + + if success: + self.core.tracklist.mark_playing(tl_track) + self._trigger_track_playback_started() + else: + self.core.tracklist.mark_unplayable(tl_track) + if on_error_step == 1: + # TODO: can cause an endless loop for single track repeat. + self.next() + elif on_error_step == -1: + self.previous() def previous(self): """ @@ -435,7 +252,9 @@ class PlaybackController(object): will continue. If it was paused, it will still be paused, etc. """ self._trigger_track_playback_ended() - self.change_track(self.tl_track_at_previous, on_error_step=-1) + tl_track = self.current_tl_track + self.change_track( + self.core.tracklist.previous_track(tl_track), on_error_step=-1) def resume(self): """If paused, resume playing the current track.""" @@ -531,10 +350,6 @@ class PlaybackController(object): 'playback_state_changed', old_state=old_state, new_state=new_state) - def _trigger_options_changed(self): - logger.debug('Triggering options changed event') - listener.CoreListener.send('options_changed') - def _trigger_volume_changed(self, volume): logger.debug('Triggering volume changed event') listener.CoreListener.send('volume_changed', volume=volume) diff --git a/mopidy/core/tracklist.py b/mopidy/core/tracklist.py index 1c8f437f..5d85e190 100644 --- a/mopidy/core/tracklist.py +++ b/mopidy/core/tracklist.py @@ -15,11 +15,16 @@ class TracklistController(object): pykka_traversable = True def __init__(self, core): - self._core = core + self.core = core self._next_tlid = 0 self._tl_tracks = [] self._version = 0 + self._shuffled = [] + self._first_shuffle = True + + ### Properties + def get_tl_tracks(self): return self._tl_tracks[:] @@ -51,7 +56,7 @@ class TracklistController(object): def _increase_version(self): self._version += 1 - self._core.playback.on_tracklist_change() + self.core.playback.on_tracklist_change() self._trigger_tracklist_changed() version = property(get_version) @@ -62,6 +67,190 @@ class TracklistController(object): Is not reset before Mopidy is restarted. """ + def get_consume(self): + return getattr(self, '_consume', False) + + def set_consume(self, value): + if self.get_consume() != value: + self._trigger_options_changed() + return setattr(self, '_consume', value) + + consume = property(get_consume, set_consume) + """ + :class:`True` + Tracks are removed from the playlist when they have been played. + :class:`False` + Tracks are not removed from the playlist. + """ + + def get_random(self): + return getattr(self, '_random', False) + + def set_random(self, value): + if self.get_random() != value: + self._trigger_options_changed() + return setattr(self, '_random', value) + + random = property(get_random, set_random) + """ + :class:`True` + Tracks are selected at random from the playlist. + :class:`False` + Tracks are played in the order of the playlist. + """ + + def get_repeat(self): + return getattr(self, '_repeat', False) + + def set_repeat(self, value): + if self.get_repeat() != value: + self._trigger_options_changed() + return setattr(self, '_repeat', value) + + repeat = property(get_repeat, set_repeat) + """ + :class:`True` + The current playlist is played repeatedly. To repeat a single track, + select both :attr:`repeat` and :attr:`single`. + :class:`False` + The current playlist is played once. + """ + + def get_single(self): + return getattr(self, '_single', False) + + def set_single(self, value): + if self.get_single() != value: + self._trigger_options_changed() + return setattr(self, '_single', value) + + single = property(get_single, set_single) + """ + :class:`True` + Playback is stopped after current song, unless in :attr:`repeat` + mode. + :class:`False` + Playback continues after current song. + """ + + ### Methods + + def index(self, tl_track): + """ + The position of the given track in the tracklist. + + :param tl_track: the track to find the index of + :type tl_track: :class:`mopidy.models.TlTrack` + :rtype: :class:`int` or :class:`None` + """ + try: + return self._tl_tracks.index(tl_track) + except ValueError: + return None + + def eot_track(self, tl_track): + """ + The track that will be played after the given track. + + Not necessarily the same track as :meth:`next_track`. + + :param tl_track: the reference track + :type tl_track: :class:`mopidy.models.TlTrack` or :class:`None` + :rtype: :class:`mopidy.models.TlTrack` or :class:`None` + """ + if not self.tl_tracks: + return None + + if self.random and not self._shuffled: + if self.repeat or self._first_shuffle: + logger.debug('Shuffling tracks') + self._shuffled = self.tl_tracks + random.shuffle(self._shuffled) + self._first_shuffle = False + + if self.random and self._shuffled: + return self._shuffled[0] + + if tl_track is None: + return self.tl_tracks[0] + + position = self.index(tl_track) + + if self.repeat and self.single: + return self.tl_tracks[position] + + if self.repeat and not self.single: + return self.tl_tracks[(position + 1) % len(self.tl_tracks)] + + try: + return self.tl_tracks[position + 1] + except IndexError: + return None + + def next_track(self, tl_track): + """ + The track that will be played if calling + :meth:`mopidy.core.PlaybackController.next()`. + + For normal playback this is the next track in the playlist. If repeat + is enabled the next track can loop around the playlist. When random is + enabled this should be a random track, all tracks should be played once + before the list repeats. + + :param tl_track: the reference track + :type tl_track: :class:`mopidy.models.TlTrack` or :class:`None` + :rtype: :class:`mopidy.models.TlTrack` or :class:`None` + """ + + if not self.tl_tracks: + return None + + if self.random and not self._shuffled: + if self.repeat or self._first_shuffle: + logger.debug('Shuffling tracks') + self._shuffled = self.tl_tracks + random.shuffle(self._shuffled) + self._first_shuffle = False + + if self.random and self._shuffled: + return self._shuffled[0] + + if tl_track is None: + return self.tl_tracks[0] + + position = self.index(tl_track) + + if self.repeat: + return self.tl_tracks[(position + 1) % len(self.tl_tracks)] + + try: + return self.tl_tracks[position + 1] + except IndexError: + return None + + def previous_track(self, tl_track): + """ + Returns the track that will be played if calling + :meth:`mopidy.core.PlaybackController.previous()`. + + For normal playback this is the previous track in the playlist. If + random and/or consume is enabled it should return the current track + instead. + + :param tl_track: the reference track + :type tl_track: :class:`mopidy.models.TlTrack` or :class:`None` + :rtype: :class:`mopidy.models.TlTrack` or :class:`None` + """ + if self.repeat or self.consume or self.random: + return tl_track + + position = self.index(tl_track) + + if position in (None, 0): + return None + + return self.tl_tracks[position - 1] + def add(self, tracks=None, at_position=None, uri=None): """ Add the track or list of tracks to the tracklist. @@ -87,7 +276,7 @@ class TracklistController(object): 'tracks or uri must be provided' if tracks is None and uri is not None: - tracks = self._core.library.lookup(uri) + tracks = self.core.library.lookup(uri) tl_tracks = [] @@ -151,18 +340,6 @@ class TracklistController(object): lambda ct: getattr(ct.track, key) == value, matches) return matches - def index(self, tl_track): - """ - Get index of the given :class:`mopidy.models.TlTrack` in the tracklist. - - Raises :exc:`ValueError` if not found. - - :param tl_track: track to find the index of - :type tl_track: :class:`mopidy.models.TlTrack` - :rtype: int - """ - return self._tl_tracks.index(tl_track) - def move(self, start, end, to_position): """ Move the tracks in the slice ``[start:end]`` to ``to_position``. @@ -259,6 +436,31 @@ class TracklistController(object): """ return self._tl_tracks[start:end] + def mark_playing(self, tl_track): + """Private method used by :class:`mopidy.core.PlaybackController`.""" + if self.random and tl_track in self._shuffled: + self._shuffled.remove(tl_track) + + def mark_unplayable(self, tl_track): + """Private method used by :class:`mopidy.core.PlaybackController`.""" + logger.warning('Track is not playable: %s', tl_track.track.uri) + if self.random and tl_track in self._shuffled: + self._shuffled.remove(tl_track) + + def mark_played(self, tl_track): + """Private method used by :class:`mopidy.core.PlaybackController`.""" + if not self.consume: + return False + self.remove(tlid=tl_track.tlid) + return True + def _trigger_tracklist_changed(self): + self._first_shuffle = True + self._shuffled = [] + logger.debug('Triggering event: tracklist_changed()') listener.CoreListener.send('tracklist_changed') + + def _trigger_options_changed(self): + logger.debug('Triggering options changed event') + listener.CoreListener.send('options_changed') diff --git a/mopidy/frontends/mpd/protocol/playback.py b/mopidy/frontends/mpd/protocol/playback.py index 8e08585f..b9289d8a 100644 --- a/mopidy/frontends/mpd/protocol/playback.py +++ b/mopidy/frontends/mpd/protocol/playback.py @@ -19,9 +19,9 @@ def consume(context, state): playlist. """ if int(state): - context.core.playback.consume = True + context.core.tracklist.consume = True else: - context.core.playback.consume = False + context.core.tracklist.consume = False @handle_request(r'^crossfade "(?P\d+)"$') @@ -263,9 +263,9 @@ def random(context, state): Sets random state to ``STATE``, ``STATE`` should be 0 or 1. """ if int(state): - context.core.playback.random = True + context.core.tracklist.random = True else: - context.core.playback.random = False + context.core.tracklist.random = False @handle_request(r'^repeat (?P[01])$') @@ -279,9 +279,9 @@ def repeat(context, state): Sets repeat state to ``STATE``, ``STATE`` should be 0 or 1. """ if int(state): - context.core.playback.repeat = True + context.core.tracklist.repeat = True else: - context.core.playback.repeat = False + context.core.tracklist.repeat = False @handle_request(r'^replay_gain_mode "(?P(off|track|album))"$') @@ -329,7 +329,8 @@ def seek(context, songpos, seconds): - issues ``seek 1 120`` without quotes around the arguments. """ - if context.core.playback.tracklist_position.get() != int(songpos): + tl_track = context.core.playback.current_tl_track.get() + if context.core.tracklist.index(tl_track).get() != int(songpos): playpos(context, songpos) context.core.playback.seek(int(seconds) * 1000).get() @@ -404,9 +405,9 @@ def single(context, state): song is repeated if the ``repeat`` mode is enabled. """ if int(state): - context.core.playback.single = True + context.core.tracklist.single = True else: - context.core.playback.single = False + context.core.tracklist.single = False @handle_request(r'^stop$') diff --git a/mopidy/frontends/mpd/protocol/status.py b/mopidy/frontends/mpd/protocol/status.py index 34e2fa64..49e08ee8 100644 --- a/mopidy/frontends/mpd/protocol/status.py +++ b/mopidy/frontends/mpd/protocol/status.py @@ -36,10 +36,10 @@ def currentsong(context): Displays the song info of the current song (same song that is identified in status). """ - current_tl_track = context.core.playback.current_tl_track.get() - if current_tl_track is not None: - position = context.core.playback.tracklist_position.get() - return track_to_mpd_format(current_tl_track, position=position) + tl_track = context.core.playback.current_tl_track.get() + if tl_track is not None: + position = context.core.tracklist.index(tl_track).get() + return track_to_mpd_format(tl_track, position=position) @handle_request(r'^idle$') @@ -178,14 +178,15 @@ def status(context): 'tracklist.length': context.core.tracklist.length, 'tracklist.version': context.core.tracklist.version, 'playback.volume': context.core.playback.volume, - 'playback.consume': context.core.playback.consume, - 'playback.random': context.core.playback.random, - 'playback.repeat': context.core.playback.repeat, - 'playback.single': context.core.playback.single, + 'tracklist.consume': context.core.tracklist.consume, + 'tracklist.random': context.core.tracklist.random, + 'tracklist.repeat': context.core.tracklist.repeat, + 'tracklist.single': context.core.tracklist.single, 'playback.state': context.core.playback.state, 'playback.current_tl_track': context.core.playback.current_tl_track, - 'playback.tracklist_position': ( - context.core.playback.tracklist_position), + 'tracklist.index': ( + context.core.tracklist.index( + context.core.playback.current_tl_track.get())), 'playback.time_position': context.core.playback.time_position, } pykka.get_all(futures.values()) @@ -218,7 +219,7 @@ def _status_bitrate(futures): def _status_consume(futures): - if futures['playback.consume'].get(): + if futures['tracklist.consume'].get(): return 1 else: return 0 @@ -233,15 +234,15 @@ def _status_playlist_version(futures): def _status_random(futures): - return int(futures['playback.random'].get()) + return int(futures['tracklist.random'].get()) def _status_repeat(futures): - return int(futures['playback.repeat'].get()) + return int(futures['tracklist.repeat'].get()) def _status_single(futures): - return int(futures['playback.single'].get()) + return int(futures['tracklist.single'].get()) def _status_songid(futures): @@ -253,7 +254,7 @@ def _status_songid(futures): def _status_songpos(futures): - return futures['playback.tracklist_position'].get() + return futures['tracklist.index'].get() def _status_state(futures): diff --git a/tests/backends/local/playback_test.py b/tests/backends/local/playback_test.py index 5df86dd1..cd67a0e6 100644 --- a/tests/backends/local/playback_test.py +++ b/tests/backends/local/playback_test.py @@ -212,13 +212,15 @@ class LocalPlaybackProviderTest(unittest.TestCase): def test_next(self): self.playback.play() - old_position = self.playback.tracklist_position - old_uri = self.playback.current_track.uri + tl_track = self.playback.current_tl_track + old_position = self.tracklist.index(tl_track) + old_uri = tl_track.track.uri self.playback.next() + tl_track = self.playback.current_tl_track self.assertEqual( - self.playback.tracklist_position, old_position + 1) + self.tracklist.index(tl_track), old_position + 1) self.assertNotEqual(self.playback.current_track.uri, old_uri) @populate_tracklist @@ -238,7 +240,8 @@ class LocalPlaybackProviderTest(unittest.TestCase): for i, track in enumerate(self.tracks): self.assertEqual(self.playback.state, PlaybackState.PLAYING) self.assertEqual(self.playback.current_track, track) - self.assertEqual(self.playback.tracklist_position, i) + tl_track = self.playback.current_tl_track + self.assertEqual(self.tracklist.index(tl_track), i) self.playback.next() @@ -274,55 +277,67 @@ class LocalPlaybackProviderTest(unittest.TestCase): @populate_tracklist def test_next_track_before_play(self): - self.assertEqual(self.playback.tl_track_at_next, self.tl_tracks[0]) + tl_track = self.playback.current_tl_track + self.assertEqual( + self.tracklist.next_track(tl_track), self.tl_tracks[0]) @populate_tracklist def test_next_track_during_play(self): self.playback.play() - self.assertEqual(self.playback.tl_track_at_next, self.tl_tracks[1]) + tl_track = self.playback.current_tl_track + self.assertEqual( + self.tracklist.next_track(tl_track), self.tl_tracks[1]) @populate_tracklist def test_next_track_after_previous(self): self.playback.play() self.playback.next() self.playback.previous() - self.assertEqual(self.playback.tl_track_at_next, self.tl_tracks[1]) + tl_track = self.playback.current_tl_track + self.assertEqual( + self.tracklist.next_track(tl_track), self.tl_tracks[1]) def test_next_track_empty_playlist(self): - self.assertEqual(self.playback.tl_track_at_next, None) + tl_track = self.playback.current_tl_track + self.assertEqual(self.tracklist.next_track(tl_track), None) @populate_tracklist def test_next_track_at_end_of_playlist(self): self.playback.play() for _ in self.tracklist.tl_tracks[1:]: self.playback.next() - self.assertEqual(self.playback.tl_track_at_next, None) + tl_track = self.playback.current_tl_track + self.assertEqual(self.tracklist.next_track(tl_track), None) @populate_tracklist def test_next_track_at_end_of_playlist_with_repeat(self): - self.playback.repeat = True + self.tracklist.repeat = True self.playback.play() for _ in self.tracks[1:]: self.playback.next() - self.assertEqual(self.playback.tl_track_at_next, self.tl_tracks[0]) + tl_track = self.playback.current_tl_track + self.assertEqual( + self.tracklist.next_track(tl_track), self.tl_tracks[0]) @populate_tracklist def test_next_track_with_random(self): random.seed(1) - self.playback.random = True - self.assertEqual(self.playback.tl_track_at_next, self.tl_tracks[2]) + self.tracklist.random = True + tl_track = self.playback.current_tl_track + self.assertEqual( + self.tracklist.next_track(tl_track), self.tl_tracks[2]) @populate_tracklist def test_next_with_consume(self): - self.playback.consume = True + self.tracklist.consume = True self.playback.play() self.playback.next() self.assertIn(self.tracks[0], self.tracklist.tracks) @populate_tracklist def test_next_with_single_and_repeat(self): - self.playback.single = True - self.playback.repeat = True + self.tracklist.single = True + self.tracklist.repeat = True self.playback.play() self.playback.next() self.assertEqual(self.playback.current_track, self.tracks[1]) @@ -331,7 +346,7 @@ class LocalPlaybackProviderTest(unittest.TestCase): def test_next_with_random(self): # FIXME feels very fragile random.seed(1) - self.playback.random = True + self.tracklist.random = True self.playback.play() self.playback.next() self.assertEqual(self.playback.current_track, self.tracks[1]) @@ -339,22 +354,28 @@ class LocalPlaybackProviderTest(unittest.TestCase): @populate_tracklist def test_next_track_with_random_after_append_playlist(self): random.seed(1) - self.playback.random = True - self.assertEqual(self.playback.tl_track_at_next, self.tl_tracks[2]) + self.tracklist.random = True + tl_track = self.playback.current_tl_track + self.assertEqual(self.tracklist.next_track(tl_track), + self.tl_tracks[2]) self.tracklist.add(self.tracks[:1]) - self.assertEqual(self.playback.tl_track_at_next, self.tl_tracks[1]) + 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(self): self.playback.play() - old_position = self.playback.tracklist_position - old_uri = self.playback.current_track.uri + 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() + tl_track = self.playback.current_tl_track self.assertEqual( - self.playback.tracklist_position, old_position + 1) + self.tracklist.index(tl_track), old_position + 1) self.assertNotEqual(self.playback.current_track.uri, old_uri) @populate_tracklist @@ -374,7 +395,8 @@ class LocalPlaybackProviderTest(unittest.TestCase): for i, track in enumerate(self.tracks): self.assertEqual(self.playback.state, PlaybackState.PLAYING) self.assertEqual(self.playback.current_track, track) - self.assertEqual(self.playback.tracklist_position, i) + tl_track = self.playback.current_tl_track + self.assertEqual(self.tracklist.index(tl_track), i) self.playback.on_end_of_track() @@ -410,47 +432,59 @@ class LocalPlaybackProviderTest(unittest.TestCase): @populate_tracklist def test_end_of_track_track_before_play(self): - self.assertEqual(self.playback.tl_track_at_next, self.tl_tracks[0]) + tl_track = self.playback.current_tl_track + self.assertEqual( + self.tracklist.next_track(tl_track), self.tl_tracks[0]) @populate_tracklist def test_end_of_track_track_during_play(self): self.playback.play() - self.assertEqual(self.playback.tl_track_at_next, self.tl_tracks[1]) + 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_track_after_previous(self): self.playback.play() self.playback.on_end_of_track() self.playback.previous() - self.assertEqual(self.playback.tl_track_at_next, self.tl_tracks[1]) + tl_track = self.playback.current_tl_track + self.assertEqual( + self.tracklist.next_track(tl_track), self.tl_tracks[1]) def test_end_of_track_track_empty_playlist(self): - self.assertEqual(self.playback.tl_track_at_next, None) + tl_track = self.playback.current_tl_track + self.assertEqual(self.tracklist.next_track(tl_track), None) @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() - self.assertEqual(self.playback.tl_track_at_next, None) + tl_track = self.playback.current_tl_track + self.assertEqual(self.tracklist.next_track(tl_track), None) @populate_tracklist def test_end_of_track_track_at_end_of_playlist_with_repeat(self): - self.playback.repeat = True + self.tracklist.repeat = True self.playback.play() for _ in self.tracks[1:]: self.playback.on_end_of_track() - self.assertEqual(self.playback.tl_track_at_next, self.tl_tracks[0]) + tl_track = self.playback.current_tl_track + self.assertEqual( + self.tracklist.next_track(tl_track), self.tl_tracks[0]) @populate_tracklist def test_end_of_track_track_with_random(self): random.seed(1) - self.playback.random = True - self.assertEqual(self.playback.tl_track_at_next, self.tl_tracks[2]) + self.tracklist.random = True + tl_track = self.playback.current_tl_track + self.assertEqual( + self.tracklist.next_track(tl_track), self.tl_tracks[2]) @populate_tracklist def test_end_of_track_with_consume(self): - self.playback.consume = True + self.tracklist.consume = True self.playback.play() self.playback.on_end_of_track() self.assertNotIn(self.tracks[0], self.tracklist.tracks) @@ -459,7 +493,7 @@ class LocalPlaybackProviderTest(unittest.TestCase): def test_end_of_track_with_random(self): # FIXME feels very fragile random.seed(1) - self.playback.random = True + self.tracklist.random = True self.playback.play() self.playback.on_end_of_track() self.assertEqual(self.playback.current_track, self.tracks[1]) @@ -467,25 +501,33 @@ class LocalPlaybackProviderTest(unittest.TestCase): @populate_tracklist def test_end_of_track_track_with_random_after_append_playlist(self): random.seed(1) - self.playback.random = True - self.assertEqual(self.playback.tl_track_at_next, self.tl_tracks[2]) + self.tracklist.random = True + tl_track = self.playback.current_tl_track + self.assertEqual( + self.tracklist.next_track(tl_track), self.tl_tracks[2]) self.tracklist.add(self.tracks[:1]) - self.assertEqual(self.playback.tl_track_at_next, self.tl_tracks[1]) + tl_track = self.playback.current_tl_track + self.assertEqual( + self.tracklist.next_track(tl_track), self.tl_tracks[1]) @populate_tracklist def test_previous_track_before_play(self): - self.assertEqual(self.playback.tl_track_at_previous, None) + tl_track = self.playback.current_tl_track + self.assertEqual(self.tracklist.previous_track(tl_track), None) @populate_tracklist def test_previous_track_after_play(self): self.playback.play() - self.assertEqual(self.playback.tl_track_at_previous, None) + tl_track = self.playback.current_tl_track + self.assertEqual(self.tracklist.previous_track(tl_track), None) @populate_tracklist def test_previous_track_after_next(self): self.playback.play() self.playback.next() - self.assertEqual(self.playback.tl_track_at_previous, self.tl_tracks[0]) + tl_track = self.playback.current_tl_track + self.assertEqual( + self.tracklist.previous_track(tl_track), self.tl_tracks[0]) @populate_tracklist def test_previous_track_after_previous(self): @@ -493,27 +535,32 @@ class LocalPlaybackProviderTest(unittest.TestCase): self.playback.next() # At track 1 self.playback.next() # At track 2 self.playback.previous() # At track 1 - self.assertEqual(self.playback.tl_track_at_previous, self.tl_tracks[0]) + tl_track = self.playback.current_tl_track + self.assertEqual( + self.tracklist.previous_track(tl_track), self.tl_tracks[0]) def test_previous_track_empty_playlist(self): - self.assertEqual(self.playback.tl_track_at_previous, None) + tl_track = self.playback.current_tl_track + self.assertEqual(self.tracklist.previous_track(tl_track), None) @populate_tracklist def test_previous_track_with_consume(self): - self.playback.consume = True + self.tracklist.consume = True for _ in self.tracks: self.playback.next() + tl_track = self.playback.current_tl_track self.assertEqual( - self.playback.tl_track_at_previous, + self.tracklist.previous_track(tl_track), self.playback.current_tl_track) @populate_tracklist def test_previous_track_with_random(self): - self.playback.random = True + self.tracklist.random = True for _ in self.tracks: self.playback.next() + tl_track = self.playback.current_tl_track self.assertEqual( - self.playback.tl_track_at_previous, + self.tracklist.previous_track(tl_track), self.playback.current_tl_track) @populate_tracklist @@ -533,24 +580,28 @@ class LocalPlaybackProviderTest(unittest.TestCase): @populate_tracklist def test_initial_tracklist_position(self): - self.assertEqual(self.playback.tracklist_position, None) + tl_track = self.playback.current_tl_track + self.assertEqual(self.tracklist.index(tl_track), None) @populate_tracklist def test_tracklist_position_during_play(self): self.playback.play() - self.assertEqual(self.playback.tracklist_position, 0) + tl_track = self.playback.current_tl_track + self.assertEqual(self.tracklist.index(tl_track), 0) @populate_tracklist def test_tracklist_position_after_next(self): self.playback.play() self.playback.next() - self.assertEqual(self.playback.tracklist_position, 1) + tl_track = self.playback.current_tl_track + self.assertEqual(self.tracklist.index(tl_track), 1) @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.assertEqual(self.playback.tracklist_position, None) + tl_track = self.playback.current_tl_track + self.assertEqual(self.tracklist.index(tl_track), None) def test_on_tracklist_change_gets_called(self): callback = self.playback.on_tracklist_change @@ -808,13 +859,13 @@ class LocalPlaybackProviderTest(unittest.TestCase): @populate_tracklist def test_play_with_consume(self): - self.playback.consume = True + self.tracklist.consume = True self.playback.play() self.assertEqual(self.playback.current_track, self.tracks[0]) @populate_tracklist def test_playlist_is_empty_after_all_tracks_are_played_with_consume(self): - self.playback.consume = True + self.tracklist.consume = True self.playback.play() for _ in range(len(self.tracklist.tracks)): self.playback.on_end_of_track() @@ -823,14 +874,14 @@ class LocalPlaybackProviderTest(unittest.TestCase): @populate_tracklist def test_play_with_random(self): random.seed(1) - self.playback.random = True + self.tracklist.random = True self.playback.play() self.assertEqual(self.playback.current_track, self.tracks[2]) @populate_tracklist def test_previous_with_random(self): random.seed(1) - self.playback.random = True + self.tracklist.random = True self.playback.play() self.playback.next() current_track = self.playback.current_track @@ -845,8 +896,8 @@ class LocalPlaybackProviderTest(unittest.TestCase): @populate_tracklist def test_end_of_song_with_single_and_repeat_starts_same(self): - self.playback.single = True - self.playback.repeat = True + self.tracklist.single = True + self.tracklist.repeat = True self.playback.play() self.playback.on_end_of_track() self.assertEqual(self.playback.current_track, self.tracks[0]) @@ -858,44 +909,47 @@ class LocalPlaybackProviderTest(unittest.TestCase): self.assertEqual(self.playback.state, PlaybackState.STOPPED) def test_repeat_off_by_default(self): - self.assertEqual(self.playback.repeat, False) + self.assertEqual(self.tracklist.repeat, False) def test_random_off_by_default(self): - self.assertEqual(self.playback.random, False) + self.assertEqual(self.tracklist.random, False) def test_consume_off_by_default(self): - self.assertEqual(self.playback.consume, False) + self.assertEqual(self.tracklist.consume, False) @populate_tracklist def test_random_until_end_of_playlist(self): - self.playback.random = True + self.tracklist.random = True self.playback.play() for _ in self.tracks[1:]: self.playback.next() - self.assertEqual(self.playback.tl_track_at_next, None) + tl_track = self.playback.current_tl_track + self.assertEqual(self.tracklist.next_track(tl_track), None) @populate_tracklist def test_random_until_end_of_playlist_and_play_from_start(self): - self.playback.repeat = True + self.tracklist.repeat = True for _ in self.tracks: self.playback.next() - self.assertNotEqual(self.playback.tl_track_at_next, None) + tl_track = self.playback.current_tl_track + self.assertNotEqual(self.tracklist.next_track(tl_track), None) self.assertEqual(self.playback.state, PlaybackState.STOPPED) self.playback.play() self.assertEqual(self.playback.state, PlaybackState.PLAYING) @populate_tracklist def test_random_until_end_of_playlist_with_repeat(self): - self.playback.repeat = True - self.playback.random = True + self.tracklist.repeat = True + self.tracklist.random = True self.playback.play() for _ in self.tracks: self.playback.next() - self.assertNotEqual(self.playback.tl_track_at_next, None) + tl_track = self.playback.current_tl_track + self.assertNotEqual(self.tracklist.next_track(tl_track), None) @populate_tracklist def test_played_track_during_random_not_played_again(self): - self.playback.random = True + self.tracklist.random = True self.playback.play() played = [] for _ in self.tracks: diff --git a/tests/backends/local/tracklist_test.py b/tests/backends/local/tracklist_test.py index a58bf5f6..8310ce1a 100644 --- a/tests/backends/local/tracklist_test.py +++ b/tests/backends/local/tracklist_test.py @@ -171,13 +171,13 @@ class LocalTracklistProviderTest(unittest.TestCase): def test_index_returns_index_of_track(self): tl_tracks = self.controller.add(self.tracks) - self.assertEquals(0, self.controller.index(tl_tracks[0])) - self.assertEquals(1, self.controller.index(tl_tracks[1])) - self.assertEquals(2, self.controller.index(tl_tracks[2])) + self.assertEqual(0, self.controller.index(tl_tracks[0])) + self.assertEqual(1, self.controller.index(tl_tracks[1])) + self.assertEqual(2, self.controller.index(tl_tracks[2])) - def test_index_raises_value_error_if_item_not_found(self): - test = lambda: self.controller.index(TlTrack(0, Track())) - self.assertRaises(ValueError, test) + def test_index_returns_none_if_item_not_found(self): + tl_track = TlTrack(0, Track()) + self.assertEqual(self.controller.index(tl_track), None) @populate_tracklist def test_move_single(self): diff --git a/tests/frontends/mpd/protocol/playback_test.py b/tests/frontends/mpd/protocol/playback_test.py index 2cfc1b98..fc91c09c 100644 --- a/tests/frontends/mpd/protocol/playback_test.py +++ b/tests/frontends/mpd/protocol/playback_test.py @@ -16,22 +16,22 @@ STOPPED = PlaybackState.STOPPED class PlaybackOptionsHandlerTest(protocol.BaseTestCase): def test_consume_off(self): self.sendRequest('consume "0"') - self.assertFalse(self.core.playback.consume.get()) + self.assertFalse(self.core.tracklist.consume.get()) self.assertInResponse('OK') def test_consume_off_without_quotes(self): self.sendRequest('consume 0') - self.assertFalse(self.core.playback.consume.get()) + self.assertFalse(self.core.tracklist.consume.get()) self.assertInResponse('OK') def test_consume_on(self): self.sendRequest('consume "1"') - self.assertTrue(self.core.playback.consume.get()) + self.assertTrue(self.core.tracklist.consume.get()) self.assertInResponse('OK') def test_consume_on_without_quotes(self): self.sendRequest('consume 1') - self.assertTrue(self.core.playback.consume.get()) + self.assertTrue(self.core.tracklist.consume.get()) self.assertInResponse('OK') def test_crossfade(self): @@ -40,42 +40,42 @@ class PlaybackOptionsHandlerTest(protocol.BaseTestCase): def test_random_off(self): self.sendRequest('random "0"') - self.assertFalse(self.core.playback.random.get()) + self.assertFalse(self.core.tracklist.random.get()) self.assertInResponse('OK') def test_random_off_without_quotes(self): self.sendRequest('random 0') - self.assertFalse(self.core.playback.random.get()) + self.assertFalse(self.core.tracklist.random.get()) self.assertInResponse('OK') def test_random_on(self): self.sendRequest('random "1"') - self.assertTrue(self.core.playback.random.get()) + self.assertTrue(self.core.tracklist.random.get()) self.assertInResponse('OK') def test_random_on_without_quotes(self): self.sendRequest('random 1') - self.assertTrue(self.core.playback.random.get()) + self.assertTrue(self.core.tracklist.random.get()) self.assertInResponse('OK') def test_repeat_off(self): self.sendRequest('repeat "0"') - self.assertFalse(self.core.playback.repeat.get()) + self.assertFalse(self.core.tracklist.repeat.get()) self.assertInResponse('OK') def test_repeat_off_without_quotes(self): self.sendRequest('repeat 0') - self.assertFalse(self.core.playback.repeat.get()) + self.assertFalse(self.core.tracklist.repeat.get()) self.assertInResponse('OK') def test_repeat_on(self): self.sendRequest('repeat "1"') - self.assertTrue(self.core.playback.repeat.get()) + self.assertTrue(self.core.tracklist.repeat.get()) self.assertInResponse('OK') def test_repeat_on_without_quotes(self): self.sendRequest('repeat 1') - self.assertTrue(self.core.playback.repeat.get()) + self.assertTrue(self.core.tracklist.repeat.get()) self.assertInResponse('OK') def test_setvol_below_min(self): @@ -115,22 +115,22 @@ class PlaybackOptionsHandlerTest(protocol.BaseTestCase): def test_single_off(self): self.sendRequest('single "0"') - self.assertFalse(self.core.playback.single.get()) + self.assertFalse(self.core.tracklist.single.get()) self.assertInResponse('OK') def test_single_off_without_quotes(self): self.sendRequest('single 0') - self.assertFalse(self.core.playback.single.get()) + self.assertFalse(self.core.tracklist.single.get()) self.assertInResponse('OK') def test_single_on(self): self.sendRequest('single "1"') - self.assertTrue(self.core.playback.single.get()) + self.assertTrue(self.core.tracklist.single.get()) self.assertInResponse('OK') def test_single_on_without_quotes(self): self.sendRequest('single 1') - self.assertTrue(self.core.playback.single.get()) + self.assertTrue(self.core.tracklist.single.get()) self.assertInResponse('OK') def test_replay_gain_mode_off(self): diff --git a/tests/frontends/mpd/status_test.py b/tests/frontends/mpd/status_test.py index ded0c3b2..d86f7dcd 100644 --- a/tests/frontends/mpd/status_test.py +++ b/tests/frontends/mpd/status_test.py @@ -64,7 +64,7 @@ class StatusHandlerTest(unittest.TestCase): self.assertEqual(int(result['repeat']), 0) def test_status_method_contains_repeat_is_1(self): - self.core.playback.repeat = 1 + self.core.tracklist.repeat = 1 result = dict(status.status(self.context)) self.assertIn('repeat', result) self.assertEqual(int(result['repeat']), 1) @@ -75,7 +75,7 @@ class StatusHandlerTest(unittest.TestCase): self.assertEqual(int(result['random']), 0) def test_status_method_contains_random_is_1(self): - self.core.playback.random = 1 + self.core.tracklist.random = 1 result = dict(status.status(self.context)) self.assertIn('random', result) self.assertEqual(int(result['random']), 1) @@ -91,7 +91,7 @@ class StatusHandlerTest(unittest.TestCase): self.assertEqual(int(result['consume']), 0) def test_status_method_contains_consume_is_1(self): - self.core.playback.consume = 1 + self.core.tracklist.consume = 1 result = dict(status.status(self.context)) self.assertIn('consume', result) self.assertEqual(int(result['consume']), 1) diff --git a/tests/utils/jsonrpc_test.py b/tests/utils/jsonrpc_test.py index 5dccbe05..c6f516bb 100644 --- a/tests/utils/jsonrpc_test.py +++ b/tests/utils/jsonrpc_test.py @@ -34,6 +34,9 @@ class Calculator(object): def _secret(self): return 'Grand Unified Theory' + def fail(self): + raise ValueError('What did you expect?') + class JsonRpcTestBase(unittest.TestCase): def setUp(self): @@ -266,12 +269,12 @@ class JsonRpcSingleNotificationTest(JsonRpcTestBase): class JsonRpcBatchTest(JsonRpcTestBase): def test_batch_of_only_commands_returns_all(self): - self.core.playback.set_random(True).get() + self.core.tracklist.set_random(True).get() request = [ - {'jsonrpc': '2.0', 'method': 'core.playback.get_repeat', 'id': 1}, - {'jsonrpc': '2.0', 'method': 'core.playback.get_random', 'id': 2}, - {'jsonrpc': '2.0', 'method': 'core.playback.get_single', 'id': 3}, + {'jsonrpc': '2.0', 'method': 'core.tracklist.get_repeat', 'id': 1}, + {'jsonrpc': '2.0', 'method': 'core.tracklist.get_random', 'id': 2}, + {'jsonrpc': '2.0', 'method': 'core.tracklist.get_single', 'id': 3}, ] response = self.jrw.handle_data(request) @@ -283,12 +286,12 @@ class JsonRpcBatchTest(JsonRpcTestBase): self.assertEqual(response[3]['result'], False) def test_batch_of_commands_and_notifications_returns_some(self): - self.core.playback.set_random(True).get() + self.core.tracklist.set_random(True).get() request = [ - {'jsonrpc': '2.0', 'method': 'core.playback.get_repeat'}, - {'jsonrpc': '2.0', 'method': 'core.playback.get_random', 'id': 2}, - {'jsonrpc': '2.0', 'method': 'core.playback.get_single', 'id': 3}, + {'jsonrpc': '2.0', 'method': 'core.tracklist.get_repeat'}, + {'jsonrpc': '2.0', 'method': 'core.tracklist.get_random', 'id': 2}, + {'jsonrpc': '2.0', 'method': 'core.tracklist.get_single', 'id': 3}, ] response = self.jrw.handle_data(request) @@ -300,12 +303,12 @@ class JsonRpcBatchTest(JsonRpcTestBase): self.assertEqual(response[3]['result'], False) def test_batch_of_only_notifications_returns_nothing(self): - self.core.playback.set_random(True).get() + self.core.tracklist.set_random(True).get() request = [ - {'jsonrpc': '2.0', 'method': 'core.playback.get_repeat'}, - {'jsonrpc': '2.0', 'method': 'core.playback.get_random'}, - {'jsonrpc': '2.0', 'method': 'core.playback.get_single'}, + {'jsonrpc': '2.0', 'method': 'core.tracklist.get_repeat'}, + {'jsonrpc': '2.0', 'method': 'core.tracklist.get_random'}, + {'jsonrpc': '2.0', 'method': 'core.tracklist.get_single'}, ] response = self.jrw.handle_data(request) @@ -316,8 +319,8 @@ class JsonRpcSingleCommandErrorTest(JsonRpcTestBase): def test_application_error_response(self): request = { 'jsonrpc': '2.0', - 'method': 'core.tracklist.index', - 'params': ['bogus'], + 'method': 'calc.fail', + 'params': [], 'id': 1, } response = self.jrw.handle_data(request) @@ -330,7 +333,7 @@ class JsonRpcSingleCommandErrorTest(JsonRpcTestBase): data = error['data'] self.assertEqual(data['type'], 'ValueError') - self.assertIn('not in list', data['message']) + self.assertIn('What did you expect?', data['message']) self.assertIn('traceback', data) self.assertIn('Traceback (most recent call last):', data['traceback']) @@ -522,10 +525,10 @@ class JsonRpcBatchErrorTest(JsonRpcTestBase): {'jsonrpc': '2.0', 'method': 'core.playback.set_volume', 'params': [47], 'id': '1'}, # Notification - {'jsonrpc': '2.0', 'method': 'core.playback.set_consume', + {'jsonrpc': '2.0', 'method': 'core.tracklist.set_consume', 'params': [True]}, # Call with positional params - {'jsonrpc': '2.0', 'method': 'core.playback.set_repeat', + {'jsonrpc': '2.0', 'method': 'core.tracklist.set_repeat', 'params': [False], 'id': '2'}, # Invalid request {'foo': 'boo'}, @@ -533,7 +536,7 @@ class JsonRpcBatchErrorTest(JsonRpcTestBase): {'jsonrpc': '2.0', 'method': 'foo.get', 'params': {'name': 'myself'}, 'id': '5'}, # Call without params - {'jsonrpc': '2.0', 'method': 'core.playback.get_random', + {'jsonrpc': '2.0', 'method': 'core.tracklist.get_random', 'id': '9'}, ] response = self.jrw.handle_data(request)