From 704b5517e12e4b48321944ebabd6331d8c012ff4 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Tue, 26 Oct 2010 13:25:52 +0200 Subject: [PATCH 01/22] Split xPlaybackController into xPlaybackController and xPlaybackProvider --- mopidy/backends/base/__init__.py | 3 +- mopidy/backends/base/playback.py | 126 ++++++++++++++----------- mopidy/backends/dummy/__init__.py | 53 ++++++----- mopidy/backends/libspotify/__init__.py | 14 ++- mopidy/backends/libspotify/playback.py | 18 ++-- mopidy/backends/local/__init__.py | 67 +++++++------ tests/backends/base/playback.py | 16 ++-- 7 files changed, 165 insertions(+), 132 deletions(-) diff --git a/mopidy/backends/base/__init__.py b/mopidy/backends/base/__init__.py index 491c5b73..f42a042c 100644 --- a/mopidy/backends/base/__init__.py +++ b/mopidy/backends/base/__init__.py @@ -6,7 +6,8 @@ import time from mopidy import settings from mopidy.backends.base.current_playlist import BaseCurrentPlaylistController from mopidy.backends.base.library import BaseLibraryController -from mopidy.backends.base.playback import BasePlaybackController +from mopidy.backends.base.playback import (BasePlaybackController, + BasePlaybackProvider) from mopidy.backends.base.stored_playlists import BaseStoredPlaylistsController from mopidy.frontends.mpd import translator from mopidy.models import Playlist diff --git a/mopidy/backends/base/playback.py b/mopidy/backends/base/playback.py index b7ceeee2..0d4ef52f 100644 --- a/mopidy/backends/base/playback.py +++ b/mopidy/backends/base/playback.py @@ -6,8 +6,10 @@ logger = logging.getLogger('mopidy.backends.base') class BasePlaybackController(object): """ - :param backend: backend the controller is a part of + :param backend: the backend :type backend: :class:`BaseBackend` + :param provider: provider the controller should use + :type provider: instance of :class:`BasePlaybackProvider` """ # pylint: disable = R0902 @@ -54,8 +56,9 @@ class BasePlaybackController(object): #: Playback continues after current song. single = False - def __init__(self, backend): + def __init__(self, backend, provider): self.backend = backend + self.provider = provider self._state = self.STOPPED self._shuffled = [] self._first_shuffle = True @@ -353,18 +356,9 @@ class BasePlaybackController(object): def pause(self): """Pause playback.""" - if self.state == self.PLAYING and self._pause(): + if self.state == self.PLAYING and self.provider.pause(): self.state = self.PAUSED - def _pause(self): - """ - To be overridden by subclass. Implement your backend's pause - functionality here. - - :rtype: :class:`True` if successful, else :class:`False` - """ - raise NotImplementedError - def play(self, cp_track=None, on_error_step=1): """ Play the given track, or if the given track is :class:`None`, play the @@ -391,7 +385,7 @@ class BasePlaybackController(object): self.state = self.STOPPED self.current_cp_track = cp_track self.state = self.PLAYING - if not self._play(cp_track[1]): + if not self.provider.play(cp_track[1]): # Track is not playable if self.random and self._shuffled: self._shuffled.remove(cp_track) @@ -405,18 +399,6 @@ class BasePlaybackController(object): self._trigger_started_playing_event() - def _play(self, track): - """ - To be overridden by subclass. Implement your backend's play - functionality here. - - :param track: the track to play - :type track: :class:`mopidy.models.Track` - :rtype: :class:`True` if successful, else :class:`False` - """ - - raise NotImplementedError - def previous(self): """Play the previous track.""" if self.cp_track_at_previous is None: @@ -428,18 +410,9 @@ class BasePlaybackController(object): def resume(self): """If paused, resume playing the current track.""" - if self.state == self.PAUSED and self._resume(): + if self.state == self.PAUSED and self.provider.resume(): self.state = self.PLAYING - def _resume(self): - """ - To be overridden by subclass. Implement your backend's resume - functionality here. - - :rtype: :class:`True` if successful, else :class:`False` - """ - raise NotImplementedError - def seek(self, time_position): """ Seeks to time position given in milliseconds. @@ -465,18 +438,7 @@ class BasePlaybackController(object): self._play_time_started = self._current_wall_time self._play_time_accumulated = time_position - return self._seek(time_position) - - def _seek(self, time_position): - """ - To be overridden by subclass. Implement your backend's seek - functionality here. - - :param time_position: time position in milliseconds - :type time_position: int - :rtype: :class:`True` if successful, else :class:`False` - """ - raise NotImplementedError + return self.provider.seek(time_position) def stop(self, clear_current_track=False): """ @@ -489,20 +451,11 @@ class BasePlaybackController(object): if self.state == self.STOPPED: return self._trigger_stopped_playing_event() - if self._stop(): + if self.provider.stop(): self.state = self.STOPPED if clear_current_track: self.current_cp_track = None - def _stop(self): - """ - To be overridden by subclass. Implement your backend's stop - functionality here. - - :rtype: :class:`True` if successful, else :class:`False` - """ - raise NotImplementedError - def _trigger_started_playing_event(self): """ Notifies frontends that a track has started playing. @@ -532,3 +485,62 @@ class BasePlaybackController(object): 'track': self.current_track, 'stop_position': self.time_position, }) + + +class BasePlaybackProvider(object): + """ + :param backend: the backend + :type backend: :class:`BaseBackend` + """ + + def __init__(self, backend): + self.backend = backend + + def pause(self): + """ + To be overridden by subclass. Implement your backend's pause + functionality here. + + :rtype: :class:`True` if successful, else :class:`False` + """ + raise NotImplementedError + + def play(self, track): + """ + To be overridden by subclass. Implement your backend's play + functionality here. + + :param track: the track to play + :type track: :class:`mopidy.models.Track` + :rtype: :class:`True` if successful, else :class:`False` + """ + raise NotImplementedError + + def resume(self): + """ + To be overridden by subclass. Implement your backend's resume + functionality here. + + :rtype: :class:`True` if successful, else :class:`False` + """ + raise NotImplementedError + + def seek(self, time_position): + """ + To be overridden by subclass. Implement your backend's seek + functionality here. + + :param time_position: time position in milliseconds + :type time_position: int + :rtype: :class:`True` if successful, else :class:`False` + """ + raise NotImplementedError + + def stop(self): + """ + To be overridden by subclass. Implement your backend's stop + functionality here. + + :rtype: :class:`True` if successful, else :class:`False` + """ + raise NotImplementedError diff --git a/mopidy/backends/dummy/__init__.py b/mopidy/backends/dummy/__init__.py index 62cbd7e2..7a2788b7 100644 --- a/mopidy/backends/dummy/__init__.py +++ b/mopidy/backends/dummy/__init__.py @@ -1,5 +1,5 @@ from mopidy.backends.base import (BaseBackend, BaseCurrentPlaylistController, - BasePlaybackController, BaseLibraryController, + BasePlaybackController, BasePlaybackProvider, BaseLibraryController, BaseStoredPlaylistsController) from mopidy.models import Playlist @@ -13,10 +13,17 @@ class DummyBackend(BaseBackend): def __init__(self, *args, **kwargs): super(DummyBackend, self).__init__(*args, **kwargs) + self.current_playlist = DummyCurrentPlaylistController(backend=self) + self.library = DummyLibraryController(backend=self) - self.playback = DummyPlaybackController(backend=self) + + playback_provider = DummyPlaybackProvider(backend=self) + self.playback = DummyPlaybackController(backend=self, + provider=playback_provider) + self.stored_playlists = DummyStoredPlaylistsController(backend=self) + self.uri_handlers = [u'dummy:'] @@ -43,30 +50,6 @@ class DummyLibraryController(BaseLibraryController): class DummyPlaybackController(BasePlaybackController): - def _next(self, track): - """Pass None as track to force failure""" - return track is not None - - def _pause(self): - return True - - def _play(self, track): - """Pass None as track to force failure""" - return track is not None - - def _previous(self, track): - """Pass None as track to force failure""" - return track is not None - - def _resume(self): - return True - - def _seek(self, time_position): - return True - - def _stop(self): - return True - def _trigger_started_playing_event(self): pass # noop @@ -74,6 +57,24 @@ class DummyPlaybackController(BasePlaybackController): pass # noop +class DummyPlaybackProvider(BasePlaybackProvider): + def pause(self): + return True + + def play(self, track): + """Pass None as track to force failure""" + return track is not None + + def resume(self): + return True + + def seek(self, time_position): + return True + + def stop(self): + return True + + class DummyStoredPlaylistsController(BaseStoredPlaylistsController): _playlists = [] diff --git a/mopidy/backends/libspotify/__init__.py b/mopidy/backends/libspotify/__init__.py index 223d9968..c067cb67 100644 --- a/mopidy/backends/libspotify/__init__.py +++ b/mopidy/backends/libspotify/__init__.py @@ -1,7 +1,8 @@ import logging from mopidy import settings -from mopidy.backends.base import BaseBackend, BaseCurrentPlaylistController +from mopidy.backends.base import (BaseBackend, BaseCurrentPlaylistController, + BasePlaybackController) logger = logging.getLogger('mopidy.backends.libspotify') @@ -34,17 +35,24 @@ class LibspotifyBackend(BaseBackend): def __init__(self, *args, **kwargs): from .library import LibspotifyLibraryController - from .playback import LibspotifyPlaybackController + from .playback import LibspotifyPlaybackProvider from .stored_playlists import LibspotifyStoredPlaylistsController super(LibspotifyBackend, self).__init__(*args, **kwargs) self.current_playlist = BaseCurrentPlaylistController(backend=self) + self.library = LibspotifyLibraryController(backend=self) - self.playback = LibspotifyPlaybackController(backend=self) + + playback_provider = LibspotifyPlaybackProvider(backend=self) + self.playback = BasePlaybackController(backend=self, + provider=playback_provider) + self.stored_playlists = LibspotifyStoredPlaylistsController( backend=self) + self.uri_handlers = [u'spotify:', u'http://open.spotify.com/'] + self.spotify = self._connect() def _connect(self): diff --git a/mopidy/backends/libspotify/playback.py b/mopidy/backends/libspotify/playback.py index 39c56bf6..29409ff4 100644 --- a/mopidy/backends/libspotify/playback.py +++ b/mopidy/backends/libspotify/playback.py @@ -2,17 +2,17 @@ import logging from spotify import Link, SpotifyError -from mopidy.backends.base import BasePlaybackController +from mopidy.backends.base import BasePlaybackProvider logger = logging.getLogger('mopidy.backends.libspotify.playback') -class LibspotifyPlaybackController(BasePlaybackController): - def _pause(self): +class LibspotifyPlaybackProvider(BasePlaybackProvider): + def pause(self): return self.backend.output.set_state('PAUSED') - def _play(self, track): + def play(self, track): self.backend.output.set_state('READY') - if self.state == self.PLAYING: + if self.backend.playback.state == self.backend.playback.PLAYING: self.backend.spotify.session.play(0) if track.uri is None: return False @@ -26,16 +26,16 @@ class LibspotifyPlaybackController(BasePlaybackController): logger.warning('Play %s failed: %s', track.uri, e) return False - def _resume(self): - return self._seek(self.time_position) + def resume(self): + return self.seek(self.backend.playback.time_position) - def _seek(self, time_position): + def seek(self, time_position): self.backend.output.set_state('READY') self.backend.spotify.session.seek(time_position) self.backend.output.set_state('PLAYING') return True - def _stop(self): + def stop(self): result = self.backend.output.set_state('READY') self.backend.spotify.session.play(0) return result diff --git a/mopidy/backends/local/__init__.py b/mopidy/backends/local/__init__.py index 04761e17..4ad8947b 100644 --- a/mopidy/backends/local/__init__.py +++ b/mopidy/backends/local/__init__.py @@ -5,9 +5,10 @@ import os import shutil from mopidy import settings -from mopidy.backends.base import (BaseBackend, BaseLibraryController, - BaseStoredPlaylistsController, BaseCurrentPlaylistController, - BasePlaybackController) +from mopidy.backends.base import (BaseBackend, + BaseCurrentPlaylistController, BaseLibraryController, + BasePlaybackController, BasePlaybackProvider, + BaseStoredPlaylistsController) from mopidy.models import Playlist, Track, Album from mopidy.utils.process import pickle_connection @@ -31,41 +32,51 @@ class LocalBackend(BaseBackend): def __init__(self, *args, **kwargs): super(LocalBackend, self).__init__(*args, **kwargs) - self.library = LocalLibraryController(self) - self.stored_playlists = LocalStoredPlaylistsController(self) - self.current_playlist = BaseCurrentPlaylistController(self) - self.playback = LocalPlaybackController(self) + self.library = LocalLibraryController(backend=self) + + self.stored_playlists = LocalStoredPlaylistsController(backend=self) + + self.current_playlist = BaseCurrentPlaylistController(backend=self) + + playback_provider = LocalPlaybackProvider(backend=self) + self.playback = LocalPlaybackController(backend=self, + provider=playback_provider) + self.uri_handlers = [u'file://'] class LocalPlaybackController(BasePlaybackController): - def __init__(self, backend): - super(LocalPlaybackController, self).__init__(backend) + def __init__(self, *args, **kwargs): + super(LocalPlaybackController, self).__init__(*args, **kwargs) + + # XXX Why do we call stop()? Is it to set GStreamer state to 'READY'? self.stop() - def _play(self, track): - return self.backend.output.play_uri(track.uri) - - def _stop(self): - return self.backend.output.set_state('READY') - - def _pause(self): - return self.backend.output.set_state('PAUSED') - - def _resume(self): - return self.backend.output.set_state('PLAYING') - - def _seek(self, time_position): - return self.backend.output.set_position(time_position) - @property def time_position(self): return self.backend.output.get_position() +class LocalPlaybackProvider(BasePlaybackProvider): + def pause(self): + return self.backend.output.set_state('PAUSED') + + def play(self, track): + return self.backend.output.play_uri(track.uri) + + def resume(self): + return self.backend.output.set_state('PLAYING') + + def seek(self, time_position): + return self.backend.output.set_position(time_position) + + def stop(self): + return self.backend.output.set_state('READY') + + class LocalStoredPlaylistsController(BaseStoredPlaylistsController): - def __init__(self, *args): - super(LocalStoredPlaylistsController, self).__init__(*args) + def __init__(self, *args, **kwargs): + super(LocalStoredPlaylistsController, self).__init__(*args, **kwargs) self._folder = os.path.expanduser(settings.LOCAL_PLAYLIST_FOLDER) self.refresh() @@ -137,8 +148,8 @@ class LocalStoredPlaylistsController(BaseStoredPlaylistsController): class LocalLibraryController(BaseLibraryController): - def __init__(self, backend): - super(LocalLibraryController, self).__init__(backend) + def __init__(self, *args, **kwargs): + super(LocalLibraryController, self).__init__(*args, **kwargs) self._uri_mapping = {} self.refresh() diff --git a/tests/backends/base/playback.py b/tests/backends/base/playback.py index 4caaf44b..7b6efe7a 100644 --- a/tests/backends/base/playback.py +++ b/tests/backends/base/playback.py @@ -104,8 +104,8 @@ class BasePlaybackControllerTest(object): @populate_playlist def test_play_skips_to_next_track_on_failure(self): - # If _play() returns False, it is a failure. - self.playback._play = lambda track: track != self.tracks[0] + # If provider.play() returns False, it is a failure. + self.playback.provider.play = lambda track: track != self.tracks[0] self.playback.play() self.assertNotEqual(self.playback.current_track, self.tracks[0]) self.assertEqual(self.playback.current_track, self.tracks[1]) @@ -164,8 +164,8 @@ class BasePlaybackControllerTest(object): @populate_playlist def test_previous_skips_to_previous_track_on_failure(self): - # If _play() returns False, it is a failure. - self.playback._play = lambda track: track != self.tracks[1] + # If provider.play() returns False, it is a failure. + self.playback.provider.play = lambda track: track != self.tracks[1] self.playback.play(self.current_playlist.cp_tracks[2]) self.assertEqual(self.playback.current_track, self.tracks[2]) self.playback.previous() @@ -228,8 +228,8 @@ class BasePlaybackControllerTest(object): @populate_playlist def test_next_skips_to_next_track_on_failure(self): - # If _play() returns False, it is a failure. - self.playback._play = lambda track: track != self.tracks[1] + # If provider.play() returns False, it is a failure. + self.playback.provider.play = lambda track: track != self.tracks[1] self.playback.play() self.assertEqual(self.playback.current_track, self.tracks[0]) self.playback.next() @@ -364,8 +364,8 @@ class BasePlaybackControllerTest(object): @populate_playlist def test_end_of_track_skips_to_next_track_on_failure(self): - # If _play() returns False, it is a failure. - self.playback._play = lambda track: track != self.tracks[1] + # If provider.play() returns False, it is a failure. + self.playback.provider.play = lambda track: track != self.tracks[1] self.playback.play() self.assertEqual(self.playback.current_track, self.tracks[0]) self.playback.on_end_of_track() From 726b62887cb494b52802d31797acc6a23f3ca9cc Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Tue, 26 Oct 2010 13:59:27 +0200 Subject: [PATCH 02/22] Add BasePlaybackProvider to __all__ --- mopidy/backends/base/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mopidy/backends/base/__init__.py b/mopidy/backends/base/__init__.py index f42a042c..eb75467c 100644 --- a/mopidy/backends/base/__init__.py +++ b/mopidy/backends/base/__init__.py @@ -15,7 +15,7 @@ from mopidy.utils import get_class logger = logging.getLogger('mopidy.backends.base') -__all__ = ['BaseBackend', 'BasePlaybackController', +__all__ = ['BaseBackend', 'BasePlaybackController', 'BasePlaybackProvider', 'BaseCurrentPlaylistController', 'BaseStoredPlaylistsController', 'BaseLibraryController'] From 545ad9486cbcd486ae2227b8e0355ccb6080f206 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Sun, 31 Oct 2010 15:56:22 +0100 Subject: [PATCH 03/22] docs: Add local paths to the start and not end of PYTHONPATH --- docs/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index d0d8f3af..16a85975 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -16,8 +16,8 @@ import sys, os # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -sys.path.append(os.path.abspath(os.path.dirname(__file__))) -sys.path.append(os.path.abspath(os.path.dirname(__file__) + '/../')) +sys.path.insert(0, os.path.abspath(os.path.dirname(__file__))) +sys.path.insert(0, os.path.abspath(os.path.dirname(__file__) + '/../')) import mopidy From acda478ed3c0781301b3502c9a84b68c7b999d13 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Sun, 31 Oct 2010 23:23:40 +0100 Subject: [PATCH 04/22] docs: Start splitting controllers into controllers and providers --- docs/api/backends.rst | 62 +++++++++++++++++++++++++++++++++---------- 1 file changed, 48 insertions(+), 14 deletions(-) diff --git a/docs/api/backends.rst b/docs/api/backends.rst index c8a72b4d..92334ab8 100644 --- a/docs/api/backends.rst +++ b/docs/api/backends.rst @@ -6,29 +6,43 @@ :synopsis: Backend API -The backend and its controllers -=============================== +The backend, controller, and provider concepts +============================================== -.. graph:: backend_relations +Backend: + The backend is mostly for convenience. It is a container that holds + references to all the controllers. +Controllers: + Each controller has responsibility for a given part of the backend + functionality. Most, but not all, controllers delegates some work to one or + more providers. The controllers are responsible for choosing the right + provider for any given task based upon i.e. the track's URI. +Providers: + Anything specific to i.e. Spotify integration or local storage is contained + in the providers. To integrate with new music sources, you just add new + providers. - backend -- current_playlist - backend -- library - backend -- playback - backend -- stored_playlists +.. digraph:: backend_relations + Backend -> "Current\nplaylist\ncontroller" + Backend -> "Library\ncontroller" + "Library\ncontroller" -> "Library\nproviders" + Backend -> "Playback\ncontroller" + "Playback\ncontroller" -> "Playback\nproviders" + Backend -> "Stored\nplaylists\ncontroller" + "Stored\nplaylists\ncontroller" -> "Stored\nplaylist\nproviders" + Backend -> Mixer + +.. _backend-api: Backend API =========== .. note:: - Currently this only documents the API that is available for use by - frontends like :mod:`mopidy.frontends.mpd`, and not what is required to - implement your own backend. :class:`mopidy.backends.base.BaseBackend` and - its controllers implements many of these methods in a matter that should be - independent of most concrete backend implementations, so you should - generally just implement or override a few of these methods yourself to - create a new backend with a complete feature set. + The backend API is the interface that is used by frontends like + :mod:`mopidy.frontends.mpd`. If you want to implement your own backend, see + the :ref:`provider-api`. .. autoclass:: mopidy.backends.base.BaseBackend :members: @@ -82,6 +96,26 @@ Manages the music library, e.g. searching for tracks to be added to a playlist. :undoc-members: +.. _provider-api: + +Provider API +============ + +.. note:: + + The provider API is the interface that must be implemented when you create + a backend. If you are working on a frontend and need to access the backend, + see the :ref:`backend-api`. + + +Playback provider +----------------- + +.. autoclass:: mopidy.backends.base.BasePlaybackProvider + :members: + :undoc-members: + + Backend implementations ======================= From a9e53e06172571eb2a2bb6762430e433794d6b39 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Mon, 1 Nov 2010 22:00:13 +0100 Subject: [PATCH 05/22] docs: Rename 'backend api' to 'backend controller api', and 'provider api' to 'backend provider api' --- docs/api/backends.rst | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/api/backends.rst b/docs/api/backends.rst index 92334ab8..de1957e8 100644 --- a/docs/api/backends.rst +++ b/docs/api/backends.rst @@ -3,7 +3,7 @@ ********************** .. automodule:: mopidy.backends - :synopsis: Backend API + :synopsis: Backend APIs The backend, controller, and provider concepts @@ -33,16 +33,16 @@ Providers: "Stored\nplaylists\ncontroller" -> "Stored\nplaylist\nproviders" Backend -> Mixer -.. _backend-api: +.. _backend-controller-api: -Backend API -=========== +Backend controller API +====================== .. note:: - The backend API is the interface that is used by frontends like + The backend controller API is the interface that is used by frontends like :mod:`mopidy.frontends.mpd`. If you want to implement your own backend, see - the :ref:`provider-api`. + the :ref:`backend-provider-api`. .. autoclass:: mopidy.backends.base.BaseBackend :members: @@ -96,16 +96,16 @@ Manages the music library, e.g. searching for tracks to be added to a playlist. :undoc-members: -.. _provider-api: +.. _backend-provider-api: -Provider API -============ +Backend provider API +==================== .. note:: - The provider API is the interface that must be implemented when you create - a backend. If you are working on a frontend and need to access the backend, - see the :ref:`backend-api`. + The backend provider API is the interface that must be implemented when you + create a backend. If you are working on a frontend and need to access the + backend, see the :ref:`backend-controller-api`. Playback provider From beeda047858d0287912f2c8cfff76d1e7fbedd7b Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Mon, 1 Nov 2010 22:52:56 +0100 Subject: [PATCH 06/22] Add destroy() to playback provider API --- mopidy/backends/base/playback.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/mopidy/backends/base/playback.py b/mopidy/backends/base/playback.py index 0d4ef52f..8b935c65 100644 --- a/mopidy/backends/base/playback.py +++ b/mopidy/backends/base/playback.py @@ -68,10 +68,8 @@ class BasePlaybackController(object): def destroy(self): """ Cleanup after component. - - May be overridden by subclasses. """ - pass + self.provider.destroy() def _get_cpid(self, cp_track): if cp_track is None: @@ -496,6 +494,14 @@ class BasePlaybackProvider(object): def __init__(self, backend): self.backend = backend + def destroy(self): + """ + Cleanup after component. + + May be overridden by subclasses. + """ + pass + def pause(self): """ To be overridden by subclass. Implement your backend's pause From f486bf512d6ddc81790cf359357597e9e9a92aad Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Mon, 1 Nov 2010 23:19:32 +0100 Subject: [PATCH 07/22] Split BaseStoredPlaylistsController in controller and provider --- docs/api/backends.rst | 12 +- mopidy/backends/base/__init__.py | 11 +- mopidy/backends/base/stored_playlists.py | 119 +++++++++++++++--- mopidy/backends/dummy/__init__.py | 10 +- mopidy/backends/libspotify/__init__.py | 8 +- .../backends/libspotify/stored_playlists.py | 4 +- mopidy/backends/local/__init__.py | 10 +- 7 files changed, 139 insertions(+), 35 deletions(-) diff --git a/docs/api/backends.rst b/docs/api/backends.rst index de1957e8..617bcb94 100644 --- a/docs/api/backends.rst +++ b/docs/api/backends.rst @@ -116,8 +116,16 @@ Playback provider :undoc-members: -Backend implementations -======================= +Stored playlists provider +------------------------- + +.. autoclass:: mopidy.backends.base.BaseStoredPlaylistsProvider + :members: + :undoc-members: + + +Backend provider implementations +================================ * :mod:`mopidy.backends.dummy` * :mod:`mopidy.backends.libspotify` diff --git a/mopidy/backends/base/__init__.py b/mopidy/backends/base/__init__.py index eb75467c..7ee86015 100644 --- a/mopidy/backends/base/__init__.py +++ b/mopidy/backends/base/__init__.py @@ -4,15 +4,16 @@ import random import time from mopidy import settings -from mopidy.backends.base.current_playlist import BaseCurrentPlaylistController -from mopidy.backends.base.library import BaseLibraryController -from mopidy.backends.base.playback import (BasePlaybackController, - BasePlaybackProvider) -from mopidy.backends.base.stored_playlists import BaseStoredPlaylistsController from mopidy.frontends.mpd import translator from mopidy.models import Playlist from mopidy.utils import get_class +from .current_playlist import BaseCurrentPlaylistController +from .library import BaseLibraryController +from .playback import BasePlaybackController, BasePlaybackProvider +from .stored_playlists import (BaseStoredPlaylistsController, + BaseStoredPlaylistsProvider) + logger = logging.getLogger('mopidy.backends.base') __all__ = ['BaseBackend', 'BasePlaybackController', 'BasePlaybackProvider', diff --git a/mopidy/backends/base/stored_playlists.py b/mopidy/backends/base/stored_playlists.py index 61722c81..cf14db9d 100644 --- a/mopidy/backends/base/stored_playlists.py +++ b/mopidy/backends/base/stored_playlists.py @@ -7,24 +7,30 @@ class BaseStoredPlaylistsController(object): """ :param backend: backend the controller is a part of :type backend: :class:`BaseBackend` + :param provider: provider the controller should use + :type provider: instance of :class:`BaseStoredPlaylistsProvider` """ - def __init__(self, backend): + def __init__(self, backend, provider): self.backend = backend - self._playlists = [] + self.provider = provider def destroy(self): """Cleanup after component.""" - pass + self.provider.destroy() @property def playlists(self): - """List of :class:`mopidy.models.Playlist`.""" - return copy(self._playlists) + """ + Currently stored playlists. + + Read/write. List of :class:`mopidy.models.Playlist`. + """ + return self.provider.playlists @playlists.setter def playlists(self, playlists): - self._playlists = playlists + self.provider.playlists = playlists def create(self, name): """ @@ -34,7 +40,7 @@ class BaseStoredPlaylistsController(object): :type name: string :rtype: :class:`mopidy.models.Playlist` """ - raise NotImplementedError + return self.provider.create(name) def delete(self, playlist): """ @@ -43,7 +49,7 @@ class BaseStoredPlaylistsController(object): :param playlist: the playlist to delete :type playlist: :class:`mopidy.models.Playlist` """ - raise NotImplementedError + return self.provider.delete(playlist) def get(self, **criteria): """ @@ -55,13 +61,14 @@ class BaseStoredPlaylistsController(object): get(name='a') # Returns track with name 'a' get(uri='xyz') # Returns track with URI 'xyz' - get(name='a', uri='xyz') # Returns track with name 'a' and URI 'xyz' + get(name='a', uri='xyz') # Returns track with name 'a' and URI + # 'xyz' :param criteria: one or more criteria to match by :type criteria: dict :rtype: :class:`mopidy.models.Playlist` """ - matches = self._playlists + matches = self.playlists for (key, value) in criteria.iteritems(): matches = filter(lambda p: getattr(p, key) == value, matches) if len(matches) == 1: @@ -82,11 +89,14 @@ class BaseStoredPlaylistsController(object): :type uri: string :rtype: :class:`mopidy.models.Playlist` """ - raise NotImplementedError + return self.provider.lookup(uri) def refresh(self): - """Refresh stored playlists.""" - raise NotImplementedError + """ + Refresh the stored playlists in + :attr:`mopidy.backends.base.BaseStoredPlaylistsController.playlists`. + """ + return self.provider.refresh(uri) def rename(self, playlist, new_name): """ @@ -97,7 +107,7 @@ class BaseStoredPlaylistsController(object): :param new_name: the new name :type new_name: string """ - raise NotImplementedError + return self.provider.rename(playlist, new_name) def save(self, playlist): """ @@ -106,4 +116,85 @@ class BaseStoredPlaylistsController(object): :param playlist: the playlist :type playlist: :class:`mopidy.models.Playlist` """ + return self.provider.save(playlist) + + +class BaseStoredPlaylistsProvider(object): + """ + :param backend: backend the controller is a part of + :type backend: :class:`BaseBackend` + """ + + def __init__(self, backend): + self.backend = backend + self._playlists = [] + + def destroy(self): + """ + Cleanup after component. + + May be overridden by subclasses. + """ + pass + + @property + def playlists(self): + """ + Currently stored playlists. + + Read/write. List of :class:`mopidy.models.Playlist`. + """ + return copy(self._playlists) + + @playlists.setter + def playlists(self, playlists): + self._playlists = playlists + + def create(self, name): + """ + To be overridden by subclass. + + See :meth:`mopidy.backends.base.BaseStoredPlaylistsController.create`. + """ raise NotImplementedError + + def delete(self, playlist): + """ + To be overridden by subclass. + + See :meth:`mopidy.backends.base.BaseStoredPlaylistsController.delete`. + """ + raise NotImplementedError + + def lookup(self, uri): + """ + To be overridden by subclass. + + See :meth:`mopidy.backends.base.BaseStoredPlaylistsController.lookup`. + """ + raise NotImplementedError + + def refresh(self): + """ + To be overridden by subclass. + + See :meth:`mopidy.backends.base.BaseStoredPlaylistsController.refresh`. + """ + raise NotImplementedError + + def rename(self, playlist, new_name): + """ + To be overridden by subclass. + + See :meth:`mopidy.backends.base.BaseStoredPlaylistsController.rename`. + """ + raise NotImplementedError + + def save(self, playlist): + """ + To be overridden by subclass. + + See :meth:`mopidy.backends.base.BaseStoredPlaylistsController.save`. + """ + raise NotImplementedError + diff --git a/mopidy/backends/dummy/__init__.py b/mopidy/backends/dummy/__init__.py index 7a2788b7..3b94452b 100644 --- a/mopidy/backends/dummy/__init__.py +++ b/mopidy/backends/dummy/__init__.py @@ -1,6 +1,6 @@ from mopidy.backends.base import (BaseBackend, BaseCurrentPlaylistController, BasePlaybackController, BasePlaybackProvider, BaseLibraryController, - BaseStoredPlaylistsController) + BaseStoredPlaylistsController, BaseStoredPlaylistsProvider) from mopidy.models import Playlist class DummyBackend(BaseBackend): @@ -22,7 +22,9 @@ class DummyBackend(BaseBackend): self.playback = DummyPlaybackController(backend=self, provider=playback_provider) - self.stored_playlists = DummyStoredPlaylistsController(backend=self) + stored_playlists_provider = DummyStoredPlaylistsProvider(backend=self) + self.stored_playlists = BaseStoredPlaylistsController(backend=self, + provider=stored_playlists_provider) self.uri_handlers = [u'dummy:'] @@ -75,9 +77,7 @@ class DummyPlaybackProvider(BasePlaybackProvider): return True -class DummyStoredPlaylistsController(BaseStoredPlaylistsController): - _playlists = [] - +class DummyStoredPlaylistsProvider(BaseStoredPlaylistsProvider): def create(self, name): playlist = Playlist(name=name) self._playlists.append(playlist) diff --git a/mopidy/backends/libspotify/__init__.py b/mopidy/backends/libspotify/__init__.py index c067cb67..dbbd4804 100644 --- a/mopidy/backends/libspotify/__init__.py +++ b/mopidy/backends/libspotify/__init__.py @@ -2,7 +2,7 @@ import logging from mopidy import settings from mopidy.backends.base import (BaseBackend, BaseCurrentPlaylistController, - BasePlaybackController) + BasePlaybackController, BaseStoredPlaylistsController) logger = logging.getLogger('mopidy.backends.libspotify') @@ -36,7 +36,7 @@ class LibspotifyBackend(BaseBackend): def __init__(self, *args, **kwargs): from .library import LibspotifyLibraryController from .playback import LibspotifyPlaybackProvider - from .stored_playlists import LibspotifyStoredPlaylistsController + from .stored_playlists import LibspotifyStoredPlaylistsProvider super(LibspotifyBackend, self).__init__(*args, **kwargs) @@ -48,8 +48,10 @@ class LibspotifyBackend(BaseBackend): self.playback = BasePlaybackController(backend=self, provider=playback_provider) - self.stored_playlists = LibspotifyStoredPlaylistsController( + stored_playlists_provider = LibspotifyStoredPlaylistsProvider( backend=self) + self.stored_playlists = BaseStoredPlaylistsController(backend=self, + provider=stored_playlists_provider) self.uri_handlers = [u'spotify:', u'http://open.spotify.com/'] diff --git a/mopidy/backends/libspotify/stored_playlists.py b/mopidy/backends/libspotify/stored_playlists.py index 3339578c..6f2a7aad 100644 --- a/mopidy/backends/libspotify/stored_playlists.py +++ b/mopidy/backends/libspotify/stored_playlists.py @@ -1,6 +1,6 @@ -from mopidy.backends.base import BaseStoredPlaylistsController +from mopidy.backends.base import BaseStoredPlaylistsProvider -class LibspotifyStoredPlaylistsController(BaseStoredPlaylistsController): +class LibspotifyStoredPlaylistsProvider(BaseStoredPlaylistsProvider): def create(self, name): pass # TODO diff --git a/mopidy/backends/local/__init__.py b/mopidy/backends/local/__init__.py index 9796414d..b2c36b72 100644 --- a/mopidy/backends/local/__init__.py +++ b/mopidy/backends/local/__init__.py @@ -8,7 +8,7 @@ from mopidy import settings from mopidy.backends.base import (BaseBackend, BaseCurrentPlaylistController, BaseLibraryController, BasePlaybackController, BasePlaybackProvider, - BaseStoredPlaylistsController) + BaseStoredPlaylistsController, BaseStoredPlaylistsProvider) from mopidy.models import Playlist, Track, Album from mopidy.utils.process import pickle_connection @@ -34,7 +34,9 @@ class LocalBackend(BaseBackend): self.library = LocalLibraryController(backend=self) - self.stored_playlists = LocalStoredPlaylistsController(backend=self) + stored_playlists_provider = LocalStoredPlaylistsProvider(backend=self) + self.stored_playlists = BaseStoredPlaylistsController(backend=self, + provider=stored_playlists_provider) self.current_playlist = BaseCurrentPlaylistController(backend=self) @@ -74,9 +76,9 @@ class LocalPlaybackProvider(BasePlaybackProvider): return self.backend.output.set_state('READY') -class LocalStoredPlaylistsController(BaseStoredPlaylistsController): +class LocalStoredPlaylistsProvider(BaseStoredPlaylistsProvider): def __init__(self, *args, **kwargs): - super(LocalStoredPlaylistsController, self).__init__(*args, **kwargs) + super(LocalStoredPlaylistsProvider, self).__init__(*args, **kwargs) self._folder = os.path.expanduser(settings.LOCAL_PLAYLIST_FOLDER) self.refresh() From 7193302c10d04507cf8ac2b577ed20de4a203af4 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Mon, 1 Nov 2010 23:27:52 +0100 Subject: [PATCH 08/22] Use a DummyQueue in DummyBackend to silence triggered events --- mopidy/backends/dummy/__init__.py | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/mopidy/backends/dummy/__init__.py b/mopidy/backends/dummy/__init__.py index 3b94452b..6549b9ec 100644 --- a/mopidy/backends/dummy/__init__.py +++ b/mopidy/backends/dummy/__init__.py @@ -3,6 +3,15 @@ from mopidy.backends.base import (BaseBackend, BaseCurrentPlaylistController, BaseStoredPlaylistsController, BaseStoredPlaylistsProvider) from mopidy.models import Playlist + +class DummyQueue(object): + def __init__(self): + self.received_messages = [] + + def put(self, message): + self.received_messages.append(message) + + class DummyBackend(BaseBackend): """ A backend which implements the backend API in the simplest way possible. @@ -14,12 +23,14 @@ class DummyBackend(BaseBackend): def __init__(self, *args, **kwargs): super(DummyBackend, self).__init__(*args, **kwargs) - self.current_playlist = DummyCurrentPlaylistController(backend=self) + self.core_queue = DummyQueue() + + self.current_playlist = BaseCurrentPlaylistController(backend=self) self.library = DummyLibraryController(backend=self) playback_provider = DummyPlaybackProvider(backend=self) - self.playback = DummyPlaybackController(backend=self, + self.playback = BasePlaybackController(backend=self, provider=playback_provider) stored_playlists_provider = DummyStoredPlaylistsProvider(backend=self) @@ -29,10 +40,6 @@ class DummyBackend(BaseBackend): self.uri_handlers = [u'dummy:'] -class DummyCurrentPlaylistController(BaseCurrentPlaylistController): - pass - - class DummyLibraryController(BaseLibraryController): _library = [] @@ -51,14 +58,6 @@ class DummyLibraryController(BaseLibraryController): return Playlist() -class DummyPlaybackController(BasePlaybackController): - def _trigger_started_playing_event(self): - pass # noop - - def _trigger_stopped_playing_event(self): - pass # noop - - class DummyPlaybackProvider(BasePlaybackProvider): def pause(self): return True From cfe4ec96a6b91258067101c0da5cb2fbb264693a Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Mon, 1 Nov 2010 23:43:07 +0100 Subject: [PATCH 09/22] docs: Split backend docs into three pages --- docs/api/backends.rst | 132 ------------------------------ docs/api/backends/concepts.rst | 28 +++++++ docs/api/backends/controllers.rst | 65 +++++++++++++++ docs/api/backends/providers.rst | 33 ++++++++ docs/api/index.rst | 5 +- 5 files changed, 130 insertions(+), 133 deletions(-) delete mode 100644 docs/api/backends.rst create mode 100644 docs/api/backends/concepts.rst create mode 100644 docs/api/backends/controllers.rst create mode 100644 docs/api/backends/providers.rst diff --git a/docs/api/backends.rst b/docs/api/backends.rst deleted file mode 100644 index 617bcb94..00000000 --- a/docs/api/backends.rst +++ /dev/null @@ -1,132 +0,0 @@ -********************** -:mod:`mopidy.backends` -********************** - -.. automodule:: mopidy.backends - :synopsis: Backend APIs - - -The backend, controller, and provider concepts -============================================== - -Backend: - The backend is mostly for convenience. It is a container that holds - references to all the controllers. -Controllers: - Each controller has responsibility for a given part of the backend - functionality. Most, but not all, controllers delegates some work to one or - more providers. The controllers are responsible for choosing the right - provider for any given task based upon i.e. the track's URI. -Providers: - Anything specific to i.e. Spotify integration or local storage is contained - in the providers. To integrate with new music sources, you just add new - providers. - -.. digraph:: backend_relations - - Backend -> "Current\nplaylist\ncontroller" - Backend -> "Library\ncontroller" - "Library\ncontroller" -> "Library\nproviders" - Backend -> "Playback\ncontroller" - "Playback\ncontroller" -> "Playback\nproviders" - Backend -> "Stored\nplaylists\ncontroller" - "Stored\nplaylists\ncontroller" -> "Stored\nplaylist\nproviders" - Backend -> Mixer - -.. _backend-controller-api: - -Backend controller API -====================== - -.. note:: - - The backend controller API is the interface that is used by frontends like - :mod:`mopidy.frontends.mpd`. If you want to implement your own backend, see - the :ref:`backend-provider-api`. - -.. autoclass:: mopidy.backends.base.BaseBackend - :members: - :undoc-members: - - -Playback controller -------------------- - -Manages playback, with actions like play, pause, stop, next, previous, and -seek. - -.. autoclass:: mopidy.backends.base.BasePlaybackController - :members: - :undoc-members: - - -Mixer controller ----------------- - -Manages volume. See :class:`mopidy.mixers.BaseMixer`. - - -Current playlist controller ---------------------------- - -Manages everything related to the currently loaded playlist. - -.. autoclass:: mopidy.backends.base.BaseCurrentPlaylistController - :members: - :undoc-members: - - -Stored playlists controller ---------------------------- - -Manages stored playlist. - -.. autoclass:: mopidy.backends.base.BaseStoredPlaylistsController - :members: - :undoc-members: - - -Library controller ------------------- - -Manages the music library, e.g. searching for tracks to be added to a playlist. - -.. autoclass:: mopidy.backends.base.BaseLibraryController - :members: - :undoc-members: - - -.. _backend-provider-api: - -Backend provider API -==================== - -.. note:: - - The backend provider API is the interface that must be implemented when you - create a backend. If you are working on a frontend and need to access the - backend, see the :ref:`backend-controller-api`. - - -Playback provider ------------------ - -.. autoclass:: mopidy.backends.base.BasePlaybackProvider - :members: - :undoc-members: - - -Stored playlists provider -------------------------- - -.. autoclass:: mopidy.backends.base.BaseStoredPlaylistsProvider - :members: - :undoc-members: - - -Backend provider implementations -================================ - -* :mod:`mopidy.backends.dummy` -* :mod:`mopidy.backends.libspotify` -* :mod:`mopidy.backends.local` diff --git a/docs/api/backends/concepts.rst b/docs/api/backends/concepts.rst new file mode 100644 index 00000000..fd7b4d13 --- /dev/null +++ b/docs/api/backends/concepts.rst @@ -0,0 +1,28 @@ +********************************************** +The backend, controller, and provider concepts +********************************************** + +Backend: + The backend is mostly for convenience. It is a container that holds + references to all the controllers. +Controllers: + Each controller has responsibility for a given part of the backend + functionality. Most, but not all, controllers delegates some work to one or + more providers. The controllers are responsible for choosing the right + provider for any given task based upon i.e. the track's URI. See + :ref:`backend-controller-api` for more details. +Providers: + Anything specific to i.e. Spotify integration or local storage is contained + in the providers. To integrate with new music sources, you just add new + providers. See :ref:`backend-provider-api` for more details. + +.. digraph:: backend_relations + + Backend -> "Current\nplaylist\ncontroller" + Backend -> "Library\ncontroller" + "Library\ncontroller" -> "Library\nproviders" + Backend -> "Playback\ncontroller" + "Playback\ncontroller" -> "Playback\nproviders" + Backend -> "Stored\nplaylists\ncontroller" + "Stored\nplaylists\ncontroller" -> "Stored\nplaylist\nproviders" + Backend -> Mixer diff --git a/docs/api/backends/controllers.rst b/docs/api/backends/controllers.rst new file mode 100644 index 00000000..a9d54504 --- /dev/null +++ b/docs/api/backends/controllers.rst @@ -0,0 +1,65 @@ +.. _backend-controller-api: + +********************** +Backend controller API +********************** + + +The backend controller API is the interface that is used by frontends like +:mod:`mopidy.frontends.mpd`. If you want to implement your own backend, see the +:ref:`backend-provider-api`. + + +The backend +=========== + +.. autoclass:: mopidy.backends.base.BaseBackend + :members: + :undoc-members: + + +Playback controller +=================== + +Manages playback, with actions like play, pause, stop, next, previous, and +seek. + +.. autoclass:: mopidy.backends.base.BasePlaybackController + :members: + :undoc-members: + + +Mixer controller +================ + +Manages volume. See :class:`mopidy.mixers.BaseMixer`. + + +Current playlist controller +=========================== + +Manages everything related to the currently loaded playlist. + +.. autoclass:: mopidy.backends.base.BaseCurrentPlaylistController + :members: + :undoc-members: + + +Stored playlists controller +=========================== + +Manages stored playlist. + +.. autoclass:: mopidy.backends.base.BaseStoredPlaylistsController + :members: + :undoc-members: + + +Library controller +================== + +Manages the music library, e.g. searching for tracks to be added to a playlist. + +.. autoclass:: mopidy.backends.base.BaseLibraryController + :members: + :undoc-members: diff --git a/docs/api/backends/providers.rst b/docs/api/backends/providers.rst new file mode 100644 index 00000000..0b042241 --- /dev/null +++ b/docs/api/backends/providers.rst @@ -0,0 +1,33 @@ +.. _backend-provider-api: + +******************** +Backend provider API +******************** + +The backend provider API is the interface that must be implemented when you +create a backend. If you are working on a frontend and need to access the +backend, see the :ref:`backend-controller-api`. + + +Playback provider +================= + +.. autoclass:: mopidy.backends.base.BasePlaybackProvider + :members: + :undoc-members: + + +Stored playlists provider +========================= + +.. autoclass:: mopidy.backends.base.BaseStoredPlaylistsProvider + :members: + :undoc-members: + + +Backend provider implementations +================================ + +* :mod:`mopidy.backends.dummy` +* :mod:`mopidy.backends.libspotify` +* :mod:`mopidy.backends.local` diff --git a/docs/api/index.rst b/docs/api/index.rst index 87ec9bb3..1f37e9ff 100644 --- a/docs/api/index.rst +++ b/docs/api/index.rst @@ -5,4 +5,7 @@ API reference .. toctree:: :glob: - ** + backends/concepts + backends/controllers + backends/providers + * From 4e0c1ce93fa4ef7881eb33cc8e10cc8d689173e0 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Mon, 1 Nov 2010 23:52:21 +0100 Subject: [PATCH 10/22] docs: Improve playback provider docs --- mopidy/backends/base/playback.py | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/mopidy/backends/base/playback.py b/mopidy/backends/base/playback.py index 8b935c65..1ab8aeda 100644 --- a/mopidy/backends/base/playback.py +++ b/mopidy/backends/base/playback.py @@ -504,8 +504,9 @@ class BasePlaybackProvider(object): def pause(self): """ - To be overridden by subclass. Implement your backend's pause - functionality here. + To be overridden by subclass. + + Pause playback. :rtype: :class:`True` if successful, else :class:`False` """ @@ -513,8 +514,9 @@ class BasePlaybackProvider(object): def play(self, track): """ - To be overridden by subclass. Implement your backend's play - functionality here. + To be overridden by subclass. + + Play given track. :param track: the track to play :type track: :class:`mopidy.models.Track` @@ -524,8 +526,9 @@ class BasePlaybackProvider(object): def resume(self): """ - To be overridden by subclass. Implement your backend's resume - functionality here. + To be overridden by subclass. + + Resume playback at the same time position playback was paused. :rtype: :class:`True` if successful, else :class:`False` """ @@ -533,8 +536,9 @@ class BasePlaybackProvider(object): def seek(self, time_position): """ - To be overridden by subclass. Implement your backend's seek - functionality here. + To be overridden by subclass. + + Seek to a given time position. :param time_position: time position in milliseconds :type time_position: int @@ -544,8 +548,9 @@ class BasePlaybackProvider(object): def stop(self): """ - To be overridden by subclass. Implement your backend's stop - functionality here. + To be overridden by subclass. + + Stop playback. :rtype: :class:`True` if successful, else :class:`False` """ From 13ece433634a9697a5921f787fe56a148e7fabef Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Tue, 2 Nov 2010 23:07:15 +0100 Subject: [PATCH 11/22] Split BaseLibraryController in controller and provider --- docs/api/backends/providers.rst | 8 +++ mopidy/backends/base/__init__.py | 2 +- mopidy/backends/base/library.py | 61 ++++++++++++++++++-- mopidy/backends/dummy/__init__.py | 13 +++-- mopidy/backends/libspotify/__init__.py | 9 ++- mopidy/backends/libspotify/library.py | 4 +- mopidy/backends/local/__init__.py | 26 +++++---- tests/frontends/mpd/current_playlist_test.py | 8 +-- 8 files changed, 100 insertions(+), 31 deletions(-) diff --git a/docs/api/backends/providers.rst b/docs/api/backends/providers.rst index 0b042241..9289dd06 100644 --- a/docs/api/backends/providers.rst +++ b/docs/api/backends/providers.rst @@ -25,6 +25,14 @@ Stored playlists provider :undoc-members: +Library provider +================ + +.. autoclass:: mopidy.backends.base.BaseLibraryProvider + :members: + :undoc-members: + + Backend provider implementations ================================ diff --git a/mopidy/backends/base/__init__.py b/mopidy/backends/base/__init__.py index 7ee86015..70b17397 100644 --- a/mopidy/backends/base/__init__.py +++ b/mopidy/backends/base/__init__.py @@ -9,7 +9,7 @@ from mopidy.models import Playlist from mopidy.utils import get_class from .current_playlist import BaseCurrentPlaylistController -from .library import BaseLibraryController +from .library import BaseLibraryController, BaseLibraryProvider from .playback import BasePlaybackController, BasePlaybackProvider from .stored_playlists import (BaseStoredPlaylistsController, BaseStoredPlaylistsProvider) diff --git a/mopidy/backends/base/library.py b/mopidy/backends/base/library.py index 94f40863..a1df83cd 100644 --- a/mopidy/backends/base/library.py +++ b/mopidy/backends/base/library.py @@ -8,12 +8,13 @@ class BaseLibraryController(object): :type backend: :class:`BaseBackend` """ - def __init__(self, backend): + def __init__(self, backend, provider): self.backend = backend + self.provider = provider def destroy(self): """Cleanup after component.""" - pass + self.provider.destroy() def find_exact(self, **query): """ @@ -32,7 +33,7 @@ class BaseLibraryController(object): :type query: dict :rtype: :class:`mopidy.models.Playlist` """ - raise NotImplementedError + return self.provider.find_exact(**query) def lookup(self, uri): """ @@ -42,7 +43,7 @@ class BaseLibraryController(object): :type uri: string :rtype: :class:`mopidy.models.Track` or :class:`None` """ - raise NotImplementedError + return self.provider.lookup(uri) def refresh(self, uri=None): """ @@ -51,7 +52,7 @@ class BaseLibraryController(object): :param uri: directory or track URI :type uri: string """ - raise NotImplementedError + return self.provider.refresh(uri) def search(self, **query): """ @@ -70,4 +71,54 @@ class BaseLibraryController(object): :type query: dict :rtype: :class:`mopidy.models.Playlist` """ + return self.provider.search(**query) + + +class BaseLibraryProvider(object): + """ + :param backend: backend the controller is a part of + :type backend: :class:`BaseBackend` + """ + + def __init__(self, backend): + self.backend = backend + + def destroy(self): + """ + Cleanup after component. + + *MAY be implemented by subclasses.* + """ + pass + + def find_exact(self, **query): + """ + See :meth:`mopidy.backends.base.BaseLibraryController.find_exact`. + + *MUST be implemented by subclass.* + """ + raise NotImplementedError + + def lookup(self, uri): + """ + See :meth:`mopidy.backends.base.BaseLibraryController.lookup`. + + *MUST be implemented by subclass.* + """ + raise NotImplementedError + + def refresh(self, uri=None): + """ + See :meth:`mopidy.backends.base.BaseLibraryController.refresh`. + + *MUST be implemented by subclass.* + """ + raise NotImplementedError + + def search(self, **query): + """ + See :meth:`mopidy.backends.base.BaseLibraryController.search`. + + *MUST be implemented by subclass.* + """ raise NotImplementedError diff --git a/mopidy/backends/dummy/__init__.py b/mopidy/backends/dummy/__init__.py index 6b259338..df4428e3 100644 --- a/mopidy/backends/dummy/__init__.py +++ b/mopidy/backends/dummy/__init__.py @@ -1,6 +1,7 @@ from mopidy.backends.base import (BaseBackend, BaseCurrentPlaylistController, BasePlaybackController, BasePlaybackProvider, BaseLibraryController, - BaseStoredPlaylistsController, BaseStoredPlaylistsProvider) + BaseLibraryProvider, BaseStoredPlaylistsController, + BaseStoredPlaylistsProvider) from mopidy.models import Playlist @@ -27,7 +28,9 @@ class DummyBackend(BaseBackend): self.current_playlist = BaseCurrentPlaylistController(backend=self) - self.library = DummyLibraryController(backend=self) + library_provider = DummyLibraryProvider(backend=self) + self.library = BaseLibraryController(backend=self, + provider=library_provider) playback_provider = DummyPlaybackProvider(backend=self) self.playback = BasePlaybackController(backend=self, @@ -40,8 +43,10 @@ class DummyBackend(BaseBackend): self.uri_handlers = [u'dummy:'] -class DummyLibraryController(BaseLibraryController): - _library = [] +class DummyLibraryProvider(BaseLibraryProvider): + def __init__(self, *args, **kwargs): + super(DummyLibraryProvider, self).__init__(*args, **kwargs) + self._library = [] def find_exact(self, **query): return Playlist() diff --git a/mopidy/backends/libspotify/__init__.py b/mopidy/backends/libspotify/__init__.py index 98b9e884..0eefcd41 100644 --- a/mopidy/backends/libspotify/__init__.py +++ b/mopidy/backends/libspotify/__init__.py @@ -2,7 +2,8 @@ import logging from mopidy import settings from mopidy.backends.base import (BaseBackend, BaseCurrentPlaylistController, - BasePlaybackController, BaseStoredPlaylistsController) + BaseLibraryController, BasePlaybackController, + BaseStoredPlaylistsController) logger = logging.getLogger('mopidy.backends.libspotify') @@ -34,7 +35,7 @@ class LibspotifyBackend(BaseBackend): # missing spotify dependencies. def __init__(self, *args, **kwargs): - from .library import LibspotifyLibraryController + from .library import LibspotifyLibraryProvider from .playback import LibspotifyPlaybackProvider from .stored_playlists import LibspotifyStoredPlaylistsProvider @@ -42,7 +43,9 @@ class LibspotifyBackend(BaseBackend): self.current_playlist = BaseCurrentPlaylistController(backend=self) - self.library = LibspotifyLibraryController(backend=self) + library_provider = LibspotifyLibraryProvider(backend=self) + self.library = BaseLibraryController(backend=self, + provider=library_provider) playback_provider = LibspotifyPlaybackProvider(backend=self) self.playback = BasePlaybackController(backend=self, diff --git a/mopidy/backends/libspotify/library.py b/mopidy/backends/libspotify/library.py index 972eaf03..948c69b2 100644 --- a/mopidy/backends/libspotify/library.py +++ b/mopidy/backends/libspotify/library.py @@ -3,14 +3,14 @@ import multiprocessing from spotify import Link, SpotifyError -from mopidy.backends.base import BaseLibraryController +from mopidy.backends.base import BaseLibraryProvider from mopidy.backends.libspotify import ENCODING from mopidy.backends.libspotify.translator import LibspotifyTranslator from mopidy.models import Playlist logger = logging.getLogger('mopidy.backends.libspotify.library') -class LibspotifyLibraryController(BaseLibraryController): +class LibspotifyLibraryProvider(BaseLibraryProvider): def find_exact(self, **query): return self.search(**query) diff --git a/mopidy/backends/local/__init__.py b/mopidy/backends/local/__init__.py index cf9cbd60..a5b6fb7a 100644 --- a/mopidy/backends/local/__init__.py +++ b/mopidy/backends/local/__init__.py @@ -5,10 +5,10 @@ import os import shutil from mopidy import settings -from mopidy.backends.base import (BaseBackend, - BaseCurrentPlaylistController, BaseLibraryController, - BasePlaybackController, BasePlaybackProvider, - BaseStoredPlaylistsController, BaseStoredPlaylistsProvider) +from mopidy.backends.base import (BaseBackend, BaseCurrentPlaylistController, + BaseLibraryController, BaseLibraryProvider, BasePlaybackController, + BasePlaybackProvider, BaseStoredPlaylistsController, + BaseStoredPlaylistsProvider) from mopidy.models import Playlist, Track, Album from mopidy.utils.process import pickle_connection @@ -32,18 +32,20 @@ class LocalBackend(BaseBackend): def __init__(self, *args, **kwargs): super(LocalBackend, self).__init__(*args, **kwargs) - self.library = LocalLibraryController(backend=self) - - stored_playlists_provider = LocalStoredPlaylistsProvider(backend=self) - self.stored_playlists = BaseStoredPlaylistsController(backend=self, - provider=stored_playlists_provider) - self.current_playlist = BaseCurrentPlaylistController(backend=self) + library_provider = LocalLibraryProvider(backend=self) + self.library = BaseLibraryController(backend=self, + provider=library_provider) + playback_provider = LocalPlaybackProvider(backend=self) self.playback = LocalPlaybackController(backend=self, provider=playback_provider) + stored_playlists_provider = LocalStoredPlaylistsProvider(backend=self) + self.stored_playlists = BaseStoredPlaylistsController(backend=self, + provider=stored_playlists_provider) + self.uri_handlers = [u'file://'] @@ -149,9 +151,9 @@ class LocalStoredPlaylistsProvider(BaseStoredPlaylistsProvider): self._playlists.append(playlist) -class LocalLibraryController(BaseLibraryController): +class LocalLibraryProvider(BaseLibraryProvider): def __init__(self, *args, **kwargs): - super(LocalLibraryController, self).__init__(*args, **kwargs) + super(LocalLibraryProvider, self).__init__(*args, **kwargs) self._uri_mapping = {} self.refresh() diff --git a/tests/frontends/mpd/current_playlist_test.py b/tests/frontends/mpd/current_playlist_test.py index 8a4b9ab5..a4179637 100644 --- a/tests/frontends/mpd/current_playlist_test.py +++ b/tests/frontends/mpd/current_playlist_test.py @@ -12,7 +12,7 @@ class CurrentPlaylistHandlerTest(unittest.TestCase): def test_add(self): needle = Track(uri='dummy://foo') - self.b.library._library = [Track(), Track(), needle, Track()] + self.b.library.provider._library = [Track(), Track(), needle, Track()] self.b.current_playlist.append( [Track(), Track(), Track(), Track(), Track()]) self.assertEqual(len(self.b.current_playlist.tracks), 5) @@ -40,7 +40,7 @@ class CurrentPlaylistHandlerTest(unittest.TestCase): def test_addid_without_songpos(self): needle = Track(uri='dummy://foo') - self.b.library._library = [Track(), Track(), needle, Track()] + self.b.library.provider._library = [Track(), Track(), needle, Track()] self.b.current_playlist.append( [Track(), Track(), Track(), Track(), Track()]) self.assertEqual(len(self.b.current_playlist.tracks), 5) @@ -58,7 +58,7 @@ class CurrentPlaylistHandlerTest(unittest.TestCase): def test_addid_with_songpos(self): needle = Track(uri='dummy://foo') - self.b.library._library = [Track(), Track(), needle, Track()] + self.b.library.provider._library = [Track(), Track(), needle, Track()] self.b.current_playlist.append( [Track(), Track(), Track(), Track(), Track()]) self.assertEqual(len(self.b.current_playlist.tracks), 5) @@ -71,7 +71,7 @@ class CurrentPlaylistHandlerTest(unittest.TestCase): def test_addid_with_songpos_out_of_bounds_should_ack(self): needle = Track(uri='dummy://foo') - self.b.library._library = [Track(), Track(), needle, Track()] + self.b.library.provider._library = [Track(), Track(), needle, Track()] self.b.current_playlist.append( [Track(), Track(), Track(), Track(), Track()]) self.assertEqual(len(self.b.current_playlist.tracks), 5) From 3e8be009e4ba19b0372cfadb29b960d1e03599e8 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Tue, 2 Nov 2010 23:33:07 +0100 Subject: [PATCH 12/22] Add consistent may/must notices to all unimplemented methods --- mopidy/backends/base/playback.py | 22 +++++++------- mopidy/backends/base/stored_playlists.py | 26 ++++++++-------- mopidy/frontends/base.py | 14 +++++++-- mopidy/mixers/__init__.py | 4 +-- mopidy/outputs/base.py | 38 +++++++++++++++++++++--- 5 files changed, 72 insertions(+), 32 deletions(-) diff --git a/mopidy/backends/base/playback.py b/mopidy/backends/base/playback.py index 1ab8aeda..1a47391f 100644 --- a/mopidy/backends/base/playback.py +++ b/mopidy/backends/base/playback.py @@ -498,26 +498,26 @@ class BasePlaybackProvider(object): """ Cleanup after component. - May be overridden by subclasses. + *MAY be implemented by subclasses.* """ pass def pause(self): """ - To be overridden by subclass. - Pause playback. + *MUST be implemented by subclass.* + :rtype: :class:`True` if successful, else :class:`False` """ raise NotImplementedError def play(self, track): """ - To be overridden by subclass. - Play given track. + *MUST be implemented by subclass.* + :param track: the track to play :type track: :class:`mopidy.models.Track` :rtype: :class:`True` if successful, else :class:`False` @@ -526,20 +526,20 @@ class BasePlaybackProvider(object): def resume(self): """ - To be overridden by subclass. - Resume playback at the same time position playback was paused. + *MUST be implemented by subclass.* + :rtype: :class:`True` if successful, else :class:`False` """ raise NotImplementedError def seek(self, time_position): """ - To be overridden by subclass. - Seek to a given time position. + *MUST be implemented by subclass.* + :param time_position: time position in milliseconds :type time_position: int :rtype: :class:`True` if successful, else :class:`False` @@ -548,10 +548,10 @@ class BasePlaybackProvider(object): def stop(self): """ - To be overridden by subclass. - Stop playback. + *MUST be implemented by subclass.* + :rtype: :class:`True` if successful, else :class:`False` """ raise NotImplementedError diff --git a/mopidy/backends/base/stored_playlists.py b/mopidy/backends/base/stored_playlists.py index cf14db9d..dd7380d6 100644 --- a/mopidy/backends/base/stored_playlists.py +++ b/mopidy/backends/base/stored_playlists.py @@ -133,7 +133,7 @@ class BaseStoredPlaylistsProvider(object): """ Cleanup after component. - May be overridden by subclasses. + *MAY be implemented by subclass.* """ pass @@ -152,49 +152,49 @@ class BaseStoredPlaylistsProvider(object): def create(self, name): """ - To be overridden by subclass. - See :meth:`mopidy.backends.base.BaseStoredPlaylistsController.create`. + + *MUST be implemented by subclass.* """ raise NotImplementedError def delete(self, playlist): """ - To be overridden by subclass. - See :meth:`mopidy.backends.base.BaseStoredPlaylistsController.delete`. + + *MUST be implemented by subclass.* """ raise NotImplementedError def lookup(self, uri): """ - To be overridden by subclass. - See :meth:`mopidy.backends.base.BaseStoredPlaylistsController.lookup`. + + *MUST be implemented by subclass.* """ raise NotImplementedError def refresh(self): """ - To be overridden by subclass. - See :meth:`mopidy.backends.base.BaseStoredPlaylistsController.refresh`. + + *MUST be implemented by subclass.* """ raise NotImplementedError def rename(self, playlist, new_name): """ - To be overridden by subclass. - See :meth:`mopidy.backends.base.BaseStoredPlaylistsController.rename`. + + *MUST be implemented by subclass.* """ raise NotImplementedError def save(self, playlist): """ - To be overridden by subclass. - See :meth:`mopidy.backends.base.BaseStoredPlaylistsController.save`. + + *MUST be implemented by subclass.* """ raise NotImplementedError diff --git a/mopidy/frontends/base.py b/mopidy/frontends/base.py index 92545b73..e15c4745 100644 --- a/mopidy/frontends/base.py +++ b/mopidy/frontends/base.py @@ -13,17 +13,27 @@ class BaseFrontend(object): self.backend = backend def start(self): - """Start the frontend.""" + """ + Start the frontend. + + *MAY be implemented by subclass.* + """ pass def destroy(self): - """Destroy the frontend.""" + """ + Destroy the frontend. + + *MAY be implemented by subclass.* + """ pass def process_message(self, message): """ Process messages for the frontend. + *MUST be implemented by subclass.* + :param message: the message :type message: dict """ diff --git a/mopidy/mixers/__init__.py b/mopidy/mixers/__init__.py index 332718a6..231154ee 100644 --- a/mopidy/mixers/__init__.py +++ b/mopidy/mixers/__init__.py @@ -42,7 +42,7 @@ class BaseMixer(object): """ Return volume as integer in range [0, 100]. :class:`None` if unknown. - *Must be implemented by subclass.* + *MUST be implemented by subclass.* """ raise NotImplementedError @@ -50,6 +50,6 @@ class BaseMixer(object): """ Set volume as integer in range [0, 100]. - *Must be implemented by subclass.* + *MUST be implemented by subclass.* """ raise NotImplementedError diff --git a/mopidy/outputs/base.py b/mopidy/outputs/base.py index bb312323..372d7d70 100644 --- a/mopidy/outputs/base.py +++ b/mopidy/outputs/base.py @@ -7,21 +7,35 @@ class BaseOutput(object): self.core_queue = core_queue def start(self): - """Start the output.""" + """ + Start the output. + + *MAY be implemented by subclasses.* + """ pass def destroy(self): - """Destroy the output.""" + """ + Destroy the output. + + *MAY be implemented by subclasses.* + """ pass def process_message(self, message): - """Process messages with the output as destination.""" + """ + Process messages with the output as destination. + + *MUST be implemented by subclass.* + """ raise NotImplementedError def play_uri(self, uri): """ Play URI. + *MUST be implemented by subclass.* + :param uri: the URI to play :type uri: string :rtype: :class:`True` if successful, else :class:`False` @@ -32,19 +46,27 @@ class BaseOutput(object): """ Deliver audio data to be played. + *MUST be implemented by subclass.* + :param capabilities: a GStreamer capabilities string :type capabilities: string """ raise NotImplementedError def end_of_data_stream(self): - """Signal that the last audio data has been delivered.""" + """ + Signal that the last audio data has been delivered. + + *MUST be implemented by subclass.* + """ raise NotImplementedError def get_position(self): """ Get position in milliseconds. + *MUST be implemented by subclass.* + :rtype: int """ raise NotImplementedError @@ -53,6 +75,8 @@ class BaseOutput(object): """ Set position in milliseconds. + *MUST be implemented by subclass.* + :param position: the position in milliseconds :type volume: int :rtype: :class:`True` if successful, else :class:`False` @@ -63,6 +87,8 @@ class BaseOutput(object): """ Set playback state. + *MUST be implemented by subclass.* + :param state: the state :type state: string :rtype: :class:`True` if successful, else :class:`False` @@ -73,6 +99,8 @@ class BaseOutput(object): """ Get volume level for software mixer. + *MUST be implemented by subclass.* + :rtype: int in range [0..100] """ raise NotImplementedError @@ -81,6 +109,8 @@ class BaseOutput(object): """ Set volume level for software mixer. + *MUST be implemented by subclass.* + :param volume: the volume in the range [0..100] :type volume: int :rtype: :class:`True` if successful, else :class:`False` From 9267cd43cdb34183dacff3863981b6e207affaf0 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Tue, 2 Nov 2010 23:35:56 +0100 Subject: [PATCH 13/22] Move BaseMixer from __init__.py to base.py --- mopidy/mixers/__init__.py | 55 ----------------------------- mopidy/mixers/alsa.py | 2 +- mopidy/mixers/base.py | 55 +++++++++++++++++++++++++++++ mopidy/mixers/denon.py | 2 +- mopidy/mixers/dummy.py | 2 +- mopidy/mixers/gstreamer_software.py | 2 +- mopidy/mixers/nad.py | 2 +- mopidy/mixers/osa.py | 2 +- 8 files changed, 61 insertions(+), 61 deletions(-) create mode 100644 mopidy/mixers/base.py diff --git a/mopidy/mixers/__init__.py b/mopidy/mixers/__init__.py index 231154ee..e69de29b 100644 --- a/mopidy/mixers/__init__.py +++ b/mopidy/mixers/__init__.py @@ -1,55 +0,0 @@ -from mopidy import settings - -class BaseMixer(object): - """ - :param backend: a backend instance - :type mixer: :class:`mopidy.backends.base.BaseBackend` - - **Settings:** - - - :attr:`mopidy.settings.MIXER_MAX_VOLUME` - """ - - def __init__(self, backend, *args, **kwargs): - self.backend = backend - self.amplification_factor = settings.MIXER_MAX_VOLUME / 100.0 - - @property - def volume(self): - """ - The audio volume - - Integer in range [0, 100]. :class:`None` if unknown. Values below 0 is - equal to 0. Values above 100 is equal to 100. - """ - if self._get_volume() is None: - return None - return int(self._get_volume() / self.amplification_factor) - - @volume.setter - def volume(self, volume): - volume = int(int(volume) * self.amplification_factor) - if volume < 0: - volume = 0 - elif volume > 100: - volume = 100 - self._set_volume(volume) - - def destroy(self): - pass - - def _get_volume(self): - """ - Return volume as integer in range [0, 100]. :class:`None` if unknown. - - *MUST be implemented by subclass.* - """ - raise NotImplementedError - - def _set_volume(self, volume): - """ - Set volume as integer in range [0, 100]. - - *MUST be implemented by subclass.* - """ - raise NotImplementedError diff --git a/mopidy/mixers/alsa.py b/mopidy/mixers/alsa.py index 6eef6da4..f90060ce 100644 --- a/mopidy/mixers/alsa.py +++ b/mopidy/mixers/alsa.py @@ -2,7 +2,7 @@ import alsaaudio import logging from mopidy import settings -from mopidy.mixers import BaseMixer +from mopidy.mixers.base import BaseMixer logger = logging.getLogger('mopidy.mixers.alsa') diff --git a/mopidy/mixers/base.py b/mopidy/mixers/base.py new file mode 100644 index 00000000..231154ee --- /dev/null +++ b/mopidy/mixers/base.py @@ -0,0 +1,55 @@ +from mopidy import settings + +class BaseMixer(object): + """ + :param backend: a backend instance + :type mixer: :class:`mopidy.backends.base.BaseBackend` + + **Settings:** + + - :attr:`mopidy.settings.MIXER_MAX_VOLUME` + """ + + def __init__(self, backend, *args, **kwargs): + self.backend = backend + self.amplification_factor = settings.MIXER_MAX_VOLUME / 100.0 + + @property + def volume(self): + """ + The audio volume + + Integer in range [0, 100]. :class:`None` if unknown. Values below 0 is + equal to 0. Values above 100 is equal to 100. + """ + if self._get_volume() is None: + return None + return int(self._get_volume() / self.amplification_factor) + + @volume.setter + def volume(self, volume): + volume = int(int(volume) * self.amplification_factor) + if volume < 0: + volume = 0 + elif volume > 100: + volume = 100 + self._set_volume(volume) + + def destroy(self): + pass + + def _get_volume(self): + """ + Return volume as integer in range [0, 100]. :class:`None` if unknown. + + *MUST be implemented by subclass.* + """ + raise NotImplementedError + + def _set_volume(self, volume): + """ + Set volume as integer in range [0, 100]. + + *MUST be implemented by subclass.* + """ + raise NotImplementedError diff --git a/mopidy/mixers/denon.py b/mopidy/mixers/denon.py index 32750f60..e6d752b6 100644 --- a/mopidy/mixers/denon.py +++ b/mopidy/mixers/denon.py @@ -4,7 +4,7 @@ from threading import Lock from serial import Serial from mopidy import settings -from mopidy.mixers import BaseMixer +from mopidy.mixers.base import BaseMixer logger = logging.getLogger(u'mopidy.mixers.denon') diff --git a/mopidy/mixers/dummy.py b/mopidy/mixers/dummy.py index b0ea0e47..12a8137e 100644 --- a/mopidy/mixers/dummy.py +++ b/mopidy/mixers/dummy.py @@ -1,4 +1,4 @@ -from mopidy.mixers import BaseMixer +from mopidy.mixers.base import BaseMixer class DummyMixer(BaseMixer): """Mixer which just stores and reports the chosen volume.""" diff --git a/mopidy/mixers/gstreamer_software.py b/mopidy/mixers/gstreamer_software.py index 333690ea..9dca3690 100644 --- a/mopidy/mixers/gstreamer_software.py +++ b/mopidy/mixers/gstreamer_software.py @@ -1,4 +1,4 @@ -from mopidy.mixers import BaseMixer +from mopidy.mixers.base import BaseMixer class GStreamerSoftwareMixer(BaseMixer): """Mixer which uses GStreamer to control volume in software.""" diff --git a/mopidy/mixers/nad.py b/mopidy/mixers/nad.py index 8caa9700..3215a761 100644 --- a/mopidy/mixers/nad.py +++ b/mopidy/mixers/nad.py @@ -3,7 +3,7 @@ from serial import Serial from multiprocessing import Pipe from mopidy import settings -from mopidy.mixers import BaseMixer +from mopidy.mixers.base import BaseMixer from mopidy.utils.process import BaseThread logger = logging.getLogger('mopidy.mixers.nad') diff --git a/mopidy/mixers/osa.py b/mopidy/mixers/osa.py index 3aeaed5c..8d69eb47 100644 --- a/mopidy/mixers/osa.py +++ b/mopidy/mixers/osa.py @@ -1,7 +1,7 @@ from subprocess import Popen, PIPE import time -from mopidy.mixers import BaseMixer +from mopidy.mixers.base import BaseMixer class OsaMixer(BaseMixer): """Mixer which uses ``osascript`` on OS X to control volume.""" From 0836418bfcfa30516489f5b783aa426e58a50476 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Tue, 2 Nov 2010 23:42:58 +0100 Subject: [PATCH 14/22] Fix pylint error --- mopidy/backends/base/stored_playlists.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mopidy/backends/base/stored_playlists.py b/mopidy/backends/base/stored_playlists.py index dd7380d6..bb86c92e 100644 --- a/mopidy/backends/base/stored_playlists.py +++ b/mopidy/backends/base/stored_playlists.py @@ -96,7 +96,7 @@ class BaseStoredPlaylistsController(object): Refresh the stored playlists in :attr:`mopidy.backends.base.BaseStoredPlaylistsController.playlists`. """ - return self.provider.refresh(uri) + return self.provider.refresh() def rename(self, playlist, new_name): """ From c82b0d01aad3571d748cf092dae304b22c1a90de Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Tue, 2 Nov 2010 23:46:47 +0100 Subject: [PATCH 15/22] We do not need __all__, cause we do not 'import *' --- mopidy/backends/base/__init__.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/mopidy/backends/base/__init__.py b/mopidy/backends/base/__init__.py index 70b17397..f4a54984 100644 --- a/mopidy/backends/base/__init__.py +++ b/mopidy/backends/base/__init__.py @@ -16,10 +16,6 @@ from .stored_playlists import (BaseStoredPlaylistsController, logger = logging.getLogger('mopidy.backends.base') -__all__ = ['BaseBackend', 'BasePlaybackController', 'BasePlaybackProvider', - 'BaseCurrentPlaylistController', 'BaseStoredPlaylistsController', - 'BaseLibraryController'] - class BaseBackend(object): """ :param core_queue: a queue for sending messages to From 79b61895cc89839fca35ac6ad720253fc790c3ff Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Tue, 2 Nov 2010 23:49:15 +0100 Subject: [PATCH 16/22] Remove unmaintained tests --- tests/backends/libspotify/__init__.py | 0 .../libspotify/backend_integrationtest.py | 44 ------------------- 2 files changed, 44 deletions(-) delete mode 100644 tests/backends/libspotify/__init__.py delete mode 100644 tests/backends/libspotify/backend_integrationtest.py diff --git a/tests/backends/libspotify/__init__.py b/tests/backends/libspotify/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/backends/libspotify/backend_integrationtest.py b/tests/backends/libspotify/backend_integrationtest.py deleted file mode 100644 index 8d1f0b0e..00000000 --- a/tests/backends/libspotify/backend_integrationtest.py +++ /dev/null @@ -1,44 +0,0 @@ -# TODO This integration test is work in progress. - -import unittest - -from mopidy.backends.libspotify import LibspotifyBackend -from mopidy.models import Track - -from tests.backends.base.current_playlist import \ - BaseCurrentPlaylistControllerTest -from tests.backends.base.library import BaseLibraryControllerTest -from tests.backends.base.playback import BasePlaybackControllerTest -from tests.backends.base.stored_playlists import \ - BaseStoredPlaylistsControllerTest - -uris = [ - 'spotify:track:6vqcpVcbI3Zu6sH3ieLDNt', - 'spotify:track:111sulhaZqgsnypz3MkiaW', - 'spotify:track:7t8oznvbeiAPMDRuK0R5ZT', -] - -class LibspotifyCurrentPlaylistControllerTest( - BaseCurrentPlaylistControllerTest, unittest.TestCase): - - backend_class = LibspotifyBackend - tracks = [Track(uri=uri, length=4464) for i, uri in enumerate(uris)] - - -class LibspotifyPlaybackControllerTest( - BasePlaybackControllerTest, unittest.TestCase): - - backend_class = LibspotifyBackend - tracks = [Track(uri=uri, length=4464) for i, uri in enumerate(uris)] - - -class LibspotifyStoredPlaylistsControllerTest( - BaseStoredPlaylistsControllerTest, unittest.TestCase): - - backend_class = LibspotifyBackend - - -class LibspotifyLibraryControllerTest( - BaseLibraryControllerTest, unittest.TestCase): - - backend_class = LibspotifyBackend From 67885e83b6076624c7a8870c08f8165bb8677a97 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Tue, 2 Nov 2010 23:50:47 +0100 Subject: [PATCH 17/22] Rename {Base => }CurrentPlaylistController --- docs/api/backends/controllers.rst | 2 +- mopidy/backends/base/__init__.py | 4 ++-- mopidy/backends/base/current_playlist.py | 2 +- mopidy/backends/base/playback.py | 2 +- mopidy/backends/dummy/__init__.py | 4 ++-- mopidy/backends/libspotify/__init__.py | 4 ++-- mopidy/backends/local/__init__.py | 4 ++-- tests/backends/base/current_playlist.py | 2 +- tests/backends/local/current_playlist_test.py | 5 ++--- 9 files changed, 14 insertions(+), 15 deletions(-) diff --git a/docs/api/backends/controllers.rst b/docs/api/backends/controllers.rst index a9d54504..16ecc9b6 100644 --- a/docs/api/backends/controllers.rst +++ b/docs/api/backends/controllers.rst @@ -40,7 +40,7 @@ Current playlist controller Manages everything related to the currently loaded playlist. -.. autoclass:: mopidy.backends.base.BaseCurrentPlaylistController +.. autoclass:: mopidy.backends.base.CurrentPlaylistController :members: :undoc-members: diff --git a/mopidy/backends/base/__init__.py b/mopidy/backends/base/__init__.py index f4a54984..39ad6e9e 100644 --- a/mopidy/backends/base/__init__.py +++ b/mopidy/backends/base/__init__.py @@ -8,7 +8,7 @@ from mopidy.frontends.mpd import translator from mopidy.models import Playlist from mopidy.utils import get_class -from .current_playlist import BaseCurrentPlaylistController +from .current_playlist import CurrentPlaylistController from .library import BaseLibraryController, BaseLibraryProvider from .playback import BasePlaybackController, BasePlaybackProvider from .stored_playlists import (BaseStoredPlaylistsController, @@ -42,7 +42,7 @@ class BaseBackend(object): core_queue = None #: The current playlist controller. An instance of - #: :class:`mopidy.backends.base.BaseCurrentPlaylistController`. + #: :class:`mopidy.backends.base.CurrentPlaylistController`. current_playlist = None #: The library controller. An instance of diff --git a/mopidy/backends/base/current_playlist.py b/mopidy/backends/base/current_playlist.py index 34a16369..fec8e5a3 100644 --- a/mopidy/backends/base/current_playlist.py +++ b/mopidy/backends/base/current_playlist.py @@ -6,7 +6,7 @@ from mopidy.frontends.mpd import translator logger = logging.getLogger('mopidy.backends.base') -class BaseCurrentPlaylistController(object): +class CurrentPlaylistController(object): """ :param backend: backend the controller is a part of :type backend: :class:`BaseBackend` diff --git a/mopidy/backends/base/playback.py b/mopidy/backends/base/playback.py index 1a47391f..fa848845 100644 --- a/mopidy/backends/base/playback.py +++ b/mopidy/backends/base/playback.py @@ -331,7 +331,7 @@ class BasePlaybackController(object): """ Tell the playback controller that the current playlist has changed. - Used by :class:`mopidy.backends.base.BaseCurrentPlaylistController`. + Used by :class:`mopidy.backends.base.CurrentPlaylistController`. """ self._first_shuffle = True self._shuffled = [] diff --git a/mopidy/backends/dummy/__init__.py b/mopidy/backends/dummy/__init__.py index df4428e3..00f8c9f2 100644 --- a/mopidy/backends/dummy/__init__.py +++ b/mopidy/backends/dummy/__init__.py @@ -1,4 +1,4 @@ -from mopidy.backends.base import (BaseBackend, BaseCurrentPlaylistController, +from mopidy.backends.base import (BaseBackend, CurrentPlaylistController, BasePlaybackController, BasePlaybackProvider, BaseLibraryController, BaseLibraryProvider, BaseStoredPlaylistsController, BaseStoredPlaylistsProvider) @@ -26,7 +26,7 @@ class DummyBackend(BaseBackend): self.core_queue = DummyQueue() - self.current_playlist = BaseCurrentPlaylistController(backend=self) + self.current_playlist = CurrentPlaylistController(backend=self) library_provider = DummyLibraryProvider(backend=self) self.library = BaseLibraryController(backend=self, diff --git a/mopidy/backends/libspotify/__init__.py b/mopidy/backends/libspotify/__init__.py index 0eefcd41..450ac7be 100644 --- a/mopidy/backends/libspotify/__init__.py +++ b/mopidy/backends/libspotify/__init__.py @@ -1,7 +1,7 @@ import logging from mopidy import settings -from mopidy.backends.base import (BaseBackend, BaseCurrentPlaylistController, +from mopidy.backends.base import (BaseBackend, CurrentPlaylistController, BaseLibraryController, BasePlaybackController, BaseStoredPlaylistsController) @@ -41,7 +41,7 @@ class LibspotifyBackend(BaseBackend): super(LibspotifyBackend, self).__init__(*args, **kwargs) - self.current_playlist = BaseCurrentPlaylistController(backend=self) + self.current_playlist = CurrentPlaylistController(backend=self) library_provider = LibspotifyLibraryProvider(backend=self) self.library = BaseLibraryController(backend=self, diff --git a/mopidy/backends/local/__init__.py b/mopidy/backends/local/__init__.py index a5b6fb7a..0c624687 100644 --- a/mopidy/backends/local/__init__.py +++ b/mopidy/backends/local/__init__.py @@ -5,7 +5,7 @@ import os import shutil from mopidy import settings -from mopidy.backends.base import (BaseBackend, BaseCurrentPlaylistController, +from mopidy.backends.base import (BaseBackend, CurrentPlaylistController, BaseLibraryController, BaseLibraryProvider, BasePlaybackController, BasePlaybackProvider, BaseStoredPlaylistsController, BaseStoredPlaylistsProvider) @@ -32,7 +32,7 @@ class LocalBackend(BaseBackend): def __init__(self, *args, **kwargs): super(LocalBackend, self).__init__(*args, **kwargs) - self.current_playlist = BaseCurrentPlaylistController(backend=self) + self.current_playlist = CurrentPlaylistController(backend=self) library_provider = LocalLibraryProvider(backend=self) self.library = BaseLibraryController(backend=self, diff --git a/tests/backends/base/current_playlist.py b/tests/backends/base/current_playlist.py index 05f08e18..2b6cb84e 100644 --- a/tests/backends/base/current_playlist.py +++ b/tests/backends/base/current_playlist.py @@ -9,7 +9,7 @@ from mopidy.utils import get_class from tests.backends.base import populate_playlist -class BaseCurrentPlaylistControllerTest(object): +class CurrentPlaylistControllerTest(object): tracks = [] def setUp(self): diff --git a/tests/backends/local/current_playlist_test.py b/tests/backends/local/current_playlist_test.py index 3895497a..6f72d7d5 100644 --- a/tests/backends/local/current_playlist_test.py +++ b/tests/backends/local/current_playlist_test.py @@ -10,11 +10,10 @@ from mopidy import settings from mopidy.backends.local import LocalBackend from mopidy.models import Track -from tests.backends.base.current_playlist import \ - BaseCurrentPlaylistControllerTest +from tests.backends.base.current_playlist import CurrentPlaylistControllerTest from tests.backends.local import generate_song -class LocalCurrentPlaylistControllerTest(BaseCurrentPlaylistControllerTest, +class LocalCurrentPlaylistControllerTest(CurrentPlaylistControllerTest, unittest.TestCase): backend_class = LocalBackend From 5ada4709bdfd5a20ec809edd4f64817ce662a608 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Tue, 2 Nov 2010 23:54:02 +0100 Subject: [PATCH 18/22] Rename {Base => }LibraryController --- docs/api/backends/controllers.rst | 2 +- mopidy/backends/base/__init__.py | 4 ++-- mopidy/backends/base/library.py | 10 +++++----- mopidy/backends/dummy/__init__.py | 4 ++-- mopidy/backends/libspotify/__init__.py | 5 ++--- mopidy/backends/local/__init__.py | 4 ++-- tests/backends/base/library.py | 2 +- tests/backends/local/library_test.py | 4 ++-- 8 files changed, 17 insertions(+), 18 deletions(-) diff --git a/docs/api/backends/controllers.rst b/docs/api/backends/controllers.rst index 16ecc9b6..d3346a27 100644 --- a/docs/api/backends/controllers.rst +++ b/docs/api/backends/controllers.rst @@ -60,6 +60,6 @@ Library controller Manages the music library, e.g. searching for tracks to be added to a playlist. -.. autoclass:: mopidy.backends.base.BaseLibraryController +.. autoclass:: mopidy.backends.base.LibraryController :members: :undoc-members: diff --git a/mopidy/backends/base/__init__.py b/mopidy/backends/base/__init__.py index 39ad6e9e..529c2179 100644 --- a/mopidy/backends/base/__init__.py +++ b/mopidy/backends/base/__init__.py @@ -9,7 +9,7 @@ from mopidy.models import Playlist from mopidy.utils import get_class from .current_playlist import CurrentPlaylistController -from .library import BaseLibraryController, BaseLibraryProvider +from .library import LibraryController, BaseLibraryProvider from .playback import BasePlaybackController, BasePlaybackProvider from .stored_playlists import (BaseStoredPlaylistsController, BaseStoredPlaylistsProvider) @@ -46,7 +46,7 @@ class BaseBackend(object): current_playlist = None #: The library controller. An instance of - # :class:`mopidy.backends.base.BaseLibraryController`. + # :class:`mopidy.backends.base.LibraryController`. library = None #: The sound mixer. An instance of :class:`mopidy.mixers.BaseMixer`. diff --git a/mopidy/backends/base/library.py b/mopidy/backends/base/library.py index a1df83cd..697d3554 100644 --- a/mopidy/backends/base/library.py +++ b/mopidy/backends/base/library.py @@ -2,7 +2,7 @@ import logging logger = logging.getLogger('mopidy.backends.base') -class BaseLibraryController(object): +class LibraryController(object): """ :param backend: backend the controller is a part of :type backend: :class:`BaseBackend` @@ -93,7 +93,7 @@ class BaseLibraryProvider(object): def find_exact(self, **query): """ - See :meth:`mopidy.backends.base.BaseLibraryController.find_exact`. + See :meth:`mopidy.backends.base.LibraryController.find_exact`. *MUST be implemented by subclass.* """ @@ -101,7 +101,7 @@ class BaseLibraryProvider(object): def lookup(self, uri): """ - See :meth:`mopidy.backends.base.BaseLibraryController.lookup`. + See :meth:`mopidy.backends.base.LibraryController.lookup`. *MUST be implemented by subclass.* """ @@ -109,7 +109,7 @@ class BaseLibraryProvider(object): def refresh(self, uri=None): """ - See :meth:`mopidy.backends.base.BaseLibraryController.refresh`. + See :meth:`mopidy.backends.base.LibraryController.refresh`. *MUST be implemented by subclass.* """ @@ -117,7 +117,7 @@ class BaseLibraryProvider(object): def search(self, **query): """ - See :meth:`mopidy.backends.base.BaseLibraryController.search`. + See :meth:`mopidy.backends.base.LibraryController.search`. *MUST be implemented by subclass.* """ diff --git a/mopidy/backends/dummy/__init__.py b/mopidy/backends/dummy/__init__.py index 00f8c9f2..62a04567 100644 --- a/mopidy/backends/dummy/__init__.py +++ b/mopidy/backends/dummy/__init__.py @@ -1,5 +1,5 @@ from mopidy.backends.base import (BaseBackend, CurrentPlaylistController, - BasePlaybackController, BasePlaybackProvider, BaseLibraryController, + BasePlaybackController, BasePlaybackProvider, LibraryController, BaseLibraryProvider, BaseStoredPlaylistsController, BaseStoredPlaylistsProvider) from mopidy.models import Playlist @@ -29,7 +29,7 @@ class DummyBackend(BaseBackend): self.current_playlist = CurrentPlaylistController(backend=self) library_provider = DummyLibraryProvider(backend=self) - self.library = BaseLibraryController(backend=self, + self.library = LibraryController(backend=self, provider=library_provider) playback_provider = DummyPlaybackProvider(backend=self) diff --git a/mopidy/backends/libspotify/__init__.py b/mopidy/backends/libspotify/__init__.py index 450ac7be..59ff1fde 100644 --- a/mopidy/backends/libspotify/__init__.py +++ b/mopidy/backends/libspotify/__init__.py @@ -2,8 +2,7 @@ import logging from mopidy import settings from mopidy.backends.base import (BaseBackend, CurrentPlaylistController, - BaseLibraryController, BasePlaybackController, - BaseStoredPlaylistsController) + LibraryController, BasePlaybackController, BaseStoredPlaylistsController) logger = logging.getLogger('mopidy.backends.libspotify') @@ -44,7 +43,7 @@ class LibspotifyBackend(BaseBackend): self.current_playlist = CurrentPlaylistController(backend=self) library_provider = LibspotifyLibraryProvider(backend=self) - self.library = BaseLibraryController(backend=self, + self.library = LibraryController(backend=self, provider=library_provider) playback_provider = LibspotifyPlaybackProvider(backend=self) diff --git a/mopidy/backends/local/__init__.py b/mopidy/backends/local/__init__.py index 0c624687..ef42f4c4 100644 --- a/mopidy/backends/local/__init__.py +++ b/mopidy/backends/local/__init__.py @@ -6,7 +6,7 @@ import shutil from mopidy import settings from mopidy.backends.base import (BaseBackend, CurrentPlaylistController, - BaseLibraryController, BaseLibraryProvider, BasePlaybackController, + LibraryController, BaseLibraryProvider, BasePlaybackController, BasePlaybackProvider, BaseStoredPlaylistsController, BaseStoredPlaylistsProvider) from mopidy.models import Playlist, Track, Album @@ -35,7 +35,7 @@ class LocalBackend(BaseBackend): self.current_playlist = CurrentPlaylistController(backend=self) library_provider = LocalLibraryProvider(backend=self) - self.library = BaseLibraryController(backend=self, + self.library = LibraryController(backend=self, provider=library_provider) playback_provider = LocalPlaybackProvider(backend=self) diff --git a/tests/backends/base/library.py b/tests/backends/base/library.py index 1239bd08..71f62147 100644 --- a/tests/backends/base/library.py +++ b/tests/backends/base/library.py @@ -3,7 +3,7 @@ from mopidy.models import Playlist, Track, Album, Artist from tests import SkipTest, data_folder -class BaseLibraryControllerTest(object): +class LibraryControllerTest(object): artists = [Artist(name='artist1'), Artist(name='artist2'), Artist()] albums = [Album(name='album1', artists=artists[:1]), Album(name='album2', artists=artists[1:2]), diff --git a/tests/backends/local/library_test.py b/tests/backends/local/library_test.py index 34465d09..0c44924a 100644 --- a/tests/backends/local/library_test.py +++ b/tests/backends/local/library_test.py @@ -10,9 +10,9 @@ from mopidy import settings from mopidy.backends.local import LocalBackend from tests import data_folder -from tests.backends.base.library import BaseLibraryControllerTest +from tests.backends.base.library import LibraryControllerTest -class LocalLibraryControllerTest(BaseLibraryControllerTest, unittest.TestCase): +class LocalLibraryControllerTest(LibraryControllerTest, unittest.TestCase): backend_class = LocalBackend From fa4818095f3e97039203f3a6622463ef70c19a7a Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Tue, 2 Nov 2010 23:56:15 +0100 Subject: [PATCH 19/22] Document 'provider' arg to LibraryController() --- mopidy/backends/base/library.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mopidy/backends/base/library.py b/mopidy/backends/base/library.py index 697d3554..f3477489 100644 --- a/mopidy/backends/base/library.py +++ b/mopidy/backends/base/library.py @@ -6,6 +6,8 @@ class LibraryController(object): """ :param backend: backend the controller is a part of :type backend: :class:`BaseBackend` + :param provider: provider the controller should use + :type provider: instance of :class:`BaseLibraryProvider` """ def __init__(self, backend, provider): From 76ce2a63450e5c4efbdab612ac10e9444f99b091 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Tue, 2 Nov 2010 23:58:10 +0100 Subject: [PATCH 20/22] Rename {Base => }StoredPlaylistController --- docs/api/backends/controllers.rst | 2 +- mopidy/backends/base/__init__.py | 4 ++-- mopidy/backends/base/stored_playlists.py | 16 ++++++++-------- mopidy/backends/dummy/__init__.py | 4 ++-- mopidy/backends/libspotify/__init__.py | 4 ++-- mopidy/backends/local/__init__.py | 4 ++-- tests/backends/base/stored_playlists.py | 2 +- tests/backends/local/stored_playlists_test.py | 4 ++-- 8 files changed, 20 insertions(+), 20 deletions(-) diff --git a/docs/api/backends/controllers.rst b/docs/api/backends/controllers.rst index d3346a27..97ce2508 100644 --- a/docs/api/backends/controllers.rst +++ b/docs/api/backends/controllers.rst @@ -50,7 +50,7 @@ Stored playlists controller Manages stored playlist. -.. autoclass:: mopidy.backends.base.BaseStoredPlaylistsController +.. autoclass:: mopidy.backends.base.StoredPlaylistsController :members: :undoc-members: diff --git a/mopidy/backends/base/__init__.py b/mopidy/backends/base/__init__.py index 529c2179..f1fdfcbe 100644 --- a/mopidy/backends/base/__init__.py +++ b/mopidy/backends/base/__init__.py @@ -11,7 +11,7 @@ from mopidy.utils import get_class from .current_playlist import CurrentPlaylistController from .library import LibraryController, BaseLibraryProvider from .playback import BasePlaybackController, BasePlaybackProvider -from .stored_playlists import (BaseStoredPlaylistsController, +from .stored_playlists import (StoredPlaylistsController, BaseStoredPlaylistsProvider) logger = logging.getLogger('mopidy.backends.base') @@ -57,7 +57,7 @@ class BaseBackend(object): playback = None #: The stored playlists controller. An instance of - #: :class:`mopidy.backends.base.BaseStoredPlaylistsController`. + #: :class:`mopidy.backends.base.StoredPlaylistsController`. stored_playlists = None #: List of URI prefixes this backend can handle. diff --git a/mopidy/backends/base/stored_playlists.py b/mopidy/backends/base/stored_playlists.py index bb86c92e..733ea46f 100644 --- a/mopidy/backends/base/stored_playlists.py +++ b/mopidy/backends/base/stored_playlists.py @@ -3,7 +3,7 @@ import logging logger = logging.getLogger('mopidy.backends.base') -class BaseStoredPlaylistsController(object): +class StoredPlaylistsController(object): """ :param backend: backend the controller is a part of :type backend: :class:`BaseBackend` @@ -94,7 +94,7 @@ class BaseStoredPlaylistsController(object): def refresh(self): """ Refresh the stored playlists in - :attr:`mopidy.backends.base.BaseStoredPlaylistsController.playlists`. + :attr:`mopidy.backends.base.StoredPlaylistsController.playlists`. """ return self.provider.refresh() @@ -152,7 +152,7 @@ class BaseStoredPlaylistsProvider(object): def create(self, name): """ - See :meth:`mopidy.backends.base.BaseStoredPlaylistsController.create`. + See :meth:`mopidy.backends.base.StoredPlaylistsController.create`. *MUST be implemented by subclass.* """ @@ -160,7 +160,7 @@ class BaseStoredPlaylistsProvider(object): def delete(self, playlist): """ - See :meth:`mopidy.backends.base.BaseStoredPlaylistsController.delete`. + See :meth:`mopidy.backends.base.StoredPlaylistsController.delete`. *MUST be implemented by subclass.* """ @@ -168,7 +168,7 @@ class BaseStoredPlaylistsProvider(object): def lookup(self, uri): """ - See :meth:`mopidy.backends.base.BaseStoredPlaylistsController.lookup`. + See :meth:`mopidy.backends.base.StoredPlaylistsController.lookup`. *MUST be implemented by subclass.* """ @@ -176,7 +176,7 @@ class BaseStoredPlaylistsProvider(object): def refresh(self): """ - See :meth:`mopidy.backends.base.BaseStoredPlaylistsController.refresh`. + See :meth:`mopidy.backends.base.StoredPlaylistsController.refresh`. *MUST be implemented by subclass.* """ @@ -184,7 +184,7 @@ class BaseStoredPlaylistsProvider(object): def rename(self, playlist, new_name): """ - See :meth:`mopidy.backends.base.BaseStoredPlaylistsController.rename`. + See :meth:`mopidy.backends.base.StoredPlaylistsController.rename`. *MUST be implemented by subclass.* """ @@ -192,7 +192,7 @@ class BaseStoredPlaylistsProvider(object): def save(self, playlist): """ - See :meth:`mopidy.backends.base.BaseStoredPlaylistsController.save`. + See :meth:`mopidy.backends.base.StoredPlaylistsController.save`. *MUST be implemented by subclass.* """ diff --git a/mopidy/backends/dummy/__init__.py b/mopidy/backends/dummy/__init__.py index 62a04567..9f3b3af1 100644 --- a/mopidy/backends/dummy/__init__.py +++ b/mopidy/backends/dummy/__init__.py @@ -1,6 +1,6 @@ from mopidy.backends.base import (BaseBackend, CurrentPlaylistController, BasePlaybackController, BasePlaybackProvider, LibraryController, - BaseLibraryProvider, BaseStoredPlaylistsController, + BaseLibraryProvider, StoredPlaylistsController, BaseStoredPlaylistsProvider) from mopidy.models import Playlist @@ -37,7 +37,7 @@ class DummyBackend(BaseBackend): provider=playback_provider) stored_playlists_provider = DummyStoredPlaylistsProvider(backend=self) - self.stored_playlists = BaseStoredPlaylistsController(backend=self, + self.stored_playlists = StoredPlaylistsController(backend=self, provider=stored_playlists_provider) self.uri_handlers = [u'dummy:'] diff --git a/mopidy/backends/libspotify/__init__.py b/mopidy/backends/libspotify/__init__.py index 59ff1fde..985a1243 100644 --- a/mopidy/backends/libspotify/__init__.py +++ b/mopidy/backends/libspotify/__init__.py @@ -2,7 +2,7 @@ import logging from mopidy import settings from mopidy.backends.base import (BaseBackend, CurrentPlaylistController, - LibraryController, BasePlaybackController, BaseStoredPlaylistsController) + LibraryController, BasePlaybackController, StoredPlaylistsController) logger = logging.getLogger('mopidy.backends.libspotify') @@ -52,7 +52,7 @@ class LibspotifyBackend(BaseBackend): stored_playlists_provider = LibspotifyStoredPlaylistsProvider( backend=self) - self.stored_playlists = BaseStoredPlaylistsController(backend=self, + self.stored_playlists = StoredPlaylistsController(backend=self, provider=stored_playlists_provider) self.uri_handlers = [u'spotify:', u'http://open.spotify.com/'] diff --git a/mopidy/backends/local/__init__.py b/mopidy/backends/local/__init__.py index ef42f4c4..44dc727b 100644 --- a/mopidy/backends/local/__init__.py +++ b/mopidy/backends/local/__init__.py @@ -7,7 +7,7 @@ import shutil from mopidy import settings from mopidy.backends.base import (BaseBackend, CurrentPlaylistController, LibraryController, BaseLibraryProvider, BasePlaybackController, - BasePlaybackProvider, BaseStoredPlaylistsController, + BasePlaybackProvider, StoredPlaylistsController, BaseStoredPlaylistsProvider) from mopidy.models import Playlist, Track, Album from mopidy.utils.process import pickle_connection @@ -43,7 +43,7 @@ class LocalBackend(BaseBackend): provider=playback_provider) stored_playlists_provider = LocalStoredPlaylistsProvider(backend=self) - self.stored_playlists = BaseStoredPlaylistsController(backend=self, + self.stored_playlists = StoredPlaylistsController(backend=self, provider=stored_playlists_provider) self.uri_handlers = [u'file://'] diff --git a/tests/backends/base/stored_playlists.py b/tests/backends/base/stored_playlists.py index 5bcd322c..0ac0b167 100644 --- a/tests/backends/base/stored_playlists.py +++ b/tests/backends/base/stored_playlists.py @@ -8,7 +8,7 @@ from mopidy.models import Playlist from tests import SkipTest, data_folder -class BaseStoredPlaylistsControllerTest(object): +class StoredPlaylistsControllerTest(object): def setUp(self): settings.LOCAL_PLAYLIST_PATH = tempfile.mkdtemp() settings.LOCAL_TAG_CACHE_FILE = data_folder('library_tag_cache') diff --git a/tests/backends/local/stored_playlists_test.py b/tests/backends/local/stored_playlists_test.py index 4db9e1e2..a7d9043f 100644 --- a/tests/backends/local/stored_playlists_test.py +++ b/tests/backends/local/stored_playlists_test.py @@ -16,10 +16,10 @@ from mopidy.utils.path import path_to_uri from tests import data_folder from tests.backends.base.stored_playlists import \ - BaseStoredPlaylistsControllerTest + StoredPlaylistsControllerTest from tests.backends.local import generate_song -class LocalStoredPlaylistsControllerTest(BaseStoredPlaylistsControllerTest, +class LocalStoredPlaylistsControllerTest(StoredPlaylistsControllerTest, unittest.TestCase): backend_class = LocalBackend From 9a1f16cba6999a2e67293d642a4e192a82dc64e5 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Wed, 3 Nov 2010 00:03:08 +0100 Subject: [PATCH 21/22] Rename {Base => }Backend --- docs/api/backends/controllers.rst | 2 +- mopidy/backends/base/__init__.py | 2 +- mopidy/backends/base/current_playlist.py | 2 +- mopidy/backends/base/library.py | 4 ++-- mopidy/backends/base/playback.py | 4 ++-- mopidy/backends/base/stored_playlists.py | 4 ++-- mopidy/backends/dummy/__init__.py | 4 ++-- mopidy/backends/libspotify/__init__.py | 4 ++-- mopidy/backends/local/__init__.py | 4 ++-- mopidy/frontends/base.py | 2 +- mopidy/mixers/base.py | 2 +- 11 files changed, 17 insertions(+), 17 deletions(-) diff --git a/docs/api/backends/controllers.rst b/docs/api/backends/controllers.rst index 97ce2508..a48a472b 100644 --- a/docs/api/backends/controllers.rst +++ b/docs/api/backends/controllers.rst @@ -13,7 +13,7 @@ The backend controller API is the interface that is used by frontends like The backend =========== -.. autoclass:: mopidy.backends.base.BaseBackend +.. autoclass:: mopidy.backends.base.Backend :members: :undoc-members: diff --git a/mopidy/backends/base/__init__.py b/mopidy/backends/base/__init__.py index f1fdfcbe..ae668807 100644 --- a/mopidy/backends/base/__init__.py +++ b/mopidy/backends/base/__init__.py @@ -16,7 +16,7 @@ from .stored_playlists import (StoredPlaylistsController, logger = logging.getLogger('mopidy.backends.base') -class BaseBackend(object): +class Backend(object): """ :param core_queue: a queue for sending messages to :class:`mopidy.process.CoreProcess` diff --git a/mopidy/backends/base/current_playlist.py b/mopidy/backends/base/current_playlist.py index fec8e5a3..fe7d1de9 100644 --- a/mopidy/backends/base/current_playlist.py +++ b/mopidy/backends/base/current_playlist.py @@ -9,7 +9,7 @@ logger = logging.getLogger('mopidy.backends.base') class CurrentPlaylistController(object): """ :param backend: backend the controller is a part of - :type backend: :class:`BaseBackend` + :type backend: :class:`mopidy.backends.base.Backend` """ def __init__(self, backend): diff --git a/mopidy/backends/base/library.py b/mopidy/backends/base/library.py index f3477489..fd018b5f 100644 --- a/mopidy/backends/base/library.py +++ b/mopidy/backends/base/library.py @@ -5,7 +5,7 @@ logger = logging.getLogger('mopidy.backends.base') class LibraryController(object): """ :param backend: backend the controller is a part of - :type backend: :class:`BaseBackend` + :type backend: :class:`mopidy.backends.base.Backend` :param provider: provider the controller should use :type provider: instance of :class:`BaseLibraryProvider` """ @@ -79,7 +79,7 @@ class LibraryController(object): class BaseLibraryProvider(object): """ :param backend: backend the controller is a part of - :type backend: :class:`BaseBackend` + :type backend: :class:`mopidy.backends.base.Backend` """ def __init__(self, backend): diff --git a/mopidy/backends/base/playback.py b/mopidy/backends/base/playback.py index fa848845..727cce00 100644 --- a/mopidy/backends/base/playback.py +++ b/mopidy/backends/base/playback.py @@ -7,7 +7,7 @@ logger = logging.getLogger('mopidy.backends.base') class BasePlaybackController(object): """ :param backend: the backend - :type backend: :class:`BaseBackend` + :type backend: :class:`mopidy.backends.base.Backend` :param provider: provider the controller should use :type provider: instance of :class:`BasePlaybackProvider` """ @@ -488,7 +488,7 @@ class BasePlaybackController(object): class BasePlaybackProvider(object): """ :param backend: the backend - :type backend: :class:`BaseBackend` + :type backend: :class:`mopidy.backends.base.Backend` """ def __init__(self, backend): diff --git a/mopidy/backends/base/stored_playlists.py b/mopidy/backends/base/stored_playlists.py index 733ea46f..6578c046 100644 --- a/mopidy/backends/base/stored_playlists.py +++ b/mopidy/backends/base/stored_playlists.py @@ -6,7 +6,7 @@ logger = logging.getLogger('mopidy.backends.base') class StoredPlaylistsController(object): """ :param backend: backend the controller is a part of - :type backend: :class:`BaseBackend` + :type backend: :class:`mopidy.backends.base.Backend` :param provider: provider the controller should use :type provider: instance of :class:`BaseStoredPlaylistsProvider` """ @@ -122,7 +122,7 @@ class StoredPlaylistsController(object): class BaseStoredPlaylistsProvider(object): """ :param backend: backend the controller is a part of - :type backend: :class:`BaseBackend` + :type backend: :class:`mopidy.backends.base.Backend` """ def __init__(self, backend): diff --git a/mopidy/backends/dummy/__init__.py b/mopidy/backends/dummy/__init__.py index 9f3b3af1..5106de14 100644 --- a/mopidy/backends/dummy/__init__.py +++ b/mopidy/backends/dummy/__init__.py @@ -1,4 +1,4 @@ -from mopidy.backends.base import (BaseBackend, CurrentPlaylistController, +from mopidy.backends.base import (Backend, CurrentPlaylistController, BasePlaybackController, BasePlaybackProvider, LibraryController, BaseLibraryProvider, StoredPlaylistsController, BaseStoredPlaylistsProvider) @@ -13,7 +13,7 @@ class DummyQueue(object): self.received_messages.append(message) -class DummyBackend(BaseBackend): +class DummyBackend(Backend): """ A backend which implements the backend API in the simplest way possible. Used in tests of the frontends. diff --git a/mopidy/backends/libspotify/__init__.py b/mopidy/backends/libspotify/__init__.py index 985a1243..00619a6c 100644 --- a/mopidy/backends/libspotify/__init__.py +++ b/mopidy/backends/libspotify/__init__.py @@ -1,14 +1,14 @@ import logging from mopidy import settings -from mopidy.backends.base import (BaseBackend, CurrentPlaylistController, +from mopidy.backends.base import (Backend, CurrentPlaylistController, LibraryController, BasePlaybackController, StoredPlaylistsController) logger = logging.getLogger('mopidy.backends.libspotify') ENCODING = 'utf-8' -class LibspotifyBackend(BaseBackend): +class LibspotifyBackend(Backend): """ A `Spotify `_ backend which uses the official `libspotify `_ diff --git a/mopidy/backends/local/__init__.py b/mopidy/backends/local/__init__.py index 44dc727b..68654749 100644 --- a/mopidy/backends/local/__init__.py +++ b/mopidy/backends/local/__init__.py @@ -5,7 +5,7 @@ import os import shutil from mopidy import settings -from mopidy.backends.base import (BaseBackend, CurrentPlaylistController, +from mopidy.backends.base import (Backend, CurrentPlaylistController, LibraryController, BaseLibraryProvider, BasePlaybackController, BasePlaybackProvider, StoredPlaylistsController, BaseStoredPlaylistsProvider) @@ -16,7 +16,7 @@ from .translator import parse_m3u, parse_mpd_tag_cache logger = logging.getLogger(u'mopidy.backends.local') -class LocalBackend(BaseBackend): +class LocalBackend(Backend): """ A backend for playing music from a local music archive. diff --git a/mopidy/frontends/base.py b/mopidy/frontends/base.py index e15c4745..bf1c9bda 100644 --- a/mopidy/frontends/base.py +++ b/mopidy/frontends/base.py @@ -5,7 +5,7 @@ class BaseFrontend(object): :param core_queue: queue for messaging the core :type core_queue: :class:`multiprocessing.Queue` :param backend: the backend - :type backend: :class:`mopidy.backends.base.BaseBackend` + :type backend: :class:`mopidy.backends.base.Backend` """ def __init__(self, core_queue, backend): diff --git a/mopidy/mixers/base.py b/mopidy/mixers/base.py index 231154ee..f7f9525c 100644 --- a/mopidy/mixers/base.py +++ b/mopidy/mixers/base.py @@ -3,7 +3,7 @@ from mopidy import settings class BaseMixer(object): """ :param backend: a backend instance - :type mixer: :class:`mopidy.backends.base.BaseBackend` + :type backend: :class:`mopidy.backends.base.Backend` **Settings:** From fc9daa5a5a95df0ce2b9fadc2cc989cea9b9f120 Mon Sep 17 00:00:00 2001 From: Stein Magnus Jodal Date: Wed, 3 Nov 2010 00:06:32 +0100 Subject: [PATCH 22/22] Rename {Base => }PlaybackController --- docs/api/backends/controllers.rst | 2 +- mopidy/backends/base/__init__.py | 4 ++-- mopidy/backends/base/playback.py | 2 +- mopidy/backends/dummy/__init__.py | 4 ++-- mopidy/backends/libspotify/__init__.py | 4 ++-- mopidy/backends/local/__init__.py | 4 ++-- tests/backends/base/playback.py | 2 +- tests/backends/local/playback_test.py | 6 ++---- 8 files changed, 13 insertions(+), 15 deletions(-) diff --git a/docs/api/backends/controllers.rst b/docs/api/backends/controllers.rst index a48a472b..88bb48ff 100644 --- a/docs/api/backends/controllers.rst +++ b/docs/api/backends/controllers.rst @@ -24,7 +24,7 @@ Playback controller Manages playback, with actions like play, pause, stop, next, previous, and seek. -.. autoclass:: mopidy.backends.base.BasePlaybackController +.. autoclass:: mopidy.backends.base.PlaybackController :members: :undoc-members: diff --git a/mopidy/backends/base/__init__.py b/mopidy/backends/base/__init__.py index ae668807..096a433f 100644 --- a/mopidy/backends/base/__init__.py +++ b/mopidy/backends/base/__init__.py @@ -10,7 +10,7 @@ from mopidy.utils import get_class from .current_playlist import CurrentPlaylistController from .library import LibraryController, BaseLibraryProvider -from .playback import BasePlaybackController, BasePlaybackProvider +from .playback import PlaybackController, BasePlaybackProvider from .stored_playlists import (StoredPlaylistsController, BaseStoredPlaylistsProvider) @@ -53,7 +53,7 @@ class Backend(object): mixer = None #: The playback controller. An instance of - #: :class:`mopidy.backends.base.BasePlaybackController`. + #: :class:`mopidy.backends.base.PlaybackController`. playback = None #: The stored playlists controller. An instance of diff --git a/mopidy/backends/base/playback.py b/mopidy/backends/base/playback.py index 727cce00..8a3eeee5 100644 --- a/mopidy/backends/base/playback.py +++ b/mopidy/backends/base/playback.py @@ -4,7 +4,7 @@ import time logger = logging.getLogger('mopidy.backends.base') -class BasePlaybackController(object): +class PlaybackController(object): """ :param backend: the backend :type backend: :class:`mopidy.backends.base.Backend` diff --git a/mopidy/backends/dummy/__init__.py b/mopidy/backends/dummy/__init__.py index 5106de14..9c6885bc 100644 --- a/mopidy/backends/dummy/__init__.py +++ b/mopidy/backends/dummy/__init__.py @@ -1,5 +1,5 @@ from mopidy.backends.base import (Backend, CurrentPlaylistController, - BasePlaybackController, BasePlaybackProvider, LibraryController, + PlaybackController, BasePlaybackProvider, LibraryController, BaseLibraryProvider, StoredPlaylistsController, BaseStoredPlaylistsProvider) from mopidy.models import Playlist @@ -33,7 +33,7 @@ class DummyBackend(Backend): provider=library_provider) playback_provider = DummyPlaybackProvider(backend=self) - self.playback = BasePlaybackController(backend=self, + self.playback = PlaybackController(backend=self, provider=playback_provider) stored_playlists_provider = DummyStoredPlaylistsProvider(backend=self) diff --git a/mopidy/backends/libspotify/__init__.py b/mopidy/backends/libspotify/__init__.py index 00619a6c..4d8b67d5 100644 --- a/mopidy/backends/libspotify/__init__.py +++ b/mopidy/backends/libspotify/__init__.py @@ -2,7 +2,7 @@ import logging from mopidy import settings from mopidy.backends.base import (Backend, CurrentPlaylistController, - LibraryController, BasePlaybackController, StoredPlaylistsController) + LibraryController, PlaybackController, StoredPlaylistsController) logger = logging.getLogger('mopidy.backends.libspotify') @@ -47,7 +47,7 @@ class LibspotifyBackend(Backend): provider=library_provider) playback_provider = LibspotifyPlaybackProvider(backend=self) - self.playback = BasePlaybackController(backend=self, + self.playback = PlaybackController(backend=self, provider=playback_provider) stored_playlists_provider = LibspotifyStoredPlaylistsProvider( diff --git a/mopidy/backends/local/__init__.py b/mopidy/backends/local/__init__.py index 68654749..532c3976 100644 --- a/mopidy/backends/local/__init__.py +++ b/mopidy/backends/local/__init__.py @@ -6,7 +6,7 @@ import shutil from mopidy import settings from mopidy.backends.base import (Backend, CurrentPlaylistController, - LibraryController, BaseLibraryProvider, BasePlaybackController, + LibraryController, BaseLibraryProvider, PlaybackController, BasePlaybackProvider, StoredPlaylistsController, BaseStoredPlaylistsProvider) from mopidy.models import Playlist, Track, Album @@ -49,7 +49,7 @@ class LocalBackend(Backend): self.uri_handlers = [u'file://'] -class LocalPlaybackController(BasePlaybackController): +class LocalPlaybackController(PlaybackController): def __init__(self, *args, **kwargs): super(LocalPlaybackController, self).__init__(*args, **kwargs) diff --git a/tests/backends/base/playback.py b/tests/backends/base/playback.py index 7b6efe7a..26662f96 100644 --- a/tests/backends/base/playback.py +++ b/tests/backends/base/playback.py @@ -13,7 +13,7 @@ from tests.backends.base import populate_playlist # TODO Test 'playlist repeat', e.g. repeat=1,single=0 -class BasePlaybackControllerTest(object): +class PlaybackControllerTest(object): tracks = [] def setUp(self): diff --git a/tests/backends/local/playback_test.py b/tests/backends/local/playback_test.py index a84dfcde..2007cff8 100644 --- a/tests/backends/local/playback_test.py +++ b/tests/backends/local/playback_test.py @@ -12,12 +12,10 @@ from mopidy.models import Track from mopidy.utils.path import path_to_uri from tests import data_folder -from tests.backends.base.playback import BasePlaybackControllerTest +from tests.backends.base.playback import PlaybackControllerTest from tests.backends.local import generate_song -class LocalPlaybackControllerTest(BasePlaybackControllerTest, - unittest.TestCase): - +class LocalPlaybackControllerTest(PlaybackControllerTest, unittest.TestCase): backend_class = LocalBackend tracks = [Track(uri=generate_song(i), length=4464) for i in range(1, 4)]