diff --git a/mopidy/backends/despotify.py b/mopidy/backends/despotify.py index a60e2aac..229f74dc 100644 --- a/mopidy/backends/despotify.py +++ b/mopidy/backends/despotify.py @@ -5,7 +5,9 @@ import sys import spytify from mopidy import config -from mopidy.backends import BaseBackend +from mopidy.backends import (BaseBackend, BaseCurrentPlaylistController, + BaseLibraryController, BasePlaybackController, + BaseStoredPlaylistsController) from mopidy.models import Artist, Album, Track, Playlist logger = logging.getLogger(u'backends.despotify') @@ -14,36 +16,91 @@ ENCODING = 'utf-8' class DespotifyBackend(BaseBackend): def __init__(self, *args, **kwargs): - super(DespotifyBackend, self).__init__(*args, **kwargs) - logger.info(u'Connecting to Spotify') - self.spotify = spytify.Spytify( - config.SPOTIFY_USERNAME, config.SPOTIFY_PASSWORD) - self.cache_stored_playlists() + self.current_playlist = DespotifyCurrentPlaylistController(backend=self) + self.library = DespotifyLibraryController(backend=self) + self.playback = DespotifyPlaybackController(backend=self) + self.stored_playlists = DespotifyStoredPlaylistsController(backend=self) + self.uri_handlers = [u'spotify:', u'http://open.spotify.com/'] + self.translate = DespotifyTranslator() + self.spotify = self._connect() + self.stored_playlists.refresh() - def cache_stored_playlists(self): + def _connect(self): + logger.info(u'Connecting to Spotify') + return spytify.Spytify( + config.SPOTIFY_USERNAME, config.SPOTIFY_PASSWORD) + + +class DespotifyCurrentPlaylistController(BaseCurrentPlaylistController): + pass + + +class DespotifyLibraryController(BaseLibraryController): + def search(self, type, what): + query = u'%s:%s' % (type, what) + result = self.backend.spotify.search(query.encode(ENCODING)) + if result is not None: + return self.backend.translate.to_mopidy_playlist(result.playlist) + + +class DespotifyPlaybackController(BasePlaybackController): + def _next(self, track): + return self._play(track) + + def _pause(self): + self.backend.spotify.pause() + return True + + def _play(self, track): + self.backend.spotify.play(self.backend.spotify.lookup(track.uri)) + return True + + def _previous(self, track): + return self._play(track) + + def _resume(self): + self.backend.spotify.resume() + return True + + def _stop(self): + self.backend.spotify.stop() + return True + + +class DespotifyStoredPlaylistsController(BaseStoredPlaylistsController): + def refresh(self): logger.info(u'Caching stored playlists') playlists = [] - for spotify_playlist in self.spotify.stored_playlists: - playlists.append(self._to_mopidy_playlist(spotify_playlist)) + for spotify_playlist in self.backend.spotify.stored_playlists: + playlists.append( + self.backend.translate.to_mopidy_playlist(spotify_playlist)) self._playlists = playlists logger.debug(u'Available playlists: %s', - u', '.join([u'<%s>' % p.name for p in self._playlists])) + u', '.join([u'<%s>' % p.name + for p in self.backend.stored_playlists.playlists])) -# Model translation - def _to_mopidy_id(self, spotify_uri): - return 0 # TODO +class DespotifyTranslator(object): + uri_to_id_map = {} + next_id = 0 - def _to_mopidy_artist(self, spotify_artist): + def to_mopidy_id(self, spotify_uri): + if spotify_uri not in self.uri_to_id_map: + id = self.next_id + self.next_id += 1 + self.uri_to_id_map[spotify_uri] = id + return self.uri_to_id_map[spotify_uri] + + def to_mopidy_artist(self, spotify_artist): return Artist( uri=spotify_artist.get_uri(), name=spotify_artist.name.decode(ENCODING) ) - def _to_mopidy_album(self, spotify_album_name): + def to_mopidy_album(self, spotify_album_name): return Album(name=spotify_album_name.decode(ENCODING)) - def _to_mopidy_track(self, spotify_track): + def to_mopidy_track(self, spotify_track): if dt.MINYEAR <= int(spotify_track.year) <= dt.MAXYEAR: date = dt.date(spotify_track.year, 1, 1) else: @@ -51,74 +108,18 @@ class DespotifyBackend(BaseBackend): return Track( uri=spotify_track.get_uri(), title=spotify_track.title.decode(ENCODING), - artists=[self._to_mopidy_artist(a) for a in spotify_track.artists], - album=self._to_mopidy_album(spotify_track.album), + artists=[self.to_mopidy_artist(a) for a in spotify_track.artists], + album=self.to_mopidy_album(spotify_track.album), track_no=spotify_track.tracknumber, date=date, length=spotify_track.length, - id=self._to_mopidy_id(spotify_track.get_uri()), + bitrate=320, + id=self.to_mopidy_id(spotify_track.get_uri()), ) - def _to_mopidy_playlist(self, spotify_playlist): + def to_mopidy_playlist(self, spotify_playlist): return Playlist( uri=spotify_playlist.get_uri(), name=spotify_playlist.name.decode(ENCODING), - tracks=[self._to_mopidy_track(t) for t in spotify_playlist.tracks], + tracks=[self.to_mopidy_track(t) for t in spotify_playlist.tracks], ) - -# Play control - - def _next(self): - self._current_song_pos += 1 - self.spotify.play(self.spotify.lookup(self._current_track.uri)) - return True - - def _pause(self): - self.spotify.pause() - return True - - def _play(self): - if self._current_track is not None: - self.spotify.play(self.spotify.lookup(self._current_track.uri)) - return True - else: - return False - - def _play_id(self, songid): - self._current_song_pos = songid # XXX - self.spotify.play(self.spotify.lookup(self._current_track.uri)) - return True - - def _play_pos(self, songpos): - self._current_song_pos = songpos - self.spotify.play(self.spotify.lookup(self._current_track.uri)) - return True - - def _previous(self): - self._current_song_pos -= 1 - self.spotify.play(self.spotify.lookup(self._current_track.uri)) - return True - - def _resume(self): - self.spotify.resume() - return True - - def _stop(self): - self.spotify.stop() - return True - -# Status querying - - def status_bitrate(self): - return 320 - - def url_handlers(self): - return [u'spotify:', u'http://open.spotify.com/'] - -# Music database - - def search(self, type, what): - query = u'%s:%s' % (type, what) - result = self.spotify.search(query.encode(ENCODING)) - if result is not None: - return self._to_mopidy_playlist(result.playlist).mpd_format()