Merge pull request #284 from jodal/feature/improved-lookup
Improved Spotify lookup by URI
This commit is contained in:
commit
e2932672d5
1
AUTHORS
1
AUTHORS
@ -12,3 +12,4 @@
|
||||
- Christian Johansen <christian@cjohansen.no>
|
||||
- Matt Bray <mattjbray@gmail.com>
|
||||
- Trygve Aaberge <trygveaa@gmail.com>
|
||||
- Wouter van Wijk <woutervanwijk@gmail.com>
|
||||
|
||||
@ -13,6 +13,17 @@ v0.11.0 (in development)
|
||||
- Add :attr:`mopidy.settings.SPOTIFY_TIMEOUT` setting which allows you to
|
||||
control how long we should wait before giving up on Spotify searches, etc.
|
||||
|
||||
- Add support for looking up albums, artists, and playlists by URI in addition
|
||||
to tracks. (Fixes: :issue:`67`)
|
||||
|
||||
As an example of how this can be used, you can try the the following MPD
|
||||
commands which now all adds one or more tracks to your tracklist::
|
||||
|
||||
add "spotify:track:1mwt9hzaH7idmC5UCoOUkz"
|
||||
add "spotify:album:3gpHG5MGwnipnap32lFYvI"
|
||||
add "spotify:artist:5TgQ66WuWkoQ2xYxaSTnVP"
|
||||
add "spotify:user:p3.no:playlist:0XX6tamRiqEgh3t6FPFEkw"
|
||||
|
||||
**MPD frontend**
|
||||
|
||||
- Add :attr:`mopidy.settings.MPD_SERVER_CONNECTION_TIMEOUT` setting which
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import logging
|
||||
import time
|
||||
|
||||
import pykka
|
||||
from spotify import Link, SpotifyError
|
||||
@ -16,9 +17,14 @@ logger = logging.getLogger('mopidy.backends.spotify')
|
||||
|
||||
class SpotifyTrack(Track):
|
||||
"""Proxy object for unloaded Spotify tracks."""
|
||||
def __init__(self, uri):
|
||||
def __init__(self, uri=None, track=None):
|
||||
super(SpotifyTrack, self).__init__()
|
||||
self._spotify_track = Link.from_string(uri).as_track()
|
||||
if (uri and track) or (not uri and not track):
|
||||
raise AttributeError('uri or track must be provided')
|
||||
elif uri:
|
||||
self._spotify_track = Link.from_string(uri).as_track()
|
||||
elif track:
|
||||
self._spotify_track = track
|
||||
self._unloaded_track = Track(uri=uri, name='[loading...]')
|
||||
self._track = None
|
||||
|
||||
@ -58,11 +64,55 @@ class SpotifyLibraryProvider(base.BaseLibraryProvider):
|
||||
|
||||
def lookup(self, uri):
|
||||
try:
|
||||
return [SpotifyTrack(uri)]
|
||||
except SpotifyError as e:
|
||||
logger.debug('Failed to lookup "%s": %s', uri, e)
|
||||
link = Link.from_string(uri)
|
||||
if link.type() == Link.LINK_TRACK:
|
||||
return self._lookup_track(uri)
|
||||
if link.type() == Link.LINK_ALBUM:
|
||||
return self._lookup_album(uri)
|
||||
elif link.type() == Link.LINK_ARTIST:
|
||||
return self._lookup_artist(uri)
|
||||
elif link.type() == Link.LINK_PLAYLIST:
|
||||
return self._lookup_playlist(uri)
|
||||
else:
|
||||
return []
|
||||
except SpotifyError as error:
|
||||
logger.debug(u'Failed to lookup "%s": %s', uri, error)
|
||||
return []
|
||||
|
||||
def _lookup_track(self, uri):
|
||||
track = Link.from_string(uri).as_track()
|
||||
self._wait_for_object_to_load(track)
|
||||
return [SpotifyTrack(track=track)]
|
||||
|
||||
def _lookup_album(self, uri):
|
||||
album = Link.from_string(uri).as_album()
|
||||
album_browser = self.backend.spotify.session.browse_album(album)
|
||||
self._wait_for_object_to_load(album_browser)
|
||||
return [SpotifyTrack(track=t) for t in album_browser]
|
||||
|
||||
def _lookup_artist(self, uri):
|
||||
artist = Link.from_string(uri).as_artist()
|
||||
artist_browser = self.backend.spotify.session.browse_artist(artist)
|
||||
self._wait_for_object_to_load(artist_browser)
|
||||
return [SpotifyTrack(track=t) for t in artist_browser]
|
||||
|
||||
def _lookup_playlist(self, uri):
|
||||
playlist = Link.from_string(uri).as_playlist()
|
||||
self._wait_for_object_to_load(playlist)
|
||||
return [SpotifyTrack(track=t) for t in playlist]
|
||||
|
||||
def _wait_for_object_to_load(
|
||||
self, spotify_obj, timeout=settings.SPOTIFY_TIMEOUT):
|
||||
# XXX Sleeping to wait for the Spotify object to load is an ugly hack,
|
||||
# but it works. We should look into other solutions for this.
|
||||
wait_until = time.time() + timeout
|
||||
while not spotify_obj.is_loaded():
|
||||
time.sleep(0.1)
|
||||
if time.time() > wait_until:
|
||||
logger.debug(
|
||||
'Timeout: Spotify object did not load in %ds', timeout)
|
||||
return
|
||||
|
||||
def refresh(self, uri=None):
|
||||
pass # TODO
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user