Merge pull request #389 from jodal/feature/spotify-using-config
Update Spotify backend to use config
This commit is contained in:
commit
7af373ca25
@ -28,7 +28,7 @@ timeout = 10
|
||||
cache_path = $XDG_CACHE_DIR/mopidy/spotify
|
||||
|
||||
# Connect to Spotify through a proxy
|
||||
proxy_host =
|
||||
proxy_hostname =
|
||||
proxy_username =
|
||||
proxy_password =
|
||||
"""
|
||||
@ -81,7 +81,7 @@ class Extension(ext.Extension):
|
||||
schema['bitrate'] = config.Integer(choices=(96, 160, 320))
|
||||
schema['timeout'] = config.Integer(minimum=0)
|
||||
schema['cache_path'] = config.String()
|
||||
schema['proxy_host'] = config.Hostname(optional=True)
|
||||
schema['proxy_hostname'] = config.Hostname(optional=True)
|
||||
schema['proxy_username'] = config.String(optional=True)
|
||||
schema['proxy_password'] = config.String(optional=True, secret=True)
|
||||
return schema
|
||||
|
||||
@ -4,23 +4,20 @@ import logging
|
||||
|
||||
import pykka
|
||||
|
||||
from mopidy import settings
|
||||
from mopidy.backends import base
|
||||
from mopidy.backends.spotify.library import SpotifyLibraryProvider
|
||||
from mopidy.backends.spotify.playback import SpotifyPlaybackProvider
|
||||
from mopidy.backends.spotify.session_manager import SpotifySessionManager
|
||||
from mopidy.backends.spotify.playlists import SpotifyPlaylistsProvider
|
||||
|
||||
logger = logging.getLogger('mopidy.backends.spotify')
|
||||
|
||||
|
||||
class SpotifyBackend(pykka.ThreadingActor, base.Backend):
|
||||
# Imports inside methods are to prevent loading of __init__.py to fail on
|
||||
# missing spotify dependencies.
|
||||
|
||||
def __init__(self, config, audio):
|
||||
super(SpotifyBackend, self).__init__()
|
||||
|
||||
from .library import SpotifyLibraryProvider
|
||||
from .playback import SpotifyPlaybackProvider
|
||||
from .session_manager import SpotifySessionManager
|
||||
from .playlists import SpotifyPlaylistsProvider
|
||||
self.config = config
|
||||
|
||||
self.library = SpotifyLibraryProvider(backend=self)
|
||||
self.playback = SpotifyPlaybackProvider(audio=audio, backend=self)
|
||||
@ -28,17 +25,8 @@ class SpotifyBackend(pykka.ThreadingActor, base.Backend):
|
||||
|
||||
self.uri_schemes = ['spotify']
|
||||
|
||||
# Fail early if settings are not present
|
||||
username = settings.SPOTIFY_USERNAME
|
||||
password = settings.SPOTIFY_PASSWORD
|
||||
proxy = settings.SPOTIFY_PROXY_HOST
|
||||
proxy_username = settings.SPOTIFY_PROXY_USERNAME
|
||||
proxy_password = settings.SPOTIFY_PROXY_PASSWORD
|
||||
|
||||
self.spotify = SpotifySessionManager(
|
||||
username, password, audio=audio, backend_ref=self.actor_ref,
|
||||
proxy=proxy, proxy_username=proxy_username,
|
||||
proxy_password=proxy_password)
|
||||
config, audio=audio, backend_ref=self.actor_ref)
|
||||
|
||||
def on_start(self):
|
||||
logger.info('Mopidy uses SPOTIFY(R) CORE')
|
||||
|
||||
@ -7,7 +7,6 @@ import urllib
|
||||
import pykka
|
||||
from spotify import Link, SpotifyError
|
||||
|
||||
from mopidy import settings
|
||||
from mopidy.backends import base
|
||||
from mopidy.models import Track, SearchResult
|
||||
|
||||
@ -62,6 +61,10 @@ class SpotifyTrack(Track):
|
||||
|
||||
|
||||
class SpotifyLibraryProvider(base.BaseLibraryProvider):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(SpotifyLibraryProvider).__init__(*args, **kwargs)
|
||||
self._timeout = self.backend.config['spotify']['timeout']
|
||||
|
||||
def find_exact(self, query=None, uris=None):
|
||||
return self.search(query=query, uris=uris)
|
||||
|
||||
@ -116,10 +119,11 @@ class SpotifyLibraryProvider(base.BaseLibraryProvider):
|
||||
SpotifyTrack(track=t)
|
||||
for t in playlist if t.availability() == TRACK_AVAILABLE]
|
||||
|
||||
def _wait_for_object_to_load(
|
||||
self, spotify_obj, timeout=settings.SPOTIFY_TIMEOUT):
|
||||
def _wait_for_object_to_load(self, spotify_obj, timeout=None):
|
||||
# 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.
|
||||
if timeout is None:
|
||||
timeout = self._timeout
|
||||
wait_until = time.time() + timeout
|
||||
while not spotify_obj.is_loaded():
|
||||
time.sleep(0.1)
|
||||
@ -166,7 +170,7 @@ class SpotifyLibraryProvider(base.BaseLibraryProvider):
|
||||
future.set(search_result)
|
||||
|
||||
# Wait always returns None on python 2.6 :/
|
||||
self.backend.spotify.connected.wait(settings.SPOTIFY_TIMEOUT)
|
||||
self.backend.spotify.connected.wait(self._timeout)
|
||||
if not self.backend.spotify.connected.is_set():
|
||||
logger.debug('Not connected: Spotify search cancelled')
|
||||
return SearchResult(uri='spotify:search')
|
||||
@ -176,11 +180,10 @@ class SpotifyLibraryProvider(base.BaseLibraryProvider):
|
||||
album_count=200, artist_count=200, track_count=200)
|
||||
|
||||
try:
|
||||
return future.get(timeout=settings.SPOTIFY_TIMEOUT)
|
||||
return future.get(timeout=self._timeout)
|
||||
except pykka.Timeout:
|
||||
logger.debug(
|
||||
'Timeout: Spotify search did not return in %ds',
|
||||
settings.SPOTIFY_TIMEOUT)
|
||||
'Timeout: Spotify search did not return in %ds', self._timeout)
|
||||
return SearchResult(uri='spotify:search')
|
||||
|
||||
def _get_all_tracks(self):
|
||||
|
||||
@ -6,7 +6,7 @@ import threading
|
||||
|
||||
from spotify.manager import SpotifySessionManager as PyspotifySessionManager
|
||||
|
||||
from mopidy import audio, settings
|
||||
from mopidy import audio
|
||||
from mopidy.backends.listener import BackendListener
|
||||
from mopidy.utils import process, versioning
|
||||
|
||||
@ -23,17 +23,21 @@ BITRATES = {96: 2, 160: 0, 320: 1}
|
||||
|
||||
|
||||
class SpotifySessionManager(process.BaseThread, PyspotifySessionManager):
|
||||
cache_location = settings.SPOTIFY_CACHE_PATH
|
||||
cache_location = None
|
||||
settings_location = cache_location
|
||||
appkey_file = os.path.join(os.path.dirname(__file__), 'spotify_appkey.key')
|
||||
user_agent = 'Mopidy %s' % versioning.get_version()
|
||||
|
||||
def __init__(self, username, password, audio, backend_ref, proxy=None,
|
||||
proxy_username=None, proxy_password=None):
|
||||
def __init__(self, config, audio, backend_ref):
|
||||
|
||||
self.cache_location = config['spotify']['cache_path']
|
||||
|
||||
PyspotifySessionManager.__init__(
|
||||
self, username, password, proxy=proxy,
|
||||
proxy_username=proxy_username,
|
||||
proxy_password=proxy_password)
|
||||
self, config['spotify']['username'], config['spotify']['password'],
|
||||
proxy=config['spotify']['proxy_hostname'],
|
||||
proxy_username=config['spotify']['proxy_username'],
|
||||
proxy_password=config['spotify']['proxy_password'])
|
||||
|
||||
process.BaseThread.__init__(self)
|
||||
self.name = 'SpotifyThread'
|
||||
|
||||
@ -41,6 +45,8 @@ class SpotifySessionManager(process.BaseThread, PyspotifySessionManager):
|
||||
self.backend = None
|
||||
self.backend_ref = backend_ref
|
||||
|
||||
self.bitrate = config['spotify']['bitrate']
|
||||
|
||||
self.connected = threading.Event()
|
||||
self.push_audio_data = True
|
||||
self.buffer_timestamp = 0
|
||||
@ -66,10 +72,8 @@ class SpotifySessionManager(process.BaseThread, PyspotifySessionManager):
|
||||
if not hasattr(self, 'session'):
|
||||
self.session = session
|
||||
|
||||
logger.debug(
|
||||
'Preferred Spotify bitrate is %s kbps',
|
||||
settings.SPOTIFY_BITRATE)
|
||||
session.set_preferred_bitrate(BITRATES[settings.SPOTIFY_BITRATE])
|
||||
logger.debug('Preferred Spotify bitrate is %d kbps', self.bitrate)
|
||||
session.set_preferred_bitrate(BITRATES[self.bitrate])
|
||||
|
||||
self.container_manager = SpotifyContainerManager(self)
|
||||
self.playlist_manager = SpotifyPlaylistManager(self)
|
||||
@ -167,9 +171,14 @@ class SpotifySessionManager(process.BaseThread, PyspotifySessionManager):
|
||||
if not self._initial_data_receive_completed:
|
||||
logger.debug('Still getting data; skipped refresh of playlists')
|
||||
return
|
||||
playlists = map(
|
||||
translator.to_mopidy_playlist, self.session.playlist_container())
|
||||
playlists.append(translator.to_mopidy_playlist(self.session.starred()))
|
||||
playlists = []
|
||||
for spotify_playlist in self.session.playlist_container():
|
||||
playlists.append(translator.to_mopidy_playlist(
|
||||
spotify_playlist,
|
||||
bitrate=self.bitrate, username=self.username))
|
||||
playlists.append(translator.to_mopidy_playlist(
|
||||
self.session.starred(),
|
||||
bitrate=self.bitrate, username=self.username))
|
||||
playlists = filter(None, playlists)
|
||||
self.backend.playlists.playlists = playlists
|
||||
logger.info('Loaded %d Spotify playlist(s)', len(playlists))
|
||||
|
||||
@ -2,7 +2,6 @@ from __future__ import unicode_literals
|
||||
|
||||
from spotify import Link
|
||||
|
||||
from mopidy import settings
|
||||
from mopidy.models import Artist, Album, Track, Playlist
|
||||
|
||||
|
||||
@ -39,7 +38,7 @@ def to_mopidy_album(spotify_album):
|
||||
return album_cache[uri]
|
||||
|
||||
|
||||
def to_mopidy_track(spotify_track):
|
||||
def to_mopidy_track(spotify_track, bitrate=None):
|
||||
if spotify_track is None:
|
||||
return
|
||||
uri = str(Link.from_track(spotify_track, 0))
|
||||
@ -60,11 +59,11 @@ def to_mopidy_track(spotify_track):
|
||||
track_no=spotify_track.index(),
|
||||
date=date,
|
||||
length=spotify_track.duration(),
|
||||
bitrate=settings.SPOTIFY_BITRATE)
|
||||
bitrate=bitrate)
|
||||
return track_cache[uri]
|
||||
|
||||
|
||||
def to_mopidy_playlist(spotify_playlist):
|
||||
def to_mopidy_playlist(spotify_playlist, bitrate=None, username=None):
|
||||
if spotify_playlist is None or spotify_playlist.type() != 'playlist':
|
||||
return
|
||||
uri = str(Link.from_playlist(spotify_playlist))
|
||||
@ -72,7 +71,7 @@ def to_mopidy_playlist(spotify_playlist):
|
||||
return Playlist(uri=uri, name='[loading...]')
|
||||
name = spotify_playlist.name()
|
||||
tracks = [
|
||||
to_mopidy_track(spotify_track)
|
||||
to_mopidy_track(spotify_track, bitrate=bitrate)
|
||||
for spotify_track in spotify_playlist
|
||||
if not spotify_track.is_local()
|
||||
]
|
||||
@ -81,9 +80,6 @@ def to_mopidy_playlist(spotify_playlist):
|
||||
# Tracks in the Starred playlist are in reverse order from the official
|
||||
# client.
|
||||
tracks.reverse()
|
||||
if spotify_playlist.owner().canonical_name() != settings.SPOTIFY_USERNAME:
|
||||
if spotify_playlist.owner().canonical_name() != username:
|
||||
name += ' by ' + spotify_playlist.owner().canonical_name()
|
||||
return Playlist(
|
||||
uri=uri,
|
||||
name=name,
|
||||
tracks=tracks)
|
||||
return Playlist(uri=uri, name=name, tracks=tracks)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user