Remove despotify backend as library is no longer maintained
This commit is contained in:
parent
0557c8a595
commit
acd0437193
@ -82,14 +82,6 @@ Manages the music library, e.g. searching for tracks to be added to a playlist.
|
||||
:undoc-members:
|
||||
|
||||
|
||||
:mod:`mopidy.backends.despotify` -- Despotify backend
|
||||
=====================================================
|
||||
|
||||
.. automodule:: mopidy.backends.despotify
|
||||
:synopsis: Spotify backend using the Despotify library
|
||||
:members:
|
||||
|
||||
|
||||
:mod:`mopidy.backends.dummy` -- Dummy backend for testing
|
||||
=========================================================
|
||||
|
||||
|
||||
@ -47,6 +47,8 @@ Another great release.
|
||||
- :meth:`mopidy.backends.base.BaseBackend()` now accepts an
|
||||
``output_queue`` which it can use to send messages (i.e. audio data)
|
||||
to the output process.
|
||||
- Remove Depsotify backend.
|
||||
- Libspotify is now the default backend.
|
||||
|
||||
|
||||
|
||||
|
||||
@ -11,8 +11,7 @@ Version 0.1
|
||||
|
||||
- Core MPD server functionality working. Gracefully handle clients' use of
|
||||
non-supported functionality.
|
||||
- Read-only support for Spotify through :mod:`mopidy.backends.despotify` and/or
|
||||
:mod:`mopidy.backends.libspotify`.
|
||||
- Read-only support for Spotify through :mod:`mopidy.backends.libspotify`.
|
||||
- Initial support for local file playback through
|
||||
:mod:`mopidy.backends.local`. The state of local file playback will not
|
||||
block the release of 0.1.
|
||||
|
||||
@ -1,73 +0,0 @@
|
||||
**********************
|
||||
Despotify installation
|
||||
**********************
|
||||
|
||||
To use the `Despotify <http://despotify.se/>`_ backend, you first need to
|
||||
install Despotify and spytify.
|
||||
|
||||
.. warning::
|
||||
|
||||
This backend requires a Spotify premium account.
|
||||
|
||||
|
||||
Installing Despotify on Linux
|
||||
=============================
|
||||
|
||||
Install Despotify's dependencies. At Debian/Ubuntu systems::
|
||||
|
||||
sudo aptitude install libssl-dev zlib1g-dev libvorbis-dev \
|
||||
libtool libncursesw5-dev libao-dev python-dev
|
||||
|
||||
Check out revision 508 of the Despotify source code::
|
||||
|
||||
svn checkout https://despotify.svn.sourceforge.net/svnroot/despotify@508
|
||||
|
||||
Build and install Despotify::
|
||||
|
||||
cd despotify/src/
|
||||
sudo make install
|
||||
|
||||
When Despotify has been installed, continue with :ref:`spytify_installation`.
|
||||
|
||||
|
||||
Installing Despotify on OS X
|
||||
============================
|
||||
|
||||
In OS X you need to have `XCode <http://developer.apple.com/tools/xcode/>`_ and
|
||||
`Homebrew <http://mxcl.github.com/homebrew/>`_ installed. Then, to install
|
||||
Despotify::
|
||||
|
||||
brew install despotify
|
||||
|
||||
When Despotify has been installed, continue with :ref:`spytify_installation`.
|
||||
|
||||
|
||||
.. _spytify_installation:
|
||||
|
||||
Installing spytify
|
||||
==================
|
||||
|
||||
spytify's source comes bundled with despotify. If you haven't already checkout
|
||||
out the despotify source, do it now::
|
||||
|
||||
svn checkout https://despotify.svn.sourceforge.net/svnroot/despotify@508
|
||||
|
||||
Build and install spytify::
|
||||
|
||||
cd despotify/src/bindings/python/
|
||||
export PKG_CONFIG_PATH=../../lib # Needed on OS X
|
||||
sudo make install
|
||||
|
||||
|
||||
Testing the installation
|
||||
========================
|
||||
|
||||
To validate that everything is working, run the ``test.py`` script which is
|
||||
distributed with spytify::
|
||||
|
||||
python test.py
|
||||
|
||||
The test script should ask for your username and password (which must be for a
|
||||
Spotify Premium account), ask for a search query, list all your playlists with
|
||||
tracks, play 10s from a random song from the search result, pause for two
|
||||
seconds, play for five more seconds, and quit.
|
||||
@ -18,7 +18,6 @@ Install dependencies
|
||||
|
||||
gstreamer
|
||||
libspotify
|
||||
despotify
|
||||
|
||||
Make sure you got the required dependencies installed.
|
||||
|
||||
@ -44,10 +43,6 @@ Make sure you got the required dependencies installed.
|
||||
|
||||
- Dependencies for at least one Mopidy backend:
|
||||
|
||||
- :mod:`mopidy.backends.despotify` (Linux and OS X)
|
||||
|
||||
- :doc:`Despotify and spytify <despotify>`
|
||||
|
||||
- :mod:`mopidy.backends.libspotify` (Linux, OS X, and Windows)
|
||||
|
||||
- :doc:`libspotify and pyspotify <libspotify>`
|
||||
@ -106,7 +101,7 @@ username and password into the file, like this::
|
||||
SPOTIFY_USERNAME = u'myusername'
|
||||
SPOTIFY_PASSWORD = u'mysecret'
|
||||
|
||||
Currently :mod:`mopidy.backends.despotify` is the default
|
||||
Currently :mod:`mopidy.backends.libspotify` is the default
|
||||
backend.
|
||||
|
||||
If you want to use :mod:`mopidy.backends.libspotify`, copy the Spotify
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
libspotify installation
|
||||
***********************
|
||||
|
||||
As an alternative to the despotify backend, we are working on a
|
||||
We are working on a
|
||||
`libspotify <http://developer.spotify.com/en/libspotify/overview/>`_ backend.
|
||||
To use the libspotify backend you must install libspotify and
|
||||
`pyspotify <http://github.com/winjer/pyspotify>`_.
|
||||
|
||||
@ -1,209 +0,0 @@
|
||||
import datetime as dt
|
||||
import logging
|
||||
import sys
|
||||
|
||||
import spytify
|
||||
|
||||
from mopidy import settings
|
||||
from mopidy.backends.base import (BaseBackend, BaseCurrentPlaylistController,
|
||||
BaseLibraryController, BasePlaybackController,
|
||||
BaseStoredPlaylistsController)
|
||||
from mopidy.models import Artist, Album, Track, Playlist
|
||||
|
||||
logger = logging.getLogger('mopidy.backends.despotify')
|
||||
|
||||
ENCODING = 'utf-8'
|
||||
|
||||
class DespotifyBackend(BaseBackend):
|
||||
"""
|
||||
A Spotify backend which uses the open source `despotify library
|
||||
<http://despotify.se/>`_.
|
||||
|
||||
`spytify <http://despotify.svn.sourceforge.net/viewvc/despotify/src/bindings/python/>`_
|
||||
is the Python bindings for the despotify library. It got litle
|
||||
documentation, but a couple of examples are available.
|
||||
|
||||
**Issues:** http://github.com/jodal/mopidy/issues/labels/backend-despotify
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(DespotifyBackend, self).__init__(*args, **kwargs)
|
||||
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.spotify = self._connect()
|
||||
self.stored_playlists.refresh()
|
||||
|
||||
def _connect(self):
|
||||
logger.info(u'Connecting to Spotify')
|
||||
try:
|
||||
return DespotifySessionManager(
|
||||
settings.SPOTIFY_USERNAME.encode(ENCODING),
|
||||
settings.SPOTIFY_PASSWORD.encode(ENCODING),
|
||||
core_queue=self.core_queue)
|
||||
except spytify.SpytifyError as e:
|
||||
logger.exception(e)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
class DespotifyCurrentPlaylistController(BaseCurrentPlaylistController):
|
||||
pass
|
||||
|
||||
|
||||
class DespotifyLibraryController(BaseLibraryController):
|
||||
def find_exact(self, **query):
|
||||
return self.search(**query)
|
||||
|
||||
def lookup(self, uri):
|
||||
track = self.backend.spotify.lookup(uri.encode(ENCODING))
|
||||
return DespotifyTranslator.to_mopidy_track(track)
|
||||
|
||||
def refresh(self, uri=None):
|
||||
pass # TODO
|
||||
|
||||
def search(self, **query):
|
||||
spotify_query = []
|
||||
for (field, values) in query.iteritems():
|
||||
if not hasattr(values, '__iter__'):
|
||||
values = [values]
|
||||
for value in values:
|
||||
if field == u'track':
|
||||
field = u'title'
|
||||
if field == u'any':
|
||||
spotify_query.append(value)
|
||||
else:
|
||||
spotify_query.append(u'%s:"%s"' % (field, value))
|
||||
spotify_query = u' '.join(spotify_query)
|
||||
logger.debug(u'Spotify search query: %s', spotify_query)
|
||||
result = self.backend.spotify.search(spotify_query.encode(ENCODING))
|
||||
if (result is None or result.playlist.tracks[0].get_uri() ==
|
||||
'spotify:track:0000000000000000000000'):
|
||||
return Playlist()
|
||||
return DespotifyTranslator.to_mopidy_playlist(result.playlist)
|
||||
|
||||
|
||||
class DespotifyPlaybackController(BasePlaybackController):
|
||||
def _pause(self):
|
||||
try:
|
||||
self.backend.spotify.pause()
|
||||
return True
|
||||
except spytify.SpytifyError as e:
|
||||
logger.error(e)
|
||||
return False
|
||||
|
||||
def _play(self, track):
|
||||
try:
|
||||
self.backend.spotify.play(self.backend.spotify.lookup(track.uri))
|
||||
return True
|
||||
except spytify.SpytifyError as e:
|
||||
logger.error(e)
|
||||
return False
|
||||
|
||||
def _resume(self):
|
||||
try:
|
||||
self.backend.spotify.resume()
|
||||
return True
|
||||
except spytify.SpytifyError as e:
|
||||
logger.error(e)
|
||||
return False
|
||||
|
||||
def _seek(self, time_position):
|
||||
pass # TODO
|
||||
|
||||
def _stop(self):
|
||||
try:
|
||||
self.backend.spotify.stop()
|
||||
return True
|
||||
except spytify.SpytifyError as e:
|
||||
logger.error(e)
|
||||
return False
|
||||
|
||||
|
||||
class DespotifyStoredPlaylistsController(BaseStoredPlaylistsController):
|
||||
def create(self, name):
|
||||
pass # TODO
|
||||
|
||||
def delete(self, playlist):
|
||||
pass # TODO
|
||||
|
||||
def lookup(self, uri):
|
||||
pass # TODO
|
||||
|
||||
def refresh(self):
|
||||
logger.info(u'Caching stored playlists')
|
||||
playlists = []
|
||||
for spotify_playlist in self.backend.spotify.stored_playlists:
|
||||
playlists.append(
|
||||
DespotifyTranslator.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]))
|
||||
logger.info(u'Done caching stored playlists')
|
||||
|
||||
def rename(self, playlist, new_name):
|
||||
pass # TODO
|
||||
|
||||
def save(self, playlist):
|
||||
pass # TODO
|
||||
|
||||
|
||||
class DespotifyTranslator(object):
|
||||
@classmethod
|
||||
def to_mopidy_artist(cls, spotify_artist):
|
||||
return Artist(
|
||||
uri=spotify_artist.get_uri(),
|
||||
name=spotify_artist.name.decode(ENCODING)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def to_mopidy_album(cls, spotify_album_name):
|
||||
return Album(name=spotify_album_name.decode(ENCODING))
|
||||
|
||||
@classmethod
|
||||
def to_mopidy_track(cls, spotify_track):
|
||||
if spotify_track is None or not spotify_track.has_meta_data():
|
||||
return None
|
||||
if dt.MINYEAR <= int(spotify_track.year) <= dt.MAXYEAR:
|
||||
date = dt.date(spotify_track.year, 1, 1)
|
||||
else:
|
||||
date = None
|
||||
return Track(
|
||||
uri=spotify_track.get_uri(),
|
||||
name=spotify_track.title.decode(ENCODING),
|
||||
artists=[cls.to_mopidy_artist(a) for a in spotify_track.artists],
|
||||
album=cls.to_mopidy_album(spotify_track.album),
|
||||
track_no=spotify_track.tracknumber,
|
||||
date=date,
|
||||
length=spotify_track.length,
|
||||
bitrate=320,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def to_mopidy_playlist(cls, spotify_playlist):
|
||||
return Playlist(
|
||||
uri=spotify_playlist.get_uri(),
|
||||
name=spotify_playlist.name.decode(ENCODING),
|
||||
tracks=filter(None,
|
||||
[cls.to_mopidy_track(t) for t in spotify_playlist.tracks]),
|
||||
)
|
||||
|
||||
|
||||
class DespotifySessionManager(spytify.Spytify):
|
||||
DESPOTIFY_NEW_TRACK = 1
|
||||
DESPOTIFY_TIME_TELL = 2
|
||||
DESPOTIFY_END_OF_PLAYLIST = 3
|
||||
DESPOTIFY_TRACK_PLAY_ERROR = 4
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs['callback'] = self.callback
|
||||
self.core_queue = kwargs.pop('core_queue')
|
||||
super(DespotifySessionManager, self).__init__(*args, **kwargs)
|
||||
|
||||
def callback(self, signal, data):
|
||||
if signal == self.DESPOTIFY_END_OF_PLAYLIST:
|
||||
logger.debug('Despotify signalled end of playlist')
|
||||
self.core_queue.put({'command': 'end_of_track'})
|
||||
elif signal == self.DESPOTIFY_TRACK_PLAY_ERROR:
|
||||
logger.error('Despotify signalled track play error')
|
||||
@ -14,13 +14,12 @@ import sys
|
||||
#: List of playback backends to use. See :mod:`mopidy.backends` for all
|
||||
#: available backends. Default::
|
||||
#:
|
||||
#: BACKENDS = (u'mopidy.backends.despotify.DespotifyBackend',)
|
||||
#: BACKENDS = (u'mopidy.backends.libspotify.LibspotifyBackend',)
|
||||
#:
|
||||
#: .. note::
|
||||
#: Currently only the first backend in the list is used.
|
||||
BACKENDS = (
|
||||
u'mopidy.backends.despotify.DespotifyBackend',
|
||||
#u'mopidy.backends.libspotify.LibspotifyBackend',
|
||||
u'mopidy.backends.libspotify.LibspotifyBackend',
|
||||
)
|
||||
|
||||
#: The log format used on the console. See
|
||||
|
||||
@ -1,35 +0,0 @@
|
||||
# TODO This integration test is work in progress.
|
||||
|
||||
import unittest
|
||||
|
||||
from mopidy.backends.despotify import DespotifyBackend
|
||||
from mopidy.models import Track
|
||||
|
||||
from tests.backends.base import *
|
||||
|
||||
uris = [
|
||||
'spotify:track:6vqcpVcbI3Zu6sH3ieLDNt',
|
||||
'spotify:track:111sulhaZqgsnypz3MkiaW',
|
||||
'spotify:track:7t8oznvbeiAPMDRuK0R5ZT',
|
||||
]
|
||||
|
||||
class DespotifyCurrentPlaylistControllerTest(
|
||||
BaseCurrentPlaylistControllerTest, unittest.TestCase):
|
||||
tracks = [Track(uri=uri, length=4464) for i, uri in enumerate(uris)]
|
||||
backend_class = DespotifyBackend
|
||||
|
||||
|
||||
class DespotifyPlaybackControllerTest(
|
||||
BasePlaybackControllerTest, unittest.TestCase):
|
||||
tracks = [Track(uri=uri, length=4464) for i, uri in enumerate(uris)]
|
||||
backend_class = DespotifyBackend
|
||||
|
||||
|
||||
class DespotifyStoredPlaylistsControllerTest(
|
||||
BaseStoredPlaylistsControllerTest, unittest.TestCase):
|
||||
backend_class = DespotifyBackend
|
||||
|
||||
|
||||
class DespotifyLibraryControllerTest(
|
||||
BaseLibraryControllerTest, unittest.TestCase):
|
||||
backend_class = DespotifyBackend
|
||||
Loading…
Reference in New Issue
Block a user