2016-09-18 04:33:46 +02:00
|
|
|
from mopidy import backend, models
|
2016-09-18 18:19:08 +02:00
|
|
|
from mopidy.models import Ref, SearchResult
|
2016-09-18 04:33:46 +02:00
|
|
|
from mopidy_subidy import uri
|
|
|
|
|
2016-09-18 18:19:08 +02:00
|
|
|
import logging
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
2016-09-18 04:33:46 +02:00
|
|
|
class SubidyLibraryProvider(backend.LibraryProvider):
|
2017-03-22 02:22:36 -04:00
|
|
|
def __create_vdirs():
|
|
|
|
vdir_templates = [
|
|
|
|
dict(id="root", name="Subsonic"),
|
|
|
|
dict(id="artists", name="Artists"),
|
|
|
|
dict(id="albums", name="Albums"),
|
|
|
|
dict(id="rootdirs", name="Directories"),
|
|
|
|
]
|
|
|
|
# Create a dict with the keys being the `id`s in `vdir_templates`
|
|
|
|
# and the values being objects containing the vdir `id`,
|
|
|
|
# the human readable name as `name`, and the URI as `uri`.
|
|
|
|
vdirs = {}
|
|
|
|
for template in vdir_templates:
|
|
|
|
vdir = template.copy()
|
|
|
|
vdir.update(uri=uri.get_vdir_uri(vdir["id"]))
|
|
|
|
vdirs[template['id']] = vdir
|
|
|
|
return vdirs
|
|
|
|
|
|
|
|
_vdirs = __create_vdirs()
|
|
|
|
|
|
|
|
def __raw_vdir_to_ref(vdir):
|
|
|
|
if vdir is None:
|
|
|
|
return None
|
|
|
|
return Ref.directory(
|
|
|
|
name=vdir['name'],
|
|
|
|
uri=vdir['uri'])
|
|
|
|
|
|
|
|
root_directory = __raw_vdir_to_ref(_vdirs['root'])
|
|
|
|
|
|
|
|
_raw_vdir_to_ref = staticmethod(__raw_vdir_to_ref)
|
2016-09-18 04:33:46 +02:00
|
|
|
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
|
|
super(SubidyLibraryProvider, self).__init__(*args, **kwargs)
|
|
|
|
self.subsonic_api = self.backend.subsonic_api
|
|
|
|
|
2017-02-28 01:45:17 -05:00
|
|
|
def browse_songs(self, album_id):
|
2017-02-28 10:07:02 -05:00
|
|
|
return self.subsonic_api.get_songs_as_refs(album_id)
|
2016-09-18 04:33:46 +02:00
|
|
|
|
2017-02-28 16:00:09 -05:00
|
|
|
def browse_albums(self, artist_id=None):
|
2017-03-17 02:28:44 -04:00
|
|
|
return self.subsonic_api.get_albums_as_refs(artist_id)
|
2016-09-18 04:33:46 +02:00
|
|
|
|
|
|
|
def browse_artists(self):
|
2017-03-17 02:28:44 -04:00
|
|
|
return self.subsonic_api.get_artists_as_refs()
|
2016-09-18 04:33:46 +02:00
|
|
|
|
2017-02-12 15:50:41 -05:00
|
|
|
def browse_rootdirs(self):
|
|
|
|
return self.subsonic_api.get_rootdirs_as_refs()
|
|
|
|
|
|
|
|
def browse_diritems(self, directory_id):
|
|
|
|
return self.subsonic_api.get_diritems_as_refs(directory_id)
|
|
|
|
|
2016-09-18 04:33:46 +02:00
|
|
|
def lookup_song(self, song_id):
|
2017-03-27 16:48:48 -04:00
|
|
|
song = self.subsonic_api.get_song_by_id(song_id)
|
|
|
|
if song is None:
|
|
|
|
return []
|
|
|
|
else:
|
|
|
|
return [song]
|
2016-09-18 04:33:46 +02:00
|
|
|
|
|
|
|
def lookup_album(self, album_id):
|
2017-03-27 16:46:53 -04:00
|
|
|
return self.subsonic_api.get_songs_as_tracks(album_id)
|
2016-09-18 04:33:46 +02:00
|
|
|
|
|
|
|
def lookup_artist(self, artist_id):
|
2017-02-16 01:25:03 -05:00
|
|
|
return list(self.subsonic_api.get_artist_as_songs_as_tracks_iter(artist_id))
|
2016-09-18 04:33:46 +02:00
|
|
|
|
2017-02-15 17:16:15 -05:00
|
|
|
def lookup_directory(self, directory_id):
|
2017-02-16 01:25:03 -05:00
|
|
|
return list(self.subsonic_api.get_recursive_dir_as_songs_as_tracks_iter(directory_id))
|
2017-02-15 17:16:15 -05:00
|
|
|
|
2017-02-28 16:16:52 -05:00
|
|
|
def lookup_playlist(self, playlist_id):
|
|
|
|
return self.subsonic_api.get_playlist_as_playlist(playlist_id).tracks
|
|
|
|
|
2016-09-18 04:33:46 +02:00
|
|
|
def browse(self, browse_uri):
|
2017-03-22 02:22:36 -04:00
|
|
|
if browse_uri == uri.get_vdir_uri('root'):
|
|
|
|
root_vdir_names = ["rootdirs", "artists", "albums"]
|
|
|
|
root_vdirs = [self._vdirs[vdir_name] for vdir_name in root_vdir_names]
|
|
|
|
sorted_root_vdirs = sorted(root_vdirs, key=lambda vdir: vdir["name"])
|
|
|
|
return [self._raw_vdir_to_ref(vdir) for vdir in sorted_root_vdirs]
|
2017-02-28 01:45:17 -05:00
|
|
|
elif browse_uri == uri.get_vdir_uri("rootdirs"):
|
2017-02-12 15:50:41 -05:00
|
|
|
return self.browse_rootdirs()
|
2017-02-28 01:45:17 -05:00
|
|
|
elif browse_uri == uri.get_vdir_uri("artists"):
|
|
|
|
return self.browse_artists()
|
2017-02-28 16:00:09 -05:00
|
|
|
elif browse_uri == uri.get_vdir_uri("albums"):
|
|
|
|
return self.browse_albums()
|
2017-02-12 15:50:41 -05:00
|
|
|
else:
|
2017-02-28 01:45:17 -05:00
|
|
|
uri_type = uri.get_type(browse_uri)
|
|
|
|
if uri_type == uri.DIRECTORY:
|
|
|
|
return self.browse_diritems(uri.get_directory_id(browse_uri))
|
|
|
|
elif uri_type == uri.ARTIST:
|
|
|
|
return self.browse_albums(uri.get_artist_id(browse_uri))
|
|
|
|
elif uri_type == uri.ALBUM:
|
|
|
|
return self.browse_songs(uri.get_album_id(browse_uri))
|
|
|
|
else:
|
|
|
|
return []
|
2016-09-18 18:19:08 +02:00
|
|
|
|
2016-09-18 04:33:46 +02:00
|
|
|
def lookup_one(self, lookup_uri):
|
|
|
|
type = uri.get_type(lookup_uri)
|
|
|
|
if type == uri.ARTIST:
|
|
|
|
return self.lookup_artist(uri.get_artist_id(lookup_uri))
|
|
|
|
if type == uri.ALBUM:
|
|
|
|
return self.lookup_album(uri.get_album_id(lookup_uri))
|
2017-02-15 17:16:15 -05:00
|
|
|
if type == uri.DIRECTORY:
|
|
|
|
return self.lookup_directory(uri.get_directory_id(lookup_uri))
|
2016-09-18 04:33:46 +02:00
|
|
|
if type == uri.SONG:
|
2017-03-27 16:48:48 -04:00
|
|
|
return self.lookup_song(uri.get_song_id(lookup_uri))
|
2017-02-28 16:16:52 -05:00
|
|
|
if type == uri.PLAYLIST:
|
|
|
|
return self.lookup_playlist(uri.get_playlist_id(lookup_uri))
|
2016-09-18 04:33:46 +02:00
|
|
|
|
|
|
|
def lookup(self, uri=None, uris=None):
|
|
|
|
if uris is not None:
|
2017-03-27 16:46:53 -04:00
|
|
|
return dict((uri, self.lookup_one(uri)) for uri in uris)
|
2016-09-18 04:33:46 +02:00
|
|
|
if uri is not None:
|
2017-03-27 16:46:53 -04:00
|
|
|
return self.lookup_one(uri)
|
2016-09-18 04:33:46 +02:00
|
|
|
return None
|
|
|
|
|
|
|
|
def refresh(self, uri):
|
|
|
|
pass
|
2016-09-18 18:19:08 +02:00
|
|
|
|
|
|
|
def search_uri(self, query):
|
|
|
|
type = uri.get_type(lookup_uri)
|
|
|
|
if type == uri.ARTIST:
|
|
|
|
artist = self.lookup_artist(uri.get_artist_id(lookup_uri))
|
|
|
|
if artist is not None:
|
|
|
|
return SearchResult(artists=[artist])
|
|
|
|
elif type == uri.ALBUM:
|
|
|
|
album = self.lookup_album(uri.get_album_id(lookup_uri))
|
|
|
|
if album is not None:
|
|
|
|
return SearchResult(albums=[album])
|
|
|
|
elif type == uri.SONG:
|
|
|
|
song = self.lookup_song(uri.get_song_id(lookup_uri))
|
|
|
|
if song is not None:
|
|
|
|
return SearchResult(tracks=[song])
|
|
|
|
return None
|
|
|
|
|
2016-09-22 22:26:57 +02:00
|
|
|
def search_by_artist_album_and_track(self, artist_name, album_name, track_name):
|
|
|
|
tracks = self.search_by_artist_and_album(artist_name, album_name)
|
|
|
|
track = next(item for item in tracks.tracks if track_name in item.name)
|
|
|
|
return SearchResult(tracks=[track])
|
|
|
|
|
2016-09-22 21:57:05 +02:00
|
|
|
def search_by_artist_and_album(self, artist_name, album_name):
|
|
|
|
artists = self.subsonic_api.get_raw_artists()
|
|
|
|
artist = next(item for item in artists if artist_name in item.get('name'))
|
|
|
|
albums = self.subsonic_api.get_raw_albums(artist.get('id'))
|
|
|
|
album = next(item for item in albums if album_name in item.get('title'))
|
|
|
|
return SearchResult(tracks=self.subsonic_api.get_songs_as_tracks(album.get('id')))
|
|
|
|
|
|
|
|
def get_distinct(self, field, query):
|
|
|
|
search_result = self.search(query)
|
|
|
|
if not search_result:
|
|
|
|
return []
|
|
|
|
if field == 'track' or field == 'title':
|
|
|
|
return [track.name for track in (search_result.tracks or [])]
|
|
|
|
if field == 'album':
|
|
|
|
return [album.name for album in (search_result.albums or [])]
|
|
|
|
if field == 'artist':
|
|
|
|
if not search_result.artists:
|
|
|
|
return [artist.name for artist in self.browse_artists()]
|
|
|
|
return [artist.name for artist in search_result.artists]
|
|
|
|
|
2016-09-18 04:33:46 +02:00
|
|
|
def search(self, query=None, uris=None, exact=False):
|
2016-09-22 22:26:57 +02:00
|
|
|
if 'artist' in query and 'album' in query and 'track_name' in query:
|
|
|
|
return self.search_by_artist_album_and_track(query.get('artist')[0], query.get('album')[0], query.get('track_name')[0])
|
2016-09-22 21:57:05 +02:00
|
|
|
if 'artist' in query and 'album' in query:
|
|
|
|
return self.search_by_artist_and_album(query.get('artist')[0], query.get('album')[0])
|
|
|
|
if 'artist' in query:
|
|
|
|
return self.subsonic_api.find_as_search_result(query.get('artist')[0])
|
2016-09-18 18:19:08 +02:00
|
|
|
if 'any' in query:
|
|
|
|
return self.subsonic_api.find_as_search_result(query.get('any')[0])
|
2016-09-22 21:57:05 +02:00
|
|
|
return SearchResult(artists=self.subsonic_api.get_artists_as_artists())
|
|
|
|
|