mopidy-subidy/mopidy_subidy/library.py

211 lines
7.7 KiB
Python
Raw Normal View History

2020-03-08 12:31:00 +01:00
import logging
2020-03-08 12:43:10 +01:00
from mopidy import backend
from mopidy.models import Ref, SearchResult
2016-09-18 04:33:46 +02:00
from mopidy_subidy import uri
logger = logging.getLogger(__name__)
2020-03-08 12:30:34 +01:00
2016-09-18 04:33:46 +02:00
class SubidyLibraryProvider(backend.LibraryProvider):
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"),
2020-11-03 20:36:28 +01:00
dict(id="random", name="Random"),
]
# 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"]))
2020-03-08 12:30:34 +01:00
vdirs[template["id"]] = vdir
return vdirs
_vdirs = __create_vdirs()
def __raw_vdir_to_ref(vdir):
if vdir is None:
return None
2020-03-08 12:30:34 +01:00
return Ref.directory(name=vdir["name"], uri=vdir["uri"])
2020-03-08 12:30:34 +01:00
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):
2020-03-08 12:30:14 +01:00
super().__init__(*args, **kwargs)
2016-09-18 04:33:46 +02:00
self.subsonic_api = self.backend.subsonic_api
2017-02-28 01:45:17 -05:00
def browse_songs(self, album_id):
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):
return self.subsonic_api.get_albums_as_refs(artist_id)
2016-09-18 04:33:46 +02:00
def browse_artists(self):
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()
2020-11-03 20:36:28 +01:00
def browse_random_songs(self):
return self.subsonic_api.get_random_songs_as_refs()
2017-02-12 15:50:41 -05:00
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):
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):
return self.subsonic_api.get_songs_as_tracks(album_id)
2016-09-18 04:33:46 +02:00
def lookup_artist(self, artist_id):
2020-03-08 12:30:34 +01: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):
2020-03-08 12:30:34 +01: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):
2020-03-08 12:30:34 +01:00
if browse_uri == uri.get_vdir_uri("root"):
2020-11-03 20:36:28 +01:00
root_vdir_names = ["rootdirs", "artists", "albums", "random"]
2020-03-08 12:30:34 +01:00
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()
2020-11-03 20:36:28 +01:00
elif browse_uri == uri.get_vdir_uri("random"):
return self.browse_random_songs()
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 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:
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:
2020-03-08 12:30:14 +01:00
return {uri: self.lookup_one(uri) for uri in uris}
2016-09-18 04:33:46 +02:00
if uri is not None:
return self.lookup_one(uri)
2016-09-18 04:33:46 +02:00
return None
def refresh(self, uri):
pass
2020-03-08 12:30:34 +01: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])
def search_by_artist_and_album(self, artist_name, album_name):
2020-11-02 21:13:27 +01:00
artists = self.subsonic_api.find_raw(artist_name).get("artist")
if artists is None:
return None
tracks = []
for artist in artists:
for album in self.subsonic_api.get_raw_albums(artist.get("id")):
if album_name in album.get("name"):
tracks.extend(
self.subsonic_api.get_songs_as_tracks(album.get("id"))
)
return SearchResult(tracks=tracks)
2020-11-03 20:36:28 +01:00
def search_by_artist(self, artist_name, exact):
2020-11-02 21:13:27 +01:00
result = self.subsonic_api.find_raw(artist_name)
if result is None:
return None
tracks = []
for artist in result.get("artist"):
2020-11-02 23:12:39 +01:00
if exact:
if not artist.get("name") == artist_name:
continue
2020-11-02 21:13:27 +01:00
tracks.extend(
self.subsonic_api.get_artist_as_songs_as_tracks_iter(
artist.get("id")
)
2020-11-02 21:13:27 +01:00
)
return SearchResult(uri=uri.get_search_uri(artist_name), tracks=tracks)
def get_distinct(self, field, query):
search_result = self.search(query)
if not search_result:
return []
2020-03-08 12:30:34 +01:00
if field == "track" or field == "title":
return [track.name for track in (search_result.tracks or [])]
2020-03-08 12:30:34 +01:00
if field == "album":
return [album.name for album in (search_result.albums or [])]
2020-03-08 12:30:34 +01:00
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):
2020-03-08 12:30:34 +01: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],
)
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:
2020-11-03 20:36:28 +01:00
return self.search_by_artist(query.get("artist")[0], exact)
if "comment" in query:
if query.get("comment")[0] == "random":
return SearchResult(
tracks=self.subsonic_api.get_random_songs_as_tracks()
)
2020-03-08 12:30:34 +01:00
if "any" in query:
return self.subsonic_api.find_as_search_result(query.get("any")[0])
return SearchResult(artists=self.subsonic_api.get_artists_as_artists())