diff --git a/mopidy_subidy/library.py b/mopidy_subidy/library.py index bc5e7c2..26868c0 100644 --- a/mopidy_subidy/library.py +++ b/mopidy_subidy/library.py @@ -15,6 +15,8 @@ class SubidyLibraryProvider(backend.LibraryProvider): dict(id="albums", name="Albums"), dict(id="rootdirs", name="Directories"), dict(id="random", name="Random"), + dict(id="randomalbum", name="Random Albums"), + dict(id="genre", name="Genre"), ] # Create a dict with the keys being the `id`s in `vdir_templates` # and the values being objects containing the vdir `id`, @@ -56,6 +58,15 @@ class SubidyLibraryProvider(backend.LibraryProvider): def browse_random_songs(self): return self.subsonic_api.get_random_songs_as_refs() + def browse_random_albums(self): + return self.subsonic_api.get_random_albums_as_refs() + + def browse_albums_by_genre(self, genre): + return self.subsonic_api.get_albums_by_genre_as_refs(genre) + + def browse_genre(self): + return self.subsonic_api.get_genres_as_refs() + def browse_diritems(self, directory_id): return self.subsonic_api.get_diritems_as_refs(directory_id) @@ -86,7 +97,8 @@ class SubidyLibraryProvider(backend.LibraryProvider): def browse(self, browse_uri): if browse_uri == uri.get_vdir_uri("root"): - root_vdir_names = ["rootdirs", "artists", "albums", "random"] + root_vdir_names = ["rootdirs", "artists", + "albums", "random", "randomalbum", "genre"] root_vdirs = [ self._vdirs[vdir_name] for vdir_name in root_vdir_names ] @@ -102,11 +114,17 @@ class SubidyLibraryProvider(backend.LibraryProvider): return self.browse_albums() elif browse_uri == uri.get_vdir_uri("random"): return self.browse_random_songs() + elif browse_uri == uri.get_vdir_uri("randomalbum"): + return self.browse_random_albums() + elif browse_uri == uri.get_vdir_uri("genre"): + return self.browse_genre() else: 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.GENRE: + return self.browse_albums_by_genre(uri.get_genre_id(browse_uri)) elif uri_type == uri.ARTIST: return self.browse_albums(uri.get_artist_id(browse_uri)) elif uri_type == uri.ALBUM: diff --git a/mopidy_subidy/subsonic_api.py b/mopidy_subidy/subsonic_api.py index 50aacf7..e93498b 100644 --- a/mopidy_subidy/subsonic_api.py +++ b/mopidy_subidy/subsonic_api.py @@ -429,6 +429,71 @@ class SubsonicApi: return songs return [] + def get_raw_random_album(self, size=MAX_LIST_RESULTS): + try: + response = self.connection.getAlbumList2( + ltype='random', size=size, offset=0 + ) + except Exception: + logger.warning( + "Connecting to subsonic failed when loading random album list." + ) + return [] + if response.get("status") != RESPONSE_OK: + logger.warning( + "Got non-okay status code from subsonic: %s" + % response.get("status") + ) + return [] + albums = response.get("albumList2").get("album") + if albums is not None: + return albums + return [] + + def get_raw_albums_by_genre(self, genre): + try: + response = self.connection.getAlbumList2( + ltype='byGenre', size=MAX_LIST_RESULTS, genre=genre, + ) + except Exception: + logger.warning( + "Connecting to subsonic failed when loading genre album list." + ) + logging.exception('') + return [] + if response.get("status") != RESPONSE_OK: + logger.warning( + "Got non-okay status code from subsonic: %s" + % response.get("status") + ) + return [] + albums = response.get("albumList2").get("album") + if albums is not None: + return albums + return [] + + def get_raw_genres(self): + try: + response = self.connection.getGenres() + except Exception: + logger.warning( + "Connecting to subsonic failed when loading genres." + ) + return [] + + if response.get("status") != RESPONSE_OK: + logger.warning( + "Got non-okay status code from subsonic: %s" + % response.get("status") + ) + return [] + + genres = response.get("genres").get("genre") + + if genres is not None: + return genres + return [] + def get_more_albums(self, ltype, size=MAX_LIST_RESULTS, offset=0): try: response = self.connection.getAlbumList2( @@ -519,6 +584,11 @@ class SubsonicApi: self.raw_song_to_ref(song) for song in self.get_raw_random_song(75) ] + def get_random_albums_as_refs(self): + return [ + self.raw_album_to_ref_with_artist(album) for album in self.get_raw_random_album(20) + ] + def get_random_songs_as_tracks(self): return [ self.raw_song_to_track(song) for song in self.get_raw_random_song() @@ -571,6 +641,18 @@ class SubsonicApi: else: yield self.raw_song_to_track(item) + def get_albums_by_genre_as_refs(self, genre): + return [ + self.raw_album_to_ref_with_artist(album) for album in self.get_raw_albums_by_genre(genre) + ] + + def get_genres_as_refs(self): + genres = self.get_raw_genres() + return [Ref.directory( + name=genre['value'], + uri=uri.get_genre_uri(genre['value']) + ) for genre in genres] + def raw_song_to_ref(self, song): if song is None: return None @@ -615,6 +697,18 @@ class SubsonicApi: uri=uri.get_album_uri(album.get("id")), ) + def raw_album_to_ref_with_artist(self, album): + if album is None: + return None + + album_name = album.get("title") or album.get("name") or UNKNOWN_ALBUM + artist = album.get("artist") or UNKNOWN_ARTIST + + return Ref.album( + name=artist + " ยท " + album_name, + uri=uri.get_album_uri(album.get("id")), + ) + def raw_album_to_album(self, album): if album is None: return None @@ -676,3 +770,4 @@ class SubsonicApi: uri=uri.get_playlist_uri(playlist.get("id")), name=playlist.get("name"), ) + diff --git a/mopidy_subidy/uri.py b/mopidy_subidy/uri.py index a4d8464..3b64170 100644 --- a/mopidy_subidy/uri.py +++ b/mopidy_subidy/uri.py @@ -6,6 +6,7 @@ PLAYLIST = "playlist" ALBUM = "album" DIRECTORY = "directory" VDIR = "vdir" +GENRE = "genre" PREFIX = "subidy" SEARCH = "search" RANDOM = "random" @@ -70,6 +71,11 @@ def get_vdir_id(uri): return None return result.group(3) +def get_genre_id(uri): + result = regex.match(uri) + if not is_id_result_valid(result, GENRE): + return None + return result.group(3) def get_type(uri): result = regex.match(uri) @@ -97,6 +103,8 @@ def get_song_uri(id): def get_directory_uri(id): return get_type_uri(DIRECTORY, id) +def get_genre_uri(id): + return get_type_uri(GENRE, id) def get_vdir_uri(id): return get_type_uri(VDIR, id)