Compare commits
No commits in common. "master" and "1.0.0" have entirely different histories.
7 changed files with 18 additions and 137 deletions
35
PKGBUILD
35
PKGBUILD
|
@ -1,35 +0,0 @@
|
||||||
# Maintainer: Matthew Gamble <git@matthewgamble.net>
|
|
||||||
# Contributor: Frederick Gnodtke <fgnodtke at cronosx dot de>
|
|
||||||
|
|
||||||
pkgname=mopidy-subidy
|
|
||||||
pkgver=1.3.0
|
|
||||||
pkgrel=2
|
|
||||||
pkgdesc="Mopidy extension for playing music from Subsonic servers"
|
|
||||||
arch=("any")
|
|
||||||
url="https://git.hannover.ccc.de/lubiana/mopidy-subidy/releases"
|
|
||||||
license=('BSD')
|
|
||||||
depends=(
|
|
||||||
"mopidy"
|
|
||||||
"python"
|
|
||||||
"python-setuptools"
|
|
||||||
"python-pykka"
|
|
||||||
"python-pysonic"
|
|
||||||
)
|
|
||||||
source=("https://git.hannover.ccc.de/lubiana/mopidy-subidy/archive/1.0.0.tar.gz")
|
|
||||||
sha256sums=("ed78ce86da58fb42f6ddf9a8de72169d23521125b269b51054d69375b57c5b73")
|
|
||||||
|
|
||||||
build() {
|
|
||||||
cd "mopidy-subidy"
|
|
||||||
|
|
||||||
python setup.py build
|
|
||||||
}
|
|
||||||
|
|
||||||
package() {
|
|
||||||
cd "mopidy-subidy"
|
|
||||||
|
|
||||||
PYTHONHASHSEED=0 python setup.py install --root="${pkgdir}" --optimize=1 --skip-build
|
|
||||||
|
|
||||||
install -Dm644 LICENSE "${pkgdir}/usr/share/licenses/mopidy-subidy/LICENSE"
|
|
||||||
install -Dm644 README.rst "${pkgdir}/usr/share/doc/mopidy-subidy/README.rst"
|
|
||||||
install -Dm644 CHANGELOG.rst "${pkgdir}/usr/share/doc/mopidy-subidy/CHANGELOG.rst"
|
|
||||||
}
|
|
|
@ -14,8 +14,6 @@ Mopidy-Subidy
|
||||||
:target: https://codecov.io/gh/Prior99/mopidy-subidy
|
:target: https://codecov.io/gh/Prior99/mopidy-subidy
|
||||||
:alt: Test coverage
|
:alt: Test coverage
|
||||||
|
|
||||||
**This library is actively looking for maintainers to help out as I do not have the time or need to maintain this anymore. Please contact me if you feel that you could maintain this.**
|
|
||||||
|
|
||||||
A Subsonic backend for Mopidy using `py-sonic
|
A Subsonic backend for Mopidy using `py-sonic
|
||||||
<https://github.com/crustymonkey/py-sonic>`_.
|
<https://github.com/crustymonkey/py-sonic>`_.
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,6 @@ class SubidyLibraryProvider(backend.LibraryProvider):
|
||||||
dict(id="artists", name="Artists"),
|
dict(id="artists", name="Artists"),
|
||||||
dict(id="albums", name="Albums"),
|
dict(id="albums", name="Albums"),
|
||||||
dict(id="rootdirs", name="Directories"),
|
dict(id="rootdirs", name="Directories"),
|
||||||
dict(id="random", name="Random"),
|
|
||||||
]
|
]
|
||||||
# Create a dict with the keys being the `id`s in `vdir_templates`
|
# Create a dict with the keys being the `id`s in `vdir_templates`
|
||||||
# and the values being objects containing the vdir `id`,
|
# and the values being objects containing the vdir `id`,
|
||||||
|
@ -53,9 +52,6 @@ class SubidyLibraryProvider(backend.LibraryProvider):
|
||||||
def browse_rootdirs(self):
|
def browse_rootdirs(self):
|
||||||
return self.subsonic_api.get_rootdirs_as_refs()
|
return self.subsonic_api.get_rootdirs_as_refs()
|
||||||
|
|
||||||
def browse_random_songs(self):
|
|
||||||
return self.subsonic_api.get_random_songs_as_refs()
|
|
||||||
|
|
||||||
def browse_diritems(self, directory_id):
|
def browse_diritems(self, directory_id):
|
||||||
return self.subsonic_api.get_diritems_as_refs(directory_id)
|
return self.subsonic_api.get_diritems_as_refs(directory_id)
|
||||||
|
|
||||||
|
@ -86,7 +82,7 @@ class SubidyLibraryProvider(backend.LibraryProvider):
|
||||||
|
|
||||||
def browse(self, browse_uri):
|
def browse(self, browse_uri):
|
||||||
if browse_uri == uri.get_vdir_uri("root"):
|
if browse_uri == uri.get_vdir_uri("root"):
|
||||||
root_vdir_names = ["rootdirs", "artists", "albums", "random"]
|
root_vdir_names = ["rootdirs", "artists", "albums"]
|
||||||
root_vdirs = [
|
root_vdirs = [
|
||||||
self._vdirs[vdir_name] for vdir_name in root_vdir_names
|
self._vdirs[vdir_name] for vdir_name in root_vdir_names
|
||||||
]
|
]
|
||||||
|
@ -100,9 +96,6 @@ class SubidyLibraryProvider(backend.LibraryProvider):
|
||||||
return self.browse_artists()
|
return self.browse_artists()
|
||||||
elif browse_uri == uri.get_vdir_uri("albums"):
|
elif browse_uri == uri.get_vdir_uri("albums"):
|
||||||
return self.browse_albums()
|
return self.browse_albums()
|
||||||
elif browse_uri == uri.get_vdir_uri("random"):
|
|
||||||
return self.browse_random_songs()
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
uri_type = uri.get_type(browse_uri)
|
uri_type = uri.get_type(browse_uri)
|
||||||
if uri_type == uri.DIRECTORY:
|
if uri_type == uri.DIRECTORY:
|
||||||
|
@ -145,34 +138,15 @@ class SubidyLibraryProvider(backend.LibraryProvider):
|
||||||
return SearchResult(tracks=[track])
|
return SearchResult(tracks=[track])
|
||||||
|
|
||||||
def search_by_artist_and_album(self, artist_name, album_name):
|
def search_by_artist_and_album(self, artist_name, album_name):
|
||||||
artists = self.subsonic_api.find_raw(artist_name).get("artist")
|
artists = self.subsonic_api.get_raw_artists()
|
||||||
if artists is None:
|
artist = next(
|
||||||
return None
|
item for item in artists if artist_name in item.get("name")
|
||||||
tracks = []
|
)
|
||||||
for artist in artists:
|
albums = self.subsonic_api.get_raw_albums(artist.get("id"))
|
||||||
for album in self.subsonic_api.get_raw_albums(artist.get("id")):
|
album = next(item for item in albums if album_name in item.get("title"))
|
||||||
if album_name in album.get("name"):
|
return SearchResult(
|
||||||
tracks.extend(
|
tracks=self.subsonic_api.get_songs_as_tracks(album.get("id"))
|
||||||
self.subsonic_api.get_songs_as_tracks(album.get("id"))
|
)
|
||||||
)
|
|
||||||
return SearchResult(tracks=tracks)
|
|
||||||
|
|
||||||
def search_by_artist(self, artist_name, exact):
|
|
||||||
result = self.subsonic_api.find_raw(artist_name)
|
|
||||||
if result is None:
|
|
||||||
return None
|
|
||||||
tracks = []
|
|
||||||
for artist in result.get("artist"):
|
|
||||||
if exact:
|
|
||||||
if not artist.get("name") == artist_name:
|
|
||||||
continue
|
|
||||||
|
|
||||||
tracks.extend(
|
|
||||||
self.subsonic_api.get_artist_as_songs_as_tracks_iter(
|
|
||||||
artist.get("id")
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return SearchResult(uri=uri.get_search_uri(artist_name), tracks=tracks)
|
|
||||||
|
|
||||||
def get_distinct(self, field, query):
|
def get_distinct(self, field, query):
|
||||||
search_result = self.search(query)
|
search_result = self.search(query)
|
||||||
|
@ -199,12 +173,9 @@ class SubidyLibraryProvider(backend.LibraryProvider):
|
||||||
query.get("artist")[0], query.get("album")[0]
|
query.get("artist")[0], query.get("album")[0]
|
||||||
)
|
)
|
||||||
if "artist" in query:
|
if "artist" in query:
|
||||||
return self.search_by_artist(query.get("artist")[0], exact)
|
return self.subsonic_api.find_as_search_result(
|
||||||
if "comment" in query:
|
query.get("artist")[0]
|
||||||
if query.get("comment")[0] == "random":
|
)
|
||||||
return SearchResult(
|
|
||||||
tracks=self.subsonic_api.get_random_songs_as_tracks()
|
|
||||||
)
|
|
||||||
if "any" in query:
|
if "any" in query:
|
||||||
return self.subsonic_api.find_as_search_result(query.get("any")[0])
|
return self.subsonic_api.find_as_search_result(query.get("any")[0])
|
||||||
return SearchResult(artists=self.subsonic_api.get_artists_as_artists())
|
return SearchResult(artists=self.subsonic_api.get_artists_as_artists())
|
||||||
|
|
|
@ -16,6 +16,3 @@ class SubidyPlaybackProvider(backend.PlaybackProvider):
|
||||||
censored_url = self.subsonic_api.get_censored_song_stream_uri(song_id)
|
censored_url = self.subsonic_api.get_censored_song_stream_uri(song_id)
|
||||||
logger.debug("Loading song from subsonic with url: '%s'" % censored_url)
|
logger.debug("Loading song from subsonic with url: '%s'" % censored_url)
|
||||||
return self.subsonic_api.get_song_stream_uri(song_id)
|
return self.subsonic_api.get_song_stream_uri(song_id)
|
||||||
|
|
||||||
def should_download(self, uri):
|
|
||||||
return True
|
|
||||||
|
|
|
@ -101,7 +101,7 @@ class SubsonicApi:
|
||||||
exclude_songs=False,
|
exclude_songs=False,
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
response = self.connection.search3(
|
response = self.connection.search2(
|
||||||
query.encode("utf-8"),
|
query.encode("utf-8"),
|
||||||
MAX_SEARCH_RESULTS if not exclude_artists else 0,
|
MAX_SEARCH_RESULTS if not exclude_artists else 0,
|
||||||
0,
|
0,
|
||||||
|
@ -119,7 +119,7 @@ class SubsonicApi:
|
||||||
% response.get("status")
|
% response.get("status")
|
||||||
)
|
)
|
||||||
return None
|
return None
|
||||||
return response.get("searchResult3")
|
return response.get("searchResult2")
|
||||||
|
|
||||||
def find_as_search_result(
|
def find_as_search_result(
|
||||||
self,
|
self,
|
||||||
|
@ -410,30 +410,9 @@ class SubsonicApi:
|
||||||
return songs
|
return songs
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def get_raw_random_song(self, size=MAX_LIST_RESULTS):
|
def get_raw_album_list(self, ltype, size=MAX_LIST_RESULTS):
|
||||||
try:
|
try:
|
||||||
response = self.connection.getRandomSongs(size)
|
response = self.connection.getAlbumList2(ltype=ltype, size=size)
|
||||||
except Exception:
|
|
||||||
logger.warning(
|
|
||||||
"Connecting to subsonic failed when loading ramdom song list."
|
|
||||||
)
|
|
||||||
return []
|
|
||||||
if response.get("status") != RESPONSE_OK:
|
|
||||||
logger.warning(
|
|
||||||
"Got non-okay status code from subsonic: %s"
|
|
||||||
% response.get("status")
|
|
||||||
)
|
|
||||||
return []
|
|
||||||
songs = response.get("randomSongs").get("song")
|
|
||||||
if songs is not None:
|
|
||||||
return songs
|
|
||||||
return []
|
|
||||||
|
|
||||||
def get_more_albums(self, ltype, size=MAX_LIST_RESULTS, offset=0):
|
|
||||||
try:
|
|
||||||
response = self.connection.getAlbumList2(
|
|
||||||
ltype=ltype, size=size, offset=offset
|
|
||||||
)
|
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
"Connecting to subsonic failed when loading album list."
|
"Connecting to subsonic failed when loading album list."
|
||||||
|
@ -450,24 +429,6 @@ class SubsonicApi:
|
||||||
return albums
|
return albums
|
||||||
return []
|
return []
|
||||||
|
|
||||||
def get_raw_album_list(self, ltype, size=MAX_LIST_RESULTS):
|
|
||||||
"""
|
|
||||||
Subsonic servers don't offer any way to retrieve the total number
|
|
||||||
of albums to get, and the spec states that the max number returned
|
|
||||||
for `getAlbumList2` is 500. To get all the albums, we make a
|
|
||||||
`getAlbumList2` request each time the response contains 500 albums. If
|
|
||||||
it does not, we assume we have all the albums and return them.
|
|
||||||
"""
|
|
||||||
offset = 0
|
|
||||||
total = []
|
|
||||||
albums = self.get_more_albums(ltype, size, offset)
|
|
||||||
total = albums
|
|
||||||
while len(albums) == size:
|
|
||||||
offset = offset + size
|
|
||||||
albums = self.get_more_albums(ltype, size, offset)
|
|
||||||
total = total + albums
|
|
||||||
return total
|
|
||||||
|
|
||||||
def get_albums_as_refs(self, artist_id=None):
|
def get_albums_as_refs(self, artist_id=None):
|
||||||
albums = (
|
albums = (
|
||||||
self.get_raw_album_list("alphabeticalByName")
|
self.get_raw_album_list("alphabeticalByName")
|
||||||
|
@ -514,16 +475,6 @@ class SubsonicApi:
|
||||||
for diritem in self.get_raw_dir(directory_id)
|
for diritem in self.get_raw_dir(directory_id)
|
||||||
]
|
]
|
||||||
|
|
||||||
def get_random_songs_as_refs(self):
|
|
||||||
return [
|
|
||||||
self.raw_song_to_ref(song) for song in self.get_raw_random_song(75)
|
|
||||||
]
|
|
||||||
|
|
||||||
def get_random_songs_as_tracks(self):
|
|
||||||
return [
|
|
||||||
self.raw_song_to_track(song) for song in self.get_raw_random_song()
|
|
||||||
]
|
|
||||||
|
|
||||||
def get_artists_as_artists(self):
|
def get_artists_as_artists(self):
|
||||||
return [
|
return [
|
||||||
self.raw_artist_to_artist(artist)
|
self.raw_artist_to_artist(artist)
|
||||||
|
|
|
@ -8,7 +8,6 @@ DIRECTORY = "directory"
|
||||||
VDIR = "vdir"
|
VDIR = "vdir"
|
||||||
PREFIX = "subidy"
|
PREFIX = "subidy"
|
||||||
SEARCH = "search"
|
SEARCH = "search"
|
||||||
RANDOM = "random"
|
|
||||||
|
|
||||||
regex = re.compile(r"(\w+?):(\w+?)(?::|$)(.+?)?$")
|
regex = re.compile(r"(\w+?):(\w+?)(?::|$)(.+?)?$")
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[metadata]
|
[metadata]
|
||||||
name = Mopidy-Subidy
|
name = Mopidy-Subidy
|
||||||
version = 1.1.0
|
version = 1.0.0
|
||||||
url = https://github.com/Prior99/mopidy-subidy
|
url = https://github.com/Prior99/mopidy-subidy
|
||||||
author = prior99
|
author = prior99
|
||||||
author_email = fgnodtke@cronosx.de
|
author_email = fgnodtke@cronosx.de
|
||||||
|
|
Loading…
Add table
Reference in a new issue