* New setting 'albums_per_page'
* New menu structure * Albums : Newest / Most played / Rencently played / by Genre * Tracks : Starred / Random by genre / Random by year * Code cleanup
This commit is contained in:
parent
2580050353
commit
7be23bfd8d
|
@ -1,5 +1,13 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v2.0.1
|
||||||
|
* New setting 'albums_per_page'
|
||||||
|
* New menu structure
|
||||||
|
* Albums : Newest / Most played / Rencently played / by Genre
|
||||||
|
* Tracks : Starred / Random by genre / Random by year
|
||||||
|
* Upgraded: libsonic to v.0.5.0 (https://github.com/crustymonkey/py-sonic)
|
||||||
|
* Code cleanup
|
||||||
|
|
||||||
## v2.0.0
|
## v2.0.0
|
||||||
Released 14 September 2015
|
Released 14 September 2015
|
||||||
|
|
||||||
|
|
205
addon.py
205
addon.py
|
@ -9,7 +9,7 @@ import xbmcaddon
|
||||||
import xbmcplugin
|
import xbmcplugin
|
||||||
|
|
||||||
# Make sure library folder is on the path
|
# Make sure library folder is on the path
|
||||||
addon = xbmcaddon.Addon("plugin.audio.subsonic")
|
addon = xbmcaddon.Addon()
|
||||||
sys.path.append(xbmc.translatePath(os.path.join(
|
sys.path.append(xbmc.translatePath(os.path.join(
|
||||||
addon.getAddonInfo("path"), "lib")))
|
addon.getAddonInfo("path"), "lib")))
|
||||||
|
|
||||||
|
@ -31,8 +31,9 @@ class Plugin(object):
|
||||||
self.username = addon.getSetting("username")
|
self.username = addon.getSetting("username")
|
||||||
self.password = addon.getSetting("password")
|
self.password = addon.getSetting("password")
|
||||||
|
|
||||||
self.random_count = int(addon.getSetting("random_count"))
|
self.albums_per_page = int(addon.getSetting("albums_per_page"))
|
||||||
self.album_list_size = int(addon.getSetting("album_list_size"))
|
self.tracks_per_page = int(addon.getSetting("tracks_per_page"))
|
||||||
|
|
||||||
self.bitrate = int(addon.getSetting("bitrate"))
|
self.bitrate = int(addon.getSetting("bitrate"))
|
||||||
self.transcode_format = addon.getSetting("transcode_format")
|
self.transcode_format = addon.getSetting("transcode_format")
|
||||||
|
|
||||||
|
@ -56,7 +57,7 @@ class Plugin(object):
|
||||||
parameter and executed the function in this instance with that name.
|
parameter and executed the function in this instance with that name.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
mode = self.addon_args.get("mode", ["main_page"])[0]
|
mode = self.addon_args.get("mode", ["main_menu"])[0]
|
||||||
|
|
||||||
if not mode.startswith("_"):
|
if not mode.startswith("_"):
|
||||||
getattr(self, mode)()
|
getattr(self, mode)()
|
||||||
|
@ -145,18 +146,17 @@ class Plugin(object):
|
||||||
xbmcplugin.addDirectoryItem(
|
xbmcplugin.addDirectoryItem(
|
||||||
handle=self.addon_handle, url=url, listitem=li, isFolder=True)
|
handle=self.addon_handle, url=url, listitem=li, isFolder=True)
|
||||||
|
|
||||||
def main_page(self):
|
def main_menu(self):
|
||||||
"""
|
"""
|
||||||
Display main menu.
|
Display main menu.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
menu = [
|
menu = [
|
||||||
{"mode": "starred_list", "foldername": "Starred"},
|
{"mode": "list_artists", "foldername": "Artists"},
|
||||||
{"mode": "playlists_list", "foldername": "Playlists"},
|
{"mode": "menu_albums", "foldername": "Albums"},
|
||||||
{"mode": "artist_list", "foldername": "Artists"},
|
{"mode": "list_playlists", "foldername": "Playlists"},
|
||||||
{"mode": "newest_albums_list", "foldername": "Recently Added Albums"},
|
{"mode": "menu_tracks", "foldername": "Tracks"}
|
||||||
{"mode": "genre_list", "foldername": "Genres"},
|
]
|
||||||
{"mode": "random_list", "foldername": "Random songs"}]
|
|
||||||
|
|
||||||
for entry in menu:
|
for entry in menu:
|
||||||
url = self.build_url(entry)
|
url = self.build_url(entry)
|
||||||
|
@ -167,19 +167,48 @@ class Plugin(object):
|
||||||
|
|
||||||
xbmcplugin.endOfDirectory(self.addon_handle)
|
xbmcplugin.endOfDirectory(self.addon_handle)
|
||||||
|
|
||||||
def starred_list(self):
|
def menu_tracks(self):
|
||||||
"""
|
"""
|
||||||
Display starred songs.
|
Display main menu.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
xbmcplugin.setContent(self.addon_handle, "songs")
|
menu = [
|
||||||
|
{"mode": "list_tracks_starred", "foldername": "Starred tracks"},
|
||||||
|
{"mode": "list_tracks_random_genre", "foldername": "Random tracks by genre"},
|
||||||
|
{"mode": "list_tracks_random_year", "foldername": "Random tracks by year"}
|
||||||
|
]
|
||||||
|
|
||||||
for starred in self.connection.walk_starred():
|
for entry in menu:
|
||||||
self.add_track(starred, show_artist=True)
|
url = self.build_url(entry)
|
||||||
|
|
||||||
|
li = xbmcgui.ListItem(entry["foldername"])
|
||||||
|
xbmcplugin.addDirectoryItem(
|
||||||
|
handle=self.addon_handle, url=url, listitem=li, isFolder=True)
|
||||||
|
|
||||||
xbmcplugin.endOfDirectory(self.addon_handle)
|
xbmcplugin.endOfDirectory(self.addon_handle)
|
||||||
|
|
||||||
def playlists_list(self):
|
def menu_albums(self):
|
||||||
|
"""
|
||||||
|
Display main menu.
|
||||||
|
"""
|
||||||
|
|
||||||
|
menu = [
|
||||||
|
{"mode": "list_albums_newest", "foldername": "Newest albums"},
|
||||||
|
{"mode": "list_albums_frequent", "foldername": "Most played albums"},
|
||||||
|
{"mode": "list_albums_recent", "foldername": "Recently played albums"},
|
||||||
|
{"mode": "list_albums_genre", "foldername": "Albums by Genre"}
|
||||||
|
]
|
||||||
|
|
||||||
|
for entry in menu:
|
||||||
|
url = self.build_url(entry)
|
||||||
|
|
||||||
|
li = xbmcgui.ListItem(entry["foldername"])
|
||||||
|
xbmcplugin.addDirectoryItem(
|
||||||
|
handle=self.addon_handle, url=url, listitem=li, isFolder=True)
|
||||||
|
|
||||||
|
xbmcplugin.endOfDirectory(self.addon_handle)
|
||||||
|
|
||||||
|
def list_playlists(self):
|
||||||
"""
|
"""
|
||||||
Display playlists.
|
Display playlists.
|
||||||
"""
|
"""
|
||||||
|
@ -188,7 +217,7 @@ class Plugin(object):
|
||||||
cover_art_url = self.connection.getCoverArtUrl(
|
cover_art_url = self.connection.getCoverArtUrl(
|
||||||
playlist["coverArt"])
|
playlist["coverArt"])
|
||||||
url = self.build_url({
|
url = self.build_url({
|
||||||
"mode": "playlist_list", "playlist_id": playlist["id"]})
|
"mode": "list_playlist_songs", "playlist_id": playlist["id"]})
|
||||||
|
|
||||||
li = xbmcgui.ListItem(playlist["name"], iconImage=cover_art_url)
|
li = xbmcgui.ListItem(playlist["name"], iconImage=cover_art_url)
|
||||||
xbmcplugin.addDirectoryItem(
|
xbmcplugin.addDirectoryItem(
|
||||||
|
@ -196,67 +225,116 @@ class Plugin(object):
|
||||||
|
|
||||||
xbmcplugin.endOfDirectory(self.addon_handle)
|
xbmcplugin.endOfDirectory(self.addon_handle)
|
||||||
|
|
||||||
def genre_list(self):
|
def list_playlist_songs(self):
|
||||||
"""
|
"""
|
||||||
Display list of genres menu.
|
Display playlist tracks.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
for genre in self.connection.walk_genres():
|
playlist_id = self.addon_args["playlist_id"][0]
|
||||||
url = self.build_url({
|
|
||||||
"mode": "albums_by_genre_list",
|
|
||||||
"foldername": genre["value"].encode("utf-8")})
|
|
||||||
|
|
||||||
li = xbmcgui.ListItem(genre["value"])
|
xbmcplugin.setContent(self.addon_handle, "songs")
|
||||||
xbmcplugin.addDirectoryItem(
|
|
||||||
handle=self.addon_handle, url=url, listitem=li, isFolder=True)
|
for track in self.connection.walk_playlist(playlist_id):
|
||||||
|
self.add_track(track, show_artist=True)
|
||||||
|
|
||||||
xbmcplugin.endOfDirectory(self.addon_handle)
|
xbmcplugin.endOfDirectory(self.addon_handle)
|
||||||
|
|
||||||
def newest_albums_list(self):
|
def list_albums_genre(self):
|
||||||
|
"""
|
||||||
|
Display albums by genre list.
|
||||||
|
"""
|
||||||
|
|
||||||
|
genres = self.connection.walk_genres()
|
||||||
|
genres_sorted = sorted(genres, key=lambda k: k['value'])
|
||||||
|
|
||||||
|
for genre in genres_sorted:
|
||||||
|
|
||||||
|
try:
|
||||||
|
|
||||||
|
genre_slug = genre["value"]
|
||||||
|
genre_name = genre_slug.replace(';',' / ')
|
||||||
|
genre_count = int(genre["albumCount"])
|
||||||
|
|
||||||
|
if genre_count == 0:
|
||||||
|
continue
|
||||||
|
|
||||||
|
|
||||||
|
genre_name += ' (' + str(genre_count) + ')'
|
||||||
|
|
||||||
|
url = self.build_url({
|
||||||
|
"mode": 'album_list_genre',
|
||||||
|
"foldername": genre_slug.encode("utf-8")})
|
||||||
|
|
||||||
|
li = xbmcgui.ListItem(genre_name)
|
||||||
|
xbmcplugin.addDirectoryItem(
|
||||||
|
handle=self.addon_handle, url=url, listitem=li, isFolder=True)
|
||||||
|
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
xbmcplugin.endOfDirectory(self.addon_handle)
|
||||||
|
|
||||||
|
def list_albums_newest(self):
|
||||||
"""
|
"""
|
||||||
Display newest album list.
|
Display newest album list.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
size = self.album_list_size
|
size = self.albums_per_page
|
||||||
|
|
||||||
xbmcplugin.setContent(self.addon_handle, "albums")
|
xbmcplugin.setContent(self.addon_handle, "albums")
|
||||||
|
|
||||||
for album in self.connection.walk_album_list('newest',size):
|
for album in self.connection.walk_albums(ltype='newest',size=size):
|
||||||
self.add_album(album, show_artist=True)
|
self.add_album(album, show_artist=True)
|
||||||
|
|
||||||
xbmcplugin.endOfDirectory(self.addon_handle)
|
xbmcplugin.endOfDirectory(self.addon_handle)
|
||||||
|
|
||||||
def albums_by_genre_list(self):
|
def list_albums_frequent(self):
|
||||||
|
"""
|
||||||
|
Display most played albums list.
|
||||||
|
"""
|
||||||
|
|
||||||
|
size = self.albums_per_page
|
||||||
|
|
||||||
|
xbmcplugin.setContent(self.addon_handle, "albums")
|
||||||
|
|
||||||
|
for album in self.connection.walk_albums(ltype='frequent',size=size):
|
||||||
|
self.add_album(album, show_artist=True)
|
||||||
|
|
||||||
|
xbmcplugin.endOfDirectory(self.addon_handle)
|
||||||
|
|
||||||
|
def list_albums_recent(self):
|
||||||
|
"""
|
||||||
|
Display recently played album list.
|
||||||
|
"""
|
||||||
|
|
||||||
|
size = self.albums_per_page
|
||||||
|
|
||||||
|
xbmcplugin.setContent(self.addon_handle, "albums")
|
||||||
|
|
||||||
|
for album in self.connection.walk_albums(ltype='recent',size=size):
|
||||||
|
self.add_album(album, show_artist=True)
|
||||||
|
|
||||||
|
xbmcplugin.endOfDirectory(self.addon_handle)
|
||||||
|
|
||||||
|
|
||||||
|
def album_list_genre(self):
|
||||||
"""
|
"""
|
||||||
Display album list by genre menu.
|
Display album list by genre menu.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
size = self.album_list_size
|
|
||||||
genre = self.addon_args["foldername"][0].decode("utf-8")
|
genre = self.addon_args["foldername"][0].decode("utf-8")
|
||||||
|
size = self.albums_per_page
|
||||||
|
|
||||||
xbmcplugin.setContent(self.addon_handle, "albums")
|
xbmcplugin.setContent(self.addon_handle, "albums")
|
||||||
|
|
||||||
for album in self.connection.walk_album_list('byGenre',size,genre=genre):
|
for album in self.connection.walk_albums(ltype='byGenre',size=size,genre=genre):
|
||||||
self.add_album(album, show_artist=True)
|
self.add_album(album, show_artist=True)
|
||||||
|
|
||||||
xbmcplugin.endOfDirectory(self.addon_handle)
|
xbmcplugin.endOfDirectory(self.addon_handle)
|
||||||
|
|
||||||
def albums_by_genre_list(self):
|
def list_artists(self):
|
||||||
"""
|
|
||||||
Display album list by genre menu.
|
|
||||||
"""
|
|
||||||
|
|
||||||
size = self.album_list_size
|
|
||||||
genre = self.addon_args["foldername"][0].decode("utf-8")
|
|
||||||
|
|
||||||
xbmcplugin.setContent(self.addon_handle, "albums")
|
|
||||||
|
|
||||||
for album in self.connection.walk_album_list('byGenre',size,None,None,genre):
|
|
||||||
self.add_album(album, show_artist=True)
|
|
||||||
|
|
||||||
xbmcplugin.endOfDirectory(self.addon_handle)
|
|
||||||
|
|
||||||
def artist_list(self):
|
|
||||||
"""
|
"""
|
||||||
Display artist list
|
Display artist list
|
||||||
"""
|
"""
|
||||||
|
@ -315,25 +393,20 @@ class Plugin(object):
|
||||||
|
|
||||||
xbmcplugin.endOfDirectory(self.addon_handle)
|
xbmcplugin.endOfDirectory(self.addon_handle)
|
||||||
|
|
||||||
def random_list(self):
|
|
||||||
|
def list_tracks_starred(self):
|
||||||
"""
|
"""
|
||||||
Display random options.
|
Display starred songs.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
menu = [
|
xbmcplugin.setContent(self.addon_handle, "songs")
|
||||||
{"mode": "random_by_genre_list", "foldername": "By genre"},
|
|
||||||
{"mode": "random_by_year_list", "foldername": "By year"}]
|
|
||||||
|
|
||||||
for entry in menu:
|
for starred in self.connection.walk_tracks_starred():
|
||||||
url = self.build_url(entry)
|
self.add_track(starred, show_artist=True)
|
||||||
|
|
||||||
li = xbmcgui.ListItem(entry["foldername"])
|
|
||||||
xbmcplugin.addDirectoryItem(
|
|
||||||
handle=self.addon_handle, url=url, listitem=li, isFolder=True)
|
|
||||||
|
|
||||||
xbmcplugin.endOfDirectory(self.addon_handle)
|
xbmcplugin.endOfDirectory(self.addon_handle)
|
||||||
|
|
||||||
def random_by_genre_list(self):
|
def list_tracks_random_genre(self):
|
||||||
"""
|
"""
|
||||||
Display random genre list.
|
Display random genre list.
|
||||||
"""
|
"""
|
||||||
|
@ -358,13 +431,13 @@ class Plugin(object):
|
||||||
|
|
||||||
xbmcplugin.setContent(self.addon_handle, "songs")
|
xbmcplugin.setContent(self.addon_handle, "songs")
|
||||||
|
|
||||||
for track in self.connection.walk_random_songs(
|
for track in self.connection.walk_tracks_random(
|
||||||
size=self.random_count, genre=genre):
|
size=self.tracks_per_page, genre=genre):
|
||||||
self.add_track(track, show_artist=True)
|
self.add_track(track, show_artist=True)
|
||||||
|
|
||||||
xbmcplugin.endOfDirectory(self.addon_handle)
|
xbmcplugin.endOfDirectory(self.addon_handle)
|
||||||
|
|
||||||
def random_by_year_list(self):
|
def list_tracks_random_year(self):
|
||||||
"""
|
"""
|
||||||
Display random tracks by year.
|
Display random tracks by year.
|
||||||
"""
|
"""
|
||||||
|
@ -376,8 +449,8 @@ class Plugin(object):
|
||||||
|
|
||||||
xbmcplugin.setContent(self.addon_handle, "songs")
|
xbmcplugin.setContent(self.addon_handle, "songs")
|
||||||
|
|
||||||
for track in self.connection.walk_random_songs(
|
for track in self.connection.walk_tracks_random(
|
||||||
size=self.random_count, from_year=from_year, to_year=to_year):
|
size=self.tracks_per_page, from_year=from_year, to_year=to_year):
|
||||||
self.add_track(track, show_artist=True)
|
self.add_track(track, show_artist=True)
|
||||||
|
|
||||||
xbmcplugin.endOfDirectory(self.addon_handle)
|
xbmcplugin.endOfDirectory(self.addon_handle)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
<addon id="plugin.audio.subsonic" name="Subsonic" version="2.0.1" provider-name="BasilFX">
|
<addon id="plugin.audio.subsonic" name="Subsonic" version="2.0.1" provider-name="BasilFX,grosbouff">
|
||||||
<requires>
|
<requires>
|
||||||
<import addon="xbmc.python" version="2.19.0"/>
|
<import addon="xbmc.python" version="2.19.0"/>
|
||||||
</requires>
|
</requires>
|
||||||
|
|
|
@ -2,7 +2,6 @@ import urllib
|
||||||
import urlparse
|
import urlparse
|
||||||
import libsonic
|
import libsonic
|
||||||
|
|
||||||
|
|
||||||
def force_list(value):
|
def force_list(value):
|
||||||
"""
|
"""
|
||||||
Coerce the input value to a list.
|
Coerce the input value to a list.
|
||||||
|
@ -336,16 +335,6 @@ class SubsonicClient(libsonic.Connection):
|
||||||
for child in response["playlist"]["entry"]:
|
for child in response["playlist"]["entry"]:
|
||||||
yield child
|
yield child
|
||||||
|
|
||||||
def walk_starred(self):
|
|
||||||
"""
|
|
||||||
Request Subsonic's starred songs and iterate over each item.
|
|
||||||
"""
|
|
||||||
|
|
||||||
response = self.getStarred()
|
|
||||||
|
|
||||||
for song in response["starred"]["song"]:
|
|
||||||
yield song
|
|
||||||
|
|
||||||
def walk_directory(self, directory_id):
|
def walk_directory(self, directory_id):
|
||||||
"""
|
"""
|
||||||
Request a Subsonic music directory and iterate over each item.
|
Request a Subsonic music directory and iterate over each item.
|
||||||
|
@ -391,7 +380,7 @@ class SubsonicClient(libsonic.Connection):
|
||||||
for genre in response["genres"]["genre"]:
|
for genre in response["genres"]["genre"]:
|
||||||
yield genre
|
yield genre
|
||||||
|
|
||||||
def walk_album_list(self, ltype, size=10, from_year=None,to_year=None, genre=None):
|
def walk_albums(self, ltype, size=None, from_year=None,to_year=None, genre=None):
|
||||||
"""
|
"""
|
||||||
Request all albums for a given genre and iterate over each album.
|
Request all albums for a given genre and iterate over each album.
|
||||||
"""
|
"""
|
||||||
|
@ -406,7 +395,7 @@ class SubsonicClient(libsonic.Connection):
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
response = self.getAlbumList2(
|
response = self.getAlbumList2(
|
||||||
ltype=ltype, size=size, offset=offset, fromYear=from_year, toYear=to_year, genre=genre)
|
ltype=ltype, genre=genre, size=size, offset=offset)
|
||||||
|
|
||||||
if not response["albumList2"]["album"]:
|
if not response["albumList2"]["album"]:
|
||||||
break
|
break
|
||||||
|
@ -426,8 +415,7 @@ class SubsonicClient(libsonic.Connection):
|
||||||
for song in response["album"]["song"]:
|
for song in response["album"]["song"]:
|
||||||
yield song
|
yield song
|
||||||
|
|
||||||
def walk_random_songs(self, size, genre=None, from_year=None,
|
def walk_tracks_random(self, size, genre=None, from_year=None,to_year=None):
|
||||||
to_year=None):
|
|
||||||
"""
|
"""
|
||||||
Request random songs by genre and/or year and iterate over each song.
|
Request random songs by genre and/or year and iterate over each song.
|
||||||
"""
|
"""
|
||||||
|
@ -437,3 +425,14 @@ class SubsonicClient(libsonic.Connection):
|
||||||
|
|
||||||
for song in response["randomSongs"]["song"]:
|
for song in response["randomSongs"]["song"]:
|
||||||
yield song
|
yield song
|
||||||
|
|
||||||
|
|
||||||
|
def walk_tracks_starred(self):
|
||||||
|
"""
|
||||||
|
Request Subsonic's starred songs and iterate over each item.
|
||||||
|
"""
|
||||||
|
|
||||||
|
response = self.getStarred()
|
||||||
|
|
||||||
|
for song in response["starred"]["song"]:
|
||||||
|
yield song
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
|
||||||
<settings>
|
<settings>
|
||||||
<setting id="subsonic_url" type="text" label="URL" default="http://demo.subsonic.org"/>
|
<category label="Server">
|
||||||
|
<setting id="subsonic_url" type="text" label="Server URL" default="http://demo.subsonic.org"/>
|
||||||
<setting id="username" type="text" label="Username" default="guest3"/>
|
<setting id="username" type="text" label="Username" default="guest3"/>
|
||||||
<setting id="password" type="text" option="hidden" label="Password" default="guest"/>
|
<setting id="password" type="text" option="hidden" label="Password" default="guest"/>
|
||||||
<setting id="random_count" type="labelenum" label="Random songs" values="10|15|20|25"/>
|
<setting type="sep" />
|
||||||
<setting id="album_list_size" type="labelenum" label="Albums list items" default="50" values="50|100|200|250|500"/>
|
<setting id="albums_per_page" type="labelenum" label="Albums per page" default="50" values="10|25|50|100|250|500"/>
|
||||||
|
<setting id="tracks_per_page" type="labelenum" label="Tracks per page" default="100" values="10|25|50|100|250|500"/>
|
||||||
|
<setting type="sep" />
|
||||||
<setting id="transcode_format" type="labelenum" label="Transcode format" values="mp3|raw|flv|ogg"/>
|
<setting id="transcode_format" type="labelenum" label="Transcode format" values="mp3|raw|flv|ogg"/>
|
||||||
<setting id="bitrate" type="labelenum" label="Bitrate" values="320|256|224|192|160|128|112|96|80|64|56|48|40|32"/>
|
<setting id="bitrate" type="labelenum" label="Bitrate" values="320|256|224|192|160|128|112|96|80|64|56|48|40|32"/>
|
||||||
|
</category>
|
||||||
</settings>
|
</settings>
|
||||||
|
|
Loading…
Reference in New Issue