Add support for starred items. General improvements.
This commit is contained in:
parent
c3a0bc6f5b
commit
4e99ed55b1
98
addon.py
98
addon.py
|
@ -41,6 +41,7 @@ class Plugin(object):
|
||||||
|
|
||||||
def build_url(self, query):
|
def build_url(self, query):
|
||||||
"""
|
"""
|
||||||
|
Create URL for page.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
parts = list(urlparse.urlparse(self.addon_url))
|
parts = list(urlparse.urlparse(self.addon_url))
|
||||||
|
@ -50,7 +51,8 @@ class Plugin(object):
|
||||||
|
|
||||||
def route(self):
|
def route(self):
|
||||||
"""
|
"""
|
||||||
Map a Kodi request to certain action.
|
Map a Kodi request to certain action. This takes the `mode' query
|
||||||
|
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_page"])[0]
|
||||||
|
@ -65,16 +67,18 @@ class Plugin(object):
|
||||||
|
|
||||||
url = self.connection.streamUrl(
|
url = self.connection.streamUrl(
|
||||||
sid=track["id"], maxBitRate=self.bitrate,
|
sid=track["id"], maxBitRate=self.bitrate,
|
||||||
tformat=self.trans_format)
|
tformat=self.transcode_format)
|
||||||
|
|
||||||
# Create list item
|
# Create list item
|
||||||
if show_artist:
|
if show_artist:
|
||||||
li = xbmcgui.ListItem(
|
title = "%s - %s" % (
|
||||||
"%s - %s" % (
|
track.get("artist", "<Unknown>"),
|
||||||
track.get("artist", "<Unknown>"),
|
track.get("title", "<Unknown>"))
|
||||||
track.get("title", "<Unknown>")))
|
|
||||||
else:
|
else:
|
||||||
li = xbmcgui.ListItem(track.get("title", "<Unknown>"))
|
title = track.get("title", "<Unknown>")
|
||||||
|
|
||||||
|
# Create item
|
||||||
|
li = xbmcgui.ListItem(title)
|
||||||
|
|
||||||
# Handle cover art
|
# Handle cover art
|
||||||
if "coverArt" in track:
|
if "coverArt" in track:
|
||||||
|
@ -86,12 +90,14 @@ class Plugin(object):
|
||||||
|
|
||||||
# Handle metadata
|
# Handle metadata
|
||||||
li.setProperty("IsPlayable", "true")
|
li.setProperty("IsPlayable", "true")
|
||||||
|
li.setMimeType(track.get("contentType"))
|
||||||
li.setInfo(type="Music", infoLabels={
|
li.setInfo(type="Music", infoLabels={
|
||||||
"Artist": track["artist"],
|
"Artist": track.get("artist"),
|
||||||
"Title": track["title"],
|
"Title": track.get("title"),
|
||||||
"Year": track.get("year"),
|
"Year": track.get("year"),
|
||||||
"Duration": track.get("duration"),
|
"Duration": track.get("duration"),
|
||||||
"Genre": track.get("genre")})
|
"Genre": track.get("genre"),
|
||||||
|
"TrackNumber": track.get("track")})
|
||||||
|
|
||||||
xbmcplugin.addDirectoryItem(
|
xbmcplugin.addDirectoryItem(
|
||||||
handle=self.addon_handle, url=url, listitem=li)
|
handle=self.addon_handle, url=url, listitem=li)
|
||||||
|
@ -107,12 +113,19 @@ class Plugin(object):
|
||||||
|
|
||||||
# Create list item
|
# Create list item
|
||||||
if show_artist:
|
if show_artist:
|
||||||
li = xbmcgui.ListItem(
|
title = "%s - %s" % (
|
||||||
"%s - %s" % (
|
album.get("artist", "<Unknown>"),
|
||||||
album.get("artist", "<Unknown>"),
|
album.get("name", "<Unknown>"))
|
||||||
album.get("name", "<Unknown>")))
|
|
||||||
else:
|
else:
|
||||||
li = xbmcgui.ListItem(album.get("name", "<Unknown>"))
|
title = album.get("name", "<Unknown>")
|
||||||
|
|
||||||
|
# Add year if applicable
|
||||||
|
if album.get("year"):
|
||||||
|
title = "%s [%d]" % (title, album.get("year"))
|
||||||
|
|
||||||
|
# Create item
|
||||||
|
li = xbmcgui.ListItem()
|
||||||
|
li.setLabel(title)
|
||||||
|
|
||||||
# Handle cover art
|
# Handle cover art
|
||||||
if "coverArt" in album:
|
if "coverArt" in album:
|
||||||
|
@ -123,7 +136,10 @@ class Plugin(object):
|
||||||
li.setProperty("fanart_image", cover_art_url)
|
li.setProperty("fanart_image", cover_art_url)
|
||||||
|
|
||||||
# Handle metadata
|
# Handle metadata
|
||||||
li.setProperty("IsPlayable", "false")
|
li.setInfo(type="music", infoLabels={
|
||||||
|
"Artist": album.get("artist"),
|
||||||
|
"Album": album.get("name"),
|
||||||
|
"Year": album.get("year")})
|
||||||
|
|
||||||
xbmcplugin.addDirectoryItem(
|
xbmcplugin.addDirectoryItem(
|
||||||
handle=self.addon_handle, url=url, listitem=li, isFolder=True)
|
handle=self.addon_handle, url=url, listitem=li, isFolder=True)
|
||||||
|
@ -134,6 +150,7 @@ class Plugin(object):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
menu = [
|
menu = [
|
||||||
|
{"mode": "starred_list", "foldername": "Starred"},
|
||||||
{"mode": "playlists_list", "foldername": "Playlists"},
|
{"mode": "playlists_list", "foldername": "Playlists"},
|
||||||
{"mode": "artist_list", "foldername": "Artists"},
|
{"mode": "artist_list", "foldername": "Artists"},
|
||||||
{"mode": "genre_list", "foldername": "Genres"},
|
{"mode": "genre_list", "foldername": "Genres"},
|
||||||
|
@ -148,6 +165,18 @@ class Plugin(object):
|
||||||
|
|
||||||
xbmcplugin.endOfDirectory(self.addon_handle)
|
xbmcplugin.endOfDirectory(self.addon_handle)
|
||||||
|
|
||||||
|
def starred_list(self):
|
||||||
|
"""
|
||||||
|
Display starred songs.
|
||||||
|
"""
|
||||||
|
|
||||||
|
xbmcplugin.setContent(self.addon_handle, "songs")
|
||||||
|
|
||||||
|
for starred in self.connection.walk_starred():
|
||||||
|
self.add_track(starred, show_artist=True)
|
||||||
|
|
||||||
|
xbmcplugin.endOfDirectory(self.addon_handle)
|
||||||
|
|
||||||
def playlists_list(self):
|
def playlists_list(self):
|
||||||
"""
|
"""
|
||||||
Display playlists.
|
Display playlists.
|
||||||
|
@ -172,10 +201,11 @@ class Plugin(object):
|
||||||
|
|
||||||
playlist_id = self.addon_args["playlist_id"][0]
|
playlist_id = self.addon_args["playlist_id"][0]
|
||||||
|
|
||||||
|
xbmcplugin.setContent(self.addon_handle, "songs")
|
||||||
|
|
||||||
for track in self.connection.walk_playlist(playlist_id):
|
for track in self.connection.walk_playlist(playlist_id):
|
||||||
self.add_track(track, show_artist=True)
|
self.add_track(track, show_artist=True)
|
||||||
|
|
||||||
xbmcplugin.setContent(self.addon_handle, "songs")
|
|
||||||
xbmcplugin.endOfDirectory(self.addon_handle)
|
xbmcplugin.endOfDirectory(self.addon_handle)
|
||||||
|
|
||||||
def genre_list(self):
|
def genre_list(self):
|
||||||
|
@ -201,10 +231,11 @@ class Plugin(object):
|
||||||
|
|
||||||
genre = self.addon_args["foldername"][0].decode("utf-8")
|
genre = self.addon_args["foldername"][0].decode("utf-8")
|
||||||
|
|
||||||
|
xbmcplugin.setContent(self.addon_handle, "albums")
|
||||||
|
|
||||||
for album in self.connection.walk_album_list_genre(genre):
|
for album in self.connection.walk_album_list_genre(genre):
|
||||||
self.add_album(album, show_artist=True)
|
self.add_album(album, show_artist=True)
|
||||||
|
|
||||||
xbmcplugin.setContent(self.addon_handle, "albums")
|
|
||||||
xbmcplugin.endOfDirectory(self.addon_handle)
|
xbmcplugin.endOfDirectory(self.addon_handle)
|
||||||
|
|
||||||
def artist_list(self):
|
def artist_list(self):
|
||||||
|
@ -212,6 +243,8 @@ class Plugin(object):
|
||||||
Display artist list
|
Display artist list
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
xbmcplugin.setContent(self.addon_handle, "artists")
|
||||||
|
|
||||||
for artist in self.connection.walk_artists():
|
for artist in self.connection.walk_artists():
|
||||||
cover_art_url = self.connection.getCoverArtUrl(artist["id"])
|
cover_art_url = self.connection.getCoverArtUrl(artist["id"])
|
||||||
url = self.build_url({
|
url = self.build_url({
|
||||||
|
@ -225,7 +258,6 @@ 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)
|
||||||
|
|
||||||
xbmcplugin.setContent(self.addon_handle, "artists")
|
|
||||||
xbmcplugin.endOfDirectory(self.addon_handle)
|
xbmcplugin.endOfDirectory(self.addon_handle)
|
||||||
|
|
||||||
def album_list(self):
|
def album_list(self):
|
||||||
|
@ -235,10 +267,20 @@ class Plugin(object):
|
||||||
|
|
||||||
artist_id = self.addon_args["artist_id"][0]
|
artist_id = self.addon_args["artist_id"][0]
|
||||||
|
|
||||||
|
xbmcplugin.setContent(self.addon_handle, "albums")
|
||||||
|
|
||||||
for album in self.connection.walk_artist(artist_id):
|
for album in self.connection.walk_artist(artist_id):
|
||||||
self.add_album(album)
|
self.add_album(album)
|
||||||
|
|
||||||
xbmcplugin.setContent(self.addon_handle, "albums")
|
xbmcplugin.addSortMethod(
|
||||||
|
self.addon_handle, xbmcplugin.SORT_METHOD_UNSORTED)
|
||||||
|
xbmcplugin.addSortMethod(
|
||||||
|
self.addon_handle, xbmcplugin.SORT_METHOD_ALBUM)
|
||||||
|
xbmcplugin.addSortMethod(
|
||||||
|
self.addon_handle, xbmcplugin.SORT_METHOD_ARTIST)
|
||||||
|
xbmcplugin.addSortMethod(
|
||||||
|
self.addon_handle, xbmcplugin.SORT_METHOD_VIDEO_YEAR)
|
||||||
|
|
||||||
xbmcplugin.endOfDirectory(self.addon_handle)
|
xbmcplugin.endOfDirectory(self.addon_handle)
|
||||||
|
|
||||||
def track_list(self):
|
def track_list(self):
|
||||||
|
@ -248,10 +290,11 @@ class Plugin(object):
|
||||||
|
|
||||||
album_id = self.addon_args["album_id"][0]
|
album_id = self.addon_args["album_id"][0]
|
||||||
|
|
||||||
|
xbmcplugin.setContent(self.addon_handle, "songs")
|
||||||
|
|
||||||
for track in self.connection.walk_album(album_id):
|
for track in self.connection.walk_album(album_id):
|
||||||
self.add_track(track)
|
self.add_track(track)
|
||||||
|
|
||||||
xbmcplugin.setContent(self.addon_handle, "songs")
|
|
||||||
xbmcplugin.endOfDirectory(self.addon_handle)
|
xbmcplugin.endOfDirectory(self.addon_handle)
|
||||||
|
|
||||||
def random_list(self):
|
def random_list(self):
|
||||||
|
@ -295,11 +338,12 @@ class Plugin(object):
|
||||||
|
|
||||||
genre = self.addon_args["foldername"][0].decode("utf-8")
|
genre = self.addon_args["foldername"][0].decode("utf-8")
|
||||||
|
|
||||||
|
xbmcplugin.setContent(self.addon_handle, "songs")
|
||||||
|
|
||||||
for track in self.connection.walk_random_songs(
|
for track in self.connection.walk_random_songs(
|
||||||
size=self.random_count, genre=genre):
|
size=self.random_count, genre=genre):
|
||||||
self.add_track(track, show_artist=True)
|
self.add_track(track, show_artist=True)
|
||||||
|
|
||||||
xbmcplugin.setContent(self.addon_handle, "songs")
|
|
||||||
xbmcplugin.endOfDirectory(self.addon_handle)
|
xbmcplugin.endOfDirectory(self.addon_handle)
|
||||||
|
|
||||||
def random_by_year_list(self):
|
def random_by_year_list(self):
|
||||||
|
@ -312,26 +356,28 @@ class Plugin(object):
|
||||||
to_year = xbmcgui.Dialog().input(
|
to_year = xbmcgui.Dialog().input(
|
||||||
"To year", type=xbmcgui.INPUT_NUMERIC)
|
"To year", type=xbmcgui.INPUT_NUMERIC)
|
||||||
|
|
||||||
|
xbmcplugin.setContent(self.addon_handle, "songs")
|
||||||
|
|
||||||
for track in self.connection.walk_random_songs(
|
for track in self.connection.walk_random_songs(
|
||||||
size=self.random_count, from_year=from_year, to_year=to_year):
|
size=self.random_count, from_year=from_year, to_year=to_year):
|
||||||
self.add_track(track, show_artist=True)
|
self.add_track(track, show_artist=True)
|
||||||
|
|
||||||
xbmcplugin.setContent(self.addon_handle, "songs")
|
|
||||||
xbmcplugin.endOfDirectory(self.addon_handle)
|
xbmcplugin.endOfDirectory(self.addon_handle)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""
|
"""
|
||||||
Entry point for this plugin.
|
Entry point for this plugin. Instantiates a new plugin object and runs the
|
||||||
|
action that is given.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
addon_url = sys.argv[0]
|
addon_url = sys.argv[0]
|
||||||
addon_handle = int(sys.argv[1])
|
addon_handle = int(sys.argv[1])
|
||||||
addon_args = urlparse.parse_qs(sys.argv[2][1:])
|
addon_args = urlparse.parse_qs(sys.argv[2][1:])
|
||||||
|
|
||||||
# Route request to action
|
# Route request to action.
|
||||||
Plugin(addon_url, addon_handle, addon_args).route()
|
Plugin(addon_url, addon_handle, addon_args).route()
|
||||||
|
|
||||||
# Start plugin from within Kodi
|
# Start plugin from within Kodi.
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -240,6 +240,22 @@ class SubsonicClient(libsonic.Connection):
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
def getStarred(self, *args, **kwargs):
|
||||||
|
"""
|
||||||
|
Improve the getStarred method. Ensures the IDs are real integers.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def _song_iterator(songs):
|
||||||
|
for song in force_list(songs):
|
||||||
|
song["id"] = int(song["id"])
|
||||||
|
yield song
|
||||||
|
|
||||||
|
response = super(SubsonicClient, self).getStarred(*args, **kwargs)
|
||||||
|
response["starred"]["song"] = list(
|
||||||
|
_song_iterator(response["starred"].get("song")))
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
def getCoverArtUrl(self, *args, **kwargs):
|
def getCoverArtUrl(self, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
Return an URL to the cover art.
|
Return an URL to the cover art.
|
||||||
|
@ -312,14 +328,24 @@ class SubsonicClient(libsonic.Connection):
|
||||||
|
|
||||||
def walk_playlist(self, playlist_id):
|
def walk_playlist(self, playlist_id):
|
||||||
"""
|
"""
|
||||||
Request SubSonic's playlist items and iterate over each item.
|
Request Subsonic's playlist items and iterate over each item.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
response = self.getPlaylist(playlist_id)
|
response = self.getPlaylist(playlist_id)
|
||||||
|
|
||||||
for order, 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.
|
||||||
|
@ -404,6 +430,4 @@ class SubsonicClient(libsonic.Connection):
|
||||||
size=size, genre=genre, fromYear=from_year, toYear=to_year)
|
size=size, genre=genre, fromYear=from_year, toYear=to_year)
|
||||||
|
|
||||||
for song in response["randomSongs"]["song"]:
|
for song in response["randomSongs"]["song"]:
|
||||||
song["id"] = int(song["id"])
|
|
||||||
|
|
||||||
yield song
|
yield song
|
||||||
|
|
Loading…
Reference in New Issue