diff --git a/README b/README index 642dabd..ed45cb3 100644 --- a/README +++ b/README @@ -27,3 +27,7 @@ To avoid random crashes in kodi don't do any operation in the last five seconds due to a kodi bug, playing next song generates a busy dialog ( impossible to avoid ) and operating on kodi generates another busy dialog. The combination of two busy dialogs working crashes kodi (https://github.com/xbmc/xbmc/issues/16756) + +When you update the 2.0 version from an old version, expecially on raspberry pi, the plugin could not work. +This behaviour is due to the kodi addon cache. To correct this one time problem, it is necessary to reboot the +mediacenter or, if the problem continues, uninstall and reinstall the plugin. diff --git a/addon.xml b/addon.xml index 5b6a989..d07a3d9 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + diff --git a/resources/language/resource.language.en_gb/strings.po b/resources/language/resource.language.en_gb/strings.po index 95dafb5..a7e91ac 100644 --- a/resources/language/resource.language.en_gb/strings.po +++ b/resources/language/resource.language.en_gb/strings.po @@ -453,3 +453,27 @@ msgstr "" msgctxt "#30204" msgid "Permission error. If you are using Nextcloud don't check api_key box" msgstr "" + +msgctxt "#30220" +msgid "Video" +msgstr "" + +msgctxt "#30221" +msgid "Videos" +msgstr "" + +msgctxt "#30222" +msgid "Search Videos..." +msgstr "" + +msgctxt "#30225" +msgid "Podcast" +msgstr "" + +msgctxt "#30226" +msgid "Podcasts" +msgstr "" + +msgctxt "#30227" +msgid "Search Podcasts..." +msgstr "" diff --git a/resources/language/resource.language.it_it/strings.po b/resources/language/resource.language.it_it/strings.po index b4182b9..22aaee2 100644 --- a/resources/language/resource.language.it_it/strings.po +++ b/resources/language/resource.language.it_it/strings.po @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: XBMC Addons\n" "Report-Msgid-Bugs-To: alanwww1@xbmc.org\n" "POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" -"PO-Revision-Date: 2021-01-06 11:30+0100\n" +"PO-Revision-Date: 2021-02-18 21:42+0100\n" "Last-Translator: \n" "Language-Team: English (http://www.transifex.com/projects/p/xbmc-addons/" "language/en/)\n" @@ -106,19 +106,19 @@ msgstr "Tutto" msgctxt "#30111" msgid "Tag" -msgstr "" +msgstr "Genere" msgctxt "#30112" msgid "Artist tag" -msgstr "Tag artista" +msgstr "Genere artista" msgctxt "#30113" msgid "Album tag" -msgstr "Tag album" +msgstr "Genere album" msgctxt "#30114" msgid "Song tag" -msgstr "Tag canzone" +msgstr "Genere canzone" msgctxt "#30115" msgid "Artists" @@ -138,7 +138,7 @@ msgstr "" msgctxt "#30119" msgid "Tags" -msgstr "" +msgstr "Generi" # code msgctxt "#30120" @@ -236,15 +236,15 @@ msgstr "Mostra tutti gli album di questo artista" msgctxt "#30142" msgid "Artist tags..." -msgstr "Tag Artisti..." +msgstr "Generi Artisti..." msgctxt "#30143" msgid "Album tags..." -msgstr "Tag Album..." +msgstr "Generi Album..." msgctxt "#30144" msgid "Song tags..." -msgstr "Tag Canzoni..." +msgstr "Generi Canzoni..." msgctxt "#30145" msgid "Recently Added..." @@ -312,7 +312,7 @@ msgstr "Canzoni Dimenticate..." msgctxt "#30161" msgid "Newest Artists..." -msgstr "Nuovi artisti.." +msgstr "Nuovi artisti..." msgctxt "#30162" msgid "Newest Albums..." @@ -420,15 +420,15 @@ msgstr "Plugin Ampache" msgctxt "#30190" msgid "Recently Played Artists..." -msgstr "Artisti suonati recentemente.." +msgstr "Artisti suonati recentemente..." msgctxt "#30191" msgid "Recently Played Albums..." -msgstr "Album suonati recentemente.." +msgstr "Album suonati recentemente..." msgctxt "#30192" msgid "Recently Played Songs..." -msgstr "Canzoni suonati recentemente..." +msgstr "Canzoni suonate recentemente..." msgctxt "#30193" msgid "Recently Played..." @@ -462,22 +462,28 @@ msgctxt "#30204" msgid "Permission error. If you are using Nextcloud don't check api_key box" msgstr "Permessi errati. Se state usando Nextcloud non utilizzare l'api_key" -#~ msgctxt "#30190" -#~ msgid "Recent Artists..." -#~ msgstr "Artisti recenti.." +msgctxt "#30220" +msgid "Video" +msgstr "" + +msgctxt "#30221" +msgid "Videos" +msgstr "Video" -#~ msgctxt "#30191" -#~ msgid "Recent Albums..." -#~ msgstr "Album recenti.." +# code +msgctxt "#30222" +msgid "Search Videos..." +msgstr "Ricerca video..." -#~ msgctxt "#30192" -#~ msgid "Recent Songs..." -#~ msgstr "Canzoni recenti..." +msgctxt "#30225" +msgid "Podcast" +msgstr "" -#~ msgctxt "#30193" -#~ msgid "Recent..." -#~ msgstr "Recenti..." +msgctxt "#30226" +msgid "Podcasts" +msgstr "" -#~ msgctxt "#30170" -#~ msgid "Enter the Name" -#~ msgstr "Inserisci il nome del server" +# code +msgctxt "#30227" +msgid "Search Podcasts..." +msgstr "Ricerca podcast..." diff --git a/resources/lib/ampache_connect.py b/resources/lib/ampache_connect.py index 6625079..6f3e760 100644 --- a/resources/lib/ampache_connect.py +++ b/resources/lib/ampache_connect.py @@ -22,7 +22,7 @@ class ConnectionError(Exception): pass def __init__(self): - self._ampache = xbmcaddon.Addon() + self._ampache = xbmcaddon.Addon("plugin.audio.ampache") jsStorServer = json_storage.JsonStorage("servers.json") serverStorage = jsStorServer.getData() self._connectionData = serverStorage["servers"][serverStorage["current_server"]] @@ -52,13 +52,18 @@ def fillConnectionSettings(self,tree,nTime): self._ampache.setSetting("albums", tree.findtext("albums")) self._ampache.setSetting("songs", tree.findtext("songs")) self._ampache.setSetting("playlists", tree.findtext("playlists")) + videos = tree.findtext("videos") + if videos: + self._ampache.setSetting("videos", videos) + podcasts = tree.findtext("podcasts") + if podcasts: + self._ampache.setSetting("podcasts", podcasts) self._ampache.setSetting("session_expire", tree.findtext("session_expire")) self._ampache.setSetting("add", tree.findtext("add")) self._ampache.setSetting("token", token) self._ampache.setSetting("token-exp", str(nTime+24000)) def getCodeMessError(self,tree): - code = None errormess = None errornode = tree.find("error") if errornode is not None: @@ -215,12 +220,6 @@ def ampache_http_request(self,action): return tree def build_ampache_url(self,action): - if ut.check_tokenexp(): - xbmc.log("refreshing token...", xbmc.LOGDEBUG ) - try: - self.AMPACHECONNECT() - except: - return token = self._ampache.getSetting("token") thisURL = self._connectionData["url"] + self.getBaseUrl() + '?action=' + action thisURL += '&auth=' + token diff --git a/resources/lib/ampache_monitor.py b/resources/lib/ampache_monitor.py index eadf834..5c270e2 100644 --- a/resources/lib/ampache_monitor.py +++ b/resources/lib/ampache_monitor.py @@ -46,6 +46,6 @@ def onNotification(self, sender, method, data): except: xbmc.log("AmpacheMonitor::no playing file " , xbmc.LOGDEBUG) return - xbmc.executebuiltin('RunPlugin(plugin://plugin.audio.ampache/?mode=47)') + xbmc.executebuiltin('RunPlugin(plugin://plugin.audio.ampache/?mode=205)') diff --git a/resources/lib/ampache_plugin.py b/resources/lib/ampache_plugin.py index 0aad5b1..20694d8 100644 --- a/resources/lib/ampache_plugin.py +++ b/resources/lib/ampache_plugin.py @@ -24,18 +24,10 @@ #possible to start a song without initialising the plugin ampache = xbmcaddon.Addon("plugin.audio.ampache") -#ampache_addon_path = ampache.getAddonInfo('path') -#ampache_dir = xbmc.translatePath( ampache_addon_path ) -#if PY2: -# ampache_dir = ampache_dir.decode('utf-8') -#BASE_RESOURCE_PATH = os.path.join( ampache_dir, 'resources' ) -#mediaDir = os.path.join( BASE_RESOURCE_PATH , 'media' ) -#imagepath = os.path.join( mediaDir ,'images') - def searchGui(): dialog = xbmcgui.Dialog() ret = dialog.contextmenu([ut.tString(30106),ut.tString(30107),ut.tString(30108),\ - ut.tString(30109),ut.tString(30110),ut.tString(30111)]) + ut.tString(30109),ut.tString(30110),ut.tString(30220),ut.tString(30225),ut.tString(30111)]) endDir = False if ret == 0: endDir = do_search("artists") @@ -48,14 +40,25 @@ def searchGui(): elif ret == 4: endDir = do_search("songs","search_songs") elif ret == 5: + endDir = do_search("videos") + elif ret == 6: + endDir = do_search("podcasts") + elif ret == 7: ret2 = dialog.contextmenu([ut.tString(30112),ut.tString(30113),ut.tString(30114)]) - if ret2 == 0: - endDir = do_search("tags","tag_artists") - elif ret2 == 1: - endDir = do_search("tags","tag_albums") - elif ret2 == 2: - endDir = do_search("tags","tag_songs") - + if(int(ampache.getSetting("api-version"))) < 500000: + if ret2 == 0: + endDir = do_search("tags","tag_artists") + elif ret2 == 1: + endDir = do_search("tags","tag_albums") + elif ret2 == 2: + endDir = do_search("tags","tag_songs") + else: + if ret2 == 0: + endDir = do_search("genres","genre_artists") + elif ret2 == 1: + endDir = do_search("genres","genre_albums") + elif ret2 == 2: + endDir = do_search("genres","genre_songs") return endDir #return album and artist name, only album could be confusing @@ -79,18 +82,9 @@ def get_album_artist_name(node): fullname = fullname + " - [ " + ut.tString(30195) + " " + disknumber + " ]" return fullname -def getRating(rating): - if rating: - #converts from five stats ampache rating to ten stars kodi rating - rating = int(float(rating)*2) - else: - #zero equals no rating - rating = 0 - return rating - def get_infolabels(object_type , node): infoLabels = None - rating = getRating(node.findtext("rating")) + rating = ut.getRating(node.findtext("rating")) if object_type == 'albums': infoLabels = { 'Title' : str(node.findtext("name")) , @@ -122,11 +116,19 @@ def get_infolabels(object_type , node): 'Mediatype' : 'song' } + elif object_type == 'videos': + infoLabels = { + 'Title' : str(node.findtext("name")) , + 'VideoResolution' : node.findtext("resolution") , + 'Size' : node.findtext("size") , + 'Mediatype' : 'video' + } + return infoLabels def getNestedTypeId(node,elem_type): obj_elem = node.find(elem_type) - obj_id = int(obj_elem.attrib["id"]) + obj_id = obj_elem.attrib["id"] return obj_id #this function is used to speed up the loading of the images using differents @@ -145,7 +147,7 @@ def precacheArt(elem,object_type): object_id = None else: try: - object_id = int(node.attrib["id"]) + object_id = node.attrib["id"] except: object_id = None if object_id == None: @@ -166,22 +168,6 @@ def check_get_art_url(node): url = node.findtext("art") return url -#it handles albumArt and song info -def fillListItemWithSongInfo(liz,node): - object_id = int(node.attrib["id"]) - image_url = check_get_art_url(node) - try: - album_id = getNestedTypeId(node,"album") - albumArt = art.get_art(album_id,"album",image_url) - except: - albumArt = art.get_art(None,"album",image_url) - liz.setLabel(str(node.findtext("title"))) - liz.setArt( art.get_artLabels(albumArt) ) - #needed by play_track to play the song, added here to uniform api - liz.setPath(node.findtext("url")) - liz.setInfo( type="music", infoLabels=get_infolabels("songs", node) ) - liz.setMimeType(node.findtext("mime")) - def addLinks(elem,object_type,useCacheArt,mode): image = "DefaultFolder.png" @@ -191,13 +177,9 @@ def addLinks(elem,object_type,useCacheArt,mode): for node in elem.iter(elem_type): cm = [] - try: - object_id = int(node.attrib["id"]) - except: - object_id == None + object_id = node.attrib["id"] + if object_id is None or object_id == "": continue - #xbmc.log("AmpachePlugin::addLinks: object_id - " + str(object_id) , xbmc.LOGDEBUG ) - #xbmc.log("AmpachePlugin::addLinks: node " + ET.tostring(node) , xbmc.LOGDEBUG ) name = str(node.findtext("name")) @@ -211,11 +193,10 @@ def addLinks(elem,object_type,useCacheArt,mode): allid.add(object_id) else: continue - try: - artist_id = getNestedTypeId(node,"artist") - cm.append( ( ut.tString(30141), "Container.Update(%s?object_id=%s&mode=2)" % ( sys.argv[0],artist_id ) ) ) - except: - pass + artist_id = getNestedTypeId(node,"artist") + if artist_id is not None and artist_id != "": + cm.append( ( ut.tString(30141),"Container.Update(%s?object_id=%s&mode=1&submode=6)" % + ( sys.argv[0],artist_id ) ) ) name = get_album_artist_name(node) if useCacheArt: @@ -248,7 +229,7 @@ def addLinks(elem,object_type,useCacheArt,mode): handle=int(sys.argv[1]) - u=sys.argv[0]+"?object_id="+str(object_id)+"&mode="+str(mode) + u=sys.argv[0]+"?object_id="+object_id+"&mode="+str(mode)+"&submode=71" #xbmc.log("AmpachePlugin::addLinks: u - " + u, xbmc.LOGDEBUG ) isFolder=True tu= (u,liz,isFolder) @@ -256,70 +237,91 @@ def addLinks(elem,object_type,useCacheArt,mode): xbmcplugin.addDirectoryItems(handle=int(sys.argv[1]),items=it,totalItems=len(elem)) -# Used to populate items for songs on XBMC. Calls plugin script with mode == 45 and object_id == (ampache song id) -# TODO: Merge with addLinks(). Same basic idea going on, this one adds links all at once, as the other one -# Also, some property things, some different context menu things. -def addSongLinks(elem): +# Used to populate items for songs on XBMC. Calls plugin script with mode == +# 45 and play_ur == (ampache item url) +def addPlayLinks(elem, object_type , object_subtype=None): - xbmcplugin.setContent(int(sys.argv[1]), "songs") - ok=True + xbmcplugin.setContent(int(sys.argv[1]), object_type) it=[] - for node in elem.iter("song"): - try: - song_id = int(node.attrib["id"]) - except: - song_id = None + + elem_type = ut.otype_to_type(object_type,object_subtype) + + #we don't use sort method for track cause songs are already sorted + #by the server and it make a mess in random playlists + if elem_type == "video": + xbmcplugin.addSortMethod(int(sys.argv[1]),xbmcplugin.SORT_METHOD_TITLE) + elif elem_type == "podcast_episode": + xbmcplugin.addSortMethod(int(sys.argv[1]),xbmcplugin.SORT_METHOD_LABEL) + + for node in elem.iter(elem_type): + object_id = node.attrib["id"] + if object_id is None or object_id == "": continue + + play_url = str(node.findtext("url")) + object_title = str(node.findtext("title")) + liz=xbmcgui.ListItem() - fillListItemWithSongInfo(liz,node) liz.setProperty("IsPlayable", "true") + liz.setPath(play_url) + liz.setLabel(object_title) - cm = [] - try: - artist_id = getNestedTypeId(node,"artist") - cm.append( ( ut.tString(30138), - "Container.Update(%s?object_id=%s&mode=15)" % ( - sys.argv[0],artist_id ) ) ) - except: - pass - - try: - album_id = getNestedTypeId(node,"album") - cm.append( ( ut.tString(30139), - "Container.Update(%s?object_id=%s&mode=16)" % ( - sys.argv[0],album_id ) ) ) - except: - pass - - song_title = str(node.findtext("title")) - cm.append( ( ut.tString(30140), - "Container.Update(%s?title=%s&mode=17)" % ( - sys.argv[0],urllib.parse.quote_plus(song_title) ) ) ) + if elem_type == "song": + image_url = check_get_art_url(node) + try: + album_id = getNestedTypeId(node,"album") + albumArt = art.get_art(album_id,"album",image_url) + except: + albumArt = art.get_art(None,"album",image_url) - if cm != []: - liz.addContextMenuItems(cm) + liz.setArt( art.get_artLabels(albumArt) ) + liz.setInfo( type="music", infoLabels=get_infolabels("songs", node) ) + liz.setMimeType(node.findtext("mime")) + + cm = [] + + artist_id = getNestedTypeId(node,"artist") + if artist_id is not None and artist_id != "": + cm.append( ( ut.tString(30138), + "Container.Update(%s?object_id=%s&mode=1&submode=6)" % ( + sys.argv[0],artist_id ) ) ) - song_url = node.findtext("url") - track_parameters = { "mode": 45, "song_url" : song_url, "object_id" : song_id} + album_id = getNestedTypeId(node,"album") + if album_id is not None and album_id != "": + cm.append( ( ut.tString(30139), + "Container.Update(%s?object_id=%s&mode=2&submode=6)" % ( + sys.argv[0],album_id ) ) ) + + cm.append( ( ut.tString(30140), + "Container.Update(%s?title=%s&mode=3&submode=12)" % ( + sys.argv[0],urllib.parse.quote_plus(object_title) ) ) ) + + if cm != []: + liz.addContextMenuItems(cm) + elif elem_type == "video": + liz.setInfo( type="video", infoLabels=get_infolabels("videos", node) ) + liz.setMimeType(node.findtext("mime")) + + track_parameters = { "mode": 200, "play_url" : play_url} url = sys.argv[0] + '?' + urllib.parse.urlencode(track_parameters) tu= (url,liz) it.append(tu) - + xbmcplugin.addDirectoryItems(handle=int(sys.argv[1]),items=it,totalItems=len(elem)) #The function that actually plays an Ampache URL by using setResolvedUrl -def play_track(object_id,song_url): - if song_url == None or object_id == None: - xbmc.log("AmpachePlugin::play_track object or song null", xbmc.LOGINFO ) +def play_track(url): + if url == None: + xbmc.log("AmpachePlugin::play_track url null", xbmc.LOGINFO ) return liz = xbmcgui.ListItem() - liz.setPath(song_url) + liz.setPath(url) xbmcplugin.setResolvedUrl(handle=int(sys.argv[1]), succeeded=True,listitem=liz) #Main function to add xbmc plugin elements -def addDir(name,object_id,mode,offset=None): +def addDir(name,mode,submode,offset=None,object_id=None): infoLabels={ "Title": name } liz=xbmcgui.ListItem(name) @@ -328,28 +330,32 @@ def addDir(name,object_id,mode,offset=None): handle=int(sys.argv[1]) - u=sys.argv[0]+"?object_id="+str(object_id)+"&mode="+str(mode) + u=sys.argv[0]+"?mode="+str(mode)+"&submode="+str(submode) #offset, in case of very long lists if offset: u = u + "&offset="+str(offset) + if object_id: + u = u + "&object_id="+object_id xbmc.log("AmpachePlugin::addDir url " + u, xbmc.LOGDEBUG) xbmcplugin.addDirectoryItem(handle=handle,url=u,listitem=liz,isFolder=True) #this function add items to the directory using the low level addLinks of ddSongLinks functions -def addItem( object_type, mode , elem, useCacheArt=True): +def addItems( object_type, mode , elem, useCacheArt=True, object_subtype=None): image = "DefaultFolder.png" - xbmc.log("AmpachePlugin::addItem: object_type - " + str(object_type) , xbmc.LOGDEBUG ) + xbmc.log("AmpachePlugin::addItems: object_type - " + str(object_type) , xbmc.LOGDEBUG ) + if object_subtype: + xbmc.log("AmpachePlugin::addItems: object_subtype - " + str(object_subtype) , xbmc.LOGDEBUG ) if useCacheArt: precacheArt(elem,object_type) - if object_type == 'songs': - addSongLinks(elem) + if object_type == 'songs' or object_type == 'videos': + addPlayLinks(elem,object_type,object_subtype) else: addLinks(elem,object_type,useCacheArt,mode) return -def get_all(object_type,offset=None): +def get_all(object_type, mode ,offset=None): if offset == None: offset=0 try: @@ -357,7 +363,7 @@ def get_all(object_type,offset=None): except: return #to not overload servers - step = 100 + step = 500 newLimit = offset+step #load images in long list if (ut.strBool_to_bool(ampache.getSetting("images-long-list"))): @@ -365,9 +371,12 @@ def get_all(object_type,offset=None): else: get_items(object_type, limit=step, offset=offset, useCacheArt=False) if newLimit < limit: - return newLimit + pass else: - return None + newLimit = None + + if newLimit: + addDir(ut.tString(30194),mode,5,offset=newLimit) #this functions handles the majority of the requests to the server #so, we have a lot of optional params @@ -388,61 +397,43 @@ def get_items(object_type, object_id=None, add=None,\ #object_id could be None in some requests, like recently added and get_all #items if object_id: - xbmc.log("AmpachePlugin::get_items: object_id " + str(object_id), xbmc.LOGDEBUG) + xbmc.log("AmpachePlugin::get_items: object_id " + object_id, xbmc.LOGDEBUG) if limit == None: limit = int(ampache.getSetting(object_type)) - mode = None - xbmcplugin.setContent(int(sys.argv[1]), object_type) #default: object_type is the action,otherwise see the if list below action = object_type + artist_action_subtypes = [ + 'artist_albums','tag_albums','genre_albums','album'] + + album_action_subtypes = [ 'tag_artists','genre_artists','artist'] + + song_action_subtypes = [ 'tag_songs','genre_songs', 'playlist_songs', + 'album_songs', 'artist_songs','search_songs', 'podcast_episodes'] + #do not use action = object_subtype cause in tags it is used only to #discriminate between subtypes if object_type == 'albums': if object_subtype == 'artist_albums': - action = 'artist_albums' - addDir("All Songs",object_id,12) - elif object_subtype == 'tag_albums': - action = 'tag_albums' - elif object_subtype == 'album': - action = 'album' + addDir("All Songs",1,72, object_id=object_id) + #do not use elif, artist_albums is checked two times + if object_subtype in artist_action_subtypes: + action = object_subtype elif object_type == 'artists': - if object_subtype == 'tag_artists': - action = 'tag_artists' - if object_subtype == 'artist': - action = 'artist' + if object_subtype in album_action_subtypes: + action = object_subtype elif object_type == 'songs': - if object_subtype == 'tag_songs': - action = 'tag_songs' - elif object_subtype == 'playlist_songs': - action = 'playlist_songs' - elif object_subtype == 'album_songs': - action = 'album_songs' - elif object_subtype == 'artist_songs': - action = 'artist_songs' - elif object_subtype == 'search_songs': - action = 'search_songs' + if object_subtype in song_action_subtypes: + action = object_subtype if object_id: thisFilter = object_id #set the mode - if object_type == 'artists': - mode = 2 - elif object_type == 'albums': - mode = 3 - elif object_type == 'playlists': - mode = 14 - elif object_type == 'tags': - if object_subtype == 'tag_artists': - mode = 19 - elif object_subtype == 'tag_albums': - mode = 20 - elif object_subtype == 'tag_songs': - mode = 21 + mode = ut.otype_to_mode(object_type, object_subtype) #here the documentation for an ampache connection #first create the connection object @@ -455,7 +446,7 @@ def get_items(object_type, object_id=None, add=None,\ #or ampache_binary_request if the server return a binary file (eg. an #image ) #it could be very simply to add json api, but we have to rewrite all - #function that rely on xml input, like additem + #function that rely on xml input, like additems try: ampConn = ampache_connect.AmpacheConnect() @@ -466,7 +457,7 @@ def get_items(object_type, object_id=None, add=None,\ ampConn.offset = offset elem = ampConn.ampache_http_request(action) - addItem( object_type, mode , elem, useCacheArt) + addItems( object_type, mode , elem, useCacheArt,object_subtype) except: return @@ -480,7 +471,7 @@ def setRating(): return object_id = ut.get_objectId_from_fileURL( file_url ) - if object_id == None: + if object_id is None or object_id == "": return rating = xbmc.getInfoLabel('MusicPlayer.UserRating') if rating == "": @@ -494,7 +485,7 @@ def setRating(): ampConn = ampache_connect.AmpacheConnect() action = "rate" - ampConn.id = str(object_id) + ampConn.id = object_id ampConn.type = "song" ampConn.rating = str(amp_rating) @@ -521,14 +512,9 @@ def do_search(object_type,object_subtype=None,thisFilter=None): def get_stats(object_type, object_subtype=None, limit=5000 ): - ampConn = ampache_connect.AmpacheConnect() - xbmc.log("AmpachePlugin::get_stats ", xbmc.LOGDEBUG) - mode = None - if object_type == 'artists': - mode = 2 - elif object_type == 'albums': - mode = 3 + + mode = ut.otype_to_mode(object_type) xbmcplugin.setContent(int(sys.argv[1]), object_type) @@ -539,90 +525,65 @@ def get_stats(object_type, object_subtype=None, limit=5000 ): else: amtype = ut.otype_to_type(object_type) thisFilter = object_subtype - + try: + ampConn = ampache_connect.AmpacheConnect() + ampConn.filter = thisFilter ampConn.limit = limit ampConn.type = amtype elem = ampConn.ampache_http_request(action) - addItem( object_type, mode , elem) + addItems( object_type, mode , elem) except: return -def get_recent(object_type,object_id,object_subtype=None): +def get_recent(object_type,submode,object_subtype=None): - if object_id == 9999998: + if submode == 31: update = ampache.getSetting("add") xbmc.log(update[:10],xbmc.LOGINFO) get_items(object_type=object_type,add=update[:10],object_subtype=object_subtype) - elif object_id == 9999997: + elif submode == 32: get_items(object_type=object_type,add=ut.get_time(-7),object_subtype=object_subtype) - elif object_id == 9999996: + elif submode == 33: get_items(object_type=object_type,add=ut.get_time(-30),object_subtype=object_subtype) - elif object_id == 9999995: + elif submode == 34: get_items(object_type=object_type,add=ut.get_time(-90),object_subtype=object_subtype) -def get_random(object_type): +def get_random(object_type, random_items): xbmc.log("AmpachePlugin::get_random: object_type " + object_type, xbmc.LOGDEBUG) - mode = None #object type can be : albums, artists, songs, playlists - ampConn = ampache_connect.AmpacheConnect() - - amtype = ut.otype_to_type(object_type) - if object_type == 'albums': - mode = 3 - elif object_type == 'artists': - mode = 2 - elif object_type == 'playlists': - mode = 14 - #song is the same mode + mode = ut.otype_to_mode(object_type) xbmcplugin.setContent(int(sys.argv[1]), object_type) - try: - random_items = (int(ampache.getSetting("random_items"))*3)+3 - xbmc.log("AmpachePlugin::get_random: random_items " + str(random_items), xbmc.LOGDEBUG ) - items = int(ampache.getSetting(object_type)) - xbmc.log("AmpachePlugin::get_random: total items in the catalog " + str(items), xbmc.LOGDEBUG ) - except: - return + items = int(ampache.getSetting(object_type)) if random_items > items: #if items are less than random_itmes, return all items get_items(object_type, limit=items) return - #playlists are not in the new stats api, so, use the old mode - if(int(ampache.getSetting("api-version"))) >= 400001 and object_type != 'playlists': - action = 'stats' - thisFilter = 'random' + + seq = random.sample(list(range(items)),random_items) + xbmc.log("AmpachePlugin::get_random: seq " + str(seq), xbmc.LOGDEBUG ) + elements = [] + for item_id in seq: try: - ampConn.filter = thisFilter - ampConn.limit = random_items - ampConn.type = amtype + ampConn = ampache_connect.AmpacheConnect() - elem = ampConn.ampache_http_request(action) - addItem( object_type, mode , elem) + ampConn.offset = item_id + ampConn.limit = 1 + elem = ampConn.ampache_http_request(object_type) + addItems( object_type, mode , elem) except: - return - - else: - seq = random.sample(list(range(items)),random_items) - xbmc.log("AmpachePlugin::get_random: seq " + str(seq), xbmc.LOGDEBUG ) - elements = [] - for item_id in seq: - try: - ampConn.offset = item_id - ampConn.limit = 1 - elem = ampConn.ampache_http_request(object_type) - addItem( object_type, mode , elem) - except: - pass + pass -def checkCloseMusicPlaylist(addon_url, mode, object_id=None, title=None): +def switchFromMusicPlaylist(addon_url, mode, submode, object_id=None, title=None): """ this function checks if musicplaylist window is active and switchs to the music window - necessary when we have to display albums or songs + necessary when we have to call a function like "get album from this + artist" """ if xbmc.getCondVisibility("Window.IsActive(musicplaylist)"): #close busydialog to activate music window @@ -630,11 +591,11 @@ def checkCloseMusicPlaylist(addon_url, mode, object_id=None, title=None): xbmc.executebuiltin('Dialog.Close(busydialog)') xbmc.executebuiltin("ActivateWindow(music)") if object_id: - xbmc.executebuiltin("Container.Update(%s?object_id=%s&mode=%s)" %\ - ( addon_url,object_id, mode ) ) + xbmc.executebuiltin("Container.Update(%s?object_id=%s&mode=%s&submode=%s)" %\ + ( addon_url,object_id, mode, submode ) ) elif title: - xbmc.executebuiltin("Container.Update(%s?title=%s&mode=%s)" %\ - ( addon_url,title, mode ) ) + xbmc.executebuiltin("Container.Update(%s?title=%s&mode=%s&submode=%s)" %\ + ( addon_url,title, mode, submode ) ) def main_params(plugin_url): @@ -646,10 +607,11 @@ def main_params(plugin_url): """ m_params={} m_params['mode'] = None + m_params['submode'] = None m_params['object_id'] = None m_params['title'] = None #used only in play tracks - m_params['song_url'] = None + m_params['play_url'] = None #used to managed very long lists m_params['offset'] = None @@ -661,8 +623,13 @@ def main_params(plugin_url): except: pass try: - m_params['object_id']=int(params["object_id"]) - xbmc.log("AmpachePlugin::object_id " + str(m_params['object_id']), xbmc.LOGDEBUG) + m_params['submode']=int(params["submode"]) + xbmc.log("AmpachePlugin::submode " + str(m_params['submode']), xbmc.LOGDEBUG) + except: + pass + try: + m_params['object_id']=params["object_id"] + xbmc.log("AmpachePlugin::object_id " + m_params['object_id'], xbmc.LOGDEBUG) except: pass try: @@ -671,8 +638,8 @@ def main_params(plugin_url): except: pass try: - m_params['song_url']=urllib.parse.unquote_plus(params["song_url"]) - xbmc.log("AmpachePlugin::song_url " + m_params['song_url'], xbmc.LOGDEBUG) + m_params['play_url']=urllib.parse.unquote_plus(params["play_url"]) + xbmc.log("AmpachePlugin::play_url " + m_params['play_url'], xbmc.LOGDEBUG) except: pass try: @@ -683,25 +650,29 @@ def main_params(plugin_url): return m_params -def manage_get_all(object_type, mode ,offset): - new_offset=get_all(object_type,offset) - if new_offset: - addDir(ut.tString(30194),None,mode,new_offset) - #add new line in case of new stat function implemented, checking the version #in menus -def manage_stats_menu(object_id, object_type, num_items): - if object_id == 9999993: +def manage_stats_menu(submode, object_type): + + num_items = (int(ampache.getSetting("random_items"))*3)+3 + + if submode == 40: + #playlists are not in the new stats api, so, use the old mode + if(int(ampache.getSetting("api-version"))) < 400001 or object_type == 'playlists': + get_random(object_type, num_items) + else: + get_stats(object_type=object_type,object_subtype="random",limit=num_items) + elif submode == 41: get_stats(object_type=object_type,object_subtype="highest",limit=num_items) - elif object_id == 9999992: + elif submode == 42: get_stats(object_type=object_type,object_subtype="frequent",limit=num_items) - elif object_id == 9999991: + elif submode == 43: get_stats(object_type=object_type,object_subtype="flagged",limit=num_items) - elif object_id == 9999990: + elif submode == 44: get_stats(object_type=object_type,object_subtype="forgotten",limit=num_items) - elif object_id == 9999989: + elif submode == 45: get_stats(object_type=object_type,object_subtype="newest",limit=num_items) - elif object_id == 9999988: + elif submode == 46: get_stats(object_type=object_type,object_subtype="recent",limit=num_items) def Main(): @@ -713,9 +684,9 @@ def Main(): #until endDirectoryMode -> endDirectoy and checkConnection #from endDirectoryMode to endCheckConnection -> no endDirectory but checkConnection #else no end and no check - endDirectoryMode = 40 - endCheckConnection = 50 - modeMax = 100 + endDirectoryMode = 200 + endCheckConnection = 300 + modeMax = 1000 endDir = True addon_url = sys.argv[0] @@ -727,12 +698,11 @@ def Main(): m_params=main_params(plugin_url) #faster to change variable mode = m_params['mode'] + submode = m_params['submode'] object_id = m_params['object_id'] servers_manager.initializeServer() - ampacheConnect = ampache_connect.AmpacheConnect() - #check if the connection is expired #connect to the server #do not connect on main screen and when we operate setting; @@ -740,6 +710,7 @@ def Main(): if mode!=None and mode < endCheckConnection: if ut.check_tokenexp(): try: + ampacheConnect = ampache_connect.AmpacheConnect() ampacheConnect.AMPACHECONNECT() except: pass @@ -747,322 +718,326 @@ def Main(): #start menu if mode==None: #search - addDir(ut.tString(30101),None,4) + addDir(ut.tString(30101),53,None) #quick access - addDir(ut.tString(30102),None,25) + addDir(ut.tString(30102),52,None) #explore - addDir(ut.tString(30103),None,23) + addDir(ut.tString(30103),50,None) #library - addDir(ut.tString(30104),None,24) + addDir(ut.tString(30104),51,None) #switch server - addDir(ut.tString(30023),None,54) + addDir(ut.tString(30023),304,None) #settings - addDir(ut.tString(30105),None,50) + addDir(ut.tString(30105),300,None) - #artist mode ( called from search screen ( mode 4 ), recent ( mode 5 ) ) - #and others + #artist mode elif mode==1: #artist, album, songs, playlist follow the same structure - #search function - num_items = (int(ampache.getSetting("random_items"))*3)+3 #get all artists - if object_id == None: - manage_get_all("artists", mode ,m_params['offset']) - #get_items("artists", limit=None, useCacheArt=False) - elif object_id == 9999999: + if submode == 5: + get_all("artists", mode ,m_params['offset']) + #get the artist from this album's artist_id + elif submode == 6: + switchFromMusicPlaylist(addon_url, mode, submode, object_id=object_id ) + get_items(object_type="artists",object_id=object_id,object_subtype="artist") + #search function + #10-30 search + elif submode == 10: endDir = do_search("artists") #recent function - elif object_id > 9999994 and object_id < 9999999: - get_recent( "artists", object_id ) - elif object_id == 9999994: - #removed cause nasty recursive call using some commands in web interface - #addDir("Refresh..",9999994,2,os.path.join(imagepath,'refresh_icon.png')) - #get random is separated from stats to mantain compatibility with - #older ampache api - get_random('artists') - #object_id between 99..93 e 99..88 ( highest .. recent ) - elif object_id >= 9999988 and object_id <=9999993: - manage_stats_menu(object_id, "artists", num_items) + #30-40 recent + elif submode > 30 and submode < 35: + get_recent( "artists", submode ) + #submode between 40-46( random.. recent ) + #40-70 stats + elif submode >= 40 and submode <= 46: + manage_stats_menu(submode, "artists") + #get all albums from an artist_id + elif submode == 71: + get_items(object_type="albums",object_id=object_id,object_subtype="artist_albums") + #get all songs from an artist_id + elif submode == 72: + get_items(object_type="songs",object_id=object_id,object_subtype="artist_songs" ) - #albums mode ( called from search screen ( mode 4 ) , recent ( mode 5 ) - #and others + #albums mode elif mode==2: - num_items = (int(ampache.getSetting("random_items"))*3)+3 #get all albums - if object_id == None: - manage_get_all("albums", mode ,m_params['offset']) - #get_items("albums", limit=None, useCacheArt=False) - elif object_id == 9999999: + if submode == 5: + get_all("albums", mode ,m_params['offset']) + #get the album from the song's album_id + elif submode == 6: + switchFromMusicPlaylist(addon_url, mode, submode, object_id=object_id ) + get_items(object_type="albums",object_id=object_id,object_subtype="album") + elif submode == 10: endDir = do_search("albums") - elif object_id > 9999994 and object_id < 9999999: - get_recent( "albums", object_id ) - elif object_id == 9999994: - #removed cause nasty recursive call using some commands in web interface - #addDir("Refresh..",9999990,2,os.path.join(imagepath, 'refresh_icon.png')) - get_random('albums') - elif object_id >= 9999988 and object_id <=9999993: - manage_stats_menu(object_id, "albums", num_items) - elif object_id: - get_items(object_type="albums",object_id=object_id,object_subtype="artist_albums") + elif submode > 30 and submode < 35: + get_recent( "albums", submode ) + elif submode >= 40 and submode <= 46: + manage_stats_menu(submode, "albums") + #get all songs from an album_id + elif submode == 71: + get_items(object_type="songs",object_id=object_id,object_subtype="album_songs") - #song mode ( called from search screen ( mode 4 ) and recent ( mode 5 ) ) - #and others + #song mode elif mode == 3: - num_items = (int(ampache.getSetting("random_items"))*3)+3 - if object_id == None: - #handle wrong object_id - pass - elif object_id > 9999994 and object_id < 9999999: - get_recent( "songs", object_id ) - elif object_id == 9999999: + #10-30 search + if submode == 10: endDir = do_search("songs") - elif object_id == 9999994: - #removed cause nasty recursive call using some commands in web interface - #addDir("Refresh..",9999994,2,os.path.join(imagepath, 'refresh_icon.png')) - get_random('songs') - elif object_id >= 9999988 and object_id <=9999993: - manage_stats_menu(object_id, "songs", num_items) - else: - get_items(object_type="songs",object_id=object_id,object_subtype="album_songs") - - #search mode + # submode 11 : search all + elif submode == 11: + endDir = do_search("songs","search_songs") + #get all song with this title + elif submode == 12: + switchFromMusicPlaylist(addon_url, mode,submode,title=m_params['title'] ) + endDir = do_search("songs",thisFilter=m_params['title']) + #30-40 recent + elif submode > 30 and submode < 35: + get_recent( "songs", submode ) + #40-70 stats + elif submode >= 40 and submode <= 46: + manage_stats_menu(submode, "songs") + + #playlist mode elif mode==4: - if not (ut.strBool_to_bool(ampache.getSetting("old-search-gui"))): - endDir = searchGui() - else: - #old search gui - #search artist - addDir(ut.tString(30120),9999999,1) - #search album - addDir(ut.tString(30121),9999999,2) - #search song - addDir(ut.tString(30122),9999999,3) - #search playlist - addDir(ut.tString(30123),9999999,13) - #search all - addDir(ut.tString(30124),9999999,11) - #search tag - addDir(ut.tString(30125),9999999,18) - - - # recently added screen - elif mode==5: - addDir(ut.tString(30126),9999998,6) - addDir(ut.tString(30127),9999997,6) - addDir(ut.tString(30128),9999996,6) - addDir(ut.tString(30129),9999995,6) - - #screen with recent time possibilities ( subscreen of recent artists, - #recent albums, recent songs ) ( called from mode 5 ) - elif mode==6: - #not clean, but i don't want to change too much the old code - if object_id > 9999995: - #object_id for playlists is 9999995 so 9999999-object_id is 4 that is search mode - #i have to use another method, so i use the hardcoded mode number (13) - mode_new = 9999999-object_id - elif object_id == 9999995: - mode_new = 13 - - addDir(ut.tString(30130),9999998,mode_new) - addDir(ut.tString(30131),9999997,mode_new) - addDir(ut.tString(30132),9999996,mode_new) - addDir(ut.tString(30133),9999995,mode_new) - - #general random mode screen - elif mode==7: - addDir(ut.tString(30134),9999994,1) - addDir(ut.tString(30135),9999994,2) - addDir(ut.tString(30136),9999994,3) - addDir(ut.tString(30137),9999994,13) - - # mode 11 : search all - elif mode==11: - endDir = do_search("songs","search_songs") - - # mode 12 : artist_songs - elif mode==12: - get_items(object_type="songs",object_id=object_id,object_subtype="artist_songs" ) - - #playlist full list - elif mode==13: - if object_id == None: - manage_get_all("playlists", mode ,m_params['offset']) - #get_items(object_type="playlists") - elif object_id == 9999999: + if submode == 5: + get_all("playlists", mode ,m_params['offset']) + elif submode == 10: endDir = do_search("playlists") - elif object_id > 9999994 and object_id < 9999999: - get_recent( "playlists", object_id ) - elif object_id == 9999994: - #removed cause nasty recursive call using some commands in web interface - #addDir("Refresh..",9999994,2,os.path.join(imagepath, 'refresh_icon.png')) - get_random('playlists') - elif object_id: - get_items(object_type="playlists",object_id=object_id) - - #playlist song mode - elif mode==14: - get_items(object_type="songs",object_id=object_id,object_subtype="playlist_songs") - - elif mode==15: - checkCloseMusicPlaylist(addon_url, mode, object_id=object_id ) - get_items(object_type="artists",object_id=object_id,object_subtype="artist") - - elif mode==16: - checkCloseMusicPlaylist(addon_url, mode, object_id=object_id ) - get_items(object_type="albums",object_id=object_id,object_subtype="album") - - elif mode==17: - checkCloseMusicPlaylist(addon_url, mode, object_id=object_id ) - endDir = do_search("songs",thisFilter=m_params['title']) - - #tags - elif mode==18: - #object_id always 9999999 - #search tag_artist - addDir(ut.tString(30142),object_id,19) - #search tag_album - addDir(ut.tString(30143),object_id,20) - #search tag_song - addDir(ut.tString(30144),object_id,21) - - elif mode==19: - if object_id == 9999999: - endDir = do_search("tags","tag_artists") - elif object_id: - get_items(object_type="artists", object_subtype="tag_artists",object_id=object_id) - else: - get_items(object_type = "tags", object_subtype="tag_artists") - - elif mode==20: - if object_id == 9999999: - endDir = do_search("tags","tag_albums") - elif object_id: - get_items(object_type="albums", object_subtype="tag_albums",object_id=object_id) - else: - get_items(object_type = "tags", object_subtype="tag_albums") - - elif mode==21: - if object_id == 9999999: - endDir = do_search("tags","tag_songs") - elif object_id: - get_items(object_type="songs", object_subtype="tag_songs",object_id=object_id) - else: - get_items(object_type = "tags", object_subtype="tag_songs") - + elif submode > 30 and submode < 35: + get_recent( "playlists", submode ) + elif submode == 40: + manage_stats_menu(submode, "playlists") + #get all songs from a playlist_id + elif submode == 71: + get_items(object_type="songs",object_id=object_id,object_subtype="playlist_songs") + + #podcasts + elif mode==5: + if submode == 5: + get_all("podcasts", mode ,m_params['offset']) + elif submode == 10: + endDir = do_search("podcasts") + #get all episodes + elif submode == 71: + if(int(ampache.getSetting("api-version"))) >= 440000: + get_items(object_type="songs",object_id=object_id,object_subtype="podcast_episodes") + + #video + elif mode==8: + if submode == 5: + get_all("videos", mode ,m_params['offset']) + elif submode == 10: + endDir = do_search("videos") + + #19-21 tags/genres mode + elif mode>=19 and mode <=21: + object_type, object_subtype = ut.mode_to_tags(mode) + #get_all tags/genres + if submode == 5: + get_items(object_type = object_type, object_subtype=object_subtype) + #search tag/genre + elif submode == 10: + endDir = do_search(object_type,object_subtype) + #get all songs from a tag_id/genre_id + elif submode == 71: + if mode == 19: + get_items(object_type="artists", object_subtype=object_subtype,object_id=object_id) + elif mode == 20: + get_items(object_type="albums", object_subtype=object_subtype,object_id=object_id) + elif mode == 21: + get_items(object_type="songs", object_subtype=object_subtype,object_id=object_id) + + #main meus 50-100 #explore - elif mode==23: + elif mode==50: #recently added - addDir(ut.tString(30145),None,5) + addDir(ut.tString(30145),107,None) #random - addDir(ut.tString(30146),None,7) + addDir(ut.tString(30146),100,None) if(int(ampache.getSetting("api-version"))) >= 400001: #highest - addDir(ut.tString(30148),9999993,30) + addDir(ut.tString(30148),101,None) #frequent - addDir(ut.tString(30164),9999992,31) + addDir(ut.tString(30164),102,None) #flagged - addDir(ut.tString(30165),9999991,32) + addDir(ut.tString(30165),103,None) #forgotten - addDir(ut.tString(30166),9999990,33) + addDir(ut.tString(30166),104,None) #newest - addDir(ut.tString(30167),9999989,34) + addDir(ut.tString(30167),105,None) #recent - addDir(ut.tString(30193),9999988,35) + addDir(ut.tString(30193),106,None) #Library - elif mode==24: - addDir(ut.tString(30115) +" (" + ampache.getSetting("artists")+ ")",None,1) - addDir(ut.tString(30116) + " (" + ampache.getSetting("albums") + ")",None,2) - addDir(ut.tString(30118) + " (" + ampache.getSetting("playlists")+ ")",None,13) + elif mode==51: + addDir(ut.tString(30115) +" (" + ampache.getSetting("artists")+ ")",1,5) + addDir(ut.tString(30116) + " (" + ampache.getSetting("albums") + ")",2,5) + addDir(ut.tString(30118) + " (" + ampache.getSetting("playlists")+ ")",4,5) + if ampache.getSetting("videos"): + addDir(ut.tString(30221) + " (" + ampache.getSetting("videos")+ ")",8,5) + if ampache.getSetting("podcasts"): + addDir(ut.tString(30226) + " (" + ampache.getSetting("podcasts")+ ")",5,5) apiVersion = int(ampache.getSetting("api-version")) if apiVersion >= 380001: - addDir(ut.tString(30119),None,18) + #get all tags ( submode 5 ) + addDir(ut.tString(30119),54,5) #quick access - elif mode==25: + elif mode==52: #random album - addDir(ut.tString(30135),9999994,2) + addDir(ut.tString(30135),2,40) if(int(ampache.getSetting("api-version"))) >= 400001: #newest albums - addDir(ut.tString(30162),9999989,2) + addDir(ut.tString(30162),2,45) #frequent albums - addDir(ut.tString(30153),9999992,2) + addDir(ut.tString(30153),2,42) #recently played albums - addDir(ut.tString(30191),9999988,2) + addDir(ut.tString(30191),2,46) else: #use recently added albums for old api versions - addDir(ut.tString(30127),9999997,6) + addDir(ut.tString(30127),55,32) #server playlist ( AKA random songs ) - addDir(ut.tString(30147),9999994,3) + addDir(ut.tString(30147),3,40) + + #search mode + elif mode==53: + if not (ut.strBool_to_bool(ampache.getSetting("old-search-gui"))): + endDir = searchGui() + else: + #old search gui + #search artist + addDir(ut.tString(30120),1,10) + #search album + addDir(ut.tString(30121),2,10) + #search song + addDir(ut.tString(30122),3,10) + #search playlist + addDir(ut.tString(30123),4,10) + #search all + addDir(ut.tString(30124),3,11) + #search tag + addDir(ut.tString(30125),54,10) + #search video + addDir(ut.tString(30222),8,10) + #search podcast + addDir(ut.tString(30227),5,10) + + #search tags + elif mode==54: + #search tag_artist + addDir(ut.tString(30142),19,submode) + #search tag_album + addDir(ut.tString(30143),20,submode) + #search tag_song + addDir(ut.tString(30144),21,submode) + + #screen with recent time possibilities ( subscreen of recent artists, + #recent albums, recent songs ) + elif mode==55: + mode_new = submode - 30 + + #last update + addDir(ut.tString(30130),mode_new,31) + #1 week + addDir(ut.tString(30131),mode_new,32) + addDir(ut.tString(30132),mode_new,33) + addDir(ut.tString(30133),mode_new,34) + + + #stats 100-150 + #random + elif mode==100: + #artists + addDir(ut.tString(30134),1,40) + #albums + addDir(ut.tString(30135),2,40) + #songs + addDir(ut.tString(30136),3,40) + #playlists + addDir(ut.tString(30137),4,40) #highest - elif mode==30: - #artist - addDir(ut.tString(30149),9999993,1) - #album - addDir(ut.tString(30150),9999993,2) - #song - addDir(ut.tString(30151),9999993,3) + elif mode==101: + #artists + addDir(ut.tString(30149),1,41) + #albums + addDir(ut.tString(30150),2,41) + #songs + addDir(ut.tString(30151),3,41) #frequent - elif mode==31: - addDir(ut.tString(30152),9999992,1) - addDir(ut.tString(30153),9999992,2) - addDir(ut.tString(30154),9999992,3) + elif mode==102: + addDir(ut.tString(30152),1,42) + addDir(ut.tString(30153),2,42) + addDir(ut.tString(30154),3,42) #flagged - elif mode==32: - addDir(ut.tString(30155),9999991,1) - addDir(ut.tString(30156),9999991,2) - addDir(ut.tString(30157),9999991,3) + elif mode==103: + addDir(ut.tString(30155),1,43) + addDir(ut.tString(30156),2,43) + addDir(ut.tString(30157),3,43) #forgotten - elif mode==33: - addDir(ut.tString(30158),9999990,1) - addDir(ut.tString(30159),9999990,2) - addDir(ut.tString(30160),9999990,3) + elif mode==104: + addDir(ut.tString(30158),1,44) + addDir(ut.tString(30159),2,44) + addDir(ut.tString(30160),3,44) #newest - elif mode==34: - addDir(ut.tString(30161),9999989,1) - addDir(ut.tString(30162),9999989,2) - addDir(ut.tString(30163),9999989,3) + elif mode==105: + addDir(ut.tString(30161),1,45) + addDir(ut.tString(30162),2,45) + addDir(ut.tString(30163),3,45) - #recent - elif mode==35: - addDir(ut.tString(30190),9999988,1) - addDir(ut.tString(30191),9999988,2) - addDir(ut.tString(30192),9999988,3) - + #recently added + elif mode==106: + addDir(ut.tString(30190),1,46) + addDir(ut.tString(30191),2,46) + addDir(ut.tString(30192),3,46) + + # recent + elif mode==107: + #recently added artist + addDir(ut.tString(30126),55,31) + #recently added album + addDir(ut.tString(30127),55,32) + #recently added song + addDir(ut.tString(30128),55,33) + #recently added playlist + addDir(ut.tString(30129),55,34) + + + #others mode 200-250 #play track mode ( mode set in add_links function ) - #mode 45 to avoid endDirectory - elif mode==45: + #mode 200 to avoid endDirectory + elif mode==200: #workaround busydialog bug xbmc.executebuiltin('Dialog.Close(busydialog)') - play_track(object_id, m_params['song_url']) + play_track(m_params['play_url']) #change rating - elif mode==47: + elif mode==205: setRating() + #settings mode 300-350 #settings - elif mode==50: + elif mode==300: ampache.openSettings() #the four modes below are used to manage servers - elif mode==51: + elif mode==301: if servers_manager.addServer(): servers_manager.switchServer() - elif mode==52: + elif mode==302: if servers_manager.deleteServer(): servers_manager.switchServer() - elif mode==53: + elif mode==303: servers_manager.modifyServer() - elif mode==54: + elif mode==304: servers_manager.switchServer() #no end directory item ( problem with failed searches ) diff --git a/resources/lib/art.py b/resources/lib/art.py index f410541..4fe44f4 100644 --- a/resources/lib/art.py +++ b/resources/lib/art.py @@ -22,21 +22,21 @@ def cacheArt(imageID,elem_type,url=None): cacheDirType = os.path.join( cacheDir , elem_type ) #security check - if imageID == None: + if imageID is None or imageID == "": raise NameError possible_ext = ["jpg", "png" , "bmp", "gif", "tiff"] for ext in possible_ext: - imageName = str(imageID) + "." + ext + imageName = imageID + "." + ext pathImage = os.path.join( cacheDirType , imageName ) if os.path.exists( pathImage ): - xbmc.log("AmpachePlugin::CacheArt: cached, id " + str(imageID) + " extension " + ext ,xbmc.LOGDEBUG) + xbmc.log("AmpachePlugin::CacheArt: cached, id " + imageID + " extension " + ext ,xbmc.LOGDEBUG) return pathImage #no return, not found ampacheConnect = ampache_connect.AmpacheConnect() action = 'get_art' - ampacheConnect.id = str(imageID) + ampacheConnect.id = imageID ampacheConnect.type = elem_type if url: @@ -44,12 +44,12 @@ def cacheArt(imageID,elem_type,url=None): headers,contents = ampacheConnect.handle_request(url) else: headers,contents = ampacheConnect.ampache_binary_request(action) - #xbmc.log("AmpachePlugin::CacheArt: File needs fetching, id " + str(imageID),xbmc.LOGDEBUG) + #xbmc.log("AmpachePlugin::CacheArt: File needs fetching, id " + imageID,xbmc.LOGDEBUG) extension = headers['content-type'] if extension: mimetype, options = cgi.parse_header(extension) #little hack when content-type is not standard - if mimetype == "JPG": + if mimetype == "JPG" or mimetype == "jpeg": maintype = "image" subtype = "jpg" else: @@ -61,20 +61,20 @@ def cacheArt(imageID,elem_type,url=None): raise NameError if maintype == 'image': if subtype == "jpeg": - fname = str(imageID) + ".jpg" + fname = imageID + ".jpg" else: - fname = str(imageID) + '.' + subtype + fname = imageID + '.' + subtype pathImage = os.path.join( cacheDirType , fname ) with open( pathImage, 'wb') as f: f.write(contents) f.close() - #xbmc.log("AmpachePlugin::CacheArt: Cached " + str(fname), xbmc.LOGDEBUG ) + #xbmc.log("AmpachePlugin::CacheArt: Cached " + fname, xbmc.LOGDEBUG ) return pathImage else: - xbmc.log("AmpachePlugin::CacheArt: It didnt work, id " + str(imageID) , xbmc.LOGDEBUG ) + xbmc.log("AmpachePlugin::CacheArt: It didnt work, id " + imageID , xbmc.LOGDEBUG ) raise NameError else: - xbmc.log("AmpachePlugin::CacheArt: No file found, id " + str(imageID) , xbmc.LOGDEBUG ) + xbmc.log("AmpachePlugin::CacheArt: No file found, id " + imageID , xbmc.LOGDEBUG ) raise NameError def get_artLabels(albumArt): diff --git a/resources/lib/art_clean.py b/resources/lib/art_clean.py index f84515e..46b46f2 100644 --- a/resources/lib/art_clean.py +++ b/resources/lib/art_clean.py @@ -19,6 +19,12 @@ user_mediaDir = os.path.join( user_dir , 'media' ) cacheDir = os.path.join( user_mediaDir , 'cache' ) +def clean_settings(): + ampache.setSetting("session_expire", "") + ampache.setSetting("add", "") + ampache.setSetting("token", "") + ampache.setSetting("token-exp", "") + def clean_cache_art(): #hack to force the creation of profile directory if don't exists if not os.path.isdir(user_dir): diff --git a/resources/lib/json_storage.py b/resources/lib/json_storage.py index ee12ada..2e27385 100644 --- a/resources/lib/json_storage.py +++ b/resources/lib/json_storage.py @@ -12,7 +12,7 @@ class JsonStorage(object): def __init__(self,filename): - ampache = xbmcaddon.Addon() + ampache = xbmcaddon.Addon("plugin.audio.ampache") if PY2: base_dir = xbmc.translatePath( ampache.getAddonInfo('profile')) base_dir = base_dir.decode('utf-8') diff --git a/resources/lib/service.py b/resources/lib/service.py index 9b0acad..33806cb 100644 --- a/resources/lib/service.py +++ b/resources/lib/service.py @@ -1,5 +1,6 @@ from ampache_monitor import AmpacheMonitor -from art_clean import clean_cache_art +from art_clean import clean_cache_art, clean_settings +clean_settings() clean_cache_art() AmpacheMonitor().run() diff --git a/resources/lib/utils.py b/resources/lib/utils.py index 9349811..82d543e 100644 --- a/resources/lib/utils.py +++ b/resources/lib/utils.py @@ -6,17 +6,65 @@ #main plugin/service library ampache = xbmcaddon.Addon("plugin.audio.ampache") -def otype_to_type(object_type): +def otype_to_mode(object_type, object_subtype=None): + mode = None + if object_type == 'artists': + mode = 1 + elif object_type == 'albums': + mode = 2 + elif object_type == 'songs': + mode = 3 + elif object_type == 'playlists': + mode = 4 + elif object_type == 'podcasts': + mode = 5 + elif object_type == 'videos': + mode = 8 + elif object_type == 'tags' or object_type == 'genres': + if object_subtype == 'tag_artists' or object_subtype == 'genre_artists': + mode = 19 + elif object_subtype == 'tag_albums' or object_subtype == 'genre_albums': + mode = 20 + elif object_subtype == 'tag_songs' or object_subtype == 'genre_songs': + mode = 21 + + return mode + +def mode_to_tags(mode): + if(int(ampache.getSetting("api-version"))) < 500000: + if mode == 19: + return "tags","tag_artists" + if mode == 20: + return "tags","tag_albums" + if mode == 21: + return "tags","tag_songs" + else: + if mode == 19: + return "genres","genre_artists" + if mode == 20: + return "genres","genre_albums" + if mode == 21: + return "genres","genre_songs" + +def otype_to_type(object_type,object_subtype=None): if object_type == 'albums': return 'album' elif object_type == 'artists': return 'artist' - elif object_type == 'songs': - return 'song' elif object_type == 'playlists': return 'playlist' elif object_type == 'tags': return 'tag' + elif object_type == 'genres': + return 'genre' + elif object_type == 'podcasts': + return 'podcast' + elif object_type == 'videos': + return 'video' + elif object_type == 'songs': + if object_subtype == 'podcast_episodes': + return 'podcast_episode' + return 'song' return None def int_to_strBool(s): @@ -38,14 +86,15 @@ def strBool_to_bool(s): raise ValueError def check_tokenexp(): - tokenexp = int(ampache.getSetting("token-exp")) + session_time = ampache.getSetting("session_expire") + if session_time is None or session_time == "": + return True #from python 3.7 we can easly compare the dates, otherwise we use the old #method if sys.version_info >= (3, 7): try: - session_time = ampache.getSetting("session_expire") s_time = datetime.datetime.fromisoformat(session_time) if datetime.datetime.now(datetime.timezone.utc) > s_time: return True @@ -95,13 +144,22 @@ def get_objectId_from_fileURL( file_url ): #i use two kind of object_id, i don't know, but sometime i have different #url, btw, no problem, i handle both and i solve the problem in this way try: - object_id=int(params["object_id"]) - xbmc.log("AmpachePlugin::object_id " + str(object_id), xbmc.LOGDEBUG) + object_id=params["object_id"] + xbmc.log("AmpachePlugin::object_id " + object_id, xbmc.LOGDEBUG) except: pass try: - object_id=int(params["oid"]) - xbmc.log("AmpachePlugin::object_id " + str(object_id), xbmc.LOGDEBUG) + object_id=params["oid"] + xbmc.log("AmpachePlugin::object_id " + object_id, xbmc.LOGDEBUG) except: pass return object_id + +def getRating(rating): + if rating: + #converts from five stats ampache rating to ten stars kodi rating + rating = int(float(rating)*2) + else: + #zero equals no rating + rating = 0 + return rating diff --git a/resources/settings.xml b/resources/settings.xml index 6d892a6..03657d2 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -7,9 +7,9 @@ - - - - + + + +