Release Ampache Client Plugin (Updated March, 22 2023 : v3.0.0)
#1
I announce the release of the new version of Ampache Client Plugin, it is a fork of http://forum.kodi.tv/showthread.php?tid=...ht=ampache

The project is now part of the official ampache repository, please check https://github.com/ampache/ampache-xbmc-plugin

The plugin is now included in the official kodi plugin repository


New version

Release 3.0.0
  • Ampache api 6.0
  • Kodi 20 support
  • Drop kodi 17-18 support
  • Podcast sorted by date

Link to the release :  https://github.com/ampache/ampache-xbmc-.../tag/3.0.0



Tested with kodi 19,20
Tested with web controls and kore app
Tested with ampache and nextcloud
The crashes in kodi are due to bugs in kodi 19-20 ( double busy dialog bug ) and in kore app.

Bug reports, feature requests, etc. are greatly appreciated.

Thanks to all the people that have contributed to the code.
Reply
#2
Awesome news, will give it a try for sure.

Also, you should ping the ampache team about it (if not done already :p)

The google group board is probably a good idea : https://groups.google.com/forum/#!forum/ampache

Anyway, thanx for the fork :-)
Reply
#3
Good idea, but it is only a free time project Smile

I don't like very much google sites, so i think i will not post there.
Reply
#4
Ok, I gave your addon a spin tonight and wasn't able to launch it. It gives me an error from Crypto.Hash import SHA256 : "ImportError: No module named Crypto.Hash"

Any idea ?

Thanx for your help !

(running latest kodi on linux)
Reply
#5
Kodi 15? It should works with 14.2 ( apart an ugly bug of 14.2 ). I need to test it. Thanks for the report
Reply
#6
It needs python-crypto, try to install it, in my default installation and on openelec it is already installed.
Reply
#7
Sorry i didn't post sooner, I was quite busy.

I just tried to install python2-crypto, and now I have something.

Still crashing but seems to have a problem with my SSL certificate (which is auto-signed).

---

10:09:19 T:140341302765312 NOTICE: https://my-server.com/music/server/xml.s...er=My-user
10:09:19 T:140341302765312 ERROR: EXCEPTION Thrown (PythonToCppException) : -->Python callback/script returned the following error<--
- NOTE: IGNORING THIS CAN LEAD TO MEMORY LEAKS!
Error Type: <class 'urllib2.URLError'>
Error Contents: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)>
Traceback (most recent call last):
File "/home/My-user/.kodi/addons/ampache-xbmc-plugin-0.5.0/default.py", line 354, in <module>
elem = AMPACHECONNECT()
File "/home/My-user/.kodi/addons/ampache-xbmc-plugin-0.5.0/default.py", line 174, in AMPACHECONNECT
response = urllib2.urlopen(req)
File "/usr/lib/python2.7/urllib2.py", line 154, in urlopen
return opener.open(url, data, timeout)
File "/usr/lib/python2.7/urllib2.py", line 431, in open
response = self._open(req, data)
File "/usr/lib/python2.7/urllib2.py", line 449, in _open
'_open', req)
File "/usr/lib/python2.7/urllib2.py", line 409, in _call_chain
result = func(*args)
File "/usr/lib/python2.7/urllib2.py", line 1240, in https_open
context=self._context)
File "/usr/lib/python2.7/urllib2.py", line 1197, in do_open
raise URLError(err)
URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)>
Reply
#8
Oh and I use Kodi 14.2 btw, sorry I didn't mention it.
Reply
#9
It is a problem in urllib2 as i have found here:

https://stackoverflow.com/questions/2783...iled-error

A possible fix is to not verify the certificate:

import ssl

and after urllib2.request

gcontext = ssl.SSLContext(ssl.PROTOCOL_TLSv1) # line to add
response = urllib2.urlopen(req, context=gcontext) # line to change

but i have not an ssl connection ( only LAN testing ), so i cannot try this patch.

there are three places where to patch:

line 174, 186, 197

Tell me if it works. Btw, with 14.2 all should works well, apart it can skip from a song to another at the end of reproduction.
Reply
#10
Hey, thanx for your quick anwser !

Connection is ok now and I can browse artists... but...

I'm sorry, my problem is more a self signed certificate problem than a problem with your addon, which looks great !

---

Code:
05:47:44 T:139849235425024   ERROR: EXCEPTION Thrown (PythonToCppException) : -->Python callback/script returned the following error<--
                                             - NOTE: IGNORING THIS CAN LEAD TO MEMORY LEAKS!
                                            Error Type: <type 'exceptions.IOError'>
                                            Error Contents: [Errno socket error] [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)
                                            Traceback (most recent call last):
                                              File "/home/My-user/.kodi/addons/ampache-xbmc-plugin-0.5.0/default.py", line 425, in <module>
                                                get_items(object_type="albums",artist=object_id)
                                              File "/home/My-user/.kodi/addons/ampache-xbmc-plugin-0.5.0/default.py", line 246, in get_items
                                                artFilename = cacheArt(image)
                                              File "/home/My-user/.kodi/addons/ampache-xbmc-plugin-0.5.0/default.py", line 37, in cacheArt
                                                opener = urllib.urlopen(url)
                                              File "/usr/lib/python2.7/urllib.py", line 87, in urlopen
                                                return opener.open(url)
                                              File "/usr/lib/python2.7/urllib.py", line 213, in open
                                                return getattr(self, name)(url)
                                              File "/usr/lib/python2.7/urllib.py", line 443, in open_https
                                                h.endheaders(data)
                                              File "/usr/lib/python2.7/httplib.py", line 1049, in endheaders
                                                self._send_output(message_body)
                                              File "/usr/lib/python2.7/httplib.py", line 893, in _send_output
                                                self.send(msg)
                                              File "/usr/lib/python2.7/httplib.py", line 855, in send
                                                self.connect()
                                              File "/usr/lib/python2.7/httplib.py", line 1274, in connect
                                                server_hostname=server_hostname)
                                              File "/usr/lib/python2.7/ssl.py", line 352, in wrap_socket
                                                _context=self)
                                              File "/usr/lib/python2.7/ssl.py", line 579, in __init__
                                                self.do_handshake()
                                              File "/usr/lib/python2.7/ssl.py", line 808, in do_handshake
                                                self._sslobj.do_handshake()
                                            IOError: [Errno socket error] [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)
                                            -->End of Python script error report<--
Reply
#11
ok plugin use also urllib for caching art ( code merged from a different repositoy ) so try this code, line 37 i think ( your line code are differents from mine )

original line:
opener = urllib.urlopen(url)

patch with:
context = ssl._create_unverified_context()
opener = urllib.urlopen(url, context=context)

and if it works paste the default.py patched so i can add a feature to handle self-certificate servers
Reply
#12
It works ! Great !

One last problem though : seems like your addon don't read the track tag (tested on regular id3 2.4 mp3 files).

Also, here's my default.py file.

Code:
import sys
import os
import socket
import re
import random,xbmcplugin,xbmcgui, datetime, time, urllib,urllib2
import xml.etree.ElementTree as ET
from Crypto.Hash import SHA256
import xbmcaddon
import ssl

# Shared resources

ampache = xbmcaddon.Addon("plugin.audio.ampache")

ampache_dir = xbmc.translatePath( ampache.getAddonInfo('path') )
BASE_RESOURCE_PATH = os.path.join( ampache_dir, "resources" )
mediaDir = os.path.join( BASE_RESOURCE_PATH , 'media' )
cacheDir = os.path.join( mediaDir , 'cache' )
imagepath = os.path.join( mediaDir ,'images')

def cacheArt(url):
    strippedAuth = url.split('&')
    imageID = re.search(r"id=(\d+)", strippedAuth[0])
        
        imageNamePng = imageID.group(1) + ".png"
        imageNameJpg = imageID.group(1) + ".jpg"
        pathPng = os.path.join( cacheDir , imageNamePng )
        pathJpg = os.path.join( cacheDir , imageNameJpg )
    if os.path.exists( pathPng ):
        print "DEBUG: png cached"
        return pathPng
        elif os.path.exists( pathJpg ):
        print "DEBUG: jpg cached"
        return pathJpg
    else:
        print "DEBUG: File needs fetching "
        context = ssl._create_unverified_context()
        opener = urllib.urlopen(url, context=context)
        if opener.headers.maintype == 'image':
            extension = opener.headers['content-type']
            tmpExt = extension.split("/")
            if tmpExt[1] == "jpeg":
                fname = imageNameJpg
            else:
                fname = imageID.group(1) + '.' + tmpExt[1]
                        pathJpg = os.path.join( cacheDir , fname )
            open( pathJpg, 'wb').write(opener.read())
            print "DEBUG: Cached " + fname
            return fname
        else:
            print "DEBUG: It didnt work"
                        raise NameError
            #return False

def addLink(name,url,iconimage,node):
        ok=True
        liz=xbmcgui.ListItem(name, iconImage=iconimage, thumbnailImage=iconimage)
        liz.setInfo( type="Music", infoLabels={ "Title": node.findtext("title"), "Artist": node.findtext("artist"), "Album": node.findtext("album"), "TrackNumber": str(node.findtext("track")) } )
        ok=xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=url,listitem=liz)
        return ok

# Used to populate items for songs on XBMC. Calls plugin script with mode == 9 and object_id == (ampache song id)
# TODO: Merge with addDir(). Same basic idea going on, this one adds links all at once, that one does it one at a time
#       Also, some property things, some different context menu things.
def addLinks(elem):
    xbmcplugin.setContent(int(sys.argv[1]), "songs")
    ok=True
    li=[]
    for node in elem:
        cm = []
        try:
            albumArt = cacheArt(node.findtext("art"))
        except NameError:
            albumArt = "DefaultFolder.png"
        print "DEBUG: albumArt - " + albumArt
        liz=xbmcgui.ListItem(label=node.findtext("title").encode("utf-8"), thumbnailImage=albumArt)
        liz.setInfo( "music", { "title": node.findtext("title").encode("utf-8"), "artist": node.findtext("artist"), "album": node.findtext("album"), "size": node.findtext("size"), "duration": node.findtext("time"),  "year": str(node.findtext("year")) } )
        liz.setProperty("mimetype", 'audio/mpeg')
        liz.setProperty("IsPlayable", "true")
        song_elem = node.find("song")
        song_id = int(node.attrib["id"])
        liz.addContextMenuItems(cm)
        track_parameters = { "mode": 9, "object_id": song_id}
        url = sys.argv[0] + '?' + urllib.urlencode(track_parameters)
        tu= (url,liz)
        li.append(tu)
    ok=xbmcplugin.addDirectoryItems(handle=int(sys.argv[1]),items=li,totalItems=len(elem))
    return ok

# The function that actually plays an Ampache URL by using setResolvedUrl. Gotta have the extra step in order to make
# song album art / play next automatically. We already have the track URL when we add the directory item so the api
# hit here is really unnecessary. Would be nice to get rid of it, the extra request adds to song gaps. It does
# guarantee that we are using a legit URL, though, if the session expired between the item being added and the actual
# playing of that item.
def play_track(id):
    ''' Start to stream the track with the given id. '''
    elem = ampache_http_request("song",filter=id)
    for thisnode in elem:
        node = thisnode
    try:
        albumArt = cacheArt(node.findtext("art"))
    except NameError:
        albumArt = "DefaultFolder.png"
    li = xbmcgui.ListItem(label=node.findtext("title").encode("utf-8"), thumbnailImage=albumArt, path=node.findtext("url"))
    li.setInfo("music", { "artist" : node.findtext("artist") , "album" : node.findtext("album") , "title": node.findtext("title") , "duration": node.findtext("time"), "size": node.findtext("size") })
    xbmcplugin.setResolvedUrl(handle=int(sys.argv[1]), succeeded=True, listitem=li)

# Main function for adding xbmc plugin elements
def addDir(name,object_id,mode,iconimage,elem=None,artFilename=None):
    if artFilename:
        liz=xbmcgui.ListItem(name, iconImage=artFilename, thumbnailImage=artFilename)
    else:
        liz=xbmcgui.ListItem(name, iconImage="DefaultFolder.png", thumbnailImage=iconimage)

    liz.setInfo( type="Music", infoLabels={ "Title": name } )
    try:
        artist_elem = elem.find("artist")
        artist_id = int(artist_elem.attrib["id"])
        cm = []
        cm.append( ( "Show all albums from artist", "XBMC.Container.Update(%s?object_id=%s&mode=2)" % ( sys.argv[0],artist_id ) ) )
        liz.addContextMenuItems(cm)
    except:
        pass
    u=sys.argv[0]+"?object_id="+str(object_id)+"&mode="+str(mode)+"&name="+urllib.quote_plus(name)
    ok=xbmcplugin.addDirectoryItem(handle=int(sys.argv[1]),url=u,listitem=liz,isFolder=True)
    return ok

def get_params():
    param=[]
    paramstring=sys.argv[2]
    if len(paramstring)>=2:
            params=sys.argv[2]
            cleanedparams=params.replace('?','')
            if (params[len(params)-1]=='/'):
                    params=params[0:len(params)-2]
            pairsofparams=cleanedparams.split('&')
            param={}
            for i in range(len(pairsofparams)):
                    splitparams={}
                    splitparams=pairsofparams[i].split('=')
                    if (len(splitparams))==2:
                            param[splitparams[0]]=splitparams[1]
                            
    return param
    
def getFilterFromUser():
    loop = True
    while(loop):
        kb = xbmc.Keyboard('', '', True)
        kb.setHeading('Enter Search Filter')
        kb.setHiddenInput(False)
        kb.doModal()
        if (kb.isConfirmed()):
            filter = kb.getText()
            loop = False
        else:
            return(False)
    return(filter)

def AMPACHECONNECT():
    socket.setdefaulttimeout(3600)
    nTime = int(time.time())
    myTimeStamp = str(nTime)
    sdf = ampache.getSetting("password")
    hasher = SHA256.new()
    hasher.update(ampache.getSetting("password"))
    myKey = hasher.hexdigest()
    hasher = SHA256.new()
    hasher.update(myTimeStamp + myKey)
    myPassphrase = hasher.hexdigest()
    myURL = ampache.getSetting("server") + '/server/xml.server.php?action=handshake&auth='
    myURL += myPassphrase + "&timestamp=" + myTimeStamp
    myURL += '&version=350001&user=' + ampache.getSetting("username")
    xbmc.log(myURL,xbmc.LOGNOTICE)
    req = urllib2.Request(myURL)
    gcontext = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
    response = urllib2.urlopen(req, context=gcontext)
    tree=ET.parse(response)
    response.close()
    elem = tree.getroot()
    token = elem.findtext('auth')
    ampache.setSetting('token',token)
    ampache.setSetting('token-exp',str(nTime+24000))
    return elem

def ampache_http_request(action,add=None, filter=None, limit=5000, offset=0):
    thisURL = build_ampache_url(action,filter=filter,add=add,limit=limit,offset=offset)
    req = urllib2.Request(thisURL)
    gcontext = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
    response = urllib2.urlopen(req, context=gcontext)
    contents = response.read()
    contents = contents.replace("\0", "")
    tree=ET.fromstring(contents)
    response.close()
    if tree.findtext("error"):
        errornode = tree.find("error")
        if errornode.attrib["code"]=="401":
            tree = AMPACHECONNECT()
            thisURL = build_ampache_url(action,filter=filter,add=add,limit=limit,offset=offset)
            req = urllib2.Request(thisURL)
            gcontext = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
            response = urllib2.urlopen(req, context=gcontext)
            contents = response.read()
            tree=ET.fromstring(contents)
            response.close()
    return tree

    
def get_items(object_type, artist=None, add=None, filter=None, limit=5000, playlist=None, playlist_song=None):
    xbmcplugin.setContent(int(sys.argv[1]), object_type)
    action = object_type
    if artist:
        filter = artist
        action = 'artist_albums'
        addDir("All Songs",artist,8, "DefaultFolder.png")
    elif playlist:
        action = 'playlist'
        filter = playlist
    elif playlist_song:
        action = 'playlist_song'
        filter = playlist_song
    elem = ampache_http_request(action,add=add,filter=filter, limit=limit)
    if object_type == 'artists':
        mode = 2
        image = "DefaultFolder.png"
    elif object_type == 'albums':
        mode = 3
    elif object_type == 'playlists':
        mode = 14
        image = "DefaultFolder.png"
    elif object_type == 'playlist_song':
        mode = 15
        image = "DefaultFolder.png"
    for node in elem:
        if object_type == 'albums':
            fullname = node.findtext("name").encode("utf-8")
            fullname += " - "
            fullname += node.findtext("year").encode("utf-8")

            image = node.findtext("art")
            print "DEBUG: object_type - " + str(object_type)
            print "DEBUG: Art - " + str(image)
            try:
                artFilename = cacheArt(image)        
            except NameError:
                image = "DefaultFolder.png"
                addDir(fullname,node.attrib["id"],mode,image,node)
            else:
                print "DEBUG: Art Filename: " + artFilename
                addDir(fullname, node.attrib["id"],mode,image,node, artFilename = artFilename)
        else:
            addDir(node.findtext("name").encode("utf-8"),node.attrib["id"],mode,image,node)

def GETSONGS(objectid=None,filter=None,add=None,limit=5000,offset=0,artist_bool=False,playlist=None):
    xbmcplugin.setContent(int(sys.argv[1]), 'songs')
    if filter:
        action = 'songs'
    elif playlist:
        action = 'playlist_songs'
        filter = playlist
    elif objectid:
        if artist_bool:
            action = 'artist_songs'
        else:
            action = 'album_songs'
        filter = objectid
    else:
        action = 'songs'
    elem = ampache_http_request(action,add=add,filter=filter)
    addLinks(elem)

def build_ampache_url(action,filter=None,add=None,limit=5000,offset=0):
    tokenexp = int(ampache.getSetting('token-exp'))
    if int(time.time()) > tokenexp:
        print "refreshing token..."
        elem = AMPACHECONNECT()

    token=ampache.getSetting('token')    
    thisURL = ampache.getSetting("server") + '/server/xml.server.php?action=' + action
    thisURL += '&auth=' + token
    thisURL += '&limit=' +str(limit)
    thisURL += '&offset=' +str(offset)
    if filter:
        thisURL += '&filter=' +urllib.quote_plus(str(filter))
    if add:
        thisURL += '&add=' + add
    return thisURL

def get_random_albums():
    xbmcplugin.setContent(int(sys.argv[1]), 'albums')
    elem = AMPACHECONNECT()
    albums = int(elem.findtext('albums'))
    print albums
    random_albums = (int(ampache.getSetting("random_albums"))*3)+3
    print random_albums
    seq = random.sample(xrange(albums),random_albums)
    for album_id in seq:
        elem = ampache_http_request('albums',offset=album_id,limit=1)
        for node in elem:
            fullname = node.findtext("name").encode("utf-8")
            fullname += " - "
            fullname += node.findtext("artist").encode("utf-8")
            fullname += " - "
            fullname += node.findtext("year").encode("utf-8")
            addDir(fullname,node.attrib["id"],3,node.findtext("art"),node)        
  
def get_random_artists():
    xbmcplugin.setContent(int(sys.argv[1]), 'artists')
    elem = AMPACHECONNECT()
    artists = int(elem.findtext('artists'))
    print artists
    random_artists = (int(ampache.getSetting("random_artists"))*3)+3
    print random_artists
    seq = random.sample(xrange(artists),random_artists)
    image = "DefaultFolder.png"
    for artist_id in seq:
        elem = ampache_http_request('artists',offset=artist_id,limit=1)
        for node in elem:
            fullname = node.findtext("name").encode("utf-8")
            addDir(fullname,node.attrib["id"],2,image,node)        

def get_random_songs():
    xbmcplugin.setContent(int(sys.argv[1]), 'songs')
    elem = AMPACHECONNECT()
    songs = int(elem.findtext('songs'))
    print songs
    random_songs = (int(ampache.getSetting("random_songs"))*3)+3
    print random_songs
    seq = random.sample(xrange(songs),random_songs)
    for song_id in seq:
        elem = ampache_http_request('songs',offset=song_id,limit=1)
        addLinks(elem)


params=get_params()
name=None
mode=None
object_id=None

try:
        name=urllib.unquote_plus(params["name"])
except:
        pass
try:
        mode=int(params["mode"])
except:
        pass
try:
        object_id=int(params["object_id"])
except:
        pass

print "Mode: "+str(mode)
print "Name: "+str(name)
print "ObjectID: "+str(object_id)

if mode==None:
    print ""
    elem = AMPACHECONNECT()
    addDir("Search...",0,4,"DefaultFolder.png")
    addDir("Recent...",0,5,"DefaultFolder.png")
    addDir("Random...",0,7,"DefaultFolder.png")
    addDir("Artists (" + str(elem.findtext("artists")) + ")",None,1,"DefaultFolder.png")
    addDir("Albums (" + str(elem.findtext("albums")) + ")",None,2,"DefaultFolder.png")
    addDir("Playlists (" + str(elem.findtext("playlists")) + ")",None,13,"DefaultFolder.png")
elif mode==1:
    if object_id == 99999:
        thisFilter = getFilterFromUser()
        if thisFilter:
            get_items(object_type="artists",filter=thisFilter)
    elif object_id == 99998:
        elem = AMPACHECONNECT()
        update = elem.findtext("add")        
        xbmc.log(update[:10],xbmc.LOGNOTICE)
        get_items(object_type="artists",add=update[:10])
    elif object_id == 99997:
        d = datetime.date.today()
        dt = datetime.timedelta(days=-7)
        nd = d + dt
        get_items(object_type="artists",add=nd.isoformat())
    elif object_id == 99996:
        d = datetime.date.today()
        dt = datetime.timedelta(days=-30)
        nd = d + dt
        get_items(object_type="artists",add=nd.isoformat())
    elif object_id == 99995:
        d = datetime.date.today()
        dt = datetime.timedelta(days=-90)
        nd = d + dt
        get_items(object_type="artists",add=nd.isoformat())
    else:
        elem = AMPACHECONNECT()
        limit=elem.findtext("artists")
        get_items(object_type="artists", limit=limit)
      
elif mode==2:
        print ""
        if object_id == 99999:
            thisFilter = getFilterFromUser()
            if thisFilter:
                get_items(object_type="albums",filter=thisFilter)
        elif object_id == 99998:
            elem = AMPACHECONNECT()
            update = elem.findtext("add")        
            xbmc.log(update[:10],xbmc.LOGNOTICE)
            get_items(object_type="albums",add=update[:10])
        elif object_id == 99997:
            d = datetime.date.today()
            dt = datetime.timedelta(days=-7)
            nd = d + dt
            get_items(object_type="albums",add=nd.isoformat())
        elif object_id == 99996:
            d = datetime.date.today()
            dt = datetime.timedelta(days=-30)
            nd = d + dt
            get_items(object_type="albums",add=nd.isoformat())
        elif object_id == 99995:
            d = datetime.date.today()
            dt = datetime.timedelta(days=-90)
            nd = d + dt
            get_items(object_type="albums",add=nd.isoformat())
        elif object_id:
            get_items(object_type="albums",artist=object_id)
        else:
            elem = AMPACHECONNECT()
            limit=elem.findtext("albums")
            get_items(object_type="albums", limit=limit)
        
elif mode==3:
        print ""
        if object_id == 99999:
            thisFilter = getFilterFromUser()
            if thisFilter:
                GETSONGS(filter=thisFilter)
        elif object_id == 99998:
            elem = AMPACHECONNECT()
            update = elem.findtext("add")        
            xbmc.log(update[:10],xbmc.LOGNOTICE)
            GETSONGS(add=update[:10])
        elif object_id == 99997:
            d = datetime.date.today()
            dt = datetime.timedelta(days=-7)
            nd = d + dt
            GETSONGS(add=nd.isoformat())
        elif object_id == 99996:
            d = datetime.date.today()
            dt = datetime.timedelta(days=-30)
            nd = d + dt
            GETSONGS(add=nd.isoformat())
        elif object_id == 99995:
            d = datetime.date.today()
            dt = datetime.timedelta(days=-90)
            nd = d + dt
            GETSONGS(add=nd.isoformat())
        else:
            GETSONGS(objectid=object_id)

elif mode==4:
    addDir("Search Artists...",99999,1,"DefaultFolder.png")
    addDir("Search Albums...",99999,2,"DefaultFolder.png")
    addDir("Search Songs...",99999,3,"DefaultFolder.png")

elif mode==5:
    addDir("Recent Artists...",99998,6,"DefaultFolder.png")
    addDir("Recent Albums...",99997,6,"DefaultFolder.png")
    addDir("Recent Songs...",99996,6,"DefaultFolder.png")

elif mode==6:
    addDir("Last Update",99998,99999-object_id,"DefaultFolder.png")
    addDir("1 Week",99997,99999-object_id,"DefaultFolder.png")
    addDir("1 Month",99996,99999-object_id,"DefaultFolder.png")
    addDir("3 Months",99995,99999-object_id,"DefaultFolder.png")

elif mode==7:
    addDir("Random Artists...",99999,8,"DefaultFolder.png")
    addDir("Random Albums...",99998,8,"DefaultFolder.png")
    addDir("Random Songs...",99997,8,"DefaultFolder.png")

elif mode==8:
    print ""
    if object_id == 99999:
        addDir("Refresh..",99999,8,os.path.join(imagepath, 'refresh_icon.png'))
        get_random_artists()
    if object_id == 99998:
        addDir("Refresh..",99998,8,os.path.join(imagepath, 'refresh_icon.png'))
        get_random_albums()
    if object_id == 99997:
        addDir("Refresh..",99997,8,os.path.join(imagepath, 'refresh_icon.png'))
        get_random_songs()
    else:
        GETSONGS(objectid=object_id, artist_bool=True )

elif mode==9:
    play_track(object_id)

elif mode==13:
#    print "Hello Ampache!!"
#    get_items(object_type="playlists")
        print "Hello Ampache!!!"
        if object_id == 99999:
            thisFilter = getFilterFromUser()
            if thisFilter:
                get_items(object_type="playlists",filter=thisFilter)
        elif object_id == 99998:
            elem = AMPACHECONNECT()
            update = elem.findtext("add")        
            xbmc.log(update[:10],xbmc.LOGNOTICE)
            get_items(object_type="playlists",add=update[:10])
        elif object_id == 99997:
            d = datetime.date.today()
            dt = datetime.timedelta(days=-7)
            nd = d + dt
            get_items(object_type="playlists",add=nd.isoformat())
        elif object_id == 99996:
            d = datetime.date.today()
            dt = datetime.timedelta(days=-30)
            nd = d + dt
            get_items(object_type="playlists",add=nd.isoformat())
        elif object_id == 99995:
            d = datetime.date.today()
            dt = datetime.timedelta(days=-90)
            nd = d + dt
            get_items(object_type="playlists",add=nd.isoformat())
        elif object_id:
            get_items(object_type="playlists",artist=object_id)
        else:
            get_items(object_type="playlists")

elif mode==14:
#    print "Hello Ampache!!"
#    get_items(object_type="playlists")
        print "Hello Ampache Playlists!!!"
        if object_id == 99999:
            thisFilter = getFilterFromUser()
            if thisFilter:
                get_items(object_type="playlist_song",filter=thisFilter)
        elif object_id == 99998:
            elem = AMPACHECONNECT()
            update = elem.findtext("add")        
            xbmc.log(update[:10],xbmc.LOGNOTICE)
            get_items(object_type="playlist_song",add=update[:10])
        elif object_id == 99997:
            d = datetime.date.today()
            dt = datetime.timedelta(days=-7)
            nd = d + dt
            get_items(object_type="playlist_song",add=nd.isoformat())
        elif object_id == 99996:
            d = datetime.date.today()
            dt = datetime.timedelta(days=-30)
            nd = d + dt
            get_items(object_type="playlist_song",add=nd.isoformat())
        elif object_id == 99995:
            d = datetime.date.today()
            dt = datetime.timedelta(days=-90)
            nd = d + dt
            get_items(object_type="playlist_song",add=nd.isoformat())
        elif object_id:
            get_items(object_type="playlist_song",playlist=object_id)
        else:
            get_items(object_type="playlist_song")

elif mode==15:
    print "Hello Ampache Playlist1!!!"
    GETSONGS(playlist=object_id)

if mode < 19:
    xbmcplugin.endOfDirectory(int(sys.argv[1]))
Reply
#13
The tag problem i think it should be tested against latest kodi release, 14.2 is buggy.
Reply
#14
I have added the possibility to disable ssl verification in master branch with an option to disable or enable it in plugin configuration. If you want to test it and it works, i will release a new version of plugin with this problem solved.
Reply
#15
Ok, I will give it a spin tonight or tomorrow.
Reply

Logout Mark Read Team Forum Stats Members Help
Ampache Client Plugin (Updated March, 22 2023 : v3.0.0)1