First working Leia version for testing

This commit is contained in:
Warwick Harris 2022-09-14 14:44:13 +10:00
parent 2c785729ee
commit ae69548107
5 changed files with 60 additions and 45 deletions

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<addon id="plugin.audio.subsonic" name="Subsonic" version="3.0.2" provider-name="BasilFX,warwickh"> <addon id="plugin.audio.subsonic" name="Subsonic" version="2.1.0" provider-name="BasilFX,warwickh">
<requires> <requires>
<import addon="xbmc.python" version="3.0.0"/> <import addon="xbmc.python" version="2.7.0"/>
</requires> </requires>
<extension point="xbmc.python.pluginsource" library="main.py"> <extension point="xbmc.python.pluginsource" library="main.py">
<provides>audio</provides> <provides>audio</provides>

View File

@ -18,11 +18,14 @@ along with py-sonic. If not, see <http://www.gnu.org/licenses/>
from libsonic.errors import * from libsonic.errors import *
from netrc import netrc from netrc import netrc
from hashlib import md5 from hashlib import md5
import urllib.request import urllib2
import urllib.error import httplib
import urllib.parse #import urllib2.request
from http import client as http_client #import urllib.error
from urllib.parse import urlencode #import urllib.parse
#from http import client as http_client
#from urllib.parse import urlencode
from urllib import urlencode
from io import StringIO from io import StringIO
import json import json
@ -37,7 +40,7 @@ API_VERSION = '1.16.1'
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class HTTPSConnectionChain(http_client.HTTPSConnection): class HTTPSConnectionChain(httplib.HTTPSConnection):
def _create_sock(self): def _create_sock(self):
sock = socket.create_connection((self.host, self.port), self.timeout) sock = socket.create_connection((self.host, self.port), self.timeout)
if self._tunnel_host: if self._tunnel_host:
@ -53,14 +56,14 @@ class HTTPSConnectionChain(http_client.HTTPSConnection):
except: except:
sock.close() sock.close()
class HTTPSHandlerChain(urllib.request.HTTPSHandler): class HTTPSHandlerChain(urllib2.HTTPSHandler):
def https_open(self, req): def https_open(self, req):
return self.do_open(HTTPSConnectionChain, req, context=self._context) return self.do_open(HTTPSConnectionChain, req, context=self._context)
# install opener # install opener
urllib.request.install_opener(urllib.request.build_opener(HTTPSHandlerChain())) urllib2.install_opener(urllib2.build_opener(HTTPSHandlerChain()))
class PysHTTPRedirectHandler(urllib.request.HTTPRedirectHandler): class PysHTTPRedirectHandler(urllib2.HTTPRedirectHandler):
""" """
This class is used to override the default behavior of the This class is used to override the default behavior of the
HTTPRedirectHandler, which does *not* redirect POST data HTTPRedirectHandler, which does *not* redirect POST data
@ -76,7 +79,7 @@ class PysHTTPRedirectHandler(urllib.request.HTTPRedirectHandler):
data = None data = None
if req.data: if req.data:
data = req.data data = req.data
return urllib.request.Request(newurl, return urllib2.Request(newurl,
data=data, data=data,
headers=newheaders, headers=newheaders,
origin_req_host=req.origin_req_host, origin_req_host=req.origin_req_host,
@ -240,7 +243,7 @@ class Connection(object):
viewName = '%s.view' % methodName viewName = '%s.view' % methodName
req = self._getRequest(viewName) req = self._getRequest(viewName)
xbmc.log("Pinging %s"%str(req.full_url),xbmc.LOGDEBUG) xbmc.log("Pinging %s"%str(req.get_full_url()),xbmc.LOGDEBUG)
try: try:
res = self._doInfoReq(req) res = self._doInfoReq(req)
except Exception as e: except Exception as e:
@ -906,8 +909,8 @@ class Connection(object):
'converted': converted}) 'converted': converted})
req = self._getRequest(viewName, q) req = self._getRequest(viewName, q)
#xbmc.log("Requesting %s"%str(req.full_url),xbmc.LOGDEBUG) #xbmc.log("Requesting %s"%str(req.get_full_url()),xbmc.LOGDEBUG)
return_url = req.full_url return_url = req.get_full_url()
if self._insecure: if self._insecure:
return_url += '&verifypeer=false' return_url += '&verifypeer=false'
xbmc.log("Request is insecure %s"%return_url,level=xbmc.LOGDEBUG) xbmc.log("Request is insecure %s"%return_url,level=xbmc.LOGDEBUG)
@ -955,8 +958,8 @@ class Connection(object):
q = self._getQueryDict({'id': aid, 'size': size}) q = self._getQueryDict({'id': aid, 'size': size})
req = self._getRequest(viewName, q) req = self._getRequest(viewName, q)
#xbmc.log("Requesting %s"%str(req.full_url),xbmc.LOGDEBUG) #xbmc.log("Requesting %s"%str(req.get_full_url()),xbmc.LOGDEBUG)
return_url = req.full_url return_url = req.get_full_url()
if self._insecure: if self._insecure:
return_url += '&verifypeer=false' return_url += '&verifypeer=false'
xbmc.log("Request is insecure %s"%return_url,level=xbmc.LOGDEBUG) xbmc.log("Request is insecure %s"%return_url,level=xbmc.LOGDEBUG)
@ -2007,7 +2010,7 @@ class Connection(object):
q['musicFolderId'] = musicFolderId q['musicFolderId'] = musicFolderId
req = self._getRequest(viewName, q) req = self._getRequest(viewName, q)
xbmc.log("Requesting %s"%str(req.full_url),xbmc.LOGDEBUG) xbmc.log("Requesting %s"%str(req.get_full_url()),xbmc.LOGDEBUG)
res = self._doInfoReq(req) res = self._doInfoReq(req)
self._checkStatus(res) self._checkStatus(res)
return res return res
@ -2765,7 +2768,7 @@ class Connection(object):
url = '%s:%d/%s/%s?%s' % (self._baseUrl, self._port, url = '%s:%d/%s/%s?%s' % (self._baseUrl, self._port,
self._separateServerPath(), viewName, methodName) self._separateServerPath(), viewName, methodName)
req = urllib.request.Request(url) req = urllib2.Request(url)
res = self._opener.open(req) res = self._opener.open(req)
res_msg = res.msg.lower() res_msg = res.msg.lower()
return res_msg == 'ok' return res_msg == 'ok'
@ -2779,7 +2782,7 @@ class Connection(object):
if sys.version_info[:3] >= (2, 7, 9) and self._insecure: if sys.version_info[:3] >= (2, 7, 9) and self._insecure:
https_chain = HTTPSHandlerChain( https_chain = HTTPSHandlerChain(
context=ssl._create_unverified_context()) context=ssl._create_unverified_context())
opener = urllib.request.build_opener( opener = urllib2.build_opener(
PysHTTPRedirectHandler, PysHTTPRedirectHandler,
https_chain, https_chain,
) )
@ -2821,11 +2824,11 @@ class Connection(object):
viewName) viewName)
#xbmc.log("Standard URL %s"%url,level=xbmc.LOGDEBUG) #xbmc.log("Standard URL %s"%url,level=xbmc.LOGDEBUG)
#xbmc.log("Qdict %s"%str(qdict),level=xbmc.LOGDEBUG) #xbmc.log("Qdict %s"%str(qdict),level=xbmc.LOGDEBUG)
req = urllib.request.Request(url, urlencode(qdict).encode('utf-8')) req = urllib2.Request(url, urlencode(qdict).encode('utf-8'))
if(self._useGET or ('getCoverArt' in viewName) or ('stream' in viewName)): if(self._useGET or ('getCoverArt' in viewName) or ('stream' in viewName)):
url += '?%s' % urlencode(qdict) url += '?%s' % urlencode(qdict)
#xbmc.log("UseGET URL %s"%(url),xbmc.LOGDEBUG) #xbmc.log("UseGET URL %s"%(url),xbmc.LOGDEBUG)
req = urllib.request.Request(url) req = urllib2.Request(url)
return req return req
def _getRequestWithList(self, viewName, listName, alist, query={}): def _getRequestWithList(self, viewName, listName, alist, query={}):
@ -2841,7 +2844,7 @@ class Connection(object):
data.write(urlencode(qdict)) data.write(urlencode(qdict))
for i in alist: for i in alist:
data.write('&%s' % urlencode({listName: i})) data.write('&%s' % urlencode({listName: i}))
req = urllib.request.Request(url, data.getvalue().encode('utf-8')) req = urllib2.Request(url, data.getvalue().encode('utf-8'))
if self._useGET: if self._useGET:
url += '?%s' % data.getvalue() url += '?%s' % data.getvalue()
@ -2868,7 +2871,7 @@ class Connection(object):
for k, l in listMap.items(): for k, l in listMap.items():
for i in l: for i in l:
data.write('&%s' % urlencode({k: i})) data.write('&%s' % urlencode({k: i}))
req = urllib.request.Request(url, data.getvalue().encode('utf-8')) req = urllib2.Request(url, data.getvalue().encode('utf-8'))
if self._useGET: if self._useGET:
url += '?%s' % data.getvalue() url += '?%s' % data.getvalue()

View File

@ -19,7 +19,7 @@ import inspect
import time import time
import hashlib import hashlib
import pickle import pickle
from collections.abc import MutableMapping from collections import MutableMapping
from collections import namedtuple from collections import namedtuple
from copy import deepcopy from copy import deepcopy
from functools import wraps from functools import wraps
@ -27,7 +27,9 @@ from shutil import copyfile
from contextlib import contextmanager from contextlib import contextmanager
from pprint import pformat from pprint import pformat
from platform import uname from platform import uname
from urllib.parse import urlencode, quote_plus, urlparse, unquote_plus, parse_qs #from urllib.parse import urlencode, quote_plus, urlparse, unquote_plus, parse_qs
from urlparse import parse_qs
from urllib import urlencode
import xbmcaddon import xbmcaddon
import xbmc import xbmc
import xbmcgui import xbmcgui
@ -36,7 +38,7 @@ import xbmcvfs
__all__ = ['SimplePluginError', 'Storage', 'MemStorage', 'Addon', 'Plugin', __all__ = ['SimplePluginError', 'Storage', 'MemStorage', 'Addon', 'Plugin',
'RoutedPlugin', 'Params', 'log_exception', 'translate_path'] 'RoutedPlugin', 'Params', 'log_exception', 'translate_path']
getargspec = inspect.getfullargspec getargspec = inspect.getargspec
Route = namedtuple('Route', ['pattern', 'func']) Route = namedtuple('Route', ['pattern', 'func'])
@ -1086,7 +1088,6 @@ class Plugin(Addon):
return action_callable(self._params) return action_callable(self._params)
class RoutedPlugin(Plugin): class RoutedPlugin(Plugin):
""" """
Plugin class that implements "pretty URL" routing similar to Flask and Bottle Plugin class that implements "pretty URL" routing similar to Flask and Bottle

43
main.py
View File

@ -12,11 +12,11 @@ import time
import hashlib import hashlib
import random import random
from datetime import datetime from datetime import datetime
from collections.abc import MutableMapping from collections import MutableMapping
from collections import namedtuple from collections import namedtuple
# Add the /lib folder to sys # Add the /lib folder to sys
sys.path.append(xbmcvfs.translatePath(os.path.join(xbmcaddon.Addon("plugin.audio.subsonic").getAddonInfo("path"), "lib"))) sys.path.append(xbmc.translatePath(os.path.join(xbmcaddon.Addon("plugin.audio.subsonic").getAddonInfo("path"), "lib")))
import libsonic import libsonic
@ -44,7 +44,7 @@ def get_connection():
if connection==None: if connection==None:
connected = False connected = False
# Create connection # Create connection
try: if 1:#try:
connection = libsonic.Connection( connection = libsonic.Connection(
baseUrl=Addon().get_setting('subsonic_url'), baseUrl=Addon().get_setting('subsonic_url'),
username=Addon().get_setting('username', convert=False), username=Addon().get_setting('username', convert=False),
@ -56,8 +56,8 @@ def get_connection():
useGET=Addon().get_setting('useget'), useGET=Addon().get_setting('useget'),
) )
connected = connection.ping() connected = connection.ping()
except: #except:
pass # pass
if connected==False: if connected==False:
popup('Connection error') popup('Connection error')
@ -1373,7 +1373,8 @@ def walk_index(folder_id=None):
plugin.log("artist: %s"%artist) plugin.log("artist: %s"%artist)
yield artist yield artist
except KeyError: except KeyError:
yield from () for emp in ():
yield emp
def walk_playlists(): def walk_playlists():
""" """
@ -1384,7 +1385,8 @@ def walk_playlists():
for child in response["playlists"]["playlist"]: for child in response["playlists"]["playlist"]:
yield child yield child
except KeyError: except KeyError:
yield from () for emp in ():
yield emp
def walk_playlist(playlist_id): def walk_playlist(playlist_id):
""" """
@ -1395,7 +1397,8 @@ def walk_playlist(playlist_id):
for child in response["playlist"]["entry"]: for child in response["playlist"]["entry"]:
yield child yield child
except KeyError: except KeyError:
yield from () for emp in ():
yield emp
def walk_folders(): def walk_folders():
response = connection.getMusicFolders() response = connection.getMusicFolders()
@ -1403,7 +1406,8 @@ def walk_folders():
for child in response["musicFolders"]["musicFolder"]: for child in response["musicFolders"]["musicFolder"]:
yield child yield child
except KeyError: except KeyError:
yield from () for emp in ():
yield emp
def walk_directory(directory_id, merge_artist = True): def walk_directory(directory_id, merge_artist = True):
""" """
@ -1419,7 +1423,8 @@ def walk_directory(directory_id, merge_artist = True):
else: else:
yield child yield child
except KeyError: except KeyError:
yield from () for emp in ():
yield emp
def walk_artist(artist_id): def walk_artist(artist_id):
""" """
@ -1431,7 +1436,8 @@ def walk_artist(artist_id):
for child in response["artist"]["album"]: for child in response["artist"]["album"]:
yield child yield child
except KeyError: except KeyError:
yield from () for emp in ():
yield emp
def walk_artists(): def walk_artists():
""" """
@ -1444,7 +1450,8 @@ def walk_artists():
for artist in index["artist"]: for artist in index["artist"]:
yield artist yield artist
except KeyError: except KeyError:
yield from () for emp in ():
yield emp
def walk_genres(): def walk_genres():
""" """
@ -1456,7 +1463,8 @@ def walk_genres():
for genre in response["genres"]["genre"]: for genre in response["genres"]["genre"]:
yield genre yield genre
except KeyError: except KeyError:
yield from () for emp in ():
yield emp
def walk_albums(ltype, size=None, fromYear=None,toYear=None, genre=None, offset=None): def walk_albums(ltype, size=None, fromYear=None,toYear=None, genre=None, offset=None):
""" """
@ -1490,7 +1498,8 @@ def walk_album(album_id):
for song in response["album"]["song"]: for song in response["album"]["song"]:
yield song yield song
except KeyError: except KeyError:
yield from () for emp in ():
yield emp
def walk_tracks_random(size=None, genre=None, fromYear=None,toYear=None): def walk_tracks_random(size=None, genre=None, fromYear=None,toYear=None):
""" """
@ -1502,7 +1511,8 @@ def walk_tracks_random(size=None, genre=None, fromYear=None,toYear=None):
for song in response["randomSongs"]["song"]: for song in response["randomSongs"]["song"]:
yield song yield song
except KeyError: except KeyError:
yield from () for emp in ():
yield emp
def walk_tracks_starred(): def walk_tracks_starred():
""" """
@ -1513,7 +1523,8 @@ def walk_tracks_starred():
for song in response["starred"]["song"]: for song in response["starred"]["song"]:
yield song yield song
except KeyError: except KeyError:
yield from () for emp in ():
yield emp
# Start plugin from within Kodi. # Start plugin from within Kodi.
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -4,7 +4,7 @@ import xbmcvfs
import os import os
import xbmcaddon import xbmcaddon
# Add the /lib folder to sys # Add the /lib folder to sys
sys.path.append(xbmcvfs.translatePath(os.path.join(xbmcaddon.Addon("plugin.audio.subsonic").getAddonInfo("path"), "lib"))) sys.path.append(xbmc.translatePath(os.path.join(xbmcaddon.Addon("plugin.audio.subsonic").getAddonInfo("path"), "lib")))
import libsonic import libsonic