mirror of
https://github.com/jellyfin/jellyfin-kodi.git
synced 2024-12-25 02:06:09 +00:00
Removed web server for image caching
This commit is contained in:
parent
2f9fb660cb
commit
3bff962cad
3 changed files with 1 additions and 181 deletions
|
@ -28,49 +28,27 @@ class Artwork(object):
|
||||||
def __init__(self, cursor):
|
def __init__(self, cursor):
|
||||||
|
|
||||||
self.cursor = cursor
|
self.cursor = cursor
|
||||||
self.enable_cache = settings('enableTextureCache.bool')
|
|
||||||
self.queue = Queue.Queue()
|
|
||||||
self.threads = []
|
|
||||||
self.kodi = {
|
|
||||||
'username': settings('webServerUser'),
|
|
||||||
'password': settings('webServerPass'),
|
|
||||||
'host': "localhost",
|
|
||||||
'port': settings('webServerPort')
|
|
||||||
}
|
|
||||||
|
|
||||||
def update(self, image_url, kodi_id, media, image):
|
def update(self, image_url, kodi_id, media, image):
|
||||||
|
|
||||||
''' Update artwork in the video database.
|
''' Update artwork in the video database.
|
||||||
Only cache artwork if it changed for the main backdrop, poster.
|
|
||||||
Delete current entry before updating with the new one.
|
Delete current entry before updating with the new one.
|
||||||
Cache fanart and poster in Kodi texture cache.
|
|
||||||
'''
|
'''
|
||||||
if not image_url or image == 'poster' and media in ('song', 'artist', 'album'):
|
if not image_url or image == 'poster' and media in ('song', 'artist', 'album'):
|
||||||
return
|
return
|
||||||
|
|
||||||
cache = False
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.cursor.execute(QU.get_art, (kodi_id, media, image,))
|
self.cursor.execute(QU.get_art, (kodi_id, media, image,))
|
||||||
url = self.cursor.fetchone()[0]
|
url = self.cursor.fetchone()[0]
|
||||||
except TypeError:
|
except TypeError:
|
||||||
|
|
||||||
cache = True
|
|
||||||
LOG.debug("ADD to kodi_id %s art: %s", kodi_id, image_url)
|
LOG.debug("ADD to kodi_id %s art: %s", kodi_id, image_url)
|
||||||
self.cursor.execute(QU.add_art, (kodi_id, media, image, image_url))
|
self.cursor.execute(QU.add_art, (kodi_id, media, image, image_url))
|
||||||
else:
|
else:
|
||||||
if url != image_url:
|
if url != image_url:
|
||||||
cache = True
|
|
||||||
|
|
||||||
if image in ('fanart', 'poster'):
|
|
||||||
self.delete_cache(url)
|
|
||||||
|
|
||||||
LOG.info("UPDATE to kodi_id %s art: %s", kodi_id, image_url)
|
LOG.info("UPDATE to kodi_id %s art: %s", kodi_id, image_url)
|
||||||
self.cursor.execute(QU.update_art, (image_url, kodi_id, media, image))
|
self.cursor.execute(QU.update_art, (image_url, kodi_id, media, image))
|
||||||
|
|
||||||
if cache and image in ('fanart', 'poster'):
|
|
||||||
self.cache(image_url)
|
|
||||||
|
|
||||||
def add(self, artwork, *args):
|
def add(self, artwork, *args):
|
||||||
|
|
||||||
''' Add all artworks.
|
''' Add all artworks.
|
||||||
|
@ -106,113 +84,3 @@ class Artwork(object):
|
||||||
|
|
||||||
elif artwork.get(art):
|
elif artwork.get(art):
|
||||||
self.update(*(artwork[art],) + args + (KODI[art],))
|
self.update(*(artwork[art],) + args + (KODI[art],))
|
||||||
|
|
||||||
def delete(self, *args):
|
|
||||||
|
|
||||||
''' Delete artwork from kodi database and remove cache for backdrop/posters.
|
|
||||||
'''
|
|
||||||
self.cursor.execute(QU.get_art_url, args)
|
|
||||||
|
|
||||||
for row in self.cursor.fetchall():
|
|
||||||
if row[1] in ('poster', 'fanart'):
|
|
||||||
self.delete_cache(row[0])
|
|
||||||
|
|
||||||
def cache(self, url):
|
|
||||||
|
|
||||||
''' Cache a single image to texture cache.
|
|
||||||
'''
|
|
||||||
if not url or not self.enable_cache:
|
|
||||||
return
|
|
||||||
|
|
||||||
url = self.double_urlencode(url)
|
|
||||||
self.queue.put(url)
|
|
||||||
self.add_worker()
|
|
||||||
|
|
||||||
def double_urlencode(self, text):
|
|
||||||
|
|
||||||
text = self.single_urlencode(text)
|
|
||||||
text = self.single_urlencode(text)
|
|
||||||
|
|
||||||
return text
|
|
||||||
|
|
||||||
def single_urlencode(self, text):
|
|
||||||
|
|
||||||
''' urlencode needs a utf-string.
|
|
||||||
return the result as unicode
|
|
||||||
'''
|
|
||||||
text = urlencode({'blahblahblah': text})
|
|
||||||
text = text[13:]
|
|
||||||
|
|
||||||
return text
|
|
||||||
|
|
||||||
def add_worker(self):
|
|
||||||
|
|
||||||
self.threads = [thread for thread in self.threads if not thread.is_done]
|
|
||||||
|
|
||||||
if self.queue.qsize() and len(self.threads) < 2:
|
|
||||||
|
|
||||||
new_thread = GetArtworkWorker(self.kodi, self.queue)
|
|
||||||
new_thread.start()
|
|
||||||
LOG.info("-->[ q:artwork/%s ]", id(new_thread))
|
|
||||||
self.threads.append(new_thread)
|
|
||||||
|
|
||||||
def delete_cache(self, url):
|
|
||||||
|
|
||||||
''' Delete cached artwork.
|
|
||||||
'''
|
|
||||||
from database import Database
|
|
||||||
|
|
||||||
with Database('texture') as texturedb:
|
|
||||||
try:
|
|
||||||
texturedb.cursor.execute(QUTEX.get_cache, (url,))
|
|
||||||
cached = texturedb.cursor.fetchone()[0]
|
|
||||||
except TypeError:
|
|
||||||
LOG.debug("Could not find cached url: %s", url)
|
|
||||||
else:
|
|
||||||
thumbnails = xbmc.translatePath("special://thumbnails/%s" % cached)
|
|
||||||
xbmcvfs.delete(thumbnails)
|
|
||||||
texturedb.cursor.execute(QUTEX.delete_cache, (url,))
|
|
||||||
LOG.info("DELETE cached %s", cached)
|
|
||||||
|
|
||||||
|
|
||||||
class GetArtworkWorker(threading.Thread):
|
|
||||||
|
|
||||||
is_done = False
|
|
||||||
|
|
||||||
def __init__(self, kodi, queue):
|
|
||||||
|
|
||||||
self.kodi = kodi
|
|
||||||
self.queue = queue
|
|
||||||
threading.Thread.__init__(self)
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
|
|
||||||
''' Prepare the request. Request removes the urlencode which is required in this case.
|
|
||||||
Use a session allows to use a pool of connections.
|
|
||||||
'''
|
|
||||||
with requests.Session() as s:
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
url = self.queue.get(timeout=2)
|
|
||||||
except Queue.Empty:
|
|
||||||
|
|
||||||
self.is_done = True
|
|
||||||
LOG.info("--<[ q:artwork/%s ]", id(self))
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
req = requests.Request(method='HEAD',
|
|
||||||
url="http://%s:%s/image/image://%s" % (self.kodi['host'], self.kodi['port'], url),
|
|
||||||
auth=(self.kodi['username'], self.kodi['password']))
|
|
||||||
prep = req.prepare()
|
|
||||||
prep.url = "http://%s:%s/image/image://%s" % (self.kodi['host'], self.kodi['port'], url)
|
|
||||||
s.send(prep, timeout=(0.01, 0.01))
|
|
||||||
s.content # release the connection
|
|
||||||
except Exception as error:
|
|
||||||
LOG.exception(error)
|
|
||||||
|
|
||||||
self.queue.task_done()
|
|
||||||
|
|
||||||
if xbmc.Monitor().abortRequested():
|
|
||||||
break
|
|
||||||
|
|
|
@ -18,50 +18,10 @@ class Setup(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
|
||||||
self.set_web_server()
|
|
||||||
self.setup()
|
self.setup()
|
||||||
|
|
||||||
LOG.info("---<[ setup ]")
|
LOG.info("---<[ setup ]")
|
||||||
|
|
||||||
def set_web_server(self):
|
|
||||||
|
|
||||||
''' Enable the webserver if not enabled. This is used to cache artwork.
|
|
||||||
Will only test once, if it fails, user will be notified only once.
|
|
||||||
'''
|
|
||||||
if settings('enableTextureCache.bool'):
|
|
||||||
|
|
||||||
get_setting = JSONRPC('Settings.GetSettingValue')
|
|
||||||
|
|
||||||
if not self.get_web_server():
|
|
||||||
|
|
||||||
set_setting = JSONRPC('Settings.SetSetingValue')
|
|
||||||
set_setting.execute({'setting': "services.webserverport", 'value': 8080})
|
|
||||||
set_setting.execute({'setting': "services.webserver", 'value': True})
|
|
||||||
|
|
||||||
if not self.get_web_server():
|
|
||||||
|
|
||||||
settings('enableTextureCache.bool', False)
|
|
||||||
dialog("ok", heading="{jellyfin}", line1=translate(33103))
|
|
||||||
|
|
||||||
return
|
|
||||||
|
|
||||||
result = get_setting.execute({'setting': "services.webserverport"})
|
|
||||||
settings('webServerPort', str(result['result']['value'] or ""))
|
|
||||||
result = get_setting.execute({'setting': "services.webserverusername"})
|
|
||||||
settings('webServerUser', str(result['result']['value'] or ""))
|
|
||||||
result = get_setting.execute({'setting': "services.webserverpassword"})
|
|
||||||
settings('webServerPass', str(result['result']['value'] or ""))
|
|
||||||
settings('useWebServer.bool', True)
|
|
||||||
|
|
||||||
def get_web_server(self):
|
|
||||||
|
|
||||||
result = JSONRPC('Settings.GetSettingValue').execute({'setting': "services.webserver"})
|
|
||||||
|
|
||||||
try:
|
|
||||||
return result['result']['value']
|
|
||||||
except (KeyError, TypeError):
|
|
||||||
return False
|
|
||||||
|
|
||||||
def setup(self):
|
def setup(self):
|
||||||
|
|
||||||
minimum = "3.0.24"
|
minimum = "3.0.24"
|
||||||
|
@ -74,8 +34,6 @@ class Setup(object):
|
||||||
|
|
||||||
self._is_mode()
|
self._is_mode()
|
||||||
LOG.info("Add-on playback: %s", settings('useDirectPaths') == "0")
|
LOG.info("Add-on playback: %s", settings('useDirectPaths') == "0")
|
||||||
self._is_artwork_caching()
|
|
||||||
LOG.info("Artwork caching: %s", settings('enableTextureCache.bool'))
|
|
||||||
|
|
||||||
# Setup completed
|
# Setup completed
|
||||||
settings('MinimumSetup', minimum)
|
settings('MinimumSetup', minimum)
|
||||||
|
@ -95,11 +53,6 @@ class Setup(object):
|
||||||
if value:
|
if value:
|
||||||
dialog("ok", heading="{jellyfin}", line1=translate(33145))
|
dialog("ok", heading="{jellyfin}", line1=translate(33145))
|
||||||
|
|
||||||
def _is_artwork_caching(self):
|
|
||||||
|
|
||||||
value = dialog("yesno", heading="{jellyfin}", line1=translate(33117))
|
|
||||||
settings('enableTextureCache.bool', value)
|
|
||||||
|
|
||||||
def _is_music(self):
|
def _is_music(self):
|
||||||
|
|
||||||
value = dialog("yesno", heading="{jellyfin}", line1=translate(33039))
|
value = dialog("yesno", heading="{jellyfin}", line1=translate(33039))
|
||||||
|
|
|
@ -28,7 +28,6 @@
|
||||||
<setting label="30515" id="limitIndex" type="slider" default="15" range="1, 1, 100" option="int" />
|
<setting label="30515" id="limitIndex" type="slider" default="15" range="1, 1, 100" option="int" />
|
||||||
<setting label="33174" id="limitThreads" type="slider" default="3" range="1, 1, 50" option="int" />
|
<setting label="33174" id="limitThreads" type="slider" default="3" range="1, 1, 50" option="int" />
|
||||||
<setting label="33176" type="lsep" />
|
<setting label="33176" type="lsep" />
|
||||||
<setting label="30512" id="enableTextureCache" type="bool" default="true" />
|
|
||||||
<setting label="30157" id="enableCoverArt" type="bool" default="true" />
|
<setting label="30157" id="enableCoverArt" type="bool" default="true" />
|
||||||
<setting label="33116" id="compressArt" type="bool" default="false" />
|
<setting label="33116" id="compressArt" type="bool" default="false" />
|
||||||
<setting id="enableMusic" visible="false" default="false" />
|
<setting id="enableMusic" visible="false" default="false" />
|
||||||
|
|
Loading…
Reference in a new issue