diff --git a/resources/language/resource.language.en_gb/strings.po b/resources/language/resource.language.en_gb/strings.po
index db179cee..e62c76dc 100644
--- a/resources/language/resource.language.en_gb/strings.po
+++ b/resources/language/resource.language.en_gb/strings.po
@@ -41,6 +41,26 @@ msgctxt "#30005"
msgid "Username: "
msgstr ""
+# Sync notification displayed if there is still artwork to be cached to Kodi
+msgctxt "#30006"
+msgid "Caching %s images"
+msgstr ""
+
+# Sync notification displayed if syncing of major artwork is done
+msgctxt "#30007"
+msgid "Major image caching done"
+msgstr ""
+
+# PKC settings artwork: Enable notifications for artwork image sync
+msgctxt "#30008"
+msgid "Enable notifications for image caching"
+msgstr ""
+
+# PKC settings artwork: Enable image caching during Kodi playback
+msgctxt "#30009"
+msgid "Enable image caching during Kodi playback (restart Kodi!)"
+msgstr ""
+
# Button text
msgctxt "#30012"
msgid "OK"
diff --git a/resources/lib/artwork.py b/resources/lib/artwork.py
index 1c39b806..84d7b612 100644
--- a/resources/lib/artwork.py
+++ b/resources/lib/artwork.py
@@ -22,6 +22,10 @@ LOG = getLogger("PLEX." + __name__)
# Disable annoying requests warnings
requests.packages.urllib3.disable_warnings()
ARTWORK_QUEUE = Queue()
+IMAGE_CACHING_SUSPENDS = ['SUSPEND_LIBRARY_THREAD', 'DB_SCAN', 'STOP_SYNC']
+if not settings('imageSyncDuringPlayback') == 'true':
+ IMAGE_CACHING_SUSPENDS.append('SUSPEND_SYNC')
+
###############################################################################
@@ -33,11 +37,9 @@ def double_urldecode(text):
return unquote(unquote(text))
-@thread_methods(add_suspends=['SUSPEND_LIBRARY_THREAD',
- 'DB_SCAN',
- 'STOP_SYNC'])
+@thread_methods(add_suspends=IMAGE_CACHING_SUSPENDS)
class Image_Cache_Thread(Thread):
- sleep_between = 50
+ sleep_between = 200
# Potentially issues with limited number of threads
# Hence let Kodi wait till download is successful
timeout = (35.1, 35.1)
@@ -47,6 +49,7 @@ class Image_Cache_Thread(Thread):
Thread.__init__(self)
def run(self):
+ LOG.info("---===### Starting Image_Cache_Thread ###===---")
stopped = self.stopped
suspended = self.suspended
queue = self.queue
@@ -65,6 +68,16 @@ class Image_Cache_Thread(Thread):
except Empty:
sleep(1000)
continue
+ if isinstance(url, ArtworkSyncMessage):
+ if state.IMAGE_SYNC_NOTIFICATIONS:
+ dialog('notification',
+ heading=lang(29999),
+ message=url.message,
+ icon='{plex}',
+ sound=False)
+ queue.task_done()
+ continue
+ url = double_urlencode(try_encode(url))
sleeptime = 0
while True:
try:
@@ -116,6 +129,44 @@ class Artwork():
if enableTextureCache:
queue = ARTWORK_QUEUE
+ def cache_major_artwork(self):
+ """
+ Takes the existing Kodi library and caches posters and fanart.
+ Necessary because otherwise PKC caches artwork e.g. from fanart.tv
+ which basically blocks Kodi from getting needed artwork fast (e.g.
+ while browsing the library)
+ """
+ if not self.enableTextureCache:
+ return
+ artworks = list()
+ # Get all posters and fanart/background for video and music
+ for kind in ('video', 'music'):
+ connection = kodi_sql(kind)
+ cursor = connection.cursor()
+ for typus in ('poster', 'fanart'):
+ cursor.execute('SELECT url FROM art WHERE type == ?',
+ (typus, ))
+ artworks.extend(cursor.fetchall())
+ connection.close()
+ artworks_to_cache = list()
+ connection = kodi_sql('texture')
+ cursor = connection.cursor()
+ for url in artworks:
+ query = 'SELECT url FROM texture WHERE url == ? LIMIT 1'
+ cursor.execute(query, (url[0], ))
+ if not cursor.fetchone():
+ artworks_to_cache.append(url)
+ connection.close()
+ if not artworks_to_cache:
+ LOG.info('Caching of major images to Kodi texture cache done')
+ return
+ LOG.info('Caching has not been completed - caching %s major images',
+ len(artworks_to_cache))
+ self.queue.put(ArtworkSyncMessage(lang(30006) % len(artworks_to_cache)))
+ for url in artworks_to_cache:
+ self.queue.put(url[0])
+ self.queue.put(ArtworkSyncMessage(lang(30007)))
+
def fullTextureCacheSync(self):
"""
This method will sync all Kodi artwork to textures13.db
@@ -174,10 +225,10 @@ class Artwork():
def cache_texture(self, url):
'''
- Cache a single image url to the texture cache
+ Cache a single image url to the texture cache. url: unicode
'''
if url and self.enableTextureCache:
- self.queue.put(double_urlencode(try_encode(url)))
+ self.queue.put(url)
def modify_artwork(self, artworks, kodi_id, kodi_type, cursor):
"""
@@ -266,3 +317,11 @@ class Artwork():
for path in paths:
makedirs(try_decode(translatePath("special://thumbnails/%s"
% path)))
+
+
+class ArtworkSyncMessage(object):
+ """
+ Put in artwork queue to display the message as a Kodi notification
+ """
+ def __init__(self, message):
+ self.message = message
diff --git a/resources/lib/entrypoint.py b/resources/lib/entrypoint.py
index 1bd5318e..7ec66d72 100644
--- a/resources/lib/entrypoint.py
+++ b/resources/lib/entrypoint.py
@@ -369,7 +369,7 @@ def getRecentEpisodes(viewid, mediatype, tagname, limit):
append_show_title = settings('RecentTvAppendShow') == 'true'
append_sxxexx = settings('RecentTvAppendSeason') == 'true'
# First we get a list of all the TV shows - filtered by tag
- allshowsIds = set()
+ allshowsIds = list()
params = {
'sort': {'order': "descending", 'method': "dateadded"},
'filter': {'operator': "is", 'field': "tag", 'value': "%s" % tagname},
diff --git a/resources/lib/kodimonitor.py b/resources/lib/kodimonitor.py
index a7c3dd65..a35af585 100644
--- a/resources/lib/kodimonitor.py
+++ b/resources/lib/kodimonitor.py
@@ -50,7 +50,8 @@ STATE_SETTINGS = {
'remapSMBphotoNew': 'remapSMBphotoNew',
'enableMusic': 'ENABLE_MUSIC',
'forceReloadSkinOnPlaybackStop': 'FORCE_RELOAD_SKIN',
- 'fetch_pms_item_number': 'FETCH_PMS_ITEM_NUMBER'
+ 'fetch_pms_item_number': 'FETCH_PMS_ITEM_NUMBER',
+ 'imageSyncNotifications': 'IMAGE_SYNC_NOTIFICATIONS'
}
###############################################################################
diff --git a/resources/lib/librarysync.py b/resources/lib/librarysync.py
index 5ce7485e..a857c586 100644
--- a/resources/lib/librarysync.py
+++ b/resources/lib/librarysync.py
@@ -16,6 +16,7 @@ from downloadutils import DownloadUtils as DU
import itemtypes
import plexdb_functions as plexdb
import kodidb_functions as kodidb
+import artwork
import videonodes
import variables as v
@@ -1463,7 +1464,6 @@ class LibrarySync(Thread):
elif state.RUN_LIB_SCAN == 'textures':
state.DB_SCAN = True
window('plex_dbScan', value="true")
- import artwork
artwork.Artwork().fullTextureCacheSync()
window('plex_dbScan', clear=True)
state.DB_SCAN = False
@@ -1527,8 +1527,6 @@ class LibrarySync(Thread):
last_time_sync = utils.unix_timestamp()
window('plex_dbScan', clear=True)
state.DB_SCAN = False
- # Start the fanart download thread
- self.fanartthread.start()
kodi_playlist_monitor = None
while not self.stopped():
@@ -1555,6 +1553,7 @@ class LibrarySync(Thread):
initial_sync_done = True
kodi_db_version_checked = True
last_sync = utils.unix_timestamp()
+ self.fanartthread.start()
else:
LOG.error('Initial start-up full sync unsuccessful')
xbmc.executebuiltin('InhibitIdleShutdown(false)')
@@ -1599,6 +1598,8 @@ class LibrarySync(Thread):
if settings('FanartTV') == 'true':
self.sync_fanart()
LOG.info('Done initial sync on Kodi startup')
+ artwork.Artwork().cache_major_artwork()
+ self.fanartthread.start()
else:
LOG.info('Startup sync has not yet been successful')
window('plex_dbScan', clear=True)
diff --git a/resources/lib/state.py b/resources/lib/state.py
index 69532239..60b15ede 100644
--- a/resources/lib/state.py
+++ b/resources/lib/state.py
@@ -39,6 +39,8 @@ FORCE_RELOAD_SKIN = True
# Stemming from the PKC settings.xml
# Shall we show Kodi dialogs when synching?
SYNC_DIALOG = True
+# Shall Kodi show dialogs for syncing/caching images? (e.g. images left to sync)
+IMAGE_SYNC_NOTIFICATIONS = True
# Is synching of Plex music enabled?
ENABLE_MUSIC = True
# How often shall we sync?
diff --git a/resources/settings.xml b/resources/settings.xml
index fea2ad2d..d8e46400 100644
--- a/resources/settings.xml
+++ b/resources/settings.xml
@@ -125,6 +125,8 @@
+
+