From dea75e97a59a5930169eca5481239201b03c8e5e Mon Sep 17 00:00:00 2001 From: jurialmunkey Date: Sat, 21 Dec 2024 15:45:12 +1100 Subject: [PATCH] :sparkles: Allow an {x} value in sourceimage --- resources/tmdbhelper/lib/monitor/common.py | 7 +- resources/tmdbhelper/lib/monitor/images.py | 136 +++++++++++++----- resources/tmdbhelper/lib/monitor/imgmon.py | 23 ++- .../tmdbhelper/lib/monitor/listitemtools.py | 11 +- resources/tmdbhelper/lib/monitor/player.py | 3 +- 5 files changed, 131 insertions(+), 49 deletions(-) diff --git a/resources/tmdbhelper/lib/monitor/common.py b/resources/tmdbhelper/lib/monitor/common.py index 2c7affba..4b7d0254 100644 --- a/resources/tmdbhelper/lib/monitor/common.py +++ b/resources/tmdbhelper/lib/monitor/common.py @@ -12,8 +12,10 @@ SETMAIN = { 'label', 'tmdb_id', 'imdb_id', 'folderpath', 'filenameandpath'} +SETMAIN_ALTERED = { + 'cropimage', 'cropimage.original', 'blurimage', 'blurimage.original', + 'desaturateimage', 'desaturateimage.original', 'colorsimage', 'colorsimage.original'} SETMAIN_ARTWORK = { - 'cropimage', 'cropimage.original', 'blurimage', 'blurimage.original', 'desaturateimage', 'desaturateimage.original', 'colorsimage', 'colorsimage.original', 'icon', 'poster', 'thumb', 'fanart', 'discart', 'clearart', 'clearlogo', 'landscape', 'banner', 'keyart', 'season.poster', 'season.thumb', 'season.fanart', 'season.discart', 'season.clearart', 'season.clearlogo', 'season.landscape', 'season.banner', 'season.keyart', 'tvshow.poster', 'tvshow.thumb', 'tvshow.fanart', 'tvshow.discart', 'tvshow.clearart', 'tvshow.clearlogo', 'tvshow.landscape', 'tvshow.banner', 'tvshow.keyart'} @@ -283,7 +285,8 @@ def set_indexed_properties(self, dictionary): k for k in list(dictionary) if k not in self.properties and k not in SETPROP_RATINGS - and k not in SETMAIN_ARTWORK) + and k not in SETMAIN_ARTWORK + and k not in SETMAIN_ALTERED) for k in keys: if k not in dictionary: diff --git a/resources/tmdbhelper/lib/monitor/images.py b/resources/tmdbhelper/lib/monitor/images.py index eb2e01a9..d866fe12 100644 --- a/resources/tmdbhelper/lib/monitor/images.py +++ b/resources/tmdbhelper/lib/monitor/images.py @@ -3,6 +3,7 @@ import xbmcvfs import colorsys import hashlib +import random from xbmc import getCacheThumbName, skinHasImage, Monitor, sleep from tmdbhelper.lib.addon.plugin import get_infolabel, get_setting, get_condvisibility, ADDONDATA from tmdbhelper.lib.monitor.propertysetter import PropertySetter @@ -350,6 +351,93 @@ def colors(self, source): return '' +class ImageArtworkGetter(): + def __init__(self, parent, source, prebuilt_artwork=None): + self._parent = parent + self._source = source + self.prebuilt_artwork = prebuilt_artwork + + @property + def infolabels(self): + try: + return self._infolabels + except AttributeError: + self._infolabels = self.get_infolabels() + return self._infolabels + + def get_infolabels(self): + if not self._source: + return ARTWORK_LOOKUP_TABLE.get('thumb') + return ARTWORK_LOOKUP_TABLE.get(self._source, self._source.split("|")) + + @property + def built_artwork(self): + try: + return self._built_artwork + except AttributeError: + self._built_artwork = self.get_built_artwork() + return self._built_artwork + + def get_built_artwork(self): + return self.prebuilt_artwork or self._parent.get_builtartwork() + + @property + def artwork(self): + try: + return self._artwork + except AttributeError: + self._artwork = self.get_artwork() + return self._artwork + + def get_artwork(self): + return next((j for j in (self.get_artwork_item(i) for i in self.infolabels) if j), None) + + @property + def artwork_fallback(self): + try: + return self._artwork_fallback + except AttributeError: + self._artwork_fallback = self.get_artwork_fallback() + return self._artwork_fallback + + def get_artwork_fallback(self): + return next((j for j in (self.get_artwork_item(i, prebuilt=True) for i in self.infolabels) if j), None) + + def get_artwork_item(self, item, prebuilt=False): + + def _get_artwork_item(i, x=''): + if not prebuilt: + return self._parent.get_infolabel(i.format(x=x)) + if not i.startswith('art('): + return + return self.built_artwork.get(i.format(x=x)[4:-1]) + + # Check if we're getting a random x position item e.g. "Art(fanart{x})" + if '{x}' not in item: + return _get_artwork_item(item) + + # If we cant get the base item e.g. "Art(fanart)" then unlikely we have extra art so exit now + artwork0 = _get_artwork_item(item) + if not artwork0: + return + + # If we can't get the first extra item e.g. "Art(fanart1)" then unlikely we'd have "Art(fanart2)" etc. so just return "Art(fanart)" + artwork1 = _get_artwork_item(item, x=1) + if not artwork1: + return artwork0 + + # Build a list of available artworks that the item has + artworks = [artwork0, artwork1] + for x in range(2, 9): + artwork = _get_artwork_item(item, x=x) + if not artwork: + break + artworks.append(artwork) + + # Then choose an artwork from the available artworks list at random + return random.choice(artworks) + + class ImageManipulations(PropertySetter): def get_infolabel(self, info): return get_infolabel(f'ListItem.{info}') @@ -361,48 +449,16 @@ def get_artwork(self, source='', build_fallback=False, built_artwork=None): source = source or '' source = source.lower() - def _get_artwork_infolabel(_infolabels): - for i in _infolabels: - artwork = self.get_infolabel(i) - if not artwork: - continue - return artwork - - def _get_artwork_fallback(_infolabels, _built_artwork): - for i in _infolabels: - if not i.startswith('art('): - continue - artwork = _built_artwork.get(i[4:-1]) - if not artwork: - continue - return artwork - - def _get_artwork(_source): - if _source: - _infolabels = ARTWORK_LOOKUP_TABLE.get(_source, _source.split("|")) - else: - _infolabels = ARTWORK_LOOKUP_TABLE.get('thumb') - - artwork = _get_artwork_infolabel(_infolabels) - - if artwork or not build_fallback: - return artwork - - nonlocal built_artwork - - built_artwork = built_artwork or self.get_builtartwork() - if not built_artwork: - return - - return _get_artwork_fallback(_infolabels, built_artwork) - for _source in source.split("||"): - artwork = _get_artwork(_source) - if not artwork: + img_get = ImageArtworkGetter(self, _source, prebuilt_artwork=built_artwork) + if img_get.artwork: + return img_get.artwork + if not build_fallback or not img_get.built_artwork: continue - return artwork + if img_get.artwork_fallback: + return img_get.artwork_fallback - def get_image_manipulations(self, use_winprops=False, built_artwork=None): + def get_image_manipulations(self, use_winprops=False, built_artwork=None, allow_list=('crop', 'blur', 'desaturate', 'colors', )): images = {} _manipulations = ( @@ -435,6 +491,8 @@ def get_image_manipulations(self, use_winprops=False, built_artwork=None): or self.get_property('Colors.Fallback')},) for i in _manipulations: + if i['method'] not in allow_list: + continue if not i['active'](): continue imgfunc = ImageFunctions(method=i['method'], is_thread=False, artwork=i['images']()) diff --git a/resources/tmdbhelper/lib/monitor/imgmon.py b/resources/tmdbhelper/lib/monitor/imgmon.py index 59ab7f28..32077e81 100644 --- a/resources/tmdbhelper/lib/monitor/imgmon.py +++ b/resources/tmdbhelper/lib/monitor/imgmon.py @@ -12,16 +12,22 @@ class ImagesMonitor(Thread, ListItemInfoGetter, ImageManipulations, Poller): "!Skin.HasSetting(TMDbHelper.EnableDesaturate) + " "!Skin.HasSetting(TMDbHelper.EnableColors)") + _allow_list = ('crop', 'blur', 'desaturate', 'colors', ) + idle_cycles = 10 / POLL_MIN_INCREMENT # Reupdate idle item every ten seconds for extrafanart TODO: Allow skin to set value? + def __init__(self, parent): Thread.__init__(self) self._cur_item = 0 self._pre_item = 1 self._cur_window = 0 self._pre_window = 1 + self._idle_cycle = 0 self.exit = False self.update_monitor = parent.update_monitor self.crop_image_cur = None self.blur_image_cur = None + self.remote_artwork = {} + self.added_artworks = {} self._allow_on_scroll = True # Allow updating while scrolling self._parent = parent @@ -29,9 +35,22 @@ def __init__(self, parent): def on_listitem(self): with self._parent.mutex_lock: self.setup_current_container() - if self.is_same_item(update=True): + if self.is_same_item(update=True) and self._idle_cycle < self.idle_cycles: + self._idle_cycle += 1 return - self.get_image_manipulations(use_winprops=True) + self._idle_cycle = 0 + self.update_artwork() + + def get_allow_list(self, check_set=False): + if not check_set: + return self._allow_list + return [k for k in self._allow_list if not self.get_property(f'ListItem.{k}Image')] + + def update_artwork(self, check_set=False): + self.added_artworks[self._pre_item] = self.get_image_manipulations( + use_winprops=True, + built_artwork=self.remote_artwork.get(self._pre_item), + allow_list=self.get_allow_list(check_set=check_set)) def _on_listitem(self): self.on_listitem() diff --git a/resources/tmdbhelper/lib/monitor/listitemtools.py b/resources/tmdbhelper/lib/monitor/listitemtools.py index e74b76ba..9995545c 100644 --- a/resources/tmdbhelper/lib/monitor/listitemtools.py +++ b/resources/tmdbhelper/lib/monitor/listitemtools.py @@ -2,7 +2,7 @@ from tmdbhelper.lib.addon.plugin import get_infolabel, get_condvisibility, get_localized, get_setting, get_skindir from tmdbhelper.lib.addon.logger import kodi_try_except from jurialmunkey.window import get_property, get_current_window -from tmdbhelper.lib.monitor.common import CommonMonitorFunctions, SETMAIN_ARTWORK, SETPROP_RATINGS +from tmdbhelper.lib.monitor.common import CommonMonitorFunctions, SETMAIN_ARTWORK, SETPROP_RATINGS, SETMAIN_ALTERED from tmdbhelper.lib.monitor.itemdetails import ListItemDetails from tmdbhelper.lib.monitor.readahead import ListItemReadAhead, READAHEAD_CHANGED from tmdbhelper.lib.monitor.baseitem import BaseItemSkinDefaults @@ -264,13 +264,14 @@ def on_finalise_winproperties(self, process_artwork=True, process_ratings=True): # Proces artwork in a thread def _process_artwork(): _artwork = _item.get_builtartwork() - _artwork.update(_item.get_image_manipulations(built_artwork=_artwork, use_winprops=False)) _artwork_properties = set() + if _pre_item != self.cur_item: + return + with self._parent.mutex_lock: - if _pre_item != self.cur_item: - return - self._parent.images_monitor._pre_item = _pre_item + self._parent.images_monitor.remote_artwork[_pre_item] = _artwork.copy() + self._parent.images_monitor.update_artwork(check_set=True) self.set_iter_properties(_artwork, SETMAIN_ARTWORK, property_object=_artwork_properties) self.clear_property_list(SETMAIN_ARTWORK.difference(_artwork_properties)) diff --git a/resources/tmdbhelper/lib/monitor/player.py b/resources/tmdbhelper/lib/monitor/player.py index 4e4927e0..aa8cf349 100644 --- a/resources/tmdbhelper/lib/monitor/player.py +++ b/resources/tmdbhelper/lib/monitor/player.py @@ -1,7 +1,7 @@ from xbmc import Player from jurialmunkey.parser import boolean from jurialmunkey.window import get_property -from tmdbhelper.lib.monitor.common import CommonMonitorFunctions, SETPROP_RATINGS, SETMAIN_ARTWORK +from tmdbhelper.lib.monitor.common import CommonMonitorFunctions, SETPROP_RATINGS, SETMAIN_ARTWORK, SETMAIN_ALTERED from tmdbhelper.lib.addon.plugin import get_condvisibility, get_infolabel @@ -138,6 +138,7 @@ def get_playingitem(self): self.properties.add('CropImage') self.properties.add('CropImage.Original') self.set_iter_properties(self.details.get('art', {}), SETMAIN_ARTWORK) + self.set_iter_properties(self.details.get('art', {}), SETMAIN_ALTERED) self.set_properties(self.details)