diff --git a/VERSION b/VERSION index 78bbcb84..141f7758 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.17.3-develop169 +1.17.3-develop170 diff --git a/defaults/overlays/languages.yml b/defaults/overlays/languages.yml index fabb20e2..83d933d6 100644 --- a/defaults/overlays/languages.yml +++ b/defaults/overlays/languages.yml @@ -30,16 +30,12 @@ external_templates: value: 26 - style: square value: - queue: - default: audio_flags - conditions: - - use_subtitles: true - value: subtitle_flags default: style: round country: <> country_<>: <> offset: 10 + queue: flags pmm: flag/<>/<>>> addon_position: <> addon_offset: <> @@ -51,8 +47,7 @@ external_templates: final_name: text(<>) queues: - audio_flags: &pos_data - + flags: default: vertical_align: top horizontal_offset: 15 @@ -69,7 +64,6 @@ queues: - vertical_offset: 137 - vertical_offset: 198 - vertical_offset: 259 - subtitle_flags: *pos_data templates: flags: diff --git a/modules/builder.py b/modules/builder.py index 30c07a77..b90e50cf 100644 --- a/modules/builder.py +++ b/modules/builder.py @@ -294,7 +294,7 @@ class CollectionBuilder: suppress = util.get_list(data[methods["suppress_overlays"]]) else: logger.error(f"Overlay Error: suppress_overlays attribute is blank") - self.overlay = Overlay(config, library, str(self.mapping_name), overlay_data, suppress, self.builder_level) + self.overlay = Overlay(config, library, metadata, str(self.mapping_name), overlay_data, suppress, self.builder_level) self.sync_to_users = None self.valid_users = [] diff --git a/modules/library.py b/modules/library.py index ac0717c0..2fed52da 100644 --- a/modules/library.py +++ b/modules/library.py @@ -18,7 +18,8 @@ class Library(ABC): self.Notifiarr = None self.collections = [] self.metadatas = [] - self.queue_names = [] + self.queues = {} + self.queue_current = 0 self.metadata_files = [] self.overlay_files = [] self.overlay_names = [] @@ -149,9 +150,11 @@ class Library(ABC): if not operations_only and not collection_only: for file_type, overlay_file, temp_vars, asset_directory in self.overlay_path: try: - overlay_obj = OverlayFile(self.config, self, file_type, overlay_file, temp_vars, asset_directory) + overlay_obj = OverlayFile(self.config, self, file_type, overlay_file, temp_vars, asset_directory, self.queue_current) self.overlay_files.append(overlay_obj) - self.queue_names.extend([q for q in overlay_obj.queues]) + for qk, qv in overlay_obj.queues.items(): + self.queues[self.queue_current] = qv + self.queue_current += 1 except Failed as e: logger.error(e) logger.info(f"Overlay File Failed To Load") diff --git a/modules/meta.py b/modules/meta.py index cafad07f..9dbada62 100644 --- a/modules/meta.py +++ b/modules/meta.py @@ -1496,7 +1496,7 @@ class PlaylistFile(DataFile): logger.info(f"Playlist File Loaded Successfully") class OverlayFile(DataFile): - def __init__(self, config, library, file_type, path, temp_vars, asset_directory): + def __init__(self, config, library, file_type, path, temp_vars, asset_directory, queue_current): super().__init__(config, file_type, path, temp_vars, asset_directory) self.library = library self.data_type = "Overlay" @@ -1508,11 +1508,10 @@ class OverlayFile(DataFile): self.templates = get_dict("templates", data) queues = get_dict("queues", data) self.queues = {} + self.queue_names = {} position = temp_vars["position"] if "position" in temp_vars and temp_vars["position"] else None for queue_name, queue in queues.items(): queue_position = temp_vars[f"position_{queue_name}"] if f"position_{queue_name}" in temp_vars and temp_vars[f"position_{queue_name}"] else position - if queue_name in library.queue_names and not queue_position: - continue initial_queue = None if queue_position and isinstance(queue_position, list): initial_queue = queue_position @@ -1548,9 +1547,10 @@ class OverlayFile(DataFile): for pk, pv in new_pos.items(): if pv is None: raise Failed(f"Config Error: queue missing {pv} attribute") - final_queue.append(new_pos) - - self.queues[queue_name] = final_queue + final_queue.append(util.parse_cords(new_pos, f"{queue_name} queue", required=True)) + self.queues[queue_current] = final_queue + self.queue_names[queue_name] = queue_current + queue_current += 1 self.external_templates(data, overlay=True) self.translation_files(data, overlay=True) if not self.overlays: diff --git a/modules/overlay.py b/modules/overlay.py index 09a34cee..bf05fbe2 100644 --- a/modules/overlay.py +++ b/modules/overlay.py @@ -55,60 +55,6 @@ vars_by_type = { "album": [f"{item}{m}" for check, sub in types_for_var.items() for item in sub for m in var_mods[item] if "album" in check], } -def parse_cords(data, parent, required=False): - horizontal_align = util.parse("Overlay", "horizontal_align", data["horizontal_align"], parent=parent, - options=["left", "center", "right"]) if "horizontal_align" in data else "left" - vertical_align = util.parse("Overlay", "vertical_align", data["vertical_align"], parent=parent, - options=["top", "center", "bottom"]) if "vertical_align" in data else "top" - - horizontal_offset = None - if "horizontal_offset" in data and data["horizontal_offset"] is not None: - x_off = data["horizontal_offset"] - per = False - if str(x_off).endswith("%"): - x_off = x_off[:-1] - per = True - x_off = util.check_num(x_off) - error = f"Overlay Error: {parent} horizontal_offset: {data['horizontal_offset']} must be a number" - if x_off is None: - raise Failed(error) - if horizontal_align != "center" and not per and x_off < 0: - raise Failed(f"{error} 0 or greater") - elif horizontal_align != "center" and per and (x_off > 100 or x_off < 0): - raise Failed(f"{error} between 0% and 100%") - elif horizontal_align == "center" and per and (x_off > 50 or x_off < -50): - raise Failed(f"{error} between -50% and 50%") - horizontal_offset = f"{x_off}%" if per else x_off - if horizontal_offset is None and horizontal_align == "center": - horizontal_offset = 0 - if required and horizontal_offset is None: - raise Failed(f"Overlay Error: {parent} horizontal_offset is required") - - vertical_offset = None - if "vertical_offset" in data and data["vertical_offset"] is not None: - y_off = data["vertical_offset"] - per = False - if str(y_off).endswith("%"): - y_off = y_off[:-1] - per = True - y_off = util.check_num(y_off) - error = f"Overlay Error: {parent} vertical_offset: {data['vertical_offset']} must be a number" - if y_off is None: - raise Failed(error) - if vertical_align != "center" and not per and y_off < 0: - raise Failed(f"{error} 0 or greater") - elif vertical_align != "center" and per and (y_off > 100 or y_off < 0): - raise Failed(f"{error} between 0% and 100%") - elif vertical_align == "center" and per and (y_off > 50 or y_off < -50): - raise Failed(f"{error} between -50% and 50%") - vertical_offset = f"{y_off}%" if per else y_off - if vertical_offset is None and vertical_align == "center": - vertical_offset = 0 - if required and vertical_offset is None: - raise Failed(f"Overlay Error: {parent} vertical_offset is required") - - return horizontal_align, horizontal_offset, vertical_align, vertical_offset - def get_canvas_size(item): if isinstance(item, Episode): return landscape_dim @@ -118,9 +64,10 @@ def get_canvas_size(item): return portrait_dim class Overlay: - def __init__(self, config, library, original_mapping_name, overlay_data, suppress, level): + def __init__(self, config, library, overlay_file, original_mapping_name, overlay_data, suppress, level): self.config = config self.library = library + self.overlay_file = overlay_file self.original_mapping_name = original_mapping_name self.data = overlay_data self.suppress = suppress @@ -136,6 +83,7 @@ class Overlay: self.square_box = None self.group = None self.queue = None + self.queue_name = None self.weight = None self.path = None self.font = None @@ -174,16 +122,19 @@ class Overlay: if "group" in self.data and self.data["group"]: self.group = str(self.data["group"]) if "queue" in self.data and self.data["queue"]: - self.queue = str(self.data["queue"]) + self.queue_name = str(self.data["queue"]) + if self.queue_name not in self.overlay_file.queue_names: + raise Failed(f"Overlay Error: queue: {self.queue_name} not found") + self.queue = self.overlay_file.queue_names[self.queue_name] if "weight" in self.data: self.weight = util.parse("Overlay", "weight", self.data["weight"], datatype="int", parent="overlay", minimum=0) if "group" in self.data and (self.weight is None or not self.group): raise Failed(f"Overlay Error: overlay attribute's group requires the weight attribute") - elif "queue" in self.data and (self.weight is None or not self.queue): + elif "queue" in self.data and (self.weight is None or not self.queue_name): raise Failed(f"Overlay Error: overlay attribute's queue requires the weight attribute") - elif self.group and self.queue: + elif self.group and self.queue_name: raise Failed(f"Overlay Error: overlay attribute's group and queue cannot be used together") - self.horizontal_align, self.horizontal_offset, self.vertical_align, self.vertical_offset = parse_cords(self.data, "overlay") + self.horizontal_align, self.horizontal_offset, self.vertical_align, self.vertical_offset = util.parse_cords(self.data, "overlay") if (self.horizontal_offset is None and self.vertical_offset is not None) or (self.vertical_offset is None and self.horizontal_offset is not None): raise Failed(f"Overlay Error: overlay attribute's horizontal_offset and vertical_offset must be used together") @@ -210,7 +161,7 @@ class Overlay: elif back_width >= 0 or back_height >= 0: self.back_box = (back_width, back_height) self.has_back = True if self.back_color or self.back_line_color else False - if self.name != "backdrop" and self.has_back and not self.has_coordinates() and not self.queue: + if self.name != "backdrop" and self.has_back and not self.has_coordinates() and not self.queue_name: raise Failed(f"Overlay Error: horizontal_offset and vertical_offset are required when using a backdrop") def get_and_save_image(image_url): @@ -264,7 +215,7 @@ class Overlay: logger.error(f"Overlay Error: failed to parse overlay blur name: {self.name} defaulting to blur(50)") self.name = "blur(50)" elif self.name.startswith("text"): - if not self.has_coordinates() and not self.queue: + if not self.has_coordinates() and not self.queue_name: raise Failed(f"Overlay Error: overlay attribute's horizontal_offset and vertical_offset are required when using text") if self.path: if not os.path.exists(self.path): diff --git a/modules/overlays.py b/modules/overlays.py index aaea1156..200be71b 100644 --- a/modules/overlays.py +++ b/modules/overlays.py @@ -24,10 +24,9 @@ class Overlays: os.makedirs(self.library.overlay_backup, exist_ok=True) key_to_overlays = {} - queues = {} properties = None if not self.library.remove_overlays: - key_to_overlays, properties, queues = self.compile_overlays() + key_to_overlays, properties = self.compile_overlays() ignore_list = [rk for rk in key_to_overlays] old_overlays = [la for la in self.library.Plex.listFilterChoices("label") if str(la.title).lower().endswith(" overlay")] @@ -95,7 +94,7 @@ class Overlays: blur_test = int(re.search("\\(([^)]+)\\)", current_overlay.name).group(1)) if blur_test > blur_num: blur_num = blur_test - elif current_overlay.queue: + elif current_overlay.queue_name: if current_overlay.queue not in queue_overlays: queue_overlays[current_overlay.queue] = {} if current_overlay.weight in queue_overlays[current_overlay.queue]: @@ -314,10 +313,7 @@ class Overlays: new_poster.paste(current_overlay.image, (0, 0), current_overlay.image) for queue, weights in queue_overlays.items(): - if queue not in queues: - logger.error(f"Overlay Error: no queue {queue} found") - continue - cords = queues[queue] + cords = self.library.queues[queue] sorted_weights = sorted(weights.items(), reverse=True) for o, cord in enumerate(cords): if len(sorted_weights) <= o: @@ -369,16 +365,8 @@ class Overlays: properties = {} overlay_groups = {} key_to_overlays = {} - queues = {} for overlay_file in self.library.overlay_files: - for k, v in overlay_file.queues.items(): - if not isinstance(v, list): - raise Failed(f"Overlay Error: Queue: {k} must be a list") - try: - queues[k] = [overlay.parse_cords(q, f"{k} queue", required=True) for q in v] - except Failed as e: - logger.error(e) for k, v in overlay_file.overlays.items(): try: builder = CollectionBuilder(self.config, overlay_file, k, v, library=self.library, overlay=True) @@ -478,7 +466,7 @@ class Overlays: for v in gv: if final != v: key_to_overlays[over_key][1].remove(v) - return key_to_overlays, properties, queues + return key_to_overlays, properties def find_poster_url(self, item): if isinstance(item, Movie): diff --git a/modules/util.py b/modules/util.py index b437c3a7..5c2ea471 100644 --- a/modules/util.py +++ b/modules/util.py @@ -775,6 +775,60 @@ def parse(error, attribute, data, datatype=None, methods=None, parent=None, defa logger.warning(f"{error} Warning: {message} using {default} as default") return translation[default] if translation is not None else default +def parse_cords(data, parent, required=False): + horizontal_align = parse("Overlay", "horizontal_align", data["horizontal_align"], parent=parent, + options=["left", "center", "right"]) if "horizontal_align" in data else "left" + vertical_align = parse("Overlay", "vertical_align", data["vertical_align"], parent=parent, + options=["top", "center", "bottom"]) if "vertical_align" in data else "top" + + horizontal_offset = None + if "horizontal_offset" in data and data["horizontal_offset"] is not None: + x_off = data["horizontal_offset"] + per = False + if str(x_off).endswith("%"): + x_off = x_off[:-1] + per = True + x_off = check_num(x_off) + error = f"Overlay Error: {parent} horizontal_offset: {data['horizontal_offset']} must be a number" + if x_off is None: + raise Failed(error) + if horizontal_align != "center" and not per and x_off < 0: + raise Failed(f"{error} 0 or greater") + elif horizontal_align != "center" and per and (x_off > 100 or x_off < 0): + raise Failed(f"{error} between 0% and 100%") + elif horizontal_align == "center" and per and (x_off > 50 or x_off < -50): + raise Failed(f"{error} between -50% and 50%") + horizontal_offset = f"{x_off}%" if per else x_off + if horizontal_offset is None and horizontal_align == "center": + horizontal_offset = 0 + if required and horizontal_offset is None: + raise Failed(f"Overlay Error: {parent} horizontal_offset is required") + + vertical_offset = None + if "vertical_offset" in data and data["vertical_offset"] is not None: + y_off = data["vertical_offset"] + per = False + if str(y_off).endswith("%"): + y_off = y_off[:-1] + per = True + y_off = check_num(y_off) + error = f"Overlay Error: {parent} vertical_offset: {data['vertical_offset']} must be a number" + if y_off is None: + raise Failed(error) + if vertical_align != "center" and not per and y_off < 0: + raise Failed(f"{error} 0 or greater") + elif vertical_align != "center" and per and (y_off > 100 or y_off < 0): + raise Failed(f"{error} between 0% and 100%") + elif vertical_align == "center" and per and (y_off > 50 or y_off < -50): + raise Failed(f"{error} between -50% and 50%") + vertical_offset = f"{y_off}%" if per else y_off + if vertical_offset is None and vertical_align == "center": + vertical_offset = 0 + if required and vertical_offset is None: + raise Failed(f"Overlay Error: {parent} vertical_offset is required") + + return horizontal_align, horizontal_offset, vertical_align, vertical_offset + def replace_label(_label, _data): replaced = False if isinstance(_data, dict):