From b61a6f3216ed24ba0e7c4f7e69f6dd79a6a23eff Mon Sep 17 00:00:00 2001 From: "Alexander G. Morano" Date: Sun, 8 Sep 2024 22:57:39 -0700 Subject: [PATCH] doubled speed of midi reader when idle cleaned up HTML templates for GLSL nodes --- __init__.py | 6 +++--- core/device_midi.py | 7 ++++++- node_list.json | 2 +- res/doc/template_node.html | 4 ++-- res/doc/template_node_plain.html | 2 +- res/glsl/create/create-palette.frag | 2 +- sup/midi.py | 20 ++++++++++++++------ sup/shader.py | 13 ++++++------- web/jovimetrix.css | 13 ++++--------- 9 files changed, 38 insertions(+), 31 deletions(-) diff --git a/__init__.py b/__init__.py index 810eec3..19bb8b0 100644 --- a/__init__.py +++ b/__init__.py @@ -598,8 +598,8 @@ def json2html(json_dict: dict) -> str: # Fill in the main template description = json_dict['description'] - if not "
" in description and not "

" in description: - description = markdown.markdown(description) + #if not "

" in description and not "

" in description: + #description = markdown.markdown(description) # description = html.escape(description) description = description.replace('\n', '
').replace(f"('", '').replace(f"')", '') @@ -1010,7 +1010,7 @@ def __init__(self, *arg, **kw) -> None: Session.CLASS_MAPPINGS[name] = class_object if not name.endswith(Lexicon.GLSL_CUSTOM): - desc = class_object.DESCRIPTION if hasattr(class_object, 'DESCRIPTION') else "" + desc = class_object.DESCRIPTION if hasattr(class_object, 'DESCRIPTION') else name NODE_LIST_MAP[name] = desc.split('.')[0].strip('\n') else: logger.debug(f"customs {name}") diff --git a/core/device_midi.py b/core/device_midi.py index 3301fea..a5c599a 100644 --- a/core/device_midi.py +++ b/core/device_midi.py @@ -71,6 +71,8 @@ class MIDIReaderNode(JOVBaseNode): Captures MIDI messages from an external MIDI device or controller. It monitors MIDI input and provides information about the received MIDI messages, including whether a note is being played, the MIDI channel, control number, note number, value, and a normalized value. This node is essential for integrating MIDI control into various applications, such as music production, live performances, and interactive installations. """ + CHANGED = False + @classmethod def INPUT_TYPES(cls) -> dict: d = super().INPUT_TYPES() @@ -83,7 +85,9 @@ def INPUT_TYPES(cls) -> dict: @classmethod def IS_CHANGED(cls, **kw) -> float: - return float("nan") + if cls.CHANGED: + cls.CHANGED = False + return float("nan") def __init__(self, *arg, **kw) -> None: super().__init__(*arg, **kw) @@ -98,6 +102,7 @@ def __init__(self, *arg, **kw) -> None: self.__SERVER.start() def __process(self, data) -> None: + MIDIReaderNode.CHANGED = True self.__channel = data.channel self.__note = 0 self.__control = 0 diff --git a/node_list.json b/node_list.json index 25a8d00..f5a1882 100644 --- a/node_list.json +++ b/node_list.json @@ -16,7 +16,7 @@ "GLSL (JOV) \ud83c\udf69": "Execute custom GLSL (OpenGL Shading Language) fragment shaders to generate images or apply effects", "GLSL BLEND LINEAR (JOV) \ud83e\uddd9\ud83c\udffd": "Simple linear blend between two images", "GLSL COLOR CONVERSION (JOV) \ud83e\uddd9\ud83c\udffd": "Convert an image from one color space (RGB, HSV, LAB, XYZ) to another", - "GLSL COLOR PALETTE (JOV) \ud83e\uddd9\ud83c\udffd": "COLOR PALETTE", + "GLSL COLOR PALETTE (JOV) \ud83e\uddd9\ud83c\udffd": "Color palette creation using the formula: color(t) = a + b * cos[tau(c*t+d)]", "GLSL CONICAL GRADIENT (JOV) \ud83e\uddd9\ud83c\udffd": "Generate a conical gradient from black to white", "GLSL DIRECTIONAL WARP (JOV) \ud83e\uddd9\ud83c\udffd": "Domain warp an image with a direction and distortion map", "GLSL GRAYSCALE (JOV) \ud83e\uddd9\ud83c\udffd": "Convert input to grayscale", diff --git a/res/doc/template_node.html b/res/doc/template_node.html index 875d721..4d5f297 100644 --- a/res/doc/template_node.html +++ b/res/doc/template_node.html @@ -8,8 +8,8 @@

${name}

${category}

-

${documentation}

- ${boop} +

${documentation}

+
${boop}

OUTPUT NODE?: ${output_node}

INPUT

${input_content} diff --git a/res/doc/template_node_plain.html b/res/doc/template_node_plain.html index 2b86fa7..2fc7306 100644 --- a/res/doc/template_node_plain.html +++ b/res/doc/template_node_plain.html @@ -8,7 +8,7 @@

${name}

${category}

-

${documentation}

+

${documentation}

OUTPUT NODE?: ${output_node}

INPUT

${input_content} diff --git a/res/glsl/create/create-palette.frag b/res/glsl/create/create-palette.frag index 672c3f7..c7199b6 100644 --- a/res/glsl/create/create-palette.frag +++ b/res/glsl/create/create-palette.frag @@ -6,7 +6,7 @@ // See https://iquilezles.org/articles/palettes for more information // // name: COLOR PALETTE -// desc: Color palette creation using the formula: color(t) = a + b ⋅ cos[2π(c⋅t+d)] +// desc: Color palette creation using the formula: color(t) = a + b * cos[tau(c*t+d)]. See https://iquilezles.org/articles/palettes for more information. // category: CREATE uniform vec3 bias; // 0.5,0.5,0.5;0 | scale and bias (dc offset) diff --git a/sup/midi.py b/sup/midi.py index d1161b4..1863484 100644 --- a/sup/midi.py +++ b/sup/midi.py @@ -82,12 +82,20 @@ def run(self) -> None: # device is not null.... logger.debug(f"starting device loop {self.__device}") - with mido.open_input(self.__device, callback=self.__callback): - while True: - if self.__device != old_device: - logger.debug(f"device loop ended {old_device}") - break - time.sleep(0.01) + failure = 0 + try: + with mido.open_input(self.__device, callback=self.__callback): + while True: + if self.__device != old_device: + logger.debug(f"device loop ended {old_device}") + break + time.sleep(0.01) + except Exception as e: + if (failure := failure + 1) > 3: + logger.exception(e) + return + logger.error(e) + time.sleep(2) class MIDIMessage: """Snap shot of a message from Midi device.""" diff --git a/sup/shader.py b/sup/shader.py index a906a28..9768b7f 100644 --- a/sup/shader.py +++ b/sup/shader.py @@ -6,8 +6,8 @@ """ import re -from enum import Enum import sys +from enum import Enum, EnumType from typing import Any, Dict, Tuple import cv2 @@ -72,7 +72,7 @@ class EnumGLSLColorConvert(Enum): RE_VARIABLE = re.compile(r"uniform\s+(\w+)\s+(\w+);(?:\s*\/\/\s*([A-Za-z0-9.,\s]*))?\s*(?:;\s*([0-9.-]+))?\s*(?:;\s*([0-9.-]+))?\s*(?:;\s*([0-9.-]+))?\s*(?:\|\s*(.*))?$", re.MULTILINE) -RE_SHADER_META = re.compile(r"^\/\/\s?([A-Za-z_]{3,}):\s?([A-Za-z_0-9 \-\(\)\[\]\/\.\,;]+)$", re.MULTILINE) +RE_SHADER_META = re.compile(r"^\/\/\s?([A-Za-z_]{3,}):\s?(.+)$", re.MULTILINE) # ============================================================================= @@ -442,12 +442,11 @@ def render(self, time_delta:float=0., texture_index += 1 elif val: funct = LAMBDA_UNIFORM[p_type] - if issubclass(p_value, (Enum,)): + if isinstance(p_value, EnumType): val = p_value[val].value - else: - if isinstance(val, str): - val = val.split(',') - val = parse_value(val, PTYPE[p_type], 0) + elif isinstance(val, str): + val = val.split(',') + val = parse_value(val, PTYPE[p_type], 0) if not isinstance(val, (list, tuple)): val = [val] funct(p_loc, *val) diff --git a/web/jovimetrix.css b/web/jovimetrix.css index 7e7fa75..5e94a8b 100644 --- a/web/jovimetrix.css +++ b/web/jovimetrix.css @@ -155,18 +155,13 @@ .jov-panel-doc { background: var(--comfy-menu-bg); color: var(--fg-color); - font: 12px monospace; - padding: 3px; - margin: 3px; - border-radius: 5px; + font: 0.9em monospace; + border-radius: 3px; border: medium solid var(--border-color); overflow: auto; width: 100%; height: 90vh; box-sizing: border-box; - display: flex; - flex-direction: column; - align-items: center; scrollbar-width: thin; scrollbar-color: var(--fg-color) var(--bg-color); } @@ -174,7 +169,7 @@ .jov-panel-doc h2, .jov-panel-doc h3 { width: 100%; text-align: center; - margin: 4px 0; + margin: 3px 0; } .jov-panel-doc p { @@ -185,7 +180,7 @@ .jov-panel-doc img { display: block; - max-width: 640px; + max-width: 512px; max-height: 70vh; width: 100%; height: auto;