Fix nonlocal scoping in CSS processing, move brightness source emoji to dropdown items

Add nonlocal declarations for _u16_a, _u16_b, _i32 in nested functions
_blend_u16 and _apply_corrections — Python treats augmented assignments
(*=, +=, >>=) as local variable bindings, causing UnboundLocalError
that prevented any frames from being sent to devices.

Move 🔢 emoji from brightness source label to dropdown option items.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-25 01:34:35 +03:00
parent 359f33fdbb
commit 16f29bee30
5 changed files with 8 additions and 10 deletions

View File

@@ -305,6 +305,7 @@ class PictureColorStripStream(ColorStripStream):
Uses pre-allocated uint16 scratch buffers (_u16_a, _u16_b). Uses pre-allocated uint16 scratch buffers (_u16_a, _u16_b).
""" """
nonlocal _u16_a, _u16_b
np.copyto(_u16_a, a, casting='unsafe') np.copyto(_u16_a, a, casting='unsafe')
np.copyto(_u16_b, b, casting='unsafe') np.copyto(_u16_b, b, casting='unsafe')
_u16_a *= (256 - alpha_b) _u16_a *= (256 - alpha_b)
@@ -318,6 +319,7 @@ class PictureColorStripStream(ColorStripStream):
Returns the (possibly reassigned) led_colors array. Returns the (possibly reassigned) led_colors array.
""" """
nonlocal _i32
if self._saturation != 1.0: if self._saturation != 1.0:
_apply_saturation(led_colors, self._saturation, _i32, _i32_gray, led_colors) _apply_saturation(led_colors, self._saturation, _i32, _i32_gray, led_colors)
if self._gamma != 1.0: if self._gamma != 1.0:

View File

@@ -363,11 +363,9 @@ function _populateKCBrightnessVsDropdown(selectedId = '') {
// Keep the first "None" option, remove the rest // Keep the first "None" option, remove the rest
while (sel.options.length > 1) sel.remove(1); while (sel.options.length > 1) sel.remove(1);
_cachedValueSources.forEach(vs => { _cachedValueSources.forEach(vs => {
const typeIcons = { static: '📊', animated: '🔄', audio: '🎵' };
const icon = typeIcons[vs.source_type] || '🔢';
const opt = document.createElement('option'); const opt = document.createElement('option');
opt.value = vs.id; opt.value = vs.id;
opt.textContent = `${icon} ${vs.name}`; opt.textContent = `🔢 ${vs.name}`;
sel.appendChild(opt); sel.appendChild(opt);
}); });
sel.value = selectedId || ''; sel.value = selectedId || '';

View File

@@ -184,9 +184,7 @@ function _populateBrightnessVsDropdown(selectedId = '') {
const select = document.getElementById('target-editor-brightness-vs'); const select = document.getElementById('target-editor-brightness-vs');
let html = `<option value="">${t('targets.brightness_vs.none')}</option>`; let html = `<option value="">${t('targets.brightness_vs.none')}</option>`;
_cachedValueSources.forEach(vs => { _cachedValueSources.forEach(vs => {
const typeIcons = { static: '📊', animated: '🔄', audio: '🎵' }; html += `<option value="${vs.id}"${vs.id === selectedId ? ' selected' : ''}>🔢 ${escapeHtml(vs.name)}</option>`;
const icon = typeIcons[vs.source_type] || '🎚️';
html += `<option value="${vs.id}"${vs.id === selectedId ? ' selected' : ''}>${icon} ${escapeHtml(vs.name)}</option>`;
}); });
select.innerHTML = html; select.innerHTML = html;
} }

View File

@@ -431,7 +431,7 @@
"kc.pattern_template": "Pattern Template:", "kc.pattern_template": "Pattern Template:",
"kc.pattern_template.hint": "Select the rectangle pattern to use for color extraction", "kc.pattern_template.hint": "Select the rectangle pattern to use for color extraction",
"kc.pattern_template.none": "-- Select a pattern template --", "kc.pattern_template.none": "-- Select a pattern template --",
"kc.brightness_vs": "🔢 Brightness Source:", "kc.brightness_vs": "Brightness Source:",
"kc.brightness_vs.hint": "Optional value source that dynamically controls brightness each frame (multiplied with the manual brightness slider)", "kc.brightness_vs.hint": "Optional value source that dynamically controls brightness each frame (multiplied with the manual brightness slider)",
"kc.brightness_vs.none": "None (manual brightness only)", "kc.brightness_vs.none": "None (manual brightness only)",
"kc.created": "Key colors target created successfully", "kc.created": "Key colors target created successfully",
@@ -847,7 +847,7 @@
"value_source.deleted": "Value source deleted", "value_source.deleted": "Value source deleted",
"value_source.delete.confirm": "Are you sure you want to delete this value source?", "value_source.delete.confirm": "Are you sure you want to delete this value source?",
"value_source.error.name_required": "Please enter a name", "value_source.error.name_required": "Please enter a name",
"targets.brightness_vs": "🔢 Brightness Source:", "targets.brightness_vs": "Brightness Source:",
"targets.brightness_vs.hint": "Optional value source that dynamically controls brightness each frame (overrides device brightness)", "targets.brightness_vs.hint": "Optional value source that dynamically controls brightness each frame (overrides device brightness)",
"targets.brightness_vs.none": "None (device brightness)" "targets.brightness_vs.none": "None (device brightness)"
} }

View File

@@ -431,7 +431,7 @@
"kc.pattern_template": "Шаблон Паттерна:", "kc.pattern_template": "Шаблон Паттерна:",
"kc.pattern_template.hint": "Выберите шаблон прямоугольников для извлечения цветов", "kc.pattern_template.hint": "Выберите шаблон прямоугольников для извлечения цветов",
"kc.pattern_template.none": "-- Выберите шаблон паттерна --", "kc.pattern_template.none": "-- Выберите шаблон паттерна --",
"kc.brightness_vs": "🔢 Источник Яркости:", "kc.brightness_vs": "Источник Яркости:",
"kc.brightness_vs.hint": "Опциональный источник значений, динамически управляющий яркостью каждый кадр (умножается на ручной слайдер яркости)", "kc.brightness_vs.hint": "Опциональный источник значений, динамически управляющий яркостью каждый кадр (умножается на ручной слайдер яркости)",
"kc.brightness_vs.none": "Нет (только ручная яркость)", "kc.brightness_vs.none": "Нет (только ручная яркость)",
"kc.created": "Цель ключевых цветов успешно создана", "kc.created": "Цель ключевых цветов успешно создана",
@@ -847,7 +847,7 @@
"value_source.deleted": "Источник значений удалён", "value_source.deleted": "Источник значений удалён",
"value_source.delete.confirm": "Удалить этот источник значений?", "value_source.delete.confirm": "Удалить этот источник значений?",
"value_source.error.name_required": "Введите название", "value_source.error.name_required": "Введите название",
"targets.brightness_vs": "🔢 Источник яркости:", "targets.brightness_vs": "Источник яркости:",
"targets.brightness_vs.hint": "Необязательный источник значений для динамического управления яркостью каждый кадр (переопределяет яркость устройства)", "targets.brightness_vs.hint": "Необязательный источник значений для динамического управления яркостью каждый кадр (переопределяет яркость устройства)",
"targets.brightness_vs.none": "Нет (яркость устройства)" "targets.brightness_vs.none": "Нет (яркость устройства)"
} }