Remove target segments, use single color strip source per target

Segments are redundant now that the "mapped" CSS type handles spatial
multiplexing internally. Each target now references one color_strip_source_id
instead of an array of segments with start/end/reverse ranges.

Backward compat: existing targets with old segments format are migrated
on load by extracting the first segment's CSS source ID.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-24 00:00:26 +03:00
parent 9efb08acb6
commit 808037775f
14 changed files with 171 additions and 513 deletions

View File

@@ -32,7 +32,6 @@ from wled_controller.api.schemas.picture_targets import (
PictureTargetUpdate,
TargetMetricsResponse,
TargetProcessingState,
TargetSegmentSchema,
)
from wled_controller.config import get_config
from wled_controller.core.capture_engines import EngineRegistry
@@ -94,15 +93,7 @@ def _target_to_response(target) -> PictureTargetResponse:
name=target.name,
target_type=target.target_type,
device_id=target.device_id,
segments=[
TargetSegmentSchema(
color_strip_source_id=s.color_strip_source_id,
start=s.start,
end=s.end,
reverse=s.reverse,
)
for s in target.segments
],
color_strip_source_id=target.color_strip_source_id,
fps=target.fps,
keepalive_interval=target.keepalive_interval,
state_check_interval=target.state_check_interval,
@@ -157,7 +148,7 @@ async def create_target(
name=data.name,
target_type=data.target_type,
device_id=data.device_id,
segments=[s.model_dump() for s in data.segments] if data.segments else None,
color_strip_source_id=data.color_strip_source_id,
fps=data.fps,
keepalive_interval=data.keepalive_interval,
state_check_interval=data.state_check_interval,
@@ -267,12 +258,11 @@ async def update_target(
kc_settings = _kc_schema_to_settings(data.key_colors_settings)
# Update in store
segments_dicts = [s.model_dump() for s in data.segments] if data.segments is not None else None
target = target_store.update_target(
target_id=target_id,
name=data.name,
device_id=data.device_id,
segments=segments_dicts,
color_strip_source_id=data.color_strip_source_id,
fps=data.fps,
keepalive_interval=data.keepalive_interval,
state_check_interval=data.state_check_interval,
@@ -288,7 +278,7 @@ async def update_target(
data.keepalive_interval is not None or
data.state_check_interval is not None or
data.key_colors_settings is not None),
segments_changed=data.segments is not None,
css_changed=data.color_strip_source_id is not None,
device_changed=data.device_id is not None,
)
except ValueError:
@@ -756,9 +746,8 @@ async def start_target_overlay(
# can start even when processing is not currently running.
calibration = None
display_info = None
if isinstance(target, WledPictureTarget) and target.segments:
# Use the first segment's CSS for calibration/overlay
first_css_id = target.segments[0].color_strip_source_id
if isinstance(target, WledPictureTarget) and target.color_strip_source_id:
first_css_id = target.color_strip_source_id
if first_css_id:
try:
css = color_strip_store.get_source(first_css_id)