Skip to content

fix(video): a cue aimed at an output the node doesn't drive stays dark (869fgq3xv) - #33

Merged
ibiltari merged 2 commits into
rc_1from
fix/869fgq3xv-unrouted-video-output
Oct 13, 2026
Merged

ibiltari merged 2 commits into
rc_1from
fix/869fgq3xv-unrouted-video-output

Conversation

@ibiltari

Copy link
Copy Markdown
Member

ClickUp: 869fgq3xv · Plan: cuems-RELATIONS/Plans/2026-10-13-engine-video-cue-unrouted-output.md (reviewed by Sonnet; decisions D1–D6 by Ion)

Problem

A video cue pointing at an output this node does not drive was loaded anyway. That covers an output dropped at node start (DISPLAY_MISMATCH, no region in display.conf), one with enabled=false, or a custom_<n> with no VideoCueOutput. With no position/scale, the videocomposer letterboxed the layer onto the whole canvas, so the content appeared on the screens that do work. The only trace was a "position/scale NOT applied" line.

Change (node engine only, log only)

  • PlayerHandler.partition_cue_outputs splits a cue's outputs into routed and unrouted. The arm and the load-time preflight both use it, so they cannot disagree. Any resolver exception counts as unrouted; nothing escapes arm_videoCue any more.
  • arm_videoCue loads routed outputs only.
    • The shared-decoder driver is the first routed layer.
    • Layer ids keep the output's index (<cue>_<i>).
    • cue._layer_outputs records layer → output.
    • A cue with every output dark still arms, so it doesn't hold the GO gate and doesn't trigger the GO fallback re-arm.
    • The error is logged once per load, then at DEBUG.
  • run_videoCue stamps _start_mtc/_end_mtc before its layer check, so a dark cue keeps its place on the timeline. Before this, zero timecodes made a go_at_end follow fire at start + postwait cluster-wide, and made an infinite loop re-base in a tight loop. Layers now map to outputs by id, not by position.
  • read_display_conf drops a section whose enabled= is anything but true/1, even when it keeps its canvas_region. It parses the way DisplayConfigurationManager::loadFromFile does: no trimming, last line wins. Repeated keys no longer raise.
  • NodeEngine.check_unrouted_video_outputs logs UNROUTED_VIDEO_OUTPUT per dark cue at each load, before anything arms. It runs in _load_project_inner, not ready_project, because ready_project is also the mid-show deploy command.

Behaviour change on upgrade: a box whose journal shows DISPLAY_MISMATCH, or that has an enabled=false section with a region, goes from mis-placed video to dark for the cues aimed there. This reverses 869f8hfra's "no output match still plays". A resolved output whose placement send fails still plays.

Out of scope:

  • The engine still reads display.conf only at node start. After a hand edit, restart the videocomposer and the node engine.
  • Nothing is reported to the UI; that waits for the display configuration manager.
  • No message between processes changes.

Tests

  • New: tests/test_video_unrouted_output.py and more cases in tests/test_display_conf.py.
  • The 869f8hfra placement tests now inject their failure at the apply step.
  • Red on rc_1 (12 failed, 26 errors). Green on test2: full suite 1334 passed.
  • black / isort / flake8 clean.

Not yet verified on a rig. §6 of the plan, on the test cluster, is still owed.

…k (869fgq3xv)

A video cue pointing at an output this node does not drive (dropped at
start with DISPLAY_MISMATCH, disabled in display.conf, or a custom region
with no VideoCueOutput) was loaded anyway. With no position/scale the
videocomposer letterboxed it onto the whole canvas, i.e. onto the screens
that do work: content on the wrong screens, and only "NOT applied" in the
journal.

- PlayerHandler.partition_cue_outputs splits a cue's outputs into routed
  and unrouted, for both the arm and the load-time preflight. Any resolver
  error counts as unrouted; nothing escapes the arm.
- arm_videoCue loads routed outputs only. The shared-decoder driver is
  the first routed layer; layer ids keep the output's index; the arm
  records layer -> output in cue._layer_outputs. A cue with every output
  dark still arms (no GO-gate hold, no fallback re-arm). The error is
  logged once per load, then at DEBUG.
- run_videoCue stamps _start_mtc/_end_mtc before its layer check, so a
  dark cue keeps its place on the timeline: with zero timecodes a
  go_at_end follow fired at start + postwait cluster-wide and an infinite
  loop re-based in a tight loop. Layers map to outputs by id, not by
  position.
- read_display_conf drops outputs with enabled=<not true/1>, read the way
  the videocomposer reads it, so the engine's outputs and canvas match.
  Repeated keys no longer raise.
- NodeEngine.check_unrouted_video_outputs logs UNROUTED_VIDEO_OUTPUT per
  dark cue at each load, before anything arms (not in ready_project,
  which is also the mid-show `deploy` command).

Reverses 869f8hfra's "no output match still plays" (Ion, 2026-10-13); a
resolved output whose placement send fails still plays. Log only: the UI
waits for the display configuration manager.

Tests: test_video_unrouted_output.py (new), test_display_conf.py; the
869f8hfra placement tests now inject at the apply step. Red on rc_1
(12 failed, 26 errors), green on test2: full suite 1334 passed.
@ibiltari
ibiltari requested a review from backenv as a code owner October 13, 2026 18:57
@ibiltari
ibiltari merged commit 93d5a2c into rc_1 Oct 13, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant