Timers: LTC is listener-only; admin switch, device/channel, grouped settings
Simplify LTC to its one working source — the built-in audio listener — and make the admin UI reflect it. Module: - Remove the stage-display websocket source (stage-ws.js, stagePassword) and the /v1/timecode/status API probe — both dead on ProPresenter 21.4. - Remove the remote-reader ingest (POST /ltc, ingestToken, tools/ ltc-reader.js): the module owns LTC end to end now. The decoder selftest moves to modules/propresenter-timers/ltc.selftest.js so the engine stays covered. - composeLtc collapses to the listener: running/stopped/nosignal, or a clear note when disabled / no device / capture failed / starting. - Manifest: ltcEnabled is now a `switch`; ltcDevice and ltcChannel carry showWhen:"ltcEnabled"; ProPresenter and LTC fields carry `group` labels. Shell (admin) — backward-compatible additions, coordinate with the shell lane: - New `switch` field type (boolean shown as the enable-toggle control). - `group`: consecutive fields render under a labeled subsection. - `showWhen: "<key>"`: a field is shown only while that boolean/switch is on (and actually collapses — .field[hidden] override, since .field's display:flex outranks the [hidden] UA default). - applyConfigPatch coerces `switch` as boolean. Documented in MODULE-GUIDE. Verified: engine selftest (29 checks); listener decodes BlackHole loopback (running 30fps, ageMs); device picker lists inputs; POST /ltc now 404s; admin shows two labeled groups, the switch, and device/channel appearing only when the switch is on (computed display none↔flex confirmed). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
7e75146838
commit
1d46657e06
@@ -262,9 +262,8 @@ export default function create({ root, moduleApi }) {
|
||||
|
||||
function updateLtcAnchor() {
|
||||
const l = state?.ltc;
|
||||
// Only the audio sources are extrapolatable — they know the frame rate.
|
||||
const live = l && l.status === 'running' && l.fps > 0
|
||||
&& (l.source === 'listener' || l.source === 'reader');
|
||||
// The listener is extrapolatable — it knows the frame rate.
|
||||
const live = l && l.status === 'running' && l.fps > 0 && l.source === 'listener';
|
||||
const tc = live ? parseTc(l.time) : null;
|
||||
if (!tc) {
|
||||
ltcAnchor = null;
|
||||
@@ -323,14 +322,9 @@ export default function create({ root, moduleApi }) {
|
||||
if (ltc.supported === false) {
|
||||
mode = 'unavailable';
|
||||
card.timeEl.textContent = '—';
|
||||
// The server says why when it knows (stage password rejected, no
|
||||
// stage field labeled LTC, reader offline, …) — surface that over
|
||||
// the generic line.
|
||||
card.stateEl.textContent = ltc.note || 'Timecode not available on this ProPresenter';
|
||||
} else if (ltc.supported === null) {
|
||||
mode = 'waiting';
|
||||
card.timeEl.textContent = displayTime(ltc.time);
|
||||
card.stateEl.textContent = 'Waiting for ProPresenter…';
|
||||
// The server says why when it knows (listener disabled, no device
|
||||
// selected, capture failed, starting up…) — surface that.
|
||||
card.stateEl.textContent = ltc.note || 'LTC not available';
|
||||
} else if (ltc.receiving) {
|
||||
mode = 'receiving';
|
||||
// With an anchor active, paint the frame it implies for now (this
|
||||
@@ -350,10 +344,9 @@ export default function create({ root, moduleApi }) {
|
||||
card.timeEl.textContent = '—';
|
||||
card.stateEl.textContent = 'No signal';
|
||||
}
|
||||
// The built-in listener and the remote reader are independent of
|
||||
// ProPresenter, so their card must not gray out with the rest when
|
||||
// only ProPresenter is unreachable.
|
||||
const live = ltc.source === 'reader' || ltc.source === 'listener' ? ' src-reader' : '';
|
||||
// The built-in listener is independent of ProPresenter, so its card
|
||||
// must not gray out with the rest when only ProPresenter is unreachable.
|
||||
const live = ltc.source === 'listener' ? ' src-reader' : '';
|
||||
card.el.className = `tm-card tm-card-ltc is-ltc-${mode}${live}`;
|
||||
}
|
||||
|
||||
@@ -377,7 +370,7 @@ export default function create({ root, moduleApi }) {
|
||||
}
|
||||
if (!state.enabled) {
|
||||
bannerEl.hidden = true;
|
||||
// The LTC listener/reader feed us with or without ProPresenter — an
|
||||
// The LTC listener feeds us with or without ProPresenter — an
|
||||
// LTC-only setup is working, not broken.
|
||||
if (state.ltc?.supported) moduleApi.setStatus('ok', 'LTC only — no ProPresenter host configured');
|
||||
else moduleApi.setStatus('error', 'No ProPresenter host configured — set one in Admin');
|
||||
|
||||
Reference in New Issue
Block a user