Timers: LTC timecode via the stage-display websocket

ProPresenter's HTTP API has no timecode route (verified: 21.4 returns
404), but its classic stage-display websocket still answers — so LTC now
comes from a stage layout field labeled "LTC": a zero-dependency RFC6455
client (stage-ws.js) authenticates (new stagePassword admin config),
resolves the LTC-labeled frame's uid from the layout list, and treats any
message carrying that uid as the timecode text. "Receiving" is a 2.5s
staleness heuristic; frozen or placeholder text reads as no-signal. The
HTTP probe stays authoritative when it ever answers (a 404 verdict is
retried once a minute), and the LTC card surfaces the reason when
timecode is unavailable (bad stage password, no LTC field). pp-timers-mock
grows a /stagedisplay websocket with --stage-pwd and --no-ltc-field to
exercise every path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Waters Church
2026-08-31 17:05:23 -04:00
co-authored by Claude Fable 5
parent f80790e3a1
commit 444f03938d
7 changed files with 551 additions and 15 deletions
+3 -1
View File
@@ -210,7 +210,9 @@ export default function create({ root, moduleApi }) {
if (ltc.supported === false) {
mode = 'unavailable';
card.timeEl.textContent = '—';
card.stateEl.textContent = 'Timecode not available on this ProPresenter';
// The server says why when it knows (stage password rejected, no
// stage field labeled LTC, …) — 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);