ProPresenter reports running timers as truncated whole seconds, and the poller re-anchored the tiles' local count at the bottom of that second on every 500 ms poll — so the displayed digit ran up to a second ahead and got yanked back a step whenever a fresh poll sampled the next flip later than the last one did. Tiles flickered ...12:33 → 12:34 → 12:33... about once a second. phase.js turns the quantized reports into one stable anchor per timer: the only information in a poll is a FLIP (the report stepping one second in the direction of travel), which dates the true boundary to the midpoint of the two polls that straddle it. While reports stay consistent with the anchor (±450 ms) the anchor holds, so tiles count along one steady clock; a report the anchor can't explain (reset, seek, resume, accumulated drift) re-anchors. Timers carry the anchor as a per-timer asOf the client extrapolates from (optional in the provider contract, documented in the guide); the client additionally refuses to tick a running card backwards over sub-1.5 s jitter. phase.selftest.js (66 checks) drives a simulated ProPresenter — truncated reports, jittered polls — through the tracker and the client's render math: digits never step backwards, dwells hold 1 s (the ~2 s zero-crossing dwell is trunc's honest behavior), anchors stay within tolerance of the true value, resets snap, pause/resume re-locks, 0.2% clock drift is absorbed. Verified live against tools/pp-timers-mock.js: 78 s of 100 ms DOM sampling across four running cards — every step ±1 in the card's own direction, dwells 998–1002 ms, zero regressions; upstream kill/restart still recovers. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
229 lines
5.4 KiB
JSON
229 lines
5.4 KiB
JSON
{
|
||
"id": "propresenter-timers",
|
||
"name": "Timers",
|
||
"version": "1.4.2",
|
||
"proddash": ">=1.4.0",
|
||
"description": "Timers, Clocks, and LTC From configured Modules",
|
||
"provides": [
|
||
"timers"
|
||
],
|
||
"permissions": [
|
||
{
|
||
"kind": "microphone",
|
||
"reason": "Decoding SMPTE LTC timecode from an audio input on this machine"
|
||
},
|
||
{
|
||
"kind": "local-network",
|
||
"reason": "Reaching ProPresenter on this network"
|
||
}
|
||
],
|
||
"client": "client.js",
|
||
"server": "server.js",
|
||
"style": "style.css",
|
||
"minSize": {
|
||
"w": 2,
|
||
"h": 1
|
||
},
|
||
"defaultSize": {
|
||
"w": 4,
|
||
"h": 3
|
||
},
|
||
"configGroups": {
|
||
"ProPresenter": {
|
||
"toggle": "ppEnabled",
|
||
"help": "The timers configured in ProPresenter, read over its network API. Enable the network in ProPresenter's Preferences › Network and enter the host and port shown there. Switch it off on a day ProPresenter isn't running and nothing is polled."
|
||
},
|
||
"LTC Timecode": {
|
||
"toggle": "ltcEnabled",
|
||
"help": "SMPTE LTC decoded from an audio input on this machine, shown as a running timecode. Pick the device and the channel the timecode arrives on; macOS has to grant ProdDash the microphone (see the launcher's Permissions)."
|
||
},
|
||
"PCO Plan": {
|
||
"toggle": "pcoEnabled",
|
||
"help": "Timers the PCO Plan module offers — service elapsed, current item, countdown to service — appear here under a PCO Plan heading when that module is installed and configured. Nothing to set up on this side."
|
||
}
|
||
},
|
||
"configSchema": {
|
||
"ppEnabled": {
|
||
"type": "switch",
|
||
"label": "ProPresenter timers",
|
||
"group": "ProPresenter",
|
||
"default": true
|
||
},
|
||
"propresenter": {
|
||
"type": "endpoint",
|
||
"label": "ProPresenter",
|
||
"group": "ProPresenter",
|
||
"default": {
|
||
"host": "",
|
||
"port": 1025
|
||
}
|
||
},
|
||
"password": {
|
||
"type": "password",
|
||
"label": "API password",
|
||
"group": "ProPresenter",
|
||
"default": "",
|
||
"help": "Only if a password is set in ProPresenter's network preferences."
|
||
},
|
||
"ltcEnabled": {
|
||
"type": "switch",
|
||
"label": "LTC timecode",
|
||
"group": "LTC Timecode",
|
||
"default": false
|
||
},
|
||
"ltcDevice": {
|
||
"type": "select",
|
||
"label": "Audio device",
|
||
"group": "LTC Timecode",
|
||
"showWhen": "ltcEnabled",
|
||
"default": "",
|
||
"optionsRoute": "/ltc/devices"
|
||
},
|
||
"ltcChannel": {
|
||
"type": "number",
|
||
"label": "Channel",
|
||
"group": "LTC Timecode",
|
||
"showWhen": "ltcEnabled",
|
||
"default": 1,
|
||
"help": "The channel on that device carrying the timecode, counted from 1."
|
||
},
|
||
"pcoEnabled": {
|
||
"type": "switch",
|
||
"label": "PCO Plan timers",
|
||
"group": "PCO Plan",
|
||
"default": true
|
||
},
|
||
"timerFont": {
|
||
"type": "select",
|
||
"label": "Timer font",
|
||
"group": "Display",
|
||
"default": "default",
|
||
"options": [
|
||
{
|
||
"value": "default",
|
||
"label": "Default (system)"
|
||
},
|
||
{
|
||
"value": "monospace",
|
||
"label": "Monospace — steadier changing digits"
|
||
}
|
||
]
|
||
}
|
||
},
|
||
"instanceGroups": {
|
||
"Show": {
|
||
"collapsed": true,
|
||
"columns": 2
|
||
},
|
||
"Clock": {
|
||
"collapsed": false,
|
||
"columns": 2
|
||
},
|
||
"Colours": {
|
||
"collapsed": true,
|
||
"columns": 2
|
||
}
|
||
},
|
||
"instanceSchema": {
|
||
"showNames": {
|
||
"type": "switch",
|
||
"label": "Names",
|
||
"default": true,
|
||
"group": "Show"
|
||
},
|
||
"showStatus": {
|
||
"type": "switch",
|
||
"label": "Status lines",
|
||
"default": true,
|
||
"group": "Show"
|
||
},
|
||
"showDetail": {
|
||
"type": "switch",
|
||
"label": "Detail lines",
|
||
"default": true,
|
||
"group": "Show"
|
||
},
|
||
"showSeconds": {
|
||
"type": "switch",
|
||
"label": "Seconds",
|
||
"default": true,
|
||
"group": "Show"
|
||
},
|
||
"leadingZeros": {
|
||
"type": "switch",
|
||
"label": "Leading zeros",
|
||
"default": false,
|
||
"group": "Show"
|
||
},
|
||
"groupBySource": {
|
||
"type": "switch",
|
||
"label": "Group by source",
|
||
"default": false,
|
||
"group": "Show"
|
||
},
|
||
"showHeadings": {
|
||
"type": "switch",
|
||
"label": "Source headings",
|
||
"default": true,
|
||
"group": "Show",
|
||
"showWhen": "groupBySource"
|
||
},
|
||
"clock24h": {
|
||
"type": "switch",
|
||
"label": "24-hour",
|
||
"default": true,
|
||
"group": "Clock"
|
||
},
|
||
"clockSeconds": {
|
||
"type": "switch",
|
||
"label": "Seconds",
|
||
"default": true,
|
||
"group": "Clock"
|
||
},
|
||
"clockDate": {
|
||
"type": "switch",
|
||
"label": "Date",
|
||
"default": false,
|
||
"group": "Clock"
|
||
},
|
||
"dateShortDay": {
|
||
"type": "switch",
|
||
"label": "Short day",
|
||
"default": false,
|
||
"group": "Clock",
|
||
"showWhen": "clockDate"
|
||
},
|
||
"dateShortMonth": {
|
||
"type": "switch",
|
||
"label": "Short month",
|
||
"default": false,
|
||
"group": "Clock",
|
||
"showWhen": "clockDate"
|
||
},
|
||
"runningColor": {
|
||
"type": "color",
|
||
"label": "Running",
|
||
"default": "#2ee59a",
|
||
"group": "Colours"
|
||
},
|
||
"warningColor": {
|
||
"type": "color",
|
||
"label": "Warning",
|
||
"default": "#f0b429",
|
||
"group": "Colours"
|
||
},
|
||
"overrunColor": {
|
||
"type": "color",
|
||
"label": "Overrun",
|
||
"default": "#f4433c",
|
||
"group": "Colours"
|
||
},
|
||
"idleColor": {
|
||
"type": "color",
|
||
"label": "Idle",
|
||
"default": "#8b98a5",
|
||
"group": "Colours"
|
||
}
|
||
}
|
||
}
|