Files
ProdDash/modules/resi-studio-cues/README.md
T

101 lines
4.9 KiB
Markdown
Raw Normal View History

# Resi Studio Cues
Puts a live "time until the next Resi cue" countdown on the stage screen.
**This folder is not a ProdDash tile.** It has no `module.json`, so the shell's module
scan skips it. It lives here because this is where the production tooling lives, not
because ProdDash loads it. That is also why it carries its own README, unlike the real
modules, which are documented in the repo README's *Included modules*.
---
## What it does
`resi_to_propresenter.py` watches a Resi decoder's playhead, works out how long until
its next cue point, and keeps a ProPresenter countdown timer armed with that number.
ProPresenter renders the countdown itself, so the stage screen is smooth and styled in
whatever the stage layout uses, and nothing has to be pushed every second. The cue's
name goes up as a ProPresenter stage message alongside it.
The cue list and the playhead both come from Resi's cloud, not from the decoder — the
decoder reports its position upstream, and `central.resi.io` hands it back. Nothing has
to be installed at the decoder end.
## Why the playhead is estimated rather than displayed
Resi republishes a decoder's `position` only every few seconds, on an irregular
cadence, and each reading is already a little stale when it appears. Sent straight to
ProPresenter, the countdown sits several seconds behind and lurches.
So every reading is kept as *media time minus wall time*, and the **largest** recent
value is the one trusted — that is the reading that reached us with the least delay, so
a slow round trip or an unlucky poll cannot drag the countdown backwards. A reading
that falls outside the link's measured noise floor is treated as a seek: the lock is
dropped, the estimate snaps, and the cue list is re-read at once instead of on its
timer. Playback is only called paused once the playhead has been still for clearly
longer than Resi's own cadence, because a fixed timeout mistakes a slow update for a
stop and freezes the countdown mid-service.
How quickly a fired cue can possibly show on stage is bounded by how often Resi
republishes the position. Nothing on this end beats that; the log prints the measured
cadence so you can see what it is.
## Running it
Settings live outside the checkout, at
`~/Library/Application Support/ResiCues/config.json`, so a `git pull` never touches
them. `config.example.json` here is the template. The Resi password is read from the
Keychain and is never written to disk:
security add-generic-password -a "you@yourchurch.org" -s resi-propresenter -w
Then pick a decoder:
python3 resi_to_propresenter.py --list
and put its `playerHardwareId` into `player` in the config (leave it blank if the
account has only one). `--dry-run` prints what it would send without touching
ProPresenter.
**Start it at login:** double-click `install-agent.command`. It writes a LaunchAgent
that runs the script at login and restarts it if it stops, logging to
`~/Library/Logs/resi-propresenter.log`. Run it again after a pull to repoint the agent.
ProPresenter needs its network API on (Settings › Network) and a **countdown** timer
whose name matches `timer_name` in the config — `NextCue` by default — placed on the
stage layout, with a Message object for the cue name.
## Tests
python3 test_playhead.py # the estimator against 9 simulated Resi profiles
python3 test_end_to_end.py http://10.1.14.225:1025
`test_playhead.py` drives the estimator on a fake clock against a simulated Resi with
a configurable update cadence, staleness, cadence jitter and network round trip; pass
those four as arguments to run one profile. `test_end_to_end.py` runs the real script
loop against a **real** ProPresenter with a simulated decoder, checks the timer is
armed and counts down in step across a cue rollover, and puts ProPresenter back as it
found it.
Both suites are written so a deliberate break turns them red — six of seven mutations
of the estimator do. Neither covers the live Resi calls, which need real credentials.
## The Companion sibling
Before the stage-screen version, the same estimator shipped as a Bitfocus Companion
module for Stream Deck buttons — a patched build of
[reykroona/companion-module-resi-studio-cues](https://github.com/reykroona/companion-module-resi-studio-cues)
(MIT), with the estimator, a PLAYING/PAUSED variable and resync actions added. It is
not needed for the stage display and is not checked in here; the packaged `.tgz` and
its patched sources are in `~/Desktop/Resi Companion/`.
## Resi's API
Undocumented and unsupported — it is what `studio.resi.io` itself uses. Don't open a
Resi ticket about it. Authentication is `POST /api/v3/login?newToken=true` with
`{userName, password}`, which sets a `livingas1` cookie used as
`Authorization: X-Bearer <cookie>`; from there `/api_v2.svc/users/me`,
`/api/v3/customers/{id}/venues`, `/api_v2.svc/users/{venueUuid}/players`,
`/api/v3/customers/{id}/events/{eventId}` and
`/api_v2.svc/streamprofiles/{profileId}/events/{eventId}/cues`.