WIP: Phase 3B playback engine handoff
This commit is contained in:
@@ -110,17 +110,70 @@ server-evaluated eligibility, immutable display/thumbnail URLs, and the
|
||||
settings revision and evaluation time used. Playlist revisions increment once
|
||||
per semantic content change. Exact no-ops and reads do not increment them.
|
||||
|
||||
Before a playback-relevant playlist, settings, or asset mutation, the playback
|
||||
service catches up using the old metadata. The domain transaction then commits
|
||||
and playback synchronously reconciles the new values at the mutation instant.
|
||||
This prevents a late timer or restart boundary from being rewritten by a later
|
||||
edit. If the post-commit reconciliation unexpectedly fails, the API returns an
|
||||
error even though the preceding domain commit may already be durable; clients
|
||||
must refetch current state before deciding whether to retry.
|
||||
|
||||
Activation is explicit. A request is held in the existing pending-activation
|
||||
state while a playable normal slide is mid-duration; otherwise the target
|
||||
playlist is prepared immediately at its first currently playable entry. The
|
||||
output-off flag remains only a visual gate, and static hold is preserved while
|
||||
the hidden normal playlist changes. Phase 3A does not include the advancing
|
||||
playback timer that will consume pending activation at a slide boundary.
|
||||
the hidden normal playlist changes. The authoritative playback service consumes
|
||||
a pending activation at the current slide boundary and never merges the old and
|
||||
new playlists.
|
||||
|
||||
Socket.IO publishes `playlists:changed` as a refetch invalidation after
|
||||
committed playlist changes and after settings or referenced-asset edits that
|
||||
affect resolved playlist data. Socket.IO is not a mutation API.
|
||||
|
||||
## Authoritative playback
|
||||
|
||||
One serialized service owns persisted global playback, timer reconciliation,
|
||||
and every playback control path. Its REST surface is:
|
||||
|
||||
- `GET /api/playback`
|
||||
- `POST /api/playback/pause`
|
||||
- `POST /api/playback/resume`
|
||||
- `POST /api/playback/next`
|
||||
- `POST /api/playback/previous`
|
||||
- `POST /api/playback/static`
|
||||
- `PUT /api/playback/mode`
|
||||
- `POST /api/playback/reload`
|
||||
|
||||
Visual output precedence is mode off (black), a valid static asset, the current
|
||||
normal entry, then black when no playable target exists. Mode off is only a
|
||||
visual gate: normal playback continues underneath unless it is independently
|
||||
paused or held by static mode. Pause and static both preserve the normal cursor
|
||||
and remaining duration. Resume clears both static and paused state together and
|
||||
continues the normal entry with its preserved remaining time. Next and previous
|
||||
wrap across currently playable entries; they change the held entry without
|
||||
unpausing when paused and are no-ops while static.
|
||||
|
||||
Normal slides use persisted absolute start times and deadlines. Chained
|
||||
timeouts reconcile from the prior authoritative deadline, including late
|
||||
callbacks and restart catch-up, so delays do not accumulate as timing drift.
|
||||
The service also arms exact schedule and asset-expiration boundaries. It skips
|
||||
disabled, out-of-schedule, expired, and non-ready entries, and safely returns to
|
||||
an eligible entry when one becomes available. Pending playlist activation is
|
||||
applied at the current normal slide boundary; an empty target playlist still
|
||||
becomes active with black normal output.
|
||||
|
||||
Socket.IO sends `playback:state` immediately on connection and after meaningful
|
||||
committed playback changes. The authoritative snapshot includes server time and
|
||||
revisions, mode and transport state, active playlist and timeline data, current
|
||||
and static targets, crossfade settings, and a display-cache manifest with
|
||||
effective duration, presentation, scheduling, expiration, and immutable media
|
||||
metadata. Enabled future-scheduled entries remain in the manifest; disabled
|
||||
entries and private S3 details do not. Reads and connections do not increment
|
||||
the playback revision.
|
||||
|
||||
Phase 3B exposes this state and behavior through REST and Socket.IO only. MQTT
|
||||
command wiring and the browser display renderer remain later phases.
|
||||
|
||||
## Storage and health
|
||||
|
||||
The API uses a small path-style S3 adapter configured by `S3_ENDPOINT`,
|
||||
|
||||
Reference in New Issue
Block a user