Skip to content

Event Player in Spectoda Studio

Author sparse per-ID Cues and upload one global mixed-ID player.show v3 for firmware 0.12.11.

Event Player authors discrete Event-value changes on the Project’s shared timeline. Studio stores the editable model in the Project, captures values from the authoritative WASM EventStore, and compiles one global mixed-ID stream for NetworkStorage playback.

  • One Track is the editing lane for exactly one Spectoda ID. It has no single Event label.
  • A Track persists Event definitions: label, valueType, priority, playback enabled, and Capture membership.
  • A Cue is one timeline time and only the Event values explicitly present at that time. It is intentionally sparse.
  • One Cue may contain only toggl = 0%; another may contain a complete scene.
  • Studio merges Cues from all enabled Tracks at the same time into one atomic Cue Group of at most 340 Event values. A Cue Group is never split.

Tracks remain per-ID because that is the clearest editing model. Compilation is global: every Controller lands every ID from the same stream, keeping the distributed EventStores aligned.

The editable source is Event Player Project schema v2 inside the Studio Project. player.show and player.NNN are generated deployment artifacts, not an editable backup. SEB contains Event-value records; it does not contain EventStates.

  1. Connect to the correct Network and place the shared playhead.
  2. Check the exact Capture IDs in the left EventStore panel.
  3. Check the exact Capture Events you want.
  4. Choose Capture Cue.
  5. Edit or move the selected Cues and save the Project.

Capture writes exactly the checked values. The selection is Project data, so it survives reload and the next Capture. Newly observed Events start unchecked. Unchecking an Event does not erase historical Cue values.

The timeline is sampled once and the native WASM EventStore is read once per selected exact ID. Capture performs no Controller write and has no fallback to a React/JS EventState mirror. An unavailable native read, a missing selected Event, or a type mismatch stops Capture before Cue mutation.

Compilation errors are collapsible and do not stop editing or Capture. Compilation and upload remain unavailable until the Project is valid.

Event Player uses the same timeline and transport as Workspace. It has no second clock.

  • Click the ruler to seek; Rewind, Play, Pause, and Space use the shared transport.
  • Double-click a lane to add a Cue.
  • Drag Cue diamonds in time or between Tracks; drag empty lane space to select several Cues.
  • Delete and Backspace remove selected Cues.
  • The Cue inspector checkbox decides whether an Event value is present in that Cue.
  • Expanding a Track shows held stepped values and type-appropriate inline editors.

Use player.be from the Global sparse-Cue Event Player example. The same source-locked example is included in Spectoda Creator Kit.

  1. Paste the complete player.be into a Project BERRY SCRIPT block.
  2. Save and upload the Project through the ordinary Studio workflow.

The script registers itself when injected. Do not add a Player() call.

There is no file-base or local-ID configuration. Add the same plugin to every participating Controller; all of them land the complete mixed-ID stream.

The complete TNGL payload must stay within 4 KiB. The example’s size test measures the complete directly injectable script.

Studio produces fixed deterministic names:

  • player.show — a small SPM v3 manifest;
  • player.000, player.001, … — ordered SEB segments.

Each manifest entry stores the segment’s exact 48-bit NetworkStorage version and absolute startMs. The filename follows from its index and is not stored. Each SEB contains whole Cue Groups, at most 340 records, and relative offsets from 0 through 65535 ms. Long shows continue in the next fixed slot.

Choose Upload. Studio preflights capacity and current metadata, publishes a newer player.show first, then uploads only changed segments and verifies exact readback. An unchanged segment may keep its current version. Upload does not pause, seek, rewind, resume, or otherwise change the timeline.

Publishing the manifest first deliberately makes incomplete Controllers inactive. The ordinary NetworkStorage union distributes the exact requested segment versions; the Berry plugin activates only when all of them are present and valid. Fixed names replace old show data instead of accumulating content-addressed filenames indefinitely.

The Project plugin polls timeline.getState() and uses SEB.land(filename,{"source":"networkStorage",...}). EventStore remains the only state authority.

  • Every Controller validates player.show, every exact segment version, and every SEB header/EOF before activation.
  • Forward playback lands only due Cue Groups and no future value.
  • Every Controller lands every ID in the stream.
  • Seek, rewind, loop, and the 24-hour wrap select the exact-target Cue Group or the immediately preceding one. That one sparse Group lands once at the causal seek time, including while paused; resume continues after it.
  • Seek never selects a future Cue, does not clear EventStore, and does not replay older history. Events absent from the selected sparse Cue keep their existing EventStates; use a complete Cue where arbitrary seek must recreate a complete visual state.
  • A missing or wrong segment version keeps that Controller inactive until ordinary NetworkStorage synchronization supplies the exact file.

A scene is a general mixed-ID SEB with zero offsets. It is landed from NetworkStorage at the trigger Event’s causal local millis and remains independent of Player timeline state. See SEB scenes and Event Player in FW 0.12.11.