State Persistence
Oscilla persists various state data so that positions, visibility, and presets survive page reloads. This document provides an overview of what gets saved and where.
Summary
| State Type | Storage Location | Auto-save | Scope |
|---|---|---|---|
| Drag positions | localStorage | Yes | Per project |
| Visibility state | Server (JSON) | Yes (1s debounce) | Per project |
| O2P Presets | localStorage + Server | Manual | Per project |
| Configurations | localStorage + Server | Manual | Per project |
| Launchers | localStorage + Server | Yes | Per project |
Drag Positions
What: X/Y positions of draggable overlays (drag(1), drag-click:1)
Storage: localStorage under key oscilla-drag-positions
Structure:
{
"project-name": {
"uid1": { "x": 100, "y": 200 },
"uid2": { "x": 150, "y": 300 }
}
}
Behavior:
- Saved immediately when drag ends
- Restored when overlay is created
- Invalid positions (too far from original) are rejected and reset
Source: button.js — saveDragPosition(), loadDragPositions()
Visibility State
What: Hidden/visible state of elements controlled by ui(uid:..., action:toggle)
Storage: Server-side JSON via /api/ui-state/{project}
Structure:
{
"rot_triangle": { "visible": false },
"synth_panel": { "visible": true }
}
Behavior:
- Auto-saved with 1 second debounce after any visibility change
- Loaded on project open and applied before display
- Triggers
oscilla:visibility-state-loadedevent when restored - Toggle button indicators update to match restored state
Source: animShared.js — saveVisibilityState(), loadVisibilityState()
See also: ui() documentation
O2P Presets
What: Saved fader/control positions for O2P animations, plus visibility state
Storage: Dual — localStorage (fast backup) + Server (project file)
- localStorage:
oscilla-presets-{project} - Server:
/api/presets/{project}
Structure:
{
"kind": "o2pPreset",
"name": "warm_mix",
"data": {
"fader_uid_1": 0.75,
"fader_uid_2": 0.5,
"_meta": { "savedAt": 1234567890, "filter": "groupA" },
"_visibility": {
"rot_triangle": { "visible": false }
}
}
}
Behavior:
- Saved manually via preset GUI or
savePreset()API - Recalled via preset GUI or
recallPreset()API _visibilitysnapshot included on save, restored on recall- Can be filtered by group when saving
Source: o2pPresets.js — savePreset(), recallPreset()
Configurations
What: Complete launcher state snapshots plus visibility
Storage: Same dual system as presets
Structure:
{
"kind": "configuration",
"name": "opening_state",
"data": {
"launchers": {
"launcher_uid": { /* launcher data */ }
},
"visibility": {
"rot_triangle": { "visible": true }
}
}
}
Behavior:
- Captures all launcher states at save time
- Restores launcher positions and visibility on recall
- Useful for saving complete performance starting states
Source: controlShared.js — saveConfiguration(), recallConfiguration()
Launchers
What: Individual O2P launcher states (fader positions, active state)
Storage: Same dual system as presets
Behavior:
- Auto-saved when launcher state changes
- Restored when project loads
- Managed through
controlShared.jsstate system
Source: controlShared.js — saveLauncher()
Storage Priority
When restoring state, the system checks sources in this order:
- Server — Authoritative source, synced across clients
- localStorage — Fast fallback if server unavailable
- SVG/cue defaults — Initial values from score definition
For visibility specifically (in toggle indicators):
- Saved JSON state — From
loadVisibilityState() visible:parameter — From cue definition- Default — Visible (true)
Clearing State
Drag positions: Clear localStorage key oscilla-drag-positions
Visibility: Delete server file or clear via API
Presets/Configurations: Use GUI delete or clear localStorage + server
Full reset: Clear localStorage and restart server to regenerate defaults
Events
| Event | Dispatched When |
|---|---|
oscilla:visibility-state-loaded |
Visibility state restored from server or preset |
Listen for this event to update UI that depends on visibility state:
window.addEventListener("oscilla:visibility-state-loaded", () => {
// Update toggle indicators, refresh UI, etc.
});
Global Functions
These are exposed on window for cross-module access:
window._loadVisibilityState() // Load and apply visibility from server
window._getVisibilitySnapshot() // Get current visibility state object
window._applyVisibilitySnapshot(obj) // Apply visibility state with optional dur
Tip: use ← → or ↑ ↓ to navigate the docs