Files
skills/docs/media/audio/audio-timeline/src/engine/engine.md
2026-05-29 08:20:56 +01:00

53 lines
2.2 KiB
Markdown

# TimelineEngine
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## Purpose
`TimelineEngine` is the central state container for the `@suaveplan/audio-timeline` package. It owns the multi-track arrangement, playback transport, mixer state, zoom/selection view state, and a full undo/redo history. All rendering is delegated to a pluggable `TimelineAdapter`, keeping the engine headless and suitable for both web and native targets.
## Features
- Track CRUD: `setTracks`, `addTrack`, `removeTrack`, `updateTrack`, `selectTrack`
- Clip CRUD: `addClip`, `removeClip`, `moveClip`, `trimClip`, `splitClip`
- Transport: `play`, `pause`, `stop`, `seek` guarded by an internal FSM
- Mixer: `setMasterVolume`, `setTrackVolume`, `setTrackMute`, `setTrackSolo`, `setTrackPan`
- View: `zoomIn`, `zoomOut`, `setZoomLevel`, `setSelection`, `setLoopRegion`, `setLoopEnabled`
- Undo/redo with transaction support (`beginTransaction`, `commitTransaction`, `abortTransaction`)
- Serialization via `toJSON` and static `fromJSON`
- Typed events via `on` / `off`
- OTel spans and counters for clip operations and transport
## Usage
### Basic
```ts
import { TimelineEngine, NullTimelineAdapter } from "@suaveplan/audio-timeline";
const engine = new TimelineEngine({ sampleRate: 44100 });
engine.setAdapter(new NullTimelineAdapter());
engine.addTrack({ name: "Drums" });
engine.play();
```
### Advanced
```ts
engine.beginTransaction();
engine.addClip(trackId, clip);
engine.moveClip(trackId, clip.id, 500);
engine.commitTransaction();
engine.undo();
```
## API Reference
`TimelineEngine` exposes the full public surface documented in the spec. Key getters: `getState()` returns an immutable snapshot; `getCurrentTime()` reads from the adapter; `getTempo()` returns current BPM.
## Implementation Notes
The engine is deliberately headless. It does not touch the DOM or Web Audio directly; every output goes through the adapter. State mutations push `Command<Track[]>` instances onto an `UndoStack`. On undo/redo, if the track count is unchanged the engine calls `adapter.updateTrack` per changed track instead of `adapter.setTracks` to avoid playback interruption. Events are emitted through an `EventBus` so UI layers can subscribe to granular changes without polling.