53 lines
2.2 KiB
Markdown
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.
|