first commit
This commit is contained in:
78
docs/media/audio/audio-sprite-player/src/events/events.md
Normal file
78
docs/media/audio/audio-sprite-player/src/events/events.md
Normal file
@@ -0,0 +1,78 @@
|
||||
# SpritePlayerEvents
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
`SpritePlayerEvents` is the typed event surface a `SpritePlayer` exposes for downstream consumers — analytics, UI feedback, observability sinks, debug overlays. It is a thin facade over `@suaveplan/events`'s `EventBus`, narrowed to the five event names the player can emit.
|
||||
|
||||
The class is intentionally write-internal / read-external: the player constructs it and emits, consumers subscribe and never emit. The internal `EventBus` is not exposed so consumers cannot dispatch arbitrary events through the player's surface, which keeps the contract auditable.
|
||||
|
||||
## Features
|
||||
|
||||
- Five typed event names: `play`, `stop`, `complete`, `voice-stolen`, `error`.
|
||||
- Strongly-typed `on` returning an unsubscribe closure — no string-typed payloads at the call site.
|
||||
- `clear()` wipes all listeners — used by `SpritePlayer.dispose()` to break consumer-to-player references.
|
||||
- Backed by `@suaveplan/events.EventBus` so payloads flow through the same FIFO dispatch used elsewhere in the platform.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { createSpritePlayer } from "@suaveplan/audio-sprite-player";
|
||||
|
||||
const player = createSpritePlayer({ adapter });
|
||||
const off = player.events.on("play", (e) => {
|
||||
console.log(`play ${e.entryName} (${e.handleId}) at ${e.startedAt}`);
|
||||
});
|
||||
// ...later
|
||||
off();
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import { createSpritePlayer } from "@suaveplan/audio-sprite-player";
|
||||
|
||||
const player = createSpritePlayer({ adapter });
|
||||
const offs = [
|
||||
player.events.on("voice-stolen", (e) => {
|
||||
metrics.voicesStolen.add(1, { entry: e.entryName });
|
||||
}),
|
||||
player.events.on("complete", (e) => {
|
||||
histograms.playMs.record(e.durationMs, { entry: e.entryName });
|
||||
}),
|
||||
player.events.on("error", (e) => {
|
||||
log.error("sprite playback failed", {
|
||||
handleId: e.handleId,
|
||||
code: e.code,
|
||||
message: e.message,
|
||||
});
|
||||
}),
|
||||
];
|
||||
|
||||
return () => offs.forEach((off) => off());
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `class SpritePlayerEvents`
|
||||
|
||||
- `on(event, listener): () => void` — subscribes, returns the unsubscribe closure.
|
||||
- `emit(event, payload): void` — internal; called by `SpritePlayer`.
|
||||
- `clear(): void` — drops every listener.
|
||||
|
||||
### Event payloads
|
||||
|
||||
- `play` → `{ handleId, entryName, startedAt }`
|
||||
- `stop` → `{ handleId, entryName, fadeOutMs }`
|
||||
- `complete` → `{ handleId, entryName, durationMs }`
|
||||
- `voice-stolen` → `{ stolenId, replacedBy, entryName }`
|
||||
- `error` → `{ handleId, entryName, code, message }`
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- The class deliberately exposes `emit` so the orchestrator can fire events; downstream consumers should treat it as internal and never call it (TypeScript visibility cannot enforce package-level boundaries, so the convention is documented here).
|
||||
- `clear()` is invoked by `SpritePlayer.dispose()` to release references — consumers should not call it directly because it would silence other listeners.
|
||||
- The underlying `EventBus` dispatches synchronously in FIFO order; throwing in a listener does not poison the bus but does prevent later listeners from running for that emission.
|
||||
Reference in New Issue
Block a user