Initial commit
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
// ─── EventBus typed event map ─────────────────────────────────────────────────
|
||||
// All inter-component communication flows through these events.
|
||||
// Views subscribe; only SyncEngine emits (except input:note from MIDI/WebMidi).
|
||||
|
||||
import type { NoteEvent, PlaybackStatus } from "./MusicData";
|
||||
|
||||
export interface SyncEventMap {
|
||||
// ── Playback events ──────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Emitted LOOKAHEAD_SECONDS before a note plays.
|
||||
* FallingNotes pre-renders the bar so it's ready when it enters the viewport.
|
||||
*/
|
||||
"note:upcoming": NoteEvent;
|
||||
|
||||
/**
|
||||
* Emitted at the exact moment a note begins playing.
|
||||
* PianoKeyboard highlights the key; Tone.js triggers the sample.
|
||||
*/
|
||||
"note:on": NoteEvent;
|
||||
|
||||
/**
|
||||
* Emitted at the exact moment a note stops playing.
|
||||
* PianoKeyboard un-highlights the key.
|
||||
*/
|
||||
"note:off": NoteEvent;
|
||||
|
||||
/**
|
||||
* Emitted every animation frame (~16ms) with the current playback position.
|
||||
* SheetMusicView drives the AlphaTab cursor; FallingNotesView moves bars.
|
||||
*/
|
||||
"transport:tick": { seconds: number; tick: number };
|
||||
|
||||
/**
|
||||
* Emitted when transport status changes (play/pause/stop/loop/waiting).
|
||||
*/
|
||||
"transport:stateChange": { status: PlaybackStatus; seconds: number };
|
||||
|
||||
// ── User input events ────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Emitted when the user plays a note on the physical piano or virtual keyboard.
|
||||
* SyncEngine uses this for wait-mode comparison.
|
||||
* PianoKeyboard echoes the key highlight with a different color.
|
||||
*/
|
||||
"input:note:on": { midi: number; velocity: number };
|
||||
|
||||
/**
|
||||
* Emitted when the user releases a note.
|
||||
*/
|
||||
"input:note:off": { midi: number };
|
||||
|
||||
// ── Document events ──────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Emitted when a new MusicDocument is loaded and all views should reset.
|
||||
*/
|
||||
"document:loaded": { id: string; title: string; totalDuration: number };
|
||||
|
||||
/**
|
||||
* Emitted when settings change that affect all views (e.g., toggle labels,
|
||||
* change hand colors, toggle fingering).
|
||||
*/
|
||||
"settings:changed": { key: string; value: unknown };
|
||||
|
||||
// ── Transport ────────────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Emitted at the start of every seek/skip so UI can release pressed keys
|
||||
* before Tone cancels pending note:off callbacks.
|
||||
*/
|
||||
"transport:seek": { seconds: number };
|
||||
|
||||
// ── Practice features ────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Emitted by SyncEngine when the speed trainer advances one step.
|
||||
* The store updates settings.speedTrainer.currentPct to keep UI in sync.
|
||||
*/
|
||||
"speedTrainer:stepped": { currentPct: number };
|
||||
|
||||
/**
|
||||
* Emitted by AccuracyTracker after each note event with running totals.
|
||||
*/
|
||||
"accuracy:update": { correct: number; wrong: number; missed: number; score: number };
|
||||
}
|
||||
|
||||
export type SyncEventName = keyof SyncEventMap;
|
||||
export type SyncEventPayload<K extends SyncEventName> = SyncEventMap[K];
|
||||
Reference in New Issue
Block a user