mirror of
https://github.com/9x/sheetmusictrainer.git
synced 2026-11-03 22:03:54 +01:00
Metronome/phrase click unification: run-driven beats, gated widget
- Phrase Mode (sync to metronome): the run's scheduler is the single click source (with count-in); the metronome widget is muted and its pendulum mirrors the run's beats via the new phraseBeatBus (audio-timestamp scheduled). No more double clicks; clicks only while the run is active (phraseRunBus gates the widget's own ticking). - Schedule entries now carry continuous beat index + accent flag (downbeats accented, count-in beat 1 accented). - 'At your pace': optional click via the metronome toggle (kept explicit). - Metronome widget: gate prop; in gated mode it listens to the beat bus instead of running its own scheduler.
This commit is contained in:
26
src/hooks/phraseRunBus.ts
Normal file
26
src/hooks/phraseRunBus.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Tiny pub/sub for the phrase trainer's running state.
|
||||
*
|
||||
* Lets the (global) metronome widget gate its pendulum/click on the phrase
|
||||
* run: in Phrase Mode the metronome should only be active while the trainer
|
||||
* is counting in or playing, not while idle.
|
||||
*/
|
||||
type Listener = (running: boolean) => void;
|
||||
|
||||
const listeners = new Set<Listener>();
|
||||
let running = false;
|
||||
|
||||
export const phraseRunBus = {
|
||||
set(v: boolean): void {
|
||||
if (v === running) return;
|
||||
running = v;
|
||||
listeners.forEach(l => l(v));
|
||||
},
|
||||
get(): boolean {
|
||||
return running;
|
||||
},
|
||||
subscribe(l: Listener): () => void {
|
||||
listeners.add(l);
|
||||
return () => { listeners.delete(l); };
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user