generated from Labyricorn/labyricorn-project-template
Post Step 4 Completion
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* XZBT Control Bus
|
||||
*
|
||||
* XZBTControlBus is a small registry of named, settable console targets
|
||||
* (ranges, toggles and triggers). Anything that wants to drive the console
|
||||
* from outside the DOM — contract adapter, hotkeys, future transports —
|
||||
* talks to the bus rather than reaching into app.js internals.
|
||||
*
|
||||
* MIDI NOTE: Web MIDI control belonged to standalone SciFi-XZBT until
|
||||
* Step 3.5. External MIDI integration will be handled by XZBT-NGN, which
|
||||
* will send canonical contract commands (set / invoke) to this exhibit.
|
||||
* The control bus itself is transport-agnostic and is intentionally kept here.
|
||||
*/
|
||||
|
||||
class XZBTControlBus {
|
||||
constructor() {
|
||||
this.targets = new Map();
|
||||
this.listeners = new Set();
|
||||
}
|
||||
register(id, spec) {
|
||||
this.targets.set(id, { id, ...spec });
|
||||
}
|
||||
set(id, value, source = 'external') {
|
||||
const t = this.targets.get(id);
|
||||
if (!t) return false;
|
||||
let v = value;
|
||||
if (t.type === 'range') {
|
||||
v = Math.max(t.min, Math.min(t.max, Number(value)));
|
||||
if (t.step) v = Math.round(v / t.step) * t.step;
|
||||
}
|
||||
if (t.apply) t.apply(v, source);
|
||||
this.listeners.forEach(fn => fn({ id, value: v, source, target: t }));
|
||||
return true;
|
||||
}
|
||||
trigger(id, source = 'external') {
|
||||
const t = this.targets.get(id);
|
||||
if (!t) return false;
|
||||
if (t.apply) t.apply(true, source);
|
||||
this.listeners.forEach(fn => fn({ id, value: true, source, target: t }));
|
||||
return true;
|
||||
}
|
||||
list() {
|
||||
return [...this.targets.values()];
|
||||
}
|
||||
}
|
||||
window.XZBTControlBus = XZBTControlBus;
|
||||
Reference in New Issue
Block a user