Initial Commit
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
# learn-mode
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
|
||||
## Purpose
|
||||
|
||||
Functional helper around the `MidiControllerPlugin.enterLearnMode` /
|
||||
`exitLearnMode` toggle. The base class natively swallows the next
|
||||
unmapped CC message and emits a `learn` event when in learn mode; this
|
||||
module wraps that flow into a promise so application code can simply
|
||||
`await captureNextLearn(controller)` to get the captured
|
||||
`(channel, controller)` pair. It also exposes a cancellation handle for
|
||||
UI flows that need to abort the capture (user closes the dialog,
|
||||
controller disconnects, etc.).
|
||||
|
||||
## Features
|
||||
|
||||
- Promise-based capture of the next CC message.
|
||||
- `cancel()` releases the subscription without exiting learn mode, so
|
||||
callers can compose multiple captures.
|
||||
- Zero new state on the plugin — uses the existing `on('learn', ...)`
|
||||
surface and `enterLearnMode()` toggle.
|
||||
|
||||
## Usage: Basic
|
||||
|
||||
```ts
|
||||
const { channel, controller: cc } = await captureNextLearn(controller);
|
||||
console.log("Mapped to channel", channel, "CC", cc);
|
||||
```
|
||||
|
||||
## Usage: Advanced
|
||||
|
||||
```ts
|
||||
const capture = captureNextLearn(controller);
|
||||
const timeout = setTimeout(() => capture.cancel(), 5000);
|
||||
try {
|
||||
const { channel, controller: cc } = await capture;
|
||||
controller.defineMappings([
|
||||
{ channel, controller: cc, target: "volume", min: 0, max: 1 },
|
||||
]);
|
||||
} finally {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `captureNextLearn(plugin)` → `Promise<LearnResult> & { cancel(): void }`.
|
||||
- `LearnResult` — `{ channel: number, controller: number }`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The promise resolves at most once. After the first `learn` emission the
|
||||
internal subscription is released so the resolver cannot fire twice; the
|
||||
base class also auto-exits learn mode on first capture, layering defence
|
||||
in depth. `cancel()` simply unsubscribes the listener, but intentionally
|
||||
does not call `exitLearnMode()` — that's the caller's policy choice if
|
||||
the UI hand-off requires keeping learn-mode armed across multiple
|
||||
controls in the same session for batch learn-mode capture workflows.
|
||||
Reference in New Issue
Block a user