Files
2026-05-27 23:47:53 +01:00

2.0 KiB

learn-mode

(no submodules)

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

const { channel, controller: cc } = await captureNextLearn(controller);
console.log("Mapped to channel", channel, "CC", cc);

Usage: Advanced

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.