Skip to Content

Knobs API

OBS is read-only. Native Tauri main and overlay windows can write knob layout changes through the revision coordinator.

Manage knob elements: rotary visualization elements bound to HID device axes (e.g., rhythm game controller knobs). While HID device buttons are mapped and visualized exactly like keyboard keys, axes are visualized with dedicated knob elements that rotate along with the physical knob.

HID input recognition is currently supported on Windows only.

Identifiers

DmNote assigns stable string identifiers to HID inputs:

KindFormatExample
ButtonHIDB:vid:pid:usagePage:usageHIDB:1ccf:101c:9:3
AxisHIDA:vid:pid:usagePage:usageHIDA:1ccf:101c:1:48

Button identifiers appear as key labels (mappable like any keyboard key and delivered through dmn.keys.onRawInput with device: 'gamepad'). Axis identifiers are stored in a knob element’s axisId.

Types

// KeyPosition styling fields are inherited (position, size, colors, images...) // including the stable element `id` (UUID): it keeps identifying the same knob // across reorders and mode switches, and full preset loads reissue new IDs (tab presets only for collections they include) type KnobItemPosition = KeyPosition & { axisId: string; // bound HID axis ("HIDA:..."), empty if unbound sensitivity: number; // rotation multiplier (default 1) reverse: boolean; // invert rotation direction }; // Axis deltas are normalized by the axis resolution internally, so // sensitivity is a pure multiplier regardless of the device: // 1 = one physical revolution ≈ one on-screen revolution, // 2 = twice the rotation, 0.5 = half. // Keyed by tab/mode id (e.g., "4key") type KnobItemPositions = Record<string, KnobItemPosition[]>;

Commonly used inherited styling fields:

  • backgroundColor / activeBackgroundColor: idle / turning fill color
  • borderColor / activeBorderColor: idle / turning border color
  • borderWidth: solid border thickness in px when explicitly greater than 0; an omitted width uses a 1 px fallback only for a gradient border, and 0 disables both border forms
  • backgroundGradient / activeBackgroundGradient: background gradient (GradientSpec, takes priority over the solid color)
  • borderGradient / activeBorderGradient: border gradient (GradientSpec)
  • shadow / activeShadow: idle / turning shadow (ElementShadowSpec; color alpha controls opacity)
  • borderRadius: corner radius in px; when unset the knob is a circle
  • inactiveImage / activeImage: idle / turning custom image
  • idleTransparent / activeTransparent: transparent background toggles

ElementShadowSpec contains enabled, color, offsetX, offsetY, and blur. Offsets accept -100–100 px and blur accepts 0–100 px.

While the physical knob is turning, the element switches to its active colors/image (like a pressed key) and rotates by accumulatedRevolutions × 360° × sensitivity.

Position Management

dmn.knobItems.getPositions(): Promise<KnobItemPositions>

Returns knob element layouts for all tabs.

const positions = await dmn.knobItems.getPositions(); console.log(positions['4key']); // knob elements on the "4key" tab

dmn.knobItems.updatePositions(positions): Promise<KnobItemPositions>

Replaces knob element layouts and persists them.

const positions = await dmn.knobItems.getPositions(); positions['4key'][0].sensitivity = 2; // 2 on-screen turns per knob revolution await dmn.knobItems.updatePositions(positions);

dmn.knobItems.onPositionsChanged(callback): Unsubscribe

Subscribes to knob layout changes (knobPositions:changed).

This event remains available for compatibility, but is deprecated for new editor state synchronization. Use dmn.editor.onCommitted() for the canonical atomic change stream.

const unsub = dmn.knobItems.onPositionsChanged((positions) => { console.log('knob layout changed', positions); });