@yam8d/m8-sdk 0.3.2 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +156 -15
- package/dist/index.js +1379 -528
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/types/client.d.ts +38 -5
- package/types/fxCommands.d.ts +47 -0
- package/types/fxInsight.d.ts +136 -0
- package/types/index.d.ts +3 -3
- package/types/parameterViews.d.ts +104 -0
- package/types/scaleInsight.d.ts +47 -0
- package/types/types.d.ts +7 -0
- package/types/viewContext.d.ts +179 -15
package/README.md
CHANGED
|
@@ -25,6 +25,7 @@ Client SDK for iframe applications that communicate with an M8 tracker host via
|
|
|
25
25
|
- [M8State](#m8state)
|
|
26
26
|
- [CursorPos / CursorRect / RGB / SystemInfos](#cursorpos--cursorrect--rgb--systeminfos)
|
|
27
27
|
- [M8SemanticContext](#m8semanticcontext)
|
|
28
|
+
- [M8DescriptionPart](#m8descriptionpart)
|
|
28
29
|
- [M8ParsedRow](#m8parsedrow)
|
|
29
30
|
- [M8ActiveField / M8ParsedField](#m8activefield--m8parsedfield)
|
|
30
31
|
- [M8FieldType](#m8fieldtype)
|
|
@@ -287,11 +288,38 @@ if (ctx?.activeField?.type === 'chainRef') {
|
|
|
287
288
|
|
|
288
289
|
Returns a human-readable one-liner, e.g.:
|
|
289
290
|
|
|
290
|
-
- `"Track 3 —
|
|
291
|
-
- `"Note
|
|
292
|
-
- `"
|
|
291
|
+
- `"Track 3: 0A — Track 3 — Song View row 01"`
|
|
292
|
+
- `"Note (N): Note C-4 — Phrase View row 00"`
|
|
293
|
+
- `"FX2 Command: KIL — (Kill: stops the playing instrument after XX ticks) — value 03: stops the note after 3 ticks — Phrase View row 01"`
|
|
293
294
|
|
|
294
|
-
Returns `null` when not connected or no view is active.
|
|
295
|
+
Returns `null` when not connected or no view is active. It is the text of `describeContextParts()` joined with `' — '`.
|
|
296
|
+
|
|
297
|
+
It reads the cursor against its surroundings when that changes the meaning:
|
|
298
|
+
|
|
299
|
+
- **FX values are explained** — `ARP37` on `C-4` → `"+3 and +7 semitones: C-4 D#4 G-4"`, `KIL04` → `"stops the note after 4 ticks"`, relative instrument commands show their sign.
|
|
300
|
+
- **REP is followed down its FX lane.** With `VOL10` above, `REP05` reads `"repeats VOL from 10 (step 1), +05 per step → 15 on this step"`, and an empty cell below it reads `"REP still active: VOL reaches 1A on this step (+05 per step since step 3)"`. A new command, `REP00`, or an `RTO` limit in the same lane ends or caps it. `^^` (a REP carried over from the previous phrase) is recognised when it can be attributed to one lane.
|
|
301
|
+
- **Relative commands are tracked.** Per the manual, a relative instrument command (`VOL`, `CUT`, `PIT`, `EA1`… — the ones the device help marks `(RELATIVE)`) keeps its change until a note is triggered with a `RET` or with an instrument number in the `I` column. `VOL02` twice reads `"VOL has moved by +04 in 2 steps since the instrument number on step 0; stays until a note with an instrument number (I) or a RET resets it"`, REP repeats are counted, and the `I` cell or `RET` that resets it lists what it wipes (`"resets the relative changes still in force (CUT +10, VOL +0B)"`). Only the current phrase is visible, so totals start at the phrase's own last reset.
|
|
302
|
+
- **Instrument-type commands say who offers them.** `FM3` → `"…; offered by FM Synth instruments"`.
|
|
303
|
+
- **Scale View** names the scale the enabled notes spell (`"Scale: C D E F G A B — Major (Ionian)"`), says what the row under the cursor is (`"E — a major 3rd (+4 semitones above C) — is in the scale"`), reports detuning, and explains the KEY / TUNE / NAME rows.
|
|
304
|
+
|
|
305
|
+
The surroundings come from a copy of the screen that the client refreshes in the background after every state event. It is only used when its row under the cursor still matches `currentLine`; otherwise the description quietly falls back to the cursor row alone. Call `await m8.getScreen()` or `await m8.captureSnapshot()` first when you need it guaranteed current.
|
|
306
|
+
|
|
307
|
+
#### `describeContextParts(): M8DescriptionPart[] | null`
|
|
308
|
+
|
|
309
|
+
The same description as ordered, tagged parts, so you can keep, drop, reorder or style some of them instead of parsing the string:
|
|
310
|
+
|
|
311
|
+
```ts
|
|
312
|
+
m8.describeContextParts()
|
|
313
|
+
// [{ kind: 'field', text: 'FX2 Command: KIL' },
|
|
314
|
+
// { kind: 'fxInfo', text: '(Kill: stops the playing instrument after XX ticks)' },
|
|
315
|
+
// { kind: 'meaning', text: 'value 03: stops the note after 3 ticks' },
|
|
316
|
+
// { kind: 'location', text: 'Phrase View row 01' }]
|
|
317
|
+
|
|
318
|
+
// Your own view label instead of the SDK's location:
|
|
319
|
+
const text = m8.describeContextParts()?.filter((p) => p.kind !== 'location').map((p) => p.text).join(' · ')
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
See [`M8DescriptionPart`](#m8descriptionpart) for the kinds. Everything a part says is also in the context as data (`activeField`, `fxLane`, `relativeFx`, `resetsRelative`, `scaleNote`, `scale`, …), for when you want to write the text yourself.
|
|
295
323
|
|
|
296
324
|
---
|
|
297
325
|
|
|
@@ -307,10 +335,12 @@ Closes the host connection and clears all event listeners and internal state.
|
|
|
307
335
|
|
|
308
336
|
These are re-exported from `@yam8d/m8-sdk` for use without an `M8Client` instance.
|
|
309
337
|
|
|
310
|
-
### `getSemanticContext(state: M8State): M8SemanticContext | null`
|
|
338
|
+
### `getSemanticContext(state: M8State, screen?: M8Screen | null): M8SemanticContext | null`
|
|
311
339
|
|
|
312
340
|
Parses an `M8State` snapshot into a semantic context. Returns `null` if `state.viewName` is not set.
|
|
313
341
|
|
|
342
|
+
Pass the whole `screen` (from `getScreen()`) to fill the context's look-around fields: `steps` (all 16 phrase steps), `fxLane` (what the FX cell under the cursor means in its lane), `relativeFx`, `resetsRelative`, `carriedRepLane`, and `scale` (Scale View). A screen whose cursor row no longer matches `state.currentLine` is ignored. `lineText` is always set for grid views.
|
|
343
|
+
|
|
314
344
|
```ts
|
|
315
345
|
import { getSemanticContext } from '@yam8d/m8-sdk'
|
|
316
346
|
|
|
@@ -325,6 +355,10 @@ if (ctx?.isGridView && ctx.row) {
|
|
|
325
355
|
|
|
326
356
|
Returns a human-readable summary of the context (see examples above).
|
|
327
357
|
|
|
358
|
+
### `describeContextParts(ctx: M8SemanticContext): M8DescriptionPart[]`
|
|
359
|
+
|
|
360
|
+
The summary as ordered, tagged parts; `describeContext()` joins their text with `' — '`.
|
|
361
|
+
|
|
328
362
|
### `formatFieldValue(field: M8ParsedField): string`
|
|
329
363
|
|
|
330
364
|
Formats a single parsed field as a display string:
|
|
@@ -339,17 +373,40 @@ Formats a single parsed field as a display string:
|
|
|
339
373
|
| `chainRef` / `phraseRef` / `fxCommand` / `volume` | raw value, e.g. `"0A"`, `"KIL"` |
|
|
340
374
|
| empty cell | `"(empty)"` |
|
|
341
375
|
|
|
342
|
-
### `lookupFxCommand(cmd: string):
|
|
376
|
+
### `lookupFxCommand(cmd: string): M8FxCommandInfo | undefined`
|
|
343
377
|
|
|
344
|
-
Looks up a 3-character FX command name (case-insensitive) across all categories (sequencer, instrument, mixer).
|
|
378
|
+
Looks up a 3-character FX command name (case-insensitive) across all categories (sequencer, instrument, modulation, mixer). Modulator commands carry their slot as the third character (`EA1`, `LF3`).
|
|
345
379
|
|
|
346
380
|
```ts
|
|
347
381
|
import { lookupFxCommand } from '@yam8d/m8-sdk'
|
|
348
382
|
|
|
349
|
-
|
|
350
|
-
// → { description: 'Kill: stops the playing instrument after XX ticks.'
|
|
383
|
+
lookupFxCommand('KIL')
|
|
384
|
+
// → { description: 'Kill: stops the playing instrument after XX ticks.',
|
|
385
|
+
// category: 'sequencer', relative: false, instrumentTypes: null, slot: null }
|
|
386
|
+
lookupFxCommand('FM3')
|
|
387
|
+
// → { …, category: 'instrument', relative: true, instrumentTypes: ['fmsynth'], slot: null }
|
|
388
|
+
lookupFxCommand('LF3')
|
|
389
|
+
// → { …, category: 'modulation', relative: false, instrumentTypes: null, slot: 3 }
|
|
351
390
|
```
|
|
352
391
|
|
|
392
|
+
`instrumentTypes` lists the instrument types that offer the command when not every type does (`null` = all, or not an instrument command).
|
|
393
|
+
|
|
394
|
+
### `getInstrumentFxCommands(type: string): M8InstrumentFxList | null`
|
|
395
|
+
|
|
396
|
+
The instrument commands offered by an instrument type (the "Current Instrument" section of the Effect Command Help view, opened with `[EDIT]+[UP/DOWN]` on an FX command). `type` is the key from `M8SemanticContext.instrumentType.key`.
|
|
397
|
+
|
|
398
|
+
```ts
|
|
399
|
+
getInstrumentFxCommands('hypersynth')
|
|
400
|
+
// → { type: 'hypersynth', verified: true,
|
|
401
|
+
// commands: ['VOL','PIT','FIN','CRD','CVO','SWM','WID','SUB','FIL','CUT','RES','AMP','LIM','PAN','SNC','ERR','DRY','SMX','SDL','SRV'] }
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
`verified: true` means the list was read from a real M8 (Model:02): **sampler, macrosynth, fmsynth, hypersynth**. Wavsynth and External were not available on that device, so their lists are unknown (`null`); `midiout` only holds the documented `CHD`/`ADD`. The Sequencer FX and Mixer/Effects sections are the same for every type, and the Instrument Mods section depends on the kind of each modulator slot (envelope: `EA AT HO DE ET`, LFO: `LA LO LS LF LT`).
|
|
405
|
+
|
|
406
|
+
### `RELATIVE_FX_RULE: string`
|
|
407
|
+
|
|
408
|
+
The manual's rule for relative commands, for tooltips.
|
|
409
|
+
|
|
353
410
|
---
|
|
354
411
|
|
|
355
412
|
## Types reference
|
|
@@ -398,18 +455,59 @@ interface M8SemanticContext {
|
|
|
398
455
|
viewDescription: string | null // long description from schema
|
|
399
456
|
viewId: string | null // item ID parsed from screen title, e.g. 'F2', '03'; null for song/instrumentpool
|
|
400
457
|
isUnsaved: boolean // true when the title carries a '*' suffix (unsaved changes)
|
|
401
|
-
isGridView: boolean // true for song/chain/phrase/table/groove/instrumentpool
|
|
458
|
+
isGridView: boolean // true for song/chain/phrase/table/groove/scale/instrumentpool
|
|
459
|
+
isParameterView: boolean // true for the label/value views (inst, mixer, project, …)
|
|
460
|
+
section: string | null // effectsettings: 'MODFX' | 'DELAY' | 'REVERB'
|
|
461
|
+
instrumentType: { text: string; key: string | null } | null // inst view + screen, e.g. { text: 'WAVSYNTH', key: 'wavsynth' }
|
|
402
462
|
row: M8ParsedRow | null // all columns on the line at cursorPos.y
|
|
403
463
|
activeField: M8ActiveField | null // the column currently under the cursor
|
|
464
|
+
lineText: string | null // cursor row text, playback marker removed
|
|
465
|
+
steps: M8ParsedRow[] | null // phrase view + screen: all 16 steps (index = step)
|
|
466
|
+
carriedRepLane: number | null // FX lane (1–3) showing '^^' (REP from previous phrase)
|
|
467
|
+
fxLane: M8FxLaneTrace | null // phrase view + screen: what the FX cell means in its lane
|
|
468
|
+
relativeFx: Record<string, M8RelativeFxState> | null // phrase view + screen: relative commands in force, with net change since the last trigger
|
|
469
|
+
resetsRelative: Record<string, M8RelativeFxState> | null // phrase view + screen: when the cursor step triggers the instrument (I number or RET), the relative changes it puts back
|
|
470
|
+
scaleNote: M8ScaleNote | null // scale view: the interval row under the cursor { interval, semitone, enabled, offset }
|
|
471
|
+
scale: M8ScaleInfo | null // scale view + screen: the 12 intervals interpreted together
|
|
404
472
|
}
|
|
405
473
|
```
|
|
406
474
|
|
|
475
|
+
### `M8DescriptionPart`
|
|
476
|
+
|
|
477
|
+
```ts
|
|
478
|
+
interface M8DescriptionPart {
|
|
479
|
+
kind: M8DescriptionPartKind
|
|
480
|
+
text: string
|
|
481
|
+
}
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
Parts come in reading order; a kind can appear more than once.
|
|
485
|
+
|
|
486
|
+
| Kind | Example |
|
|
487
|
+
|---|---|
|
|
488
|
+
| `field` | `"FX1 Command: KIL"`, `"Tempo (TEMPO): 120.00 BPM"` |
|
|
489
|
+
| `fxInfo` | `"(Kill: stops the playing instrument after XX ticks)"` |
|
|
490
|
+
| `fxTarget` | on an FX value: `"for KIL (…)"` |
|
|
491
|
+
| `meaning` | `"value 03: stops the note after 3 ticks"`, `"E is detuned by −0.50 st"` |
|
|
492
|
+
| `fxLane` | `"REP still active: VOL reaches 09 on this step (+02 per step since step 1)"` |
|
|
493
|
+
| `relative` | `"relative: VOL has moved by +0C over 2 steps since …"`, `"triggers the instrument again: resets …"` |
|
|
494
|
+
| `optionInfo` | what the selected option does |
|
|
495
|
+
| `fieldInfo` | what the field is |
|
|
496
|
+
| `fileInfo` | `"directory: [EDIT] opens it"` |
|
|
497
|
+
| `instrument` | `"Wavsynth instrument"` |
|
|
498
|
+
| `section` | `"Delay"`, `"MOD2"` |
|
|
499
|
+
| `scale` | `"Scale: C D E F G A B"`, `"Major (Ionian); detuned: E −0.50 st"` |
|
|
500
|
+
| `track` | `"Track 3"` |
|
|
501
|
+
| `location` | `"Phrase View row 07"`, `"Mixer View"` |
|
|
502
|
+
| `line` | the cursor row's text, when no field on it is recognised |
|
|
503
|
+
|
|
407
504
|
### `M8ParsedRow`
|
|
408
505
|
|
|
409
506
|
```ts
|
|
410
507
|
interface M8ParsedRow {
|
|
411
508
|
rowIndex: number | null // hex row index from leftmost chars; null if unparseable
|
|
412
509
|
rowKey: string // schema key, e.g. 'songRow', 'step', 'chainPos'
|
|
510
|
+
rowId: string | null // parameter views: matched schema row ('tempo', 'gain', …)
|
|
413
511
|
fields: Record<string, M8ParsedField> // column key → parsed field
|
|
414
512
|
}
|
|
415
513
|
```
|
|
@@ -427,6 +525,15 @@ interface M8ParsedField {
|
|
|
427
525
|
hexValue: number | null // parsed integer; null for empty cells and text types
|
|
428
526
|
isEmpty: boolean // true when '--', '---', '---00', etc.
|
|
429
527
|
meta?: Record<string, unknown> // view-specific extras (e.g. { trackIndex: 3 })
|
|
528
|
+
// parameter views (all optional):
|
|
529
|
+
description?: string // what the field is
|
|
530
|
+
text?: string | null // non-numeric part: option name, caption, name, instrument type
|
|
531
|
+
numericValue?: number | null // value in its natural base (hex, decimal, fractional)
|
|
532
|
+
values?: number[] | null // both numbers of an 'XX:YY' pair
|
|
533
|
+
parts?: string[] // names of those numbers, e.g. ['left time', 'right time']
|
|
534
|
+
unit?: string // e.g. ' BPM', ' dB'
|
|
535
|
+
valueDescription?: string // what the selected option does
|
|
536
|
+
fileKind?: M8FileKind // file browser rows: 'parent' | 'directory' | 'instrumentPreset' | 'sample' | 'm8file' | 'file'
|
|
430
537
|
}
|
|
431
538
|
|
|
432
539
|
interface M8ActiveField extends M8ParsedField {
|
|
@@ -453,6 +560,16 @@ type M8FieldType =
|
|
|
453
560
|
| 'instrumentName' // instrument name text ≤12 chars; no hexValue
|
|
454
561
|
| 'eqSlot' // EQ slot assignment hex; '--' = none
|
|
455
562
|
| 'rowIndex' // row/step index hex
|
|
563
|
+
| 'noteInterval' // scale view row label: C, C#, D, …
|
|
564
|
+
| 'onOff' // 'ON' / 'OFF' toggle
|
|
565
|
+
| 'semitoneOffset' // scale view detune, e.g. '-00.50'
|
|
566
|
+
| 'swing' // groove swing percentage
|
|
567
|
+
| 'instrumentType' // instrument engine: WAVSYNTH, SAMPLER, FMSYNTH, …
|
|
568
|
+
| 'name' // free-text name field; dashes = unnamed
|
|
569
|
+
| 'parameter' // named editable value: CUTOFF, TEMPO, GAIN, …
|
|
570
|
+
| 'option' // choice from a list: '00CHORUS', 'BELL', 'STEREO'
|
|
571
|
+
| 'action' // button: LOAD, SAVE, RENDER, SETTINGS, EQ, …
|
|
572
|
+
| 'fileEntry' // file browser row: '/folder', '/..', 'Bass.m8i'
|
|
456
573
|
```
|
|
457
574
|
|
|
458
575
|
### `M8KeyName`
|
|
@@ -495,16 +612,28 @@ The semantic context parser supports these `viewName` values:
|
|
|
495
612
|
| `chain` | `phrase` (phraseRef), `transpose` |
|
|
496
613
|
| `phrase` | `note`, `vel`, `inst`, `fx1cmd`, `fx1val`, `fx2cmd`, `fx2val`, `fx3cmd`, `fx3val` |
|
|
497
614
|
| `table` | `transpose`, `volume`, `fx1cmd`, `fx1val`, `fx2cmd`, `fx2val`, `fx3cmd`, `fx3val` |
|
|
498
|
-
| `groove` | `ticks`, `ppq` (row 0 only) |
|
|
615
|
+
| `groove` | `ticks`, `ppq` (row 0 only), `swing` (row 0 only) |
|
|
616
|
+
| `scale` | `interval`, `en` (onOff), `offset` (semitoneOffset) |
|
|
499
617
|
| `instrumentpool` | `name`, `dry`, `mx`, `de`, `rv`, `eq` |
|
|
500
|
-
|
|
501
|
-
|
|
618
|
+
| `inst` | header: `instrumentType`, `load`/`save` (action), `name`, `transpose` (onOff), `tableTic`, `eq`; then the type's parameters as label/value pairs (`parameter` / `option`), described per instrument type |
|
|
619
|
+
| `instmods` | per modulation slot: type (`option`), `dest`, and the type's parameters (`amt`, `atk`, `hold`, `dec`, `sus`, `rel`, `peak`, `body`, `osc`, `trig`, `freq`, `src`, `lval`, `hval`) |
|
|
620
|
+
| `mixer` | `speakerVol`, `track1`–`track8`, `modfxVol`/`delayVol`/`reverbVol`, `inputVol`/`inputVol2`/`usbVol` and their sends, `mixEq` (action), `mainVol`, `limiter`, `djFilter`, `ott` |
|
|
621
|
+
| `project` | `tempo`, `transpose`, `groove`/`scale`/`liveQuantize` (option), `name`, and the `load`/`save`/`new`/`render`/`bundle`/… actions |
|
|
622
|
+
| `effectsettings` | per `section` (MODFX / DELAY / REVERB): type, input EQ (action), depth/frequency pairs, width, sends, delay time, feedback, room size, decay/shimmer |
|
|
623
|
+
| `mixeq`, `modfxeq`, `delayeq`, `reverbeq` | LOW/MID/HIGH band `gain`, `freq`, `q`, `type` (option), `mode` (option) |
|
|
624
|
+
| `mixscope`, `limiterscope` | `zoom`, `peak`, `softClip`, `mainVol`, `limiter`, `djFilter`, `ott`, `mixEq`; `atk`/`rel`/`type`/`res`/`time`/`color` as label/value pairs |
|
|
625
|
+
| `systemsettings` | `backlight`, `fontOptions`, `editTheme` (action), `notePreview`, `recCountIn`, `metronomeVol`, `usbAudioMode`, `usbMainOut`, `lineInGate`, `keyDelayRep`, … |
|
|
626
|
+
| `loadinstrument`, `selectsavedirectory` | `entry` (fileEntry) |
|
|
627
|
+
| `createdirectory` | `name` |
|
|
628
|
+
|
|
629
|
+
Grid views are read by column position (`src/m8-view-context.json`). Parameter views are label/value screens: a row is recognised from its label text and its cells come from `src/m8-parameter-views.json`, whose column positions were measured on the manual's screenshots. Instrument parameters vary with the instrument type, so they are read as label/value pairs and looked up in a per-type vocabulary. Layouts that only appear for some instrument types (Sampler `SAMPLE` row, FM operators, Hypersynth chord, MIDI CC rows) are best-effort.
|
|
502
630
|
|
|
503
631
|
---
|
|
504
632
|
|
|
505
633
|
## Notes
|
|
506
634
|
|
|
507
|
-
- **
|
|
635
|
+
- **Screen geometry** — The screen is 40 × 24 characters. Every row has a one-column left margin, so schema `x` positions count from column 1 and `cursorPos.x` is the schema `x` + 1 (the SDK accounts for this). Titles are on row 3 and content starts on row 5. The text stream is lower case (`tempo`, `b-4`, `ff`); the SDK matches case-insensitively and shows values upper case, except user-typed names and file names.
|
|
636
|
+
- **Playback indicator** — When a row is actively playing the M8 draws `<` or `>` in the left margin, so it appears as the first character of `currentLine`. The SDK strips this automatically before parsing so column offsets remain consistent.
|
|
508
637
|
- **Font mode** — All column offsets assume font mode 0 (Headless: 8×10 px cells; Model:02: 12×14 px cells). Font modes 1 (bold) and 2 (large) may shift positions.
|
|
509
638
|
- **Schema file** — View and column definitions live in `src/m8-view-context.json` and are bundled into `dist/index.js` at build time.
|
|
510
639
|
- **Requirement** — The app must run inside the yam8d host iframe. The `ChildHandshake` from `post-me` will never resolve in a standalone tab.
|
|
@@ -565,7 +694,9 @@ The SDK can interpret the current cursor position and row text as typed, labelle
|
|
|
565
694
|
const ctx = m8.getSemanticContext()
|
|
566
695
|
// or as a human-readable string:
|
|
567
696
|
const description = m8.describeContext()
|
|
568
|
-
// e.g. "Track 3 —
|
|
697
|
+
// e.g. "Track 3: 0A — Track 3 — Song View row 01"
|
|
698
|
+
// or as tagged parts to build your own:
|
|
699
|
+
const parts = m8.describeContextParts()
|
|
569
700
|
```
|
|
570
701
|
|
|
571
702
|
### Standalone functions
|
|
@@ -645,6 +776,16 @@ interface M8ParsedField {
|
|
|
645
776
|
| `instrumentName` | Instrument name text (up to 12 chars). No `hexValue`. |
|
|
646
777
|
| `eqSlot` | EQ slot assignment (hex). `--` = none. |
|
|
647
778
|
| `rowIndex` | Row/step index (hex). |
|
|
779
|
+
| `noteInterval` | Scale View row label (`C`, `C#`, …). |
|
|
780
|
+
| `onOff` | `ON` / `OFF` toggle. |
|
|
781
|
+
| `semitoneOffset` | Scale View detune, e.g. `-00.50`. |
|
|
782
|
+
| `swing` | Groove swing percentage. |
|
|
783
|
+
| `instrumentType` | Instrument engine (`WAVSYNTH`, `SAMPLER`, …); `text` holds the name. |
|
|
784
|
+
| `name` | Free-text name field; a row of dashes = unnamed. |
|
|
785
|
+
| `parameter` | Named editable value (`CUTOFF`, `TEMPO`, `GAIN`); read `hexValue` / `numericValue` / `values`. |
|
|
786
|
+
| `option` | Choice from a list (`00CHORUS`, `BELL`); `hexValue` is the index when shown, `text` the name. |
|
|
787
|
+
| `action` | Button caption (`LOAD`, `SAVE`, `RENDER`, `SETTINGS`); `text` holds it. |
|
|
788
|
+
| `fileEntry` | File browser row: `/folder`, `/..`, or a file name. |
|
|
648
789
|
|
|
649
790
|
### Playback indicator
|
|
650
791
|
|