@yam8d/m8-sdk 0.3.3 → 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 +1377 -204
- 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/types/viewContext.d.ts
CHANGED
|
@@ -4,11 +4,51 @@
|
|
|
4
4
|
* Derives semantic meaning from raw M8State by mapping cursor position and
|
|
5
5
|
* currentLine content to typed, labelled fields using the m8-view-context.json schema.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* Every view listed in viewlist.json is mapped: the grid views (song, chain, phrase,
|
|
8
|
+
* table, groove, scale, instrument pool) through their columns, the parameter views
|
|
9
|
+
* (instrument, modulation, mixer, project, effects, EQ, scope, system settings, file
|
|
10
|
+
* browsers) through the label/value layouts in m8-parameter-views.json.
|
|
9
11
|
*/
|
|
10
|
-
import type { M8State } from './types';
|
|
11
|
-
|
|
12
|
+
import type { M8Screen, M8State } from './types';
|
|
13
|
+
import { type ValueFormat } from './parameterViews';
|
|
14
|
+
import { type M8FxLaneTrace, type M8RelativeFxState } from './fxInsight';
|
|
15
|
+
import { type M8ScaleInfo, type M8ScaleNote } from './scaleInsight';
|
|
16
|
+
export type { M8FxLaneTrace, M8RelativeFxState } from './fxInsight';
|
|
17
|
+
export { getInstrumentFxCommands, lookupFxCommand, RELATIVE_FX_RULE } from './fxCommands';
|
|
18
|
+
export type { M8FxCommandInfo, M8InstrumentFxList } from './fxCommands';
|
|
19
|
+
export type { M8ScaleInfo, M8ScaleNote } from './scaleInsight';
|
|
20
|
+
export type M8FieldType = 'chainRef' | 'phraseRef' | 'note' | 'velocity' | 'instrumentRef' | 'fxCommand' | 'fxValue' | 'transpose' | 'ticks' | 'volume' | 'ppq' | 'instrumentName' | 'eqSlot' | 'rowIndex' | 'noteInterval' | 'onOff' | 'semitoneOffset' | 'swing'
|
|
21
|
+
/** Instrument engine of the TYPE field (WAVSYNTH, SAMPLER, …). */
|
|
22
|
+
| 'instrumentType'
|
|
23
|
+
/** Free-text name field (instrument, song, directory). */
|
|
24
|
+
| 'name'
|
|
25
|
+
/** Named, editable value (CUTOFF, TEMPO, GAIN, …). */
|
|
26
|
+
| 'parameter'
|
|
27
|
+
/** Choice from a list, e.g. '00CHORUS', 'BELL'. */
|
|
28
|
+
| 'option'
|
|
29
|
+
/** Button-like caption (LOAD, SAVE, RENDER, SETTINGS, …). */
|
|
30
|
+
| 'action'
|
|
31
|
+
/** Row of a file browser ('/folder', '/..', 'Bass.m8i'). */
|
|
32
|
+
| 'fileEntry';
|
|
33
|
+
/** What a file browser entry is: '/..', '/folder', 'Bass.m8i', 'kick.wav', 'song.m8s', anything else. */
|
|
34
|
+
export type M8FileKind = 'parent' | 'directory' | 'instrumentPreset' | 'sample' | 'm8file' | 'file';
|
|
35
|
+
export interface ColumnDef {
|
|
36
|
+
x: number;
|
|
37
|
+
width: number;
|
|
38
|
+
key: string;
|
|
39
|
+
type: M8FieldType;
|
|
40
|
+
label: string;
|
|
41
|
+
description?: string;
|
|
42
|
+
meta?: Record<string, unknown>;
|
|
43
|
+
/** How to read the text (parameter views); grid views use the type's built-in reading. */
|
|
44
|
+
format?: ValueFormat;
|
|
45
|
+
/** Unit appended when showing the value (' BPM', ' dB', ' ms'). */
|
|
46
|
+
unit?: string;
|
|
47
|
+
/** Names of the numbers of an 'XX:YY' pair (['delay', 'repeat']). */
|
|
48
|
+
parts?: string[];
|
|
49
|
+
/** Explanations of the options a choice cell can show, keyed by option name. */
|
|
50
|
+
options?: Record<string, string>;
|
|
51
|
+
}
|
|
12
52
|
/**
|
|
13
53
|
* A single parsed field value extracted from the currentLine.
|
|
14
54
|
*/
|
|
@@ -30,6 +70,25 @@ export interface M8ParsedField {
|
|
|
30
70
|
isEmpty: boolean;
|
|
31
71
|
/** Extra view-specific metadata (e.g. { trackIndex: 2 } for song view track columns). */
|
|
32
72
|
meta?: Record<string, unknown>;
|
|
73
|
+
/** What this field is, from the schema (parameter views). */
|
|
74
|
+
description?: string;
|
|
75
|
+
/**
|
|
76
|
+
* Parameter views: the non-numeric part of the value - option name ('CHORUS'),
|
|
77
|
+
* button caption ('LOAD'), instrument type ('WAVSYNTH'), name text. null otherwise.
|
|
78
|
+
*/
|
|
79
|
+
text?: string | null;
|
|
80
|
+
/** Parameter views: the value as a number in its natural base (hex, decimal or fractional). */
|
|
81
|
+
numericValue?: number | null;
|
|
82
|
+
/** Parameter views: both numbers of an 'XX:YY' pair (e.g. delay time left/right). */
|
|
83
|
+
values?: number[] | null;
|
|
84
|
+
/** Names of the numbers in `values`, e.g. ['left time', 'right time']. */
|
|
85
|
+
parts?: string[];
|
|
86
|
+
/** Unit of the value, e.g. ' BPM'. */
|
|
87
|
+
unit?: string;
|
|
88
|
+
/** What the currently selected option does (choice cells that list their options). */
|
|
89
|
+
valueDescription?: string;
|
|
90
|
+
/** File browser rows: what the entry is. */
|
|
91
|
+
fileKind?: M8FileKind;
|
|
33
92
|
}
|
|
34
93
|
/**
|
|
35
94
|
* All fields parsed from the current row (line at cursorPos.y).
|
|
@@ -39,6 +98,8 @@ export interface M8ParsedRow {
|
|
|
39
98
|
rowIndex: number | null;
|
|
40
99
|
/** Schema key for the row index field (e.g. 'songRow', 'step', 'chainPos'). */
|
|
41
100
|
rowKey: string;
|
|
101
|
+
/** Parameter views: id of the schema row that matched this line ('tempo', 'gain', …); null for grid views. */
|
|
102
|
+
rowId: string | null;
|
|
42
103
|
/** Map of column key → parsed field for every column in this view. */
|
|
43
104
|
fields: Record<string, M8ParsedField>;
|
|
44
105
|
}
|
|
@@ -71,21 +132,108 @@ export interface M8SemanticContext {
|
|
|
71
132
|
isUnsaved: boolean;
|
|
72
133
|
/** Whether this view is a structured grid (song/chain/phrase/table/groove). */
|
|
73
134
|
isGridView: boolean;
|
|
135
|
+
/** Whether this is a label/value parameter view (instrument, mixer, project, effects, EQ, …). */
|
|
136
|
+
isParameterView: boolean;
|
|
137
|
+
/** Effect Settings View: the block the cursor is in ('MODFX', 'DELAY', 'REVERB'). */
|
|
138
|
+
section: string | null;
|
|
139
|
+
/**
|
|
140
|
+
* Instrument View: the engine on the TYPE row as displayed ('WAVSYNTH'), and its
|
|
141
|
+
* normalised key ('wavsynth', 'macrosynth', 'sampler', 'fmsynth', 'hypersynth',
|
|
142
|
+
* 'external', 'midiout'). Needs the screen; null otherwise.
|
|
143
|
+
*/
|
|
144
|
+
instrumentType: {
|
|
145
|
+
text: string;
|
|
146
|
+
key: string | null;
|
|
147
|
+
} | null;
|
|
74
148
|
/** All fields on the line at cursorPos.y (null for non-grid views or missing line). */
|
|
75
149
|
row: M8ParsedRow | null;
|
|
76
150
|
/** The specific field under the cursor (null when cursor is out of any column range). */
|
|
77
151
|
activeField: M8ActiveField | null;
|
|
152
|
+
/** Text of the cursor row with the playback marker removed (null when there is none). */
|
|
153
|
+
lineText: string | null;
|
|
154
|
+
/**
|
|
155
|
+
* Every step of the current phrase (index = step 0-F), so an FX cell can be read
|
|
156
|
+
* against the cells above it. Only filled for the phrase view, and only when a
|
|
157
|
+
* screen matching the cursor row was passed to getSemanticContext().
|
|
158
|
+
*/
|
|
159
|
+
steps: M8ParsedRow[] | null;
|
|
160
|
+
/**
|
|
161
|
+
* FX lane (1-3) that shows the '^^' marker: a REP from a previous phrase is still
|
|
162
|
+
* running there. null when no marker is on screen or there is no screen.
|
|
163
|
+
*/
|
|
164
|
+
carriedRepLane: number | null;
|
|
165
|
+
/** What the active FX cell means in the light of its lane (phrase view with `steps`). */
|
|
166
|
+
fxLane: M8FxLaneTrace | null;
|
|
167
|
+
/**
|
|
168
|
+
* Relative instrument commands (VOL, CUT…) in force after the active step, with their
|
|
169
|
+
* net change since the last note trigger (an instrument number in the I column or a RET).
|
|
170
|
+
* Phrase view with `steps` only; null otherwise.
|
|
171
|
+
*/
|
|
172
|
+
relativeFx: Record<string, M8RelativeFxState> | null;
|
|
173
|
+
/**
|
|
174
|
+
* When the cursor step triggers the instrument again (an instrument number in the I
|
|
175
|
+
* column, or a RET), the relative commands in force just before it: the trigger puts
|
|
176
|
+
* their parameters back. Entries can have a net change of 0. Phrase view with `steps`,
|
|
177
|
+
* from step 1 on; null otherwise.
|
|
178
|
+
*/
|
|
179
|
+
resetsRelative: Record<string, M8RelativeFxState> | null;
|
|
180
|
+
/** Scale View: the interval row under the cursor. Null on the other rows and views. */
|
|
181
|
+
scaleNote: M8ScaleNote | null;
|
|
182
|
+
/** Scale View only, when the whole screen was passed: the 12 intervals interpreted together. */
|
|
183
|
+
scale: M8ScaleInfo | null;
|
|
184
|
+
}
|
|
185
|
+
/** What a part of the description says, so a consumer can keep, drop, reorder or style it. */
|
|
186
|
+
export type M8DescriptionPartKind =
|
|
187
|
+
/** Label and value of the field under the cursor: "FX1 Command: KIL", "Tempo (TEMPO): 120.00 BPM". */
|
|
188
|
+
'field'
|
|
189
|
+
/** What the FX command does in general: "(Kill: stops the playing instrument after XX ticks)". */
|
|
190
|
+
| 'fxInfo'
|
|
191
|
+
/** On an FX value, the command it belongs to: "for KIL (…)". */
|
|
192
|
+
| 'fxTarget'
|
|
193
|
+
/** What the value does here: "value 03: stops the note after 3 ticks", "E is detuned by −0.50 st". */
|
|
194
|
+
| 'meaning'
|
|
195
|
+
/** The FX lane read down the phrase: a running REP, its RTO limit, REP00… */
|
|
196
|
+
| 'fxLane'
|
|
197
|
+
/** Relative commands: their net change since the last trigger, or what a trigger resets. */
|
|
198
|
+
| 'relative'
|
|
199
|
+
/** What the selected option does. */
|
|
200
|
+
| 'optionInfo'
|
|
201
|
+
/** What the field is. */
|
|
202
|
+
| 'fieldInfo'
|
|
203
|
+
/** File browser: what the entry is and what [EDIT] does. */
|
|
204
|
+
| 'fileInfo'
|
|
205
|
+
/** Instrument View: the engine ("Wavsynth instrument"). */
|
|
206
|
+
| 'instrument'
|
|
207
|
+
/** Effect Settings block or modulator slot ("Delay", "MOD2"). */
|
|
208
|
+
| 'section'
|
|
209
|
+
/** Scale View: the scale the 12 intervals spell. */
|
|
210
|
+
| 'scale'
|
|
211
|
+
/** Song View: the track of the cell. */
|
|
212
|
+
| 'track'
|
|
213
|
+
/** Where the cursor is: view, item number, row ("Phrase View row 07", "Mixer View"). */
|
|
214
|
+
| 'location'
|
|
215
|
+
/** Text of the cursor row, when no field on it is recognised. */
|
|
216
|
+
| 'line';
|
|
217
|
+
/** One piece of describeContext(); a kind can appear more than once. */
|
|
218
|
+
export interface M8DescriptionPart {
|
|
219
|
+
kind: M8DescriptionPartKind;
|
|
220
|
+
text: string;
|
|
78
221
|
}
|
|
79
222
|
/**
|
|
80
|
-
*
|
|
81
|
-
*
|
|
223
|
+
* Every screen row has a one-column left margin (the playback marker '<' / '>' is drawn
|
|
224
|
+
* in it), so the schema's x positions are counted from column 1, and `cursorPos.x` is
|
|
225
|
+
* one more than the schema x of the cell it covers. `currentLine` is trimmed and so
|
|
226
|
+
* already starts at the schema's column 0.
|
|
82
227
|
*/
|
|
83
|
-
export declare
|
|
84
|
-
description: string;
|
|
85
|
-
} | undefined;
|
|
228
|
+
export declare const SCREEN_MARGIN = 1;
|
|
86
229
|
/**
|
|
87
230
|
* Derives a full semantic context from the current M8State.
|
|
88
231
|
*
|
|
232
|
+
* Pass the whole `screen` (see M8Client.getScreen) to let the context look beyond the
|
|
233
|
+
* cursor row: the other steps of a phrase (so an FX cell can be read against the
|
|
234
|
+
* commands above it) and the other rows of the Scale View. Without a screen, or with
|
|
235
|
+
* one that no longer matches the cursor row, only the cursor row is interpreted.
|
|
236
|
+
*
|
|
89
237
|
* @example
|
|
90
238
|
* ```ts
|
|
91
239
|
* const ctx = getSemanticContext(state)
|
|
@@ -96,17 +244,33 @@ export declare function lookupFxCommand(cmd: string): {
|
|
|
96
244
|
* }
|
|
97
245
|
* ```
|
|
98
246
|
*/
|
|
99
|
-
export declare function getSemanticContext(state: M8State): M8SemanticContext | null;
|
|
247
|
+
export declare function getSemanticContext(state: M8State, screen?: M8Screen | null): M8SemanticContext | null;
|
|
248
|
+
/**
|
|
249
|
+
* What the cursor is on, as ordered, tagged parts. Every part is built from
|
|
250
|
+
* `ctx` alone, so a consumer can keep, drop, reorder or restyle them, or ignore them
|
|
251
|
+
* and write its own text from the context.
|
|
252
|
+
*
|
|
253
|
+
* @example
|
|
254
|
+
* ```ts
|
|
255
|
+
* describeContextParts(ctx)
|
|
256
|
+
* // [{ kind: 'field', text: 'FX2 Command: KIL' },
|
|
257
|
+
* // { kind: 'fxInfo', text: '(Kill: stops the playing instrument after XX ticks)' },
|
|
258
|
+
* // { kind: 'meaning', text: 'value 03: stops the note after 3 ticks' },
|
|
259
|
+
* // { kind: 'location', text: 'Phrase View row 01' }]
|
|
260
|
+
* ```
|
|
261
|
+
*/
|
|
262
|
+
export declare function describeContextParts(ctx: M8SemanticContext): M8DescriptionPart[];
|
|
100
263
|
/**
|
|
101
|
-
* Returns a short human-readable description of what the cursor is currently on
|
|
264
|
+
* Returns a short human-readable description of what the cursor is currently on:
|
|
265
|
+
* the text of describeContextParts(), joined with ' — '.
|
|
102
266
|
*
|
|
103
267
|
* @example
|
|
104
|
-
* "Track 3 —
|
|
105
|
-
* "Note
|
|
106
|
-
* "
|
|
268
|
+
* "Track 3: 0A — Track 3 — Song View row 01"
|
|
269
|
+
* "Note (N): Note C-4 — Phrase View row 00"
|
|
270
|
+
* "FX2 Command: KIL — (Kill: stops the playing instrument after XX ticks) — value 03: stops the note after 3 ticks — Phrase View row 01"
|
|
107
271
|
*/
|
|
108
272
|
export declare function describeContext(ctx: M8SemanticContext): string;
|
|
109
273
|
/**
|
|
110
274
|
* Formats a parsed field value as a human-readable string.
|
|
111
275
|
*/
|
|
112
|
-
export declare function formatFieldValue(
|
|
276
|
+
export declare function formatFieldValue(input: M8ParsedField): string;
|