@yam8d/m8-sdk 0.3.3 → 0.5.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 +898 -655
- package/dist/index.js +4470 -249
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/types/client.d.ts +94 -5
- package/types/engine/astar.d.ts +15 -0
- package/types/engine/audio.d.ts +29 -0
- package/types/engine/bus.d.ts +13 -0
- package/types/engine/connectWithRetry.d.ts +9 -0
- package/types/engine/connection.d.ts +56 -0
- package/types/engine/cursorNavigator.d.ts +15 -0
- package/types/engine/engine.d.ts +30 -0
- package/types/engine/eventBus.d.ts +5 -0
- package/types/engine/host/fileBrowserHelpers.d.ts +59 -0
- package/types/engine/host/fileBrowserSearch.d.ts +13 -0
- package/types/engine/host/floatEditor.d.ts +2 -0
- package/types/engine/host/hostIO.d.ts +30 -0
- package/types/engine/host/hostMethods.d.ts +22 -0
- package/types/engine/host/hostState.d.ts +7 -0
- package/types/engine/host/keySequences.d.ts +2 -0
- package/types/engine/host/midiTransport.d.ts +10 -0
- package/types/engine/host/valueEditors.d.ts +7 -0
- package/types/engine/host/valueParsers.d.ts +24 -0
- package/types/engine/index.d.ts +14 -0
- package/types/engine/keys.d.ts +28 -0
- package/types/engine/macroRunner.d.ts +15 -0
- package/types/engine/protocol.d.ts +138 -0
- package/types/engine/queuedReaders.d.ts +18 -0
- package/types/engine/store.d.ts +65 -0
- package/types/engine/viewExtractor.d.ts +27 -0
- package/types/engine/viewGraph.d.ts +9 -0
- package/types/engine/viewNavigation.d.ts +16 -0
- package/types/fxCommands.d.ts +47 -0
- package/types/fxInsight.d.ts +136 -0
- package/types/index.d.ts +9 -3
- package/types/parameterViews.d.ts +104 -0
- package/types/scaleInsight.d.ts +47 -0
- package/types/theme.d.ts +42 -0
- package/types/types.d.ts +131 -0
- package/types/viewContext.d.ts +216 -15
package/types/types.d.ts
CHANGED
|
@@ -26,6 +26,11 @@ export interface M8State {
|
|
|
26
26
|
highlightColor: RGB | null;
|
|
27
27
|
titleColor: RGB | null;
|
|
28
28
|
backgroundColor: RGB | null;
|
|
29
|
+
/**
|
|
30
|
+
* Colour of the cursor rectangle as last drawn. The M8 animates the cursor, so it is not
|
|
31
|
+
* the theme's CURSOR colour (read that with parseThemeScreen). Absent before SDK 0.5.
|
|
32
|
+
*/
|
|
33
|
+
cursorColor?: RGB | null;
|
|
29
34
|
textUnderCursor: string | null;
|
|
30
35
|
currentLine: string | null;
|
|
31
36
|
deviceModel: string | null;
|
|
@@ -35,7 +40,38 @@ export interface M8State {
|
|
|
35
40
|
macroCurrentStep?: number;
|
|
36
41
|
macroSequenceLength?: number;
|
|
37
42
|
}
|
|
43
|
+
export interface M8Screen {
|
|
44
|
+
width: number;
|
|
45
|
+
height: number;
|
|
46
|
+
/** One string per screen row; columns preserved, trailing spaces trimmed. */
|
|
47
|
+
lines: string[];
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* The screen with the colour of every character cell, for apps that want to look like
|
|
51
|
+
* the device (or learn which theme colour the M8 uses for what).
|
|
52
|
+
*/
|
|
53
|
+
export interface M8ScreenCells extends M8Screen {
|
|
54
|
+
/** fg[row][col]: foreground colour as '#rrggbb'; null where no character was drawn. Each row has `width` entries. */
|
|
55
|
+
fg: (string | null)[][];
|
|
56
|
+
/** bg[row][col]: background colour behind the character, same layout as `fg`. */
|
|
57
|
+
bg: (string | null)[][];
|
|
58
|
+
}
|
|
38
59
|
export type M8KeyName = 'left' | 'right' | 'up' | 'down' | 'shift' | 'play' | 'opt' | 'edit';
|
|
60
|
+
/**
|
|
61
|
+
* MIDI clock / transport from the M8 (SYNC OUT in its MIDI Settings, stored per song).
|
|
62
|
+
* `at` is epoch milliseconds (performance.timeOrigin + timestamp), comparable across frames.
|
|
63
|
+
* `clock` comes once per sixteenth (6 ticks at 24 PPQ); `ticks` counts clock ticks since the
|
|
64
|
+
* host started listening (monotonic: the M8 can send clock while stopped and without Start);
|
|
65
|
+
* `msPerTick` is the measured tick length, null until known.
|
|
66
|
+
*/
|
|
67
|
+
export interface M8TransportEvent {
|
|
68
|
+
kind: 'start' | 'stop' | 'continue' | 'clock' | 'position';
|
|
69
|
+
ticks: number;
|
|
70
|
+
at: number;
|
|
71
|
+
msPerTick: number | null;
|
|
72
|
+
/** Song Position Pointer (sixteenths), on 'position' events. */
|
|
73
|
+
spp?: number;
|
|
74
|
+
}
|
|
39
75
|
export interface M8HostMethods {
|
|
40
76
|
navigateToView(viewName: string): Promise<boolean>;
|
|
41
77
|
navigateTo(x: number, y: number): Promise<void>;
|
|
@@ -49,6 +85,12 @@ export interface M8HostMethods {
|
|
|
49
85
|
sendKeyDown(keys: M8KeyName[]): Promise<void>;
|
|
50
86
|
sendKeyUp(): Promise<void>;
|
|
51
87
|
getState(): Promise<M8State>;
|
|
88
|
+
getScreen(): Promise<M8Screen>;
|
|
89
|
+
getScreenCells(): Promise<M8ScreenCells>;
|
|
90
|
+
enableMidiTransport(): Promise<{
|
|
91
|
+
ok: boolean;
|
|
92
|
+
error?: string;
|
|
93
|
+
}>;
|
|
52
94
|
}
|
|
53
95
|
export interface M8ClientMethods {
|
|
54
96
|
ping(): Promise<string>;
|
|
@@ -71,6 +113,7 @@ export interface M8HostEvents {
|
|
|
71
113
|
keyPressed: {
|
|
72
114
|
keys: number;
|
|
73
115
|
};
|
|
116
|
+
transport: M8TransportEvent;
|
|
74
117
|
}
|
|
75
118
|
export interface M8ClientEvents {
|
|
76
119
|
ready: undefined;
|
|
@@ -78,6 +121,94 @@ export interface M8ClientEvents {
|
|
|
78
121
|
message: string;
|
|
79
122
|
};
|
|
80
123
|
}
|
|
124
|
+
/** 'host': yam8d owns the M8 and the app talks to it from an iframe. 'standalone': the app connects to the M8 itself. */
|
|
125
|
+
export type M8ClientMode = 'host' | 'standalone';
|
|
126
|
+
/** The browser API a standalone client uses to reach the M8. */
|
|
127
|
+
export type M8DeviceTransport = 'serial' | 'usb' | 'midi';
|
|
81
128
|
export interface M8SdkConfig {
|
|
82
129
|
debug?: boolean;
|
|
130
|
+
/**
|
|
131
|
+
* 'auto' (default): use the yam8d host when the page runs in a yam8d External Apps iframe,
|
|
132
|
+
* otherwise connect to the M8 from this page. 'host' and 'standalone' force one mode.
|
|
133
|
+
*/
|
|
134
|
+
mode?: 'auto' | M8ClientMode;
|
|
135
|
+
/**
|
|
136
|
+
* Auto mode in an iframe that yam8d did not mark: how long to wait for a host handshake
|
|
137
|
+
* before going standalone. Default 3000 ms.
|
|
138
|
+
*/
|
|
139
|
+
handshakeTimeoutMs?: number;
|
|
140
|
+
/**
|
|
141
|
+
* Standalone: at connect, reopen a device this page was granted before, without a prompt.
|
|
142
|
+
* Default true. A first connection always needs connectDevice() from a user gesture.
|
|
143
|
+
*/
|
|
144
|
+
autoConnect?: boolean;
|
|
145
|
+
}
|
|
146
|
+
export interface M8DeviceConnectOptions {
|
|
147
|
+
/** 'auto' (default) picks Web Serial, then WebUSB, then Web MIDI SysEx, by browser support. */
|
|
148
|
+
transport?: 'auto' | M8DeviceTransport;
|
|
149
|
+
/** Also play the M8's USB audio through the page (see M8Client.connectAudio). Default false. */
|
|
150
|
+
audio?: boolean;
|
|
151
|
+
}
|
|
152
|
+
/** Which device APIs this browser offers for standalone mode. */
|
|
153
|
+
export interface M8DeviceSupport {
|
|
154
|
+
serial: boolean;
|
|
155
|
+
usb: boolean;
|
|
156
|
+
midi: boolean;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Low-level access to the M8 a standalone client is connected to: the raw draw / key /
|
|
160
|
+
* system events and the device commands. For apps that render the screen themselves or
|
|
161
|
+
* play notes; everything else is simpler through the client methods.
|
|
162
|
+
*/
|
|
163
|
+
export interface M8DeviceBus {
|
|
164
|
+
readonly transport: M8DeviceTransport;
|
|
165
|
+
readonly events: {
|
|
166
|
+
on<K extends keyof M8DeviceEvents>(event: K, callback: (data: M8DeviceEvents[K]) => void): void;
|
|
167
|
+
off<K extends keyof M8DeviceEvents>(event: K, callback: (data: M8DeviceEvents[K]) => void): void;
|
|
168
|
+
};
|
|
169
|
+
readonly commands: {
|
|
170
|
+
/** Raw key mask (see M8KeyMask); 0 releases every key. */
|
|
171
|
+
sendKeys(keys: number): void;
|
|
172
|
+
/** Asks the M8 to redraw the whole screen. */
|
|
173
|
+
resetScreen(): void;
|
|
174
|
+
sendNoteOn(note: number, velocity: number): void;
|
|
175
|
+
sendNoteOff(): void;
|
|
176
|
+
sendProgramChange(program: number, channel?: number): void;
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
/** Payloads of the M8 display protocol, in M8 pixel coordinates. */
|
|
180
|
+
export interface M8DeviceEvents {
|
|
181
|
+
text: {
|
|
182
|
+
character: string;
|
|
183
|
+
pos: {
|
|
184
|
+
x: number;
|
|
185
|
+
y: number;
|
|
186
|
+
};
|
|
187
|
+
foreground: RGB;
|
|
188
|
+
background: RGB;
|
|
189
|
+
};
|
|
190
|
+
rect: {
|
|
191
|
+
type: number;
|
|
192
|
+
pos: {
|
|
193
|
+
x: number;
|
|
194
|
+
y: number;
|
|
195
|
+
};
|
|
196
|
+
size: {
|
|
197
|
+
width: number;
|
|
198
|
+
height: number;
|
|
199
|
+
};
|
|
200
|
+
color?: RGB;
|
|
201
|
+
};
|
|
202
|
+
wave: {
|
|
203
|
+
color: RGB;
|
|
204
|
+
wave: number[];
|
|
205
|
+
};
|
|
206
|
+
key: {
|
|
207
|
+
keys: number;
|
|
208
|
+
};
|
|
209
|
+
system: {
|
|
210
|
+
model: string;
|
|
211
|
+
version: string;
|
|
212
|
+
fontMode: 0 | 1 | 2;
|
|
213
|
+
};
|
|
83
214
|
}
|
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,145 @@ 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;
|
|
221
|
+
}
|
|
222
|
+
/** The item number of a screen title and the marker after it ('PHRASE 1F*', 'PHRASE 27^'). */
|
|
223
|
+
export declare function parseViewTitle(rawTitle: string | null): {
|
|
224
|
+
viewId: string | null;
|
|
225
|
+
isUnsaved: boolean;
|
|
226
|
+
marker: '*' | '^' | null;
|
|
227
|
+
};
|
|
228
|
+
/**
|
|
229
|
+
* Every screen row has a one-column left margin (the playback marker '<' / '>' is drawn
|
|
230
|
+
* in it), so the schema's x positions are counted from column 1, and `cursorPos.x` is
|
|
231
|
+
* one more than the schema x of the cell it covers. `currentLine` is trimmed and so
|
|
232
|
+
* already starts at the schema's column 0.
|
|
233
|
+
*/
|
|
234
|
+
export declare const SCREEN_MARGIN = 1;
|
|
235
|
+
/** A grid row read off the whole screen, with the screen row it was found on. */
|
|
236
|
+
export interface M8ScreenGridRow extends M8ParsedRow {
|
|
237
|
+
screenRow: number;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Every content row of a grid view (song, chain, phrase, table, groove, instrument pool)
|
|
241
|
+
* read off the whole screen, top to bottom. Rows whose index column does not parse are
|
|
242
|
+
* skipped, so check `rowIndex` continuity when you need a full page.
|
|
243
|
+
*
|
|
244
|
+
* @example
|
|
245
|
+
* ```ts
|
|
246
|
+
* const rows = parseGridScreen('phrase', await m8.getScreen())
|
|
247
|
+
* rows[0].fields.note.rawValue // 'C-4'
|
|
248
|
+
* ```
|
|
249
|
+
*/
|
|
250
|
+
export declare function parseGridScreen(viewName: string, screen: M8Screen): M8ScreenGridRow[];
|
|
251
|
+
/** Where the song is playing, as far as the screen shows it. */
|
|
252
|
+
export interface M8PlayPositions {
|
|
253
|
+
/** Song view: the song row each track's play marker is on (null when its marker is not on screen). */
|
|
254
|
+
tracks: (number | null)[] | null;
|
|
255
|
+
/** Chain, phrase, table, groove views: the row with the play marker after its index. */
|
|
256
|
+
row: number | null;
|
|
78
257
|
}
|
|
79
258
|
/**
|
|
80
|
-
*
|
|
81
|
-
*
|
|
259
|
+
* Reads the play markers off a grid view. On the Song view the M8 draws a marker in the
|
|
260
|
+
* blank just left of each playing chain (`00>00>01>02`); on the other grid views in the
|
|
261
|
+
* blank after the row index of the playing row (`F>--- -- --`), both seen on a Model:02,
|
|
262
|
+
* firmware 6.5. The '<' drawn in the margin marks the cursor row, not playback. Returns
|
|
263
|
+
* null for views without a grid; all nulls when nothing is playing.
|
|
82
264
|
*/
|
|
83
|
-
export declare function
|
|
84
|
-
description: string;
|
|
85
|
-
} | undefined;
|
|
265
|
+
export declare function readPlayPositions(viewName: string, screen: M8Screen): M8PlayPositions | null;
|
|
86
266
|
/**
|
|
87
267
|
* Derives a full semantic context from the current M8State.
|
|
88
268
|
*
|
|
269
|
+
* Pass the whole `screen` (see M8Client.getScreen) to let the context look beyond the
|
|
270
|
+
* cursor row: the other steps of a phrase (so an FX cell can be read against the
|
|
271
|
+
* commands above it) and the other rows of the Scale View. Without a screen, or with
|
|
272
|
+
* one that no longer matches the cursor row, only the cursor row is interpreted.
|
|
273
|
+
*
|
|
89
274
|
* @example
|
|
90
275
|
* ```ts
|
|
91
276
|
* const ctx = getSemanticContext(state)
|
|
@@ -96,17 +281,33 @@ export declare function lookupFxCommand(cmd: string): {
|
|
|
96
281
|
* }
|
|
97
282
|
* ```
|
|
98
283
|
*/
|
|
99
|
-
export declare function getSemanticContext(state: M8State): M8SemanticContext | null;
|
|
284
|
+
export declare function getSemanticContext(state: M8State, screen?: M8Screen | null): M8SemanticContext | null;
|
|
285
|
+
/**
|
|
286
|
+
* What the cursor is on, as ordered, tagged parts. Every part is built from
|
|
287
|
+
* `ctx` alone, so a consumer can keep, drop, reorder or restyle them, or ignore them
|
|
288
|
+
* and write its own text from the context.
|
|
289
|
+
*
|
|
290
|
+
* @example
|
|
291
|
+
* ```ts
|
|
292
|
+
* describeContextParts(ctx)
|
|
293
|
+
* // [{ kind: 'field', text: 'FX2 Command: KIL' },
|
|
294
|
+
* // { kind: 'fxInfo', text: '(Kill: stops the playing instrument after XX ticks)' },
|
|
295
|
+
* // { kind: 'meaning', text: 'value 03: stops the note after 3 ticks' },
|
|
296
|
+
* // { kind: 'location', text: 'Phrase View row 01' }]
|
|
297
|
+
* ```
|
|
298
|
+
*/
|
|
299
|
+
export declare function describeContextParts(ctx: M8SemanticContext): M8DescriptionPart[];
|
|
100
300
|
/**
|
|
101
|
-
* Returns a short human-readable description of what the cursor is currently on
|
|
301
|
+
* Returns a short human-readable description of what the cursor is currently on:
|
|
302
|
+
* the text of describeContextParts(), joined with ' — '.
|
|
102
303
|
*
|
|
103
304
|
* @example
|
|
104
|
-
* "Track 3 —
|
|
105
|
-
* "Note
|
|
106
|
-
* "
|
|
305
|
+
* "Track 3: 0A — Track 3 — Song View row 01"
|
|
306
|
+
* "Note (N): Note C-4 — Phrase View row 00"
|
|
307
|
+
* "FX2 Command: KIL — (Kill: stops the playing instrument after XX ticks) — value 03: stops the note after 3 ticks — Phrase View row 01"
|
|
107
308
|
*/
|
|
108
309
|
export declare function describeContext(ctx: M8SemanticContext): string;
|
|
109
310
|
/**
|
|
110
311
|
* Formats a parsed field value as a human-readable string.
|
|
111
312
|
*/
|
|
112
|
-
export declare function formatFieldValue(
|
|
313
|
+
export declare function formatFieldValue(input: M8ParsedField): string;
|