@yam8d/m8-sdk 0.1.0 → 0.3.1

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/dist/index.js CHANGED
@@ -1,6 +1,650 @@
1
1
  import { ChildHandshake as e, DebugMessenger as t, WindowMessenger as n } from "post-me";
2
+ var r = {
3
+ version: "1.0",
4
+ description: "Semantic mapping of M8 tracker views: defines the structure of each grid view so cursor position + line text can be interpreted as typed field values.",
5
+ notes: {
6
+ fontMode: "All x/width values assume font mode 0 (standard, 12×14 px cells, 40 cols × ~22 rows). Font modes 1 (bold uppercase) and 2 (large) may shift column positions.",
7
+ playbackIndicator: "The M8 renders a '>' character one column to the left of the first data column when that step/row/track is currently playing. This character is part of the text stream; the editing cursor is a separate rect overlay.",
8
+ emptyCell: "An empty or unused cell displays '--' (2 chars) or '---' (3 chars) or '---00' (command+value). Parsed hexValue will be null for these.",
9
+ relativeHex: "Transpose and some FX values use relative hex: 00 = no change, 01-7F = +1-127, FF-80 = -1-128. See 'Relative and Absolute FX Commands' in the manual.",
10
+ rowIndex: "Row/step indices are parsed from the leftmost characters of currentLine. They are hex for all grid views."
11
+ },
12
+ fieldTypes: {
13
+ chainRef: "Reference to a chain number (hex 00-FF). '--' means empty/unused.",
14
+ phraseRef: "Reference to a phrase number (hex 00-FF). '--' means empty/unused.",
15
+ note: "Musical note in M8 format: [A-G][#|-][0-9] e.g. 'C-4', 'A#3'. '---' = empty. 'OFF' = note-off.",
16
+ velocity: "Note velocity 00-7F (hex). Default is 64 (hex). '--' = inherit.",
17
+ instrumentRef: "Instrument number 00-7F (hex). '--' = no retrigger (keep current instrument).",
18
+ fxCommand: "3-character sequencer or instrument FX command name, e.g. 'KIL', 'ARP', 'DEL'. '---' = none.",
19
+ fxValue: "2-char hex value 00-FF accompanying an FX command. Interpretation depends on the command.",
20
+ transpose: "Semitone or tick transpose. Relative: 00=none, 01-7F=+1-+127, FF-80=-1--128.",
21
+ ticks: "Number of ticks this step consumes in a groove (hex 01-FF). '00' skips the step. '--' = empty (groove loops at this point).",
22
+ volume: "Volume multiplier 00-FF (hex). Multiplied with the phrase-row velocity. '--' = no override.",
23
+ ppq: "Pulses Per Quarter note: resolution of the groove clock (decimal). Only editable on groove row 0.",
24
+ instrumentName: "Instrument name string (up to 12 characters). Text field, no hex value.",
25
+ eqSlot: "EQ slot assignment (hex). '--' = no EQ applied to this instrument.",
26
+ rowIndex: "The positional index of this row in the current view (song row, chain position, phrase step, etc.)."
27
+ },
28
+ views: {
29
+ song: {
30
+ title: "Song View",
31
+ type: "grid",
32
+ description: "Arranges chains across 8 independent tracks to form the song structure. Each row is a song position; each column is a track.",
33
+ rowField: {
34
+ x: 0,
35
+ width: 2,
36
+ parse: "hex",
37
+ type: "rowIndex",
38
+ key: "songRow",
39
+ description: "Song row 00-FF. Each track loops back to row 00 when it reaches '--'."
40
+ },
41
+ columns: [
42
+ {
43
+ x: 3,
44
+ width: 2,
45
+ key: "track1",
46
+ type: "chainRef",
47
+ label: "Track 1",
48
+ meta: { trackIndex: 1 }
49
+ },
50
+ {
51
+ x: 6,
52
+ width: 2,
53
+ key: "track2",
54
+ type: "chainRef",
55
+ label: "Track 2",
56
+ meta: { trackIndex: 2 }
57
+ },
58
+ {
59
+ x: 9,
60
+ width: 2,
61
+ key: "track3",
62
+ type: "chainRef",
63
+ label: "Track 3",
64
+ meta: { trackIndex: 3 }
65
+ },
66
+ {
67
+ x: 12,
68
+ width: 2,
69
+ key: "track4",
70
+ type: "chainRef",
71
+ label: "Track 4",
72
+ meta: { trackIndex: 4 }
73
+ },
74
+ {
75
+ x: 15,
76
+ width: 2,
77
+ key: "track5",
78
+ type: "chainRef",
79
+ label: "Track 5",
80
+ meta: { trackIndex: 5 }
81
+ },
82
+ {
83
+ x: 18,
84
+ width: 2,
85
+ key: "track6",
86
+ type: "chainRef",
87
+ label: "Track 6",
88
+ meta: { trackIndex: 6 }
89
+ },
90
+ {
91
+ x: 21,
92
+ width: 2,
93
+ key: "track7",
94
+ type: "chainRef",
95
+ label: "Track 7",
96
+ meta: { trackIndex: 7 }
97
+ },
98
+ {
99
+ x: 24,
100
+ width: 2,
101
+ key: "track8",
102
+ type: "chainRef",
103
+ label: "Track 8",
104
+ meta: { trackIndex: 8 }
105
+ }
106
+ ]
107
+ },
108
+ chain: {
109
+ title: "Chain View",
110
+ type: "grid",
111
+ description: "An ordered list of up to 16 phrases. The first '--' phrase ends the chain and loops back to the song.",
112
+ rowField: {
113
+ x: 0,
114
+ width: 1,
115
+ parse: "hex",
116
+ type: "rowIndex",
117
+ key: "chainPos",
118
+ description: "Position within the chain (0-F, max 16 entries)."
119
+ },
120
+ columns: [{
121
+ x: 2,
122
+ width: 2,
123
+ key: "phrase",
124
+ type: "phraseRef",
125
+ label: "Phrase (PH)",
126
+ description: "Phrase number to play at this chain position."
127
+ }, {
128
+ x: 5,
129
+ width: 2,
130
+ key: "transpose",
131
+ type: "transpose",
132
+ label: "Transpose (TSP)",
133
+ description: "Optional note transpose in semitones applied to every note in the phrase (relative hex)."
134
+ }]
135
+ },
136
+ phrase: {
137
+ title: "Phrase View",
138
+ type: "grid",
139
+ description: "A 16-step sequence. Each step holds a note, velocity, instrument assignment, and up to 3 FX command+value pairs.",
140
+ rowField: {
141
+ x: 0,
142
+ width: 1,
143
+ parse: "hex",
144
+ type: "rowIndex",
145
+ key: "step",
146
+ description: "Step index 0-F (16th note by default; altered by groove)."
147
+ },
148
+ columns: [
149
+ {
150
+ x: 2,
151
+ width: 3,
152
+ key: "note",
153
+ type: "note",
154
+ label: "Note (N)"
155
+ },
156
+ {
157
+ x: 6,
158
+ width: 2,
159
+ key: "vel",
160
+ type: "velocity",
161
+ label: "Velocity (V)"
162
+ },
163
+ {
164
+ x: 9,
165
+ width: 2,
166
+ key: "inst",
167
+ type: "instrumentRef",
168
+ label: "Instrument (I)"
169
+ },
170
+ {
171
+ x: 12,
172
+ width: 3,
173
+ key: "fx1cmd",
174
+ type: "fxCommand",
175
+ label: "FX1 Command"
176
+ },
177
+ {
178
+ x: 15,
179
+ width: 2,
180
+ key: "fx1val",
181
+ type: "fxValue",
182
+ label: "FX1 Value"
183
+ },
184
+ {
185
+ x: 18,
186
+ width: 3,
187
+ key: "fx2cmd",
188
+ type: "fxCommand",
189
+ label: "FX2 Command"
190
+ },
191
+ {
192
+ x: 21,
193
+ width: 2,
194
+ key: "fx2val",
195
+ type: "fxValue",
196
+ label: "FX2 Value"
197
+ },
198
+ {
199
+ x: 24,
200
+ width: 3,
201
+ key: "fx3cmd",
202
+ type: "fxCommand",
203
+ label: "FX3 Command"
204
+ },
205
+ {
206
+ x: 27,
207
+ width: 2,
208
+ key: "fx3val",
209
+ type: "fxValue",
210
+ label: "FX3 Value"
211
+ }
212
+ ]
213
+ },
214
+ table: {
215
+ title: "Table View",
216
+ type: "grid",
217
+ description: "A 16-step mini-sequencer that runs alongside an instrument. Used for arpeggios, multi-stage envelopes, and automated FX.",
218
+ rowField: {
219
+ x: 0,
220
+ width: 1,
221
+ parse: "hex",
222
+ type: "rowIndex",
223
+ key: "step",
224
+ description: "Table step 0-F. Loops from bottom unless a HOP command redirects."
225
+ },
226
+ columns: [
227
+ {
228
+ x: 2,
229
+ width: 2,
230
+ key: "transpose",
231
+ type: "transpose",
232
+ label: "Transpose (N)",
233
+ description: "Transposes the instrument for this step (relative hex). '--' = no transpose."
234
+ },
235
+ {
236
+ x: 5,
237
+ width: 2,
238
+ key: "volume",
239
+ type: "volume",
240
+ label: "Volume (V)",
241
+ description: "Volume multiplier applied on top of the phrase velocity (hex). '--' = no override."
242
+ },
243
+ {
244
+ x: 8,
245
+ width: 3,
246
+ key: "fx1cmd",
247
+ type: "fxCommand",
248
+ label: "FX1 Command",
249
+ description: "3-char command name for table FX slot 1."
250
+ },
251
+ {
252
+ x: 11,
253
+ width: 2,
254
+ key: "fx1val",
255
+ type: "fxValue",
256
+ label: "FX1 Value",
257
+ description: "Value for table FX1."
258
+ },
259
+ {
260
+ x: 14,
261
+ width: 3,
262
+ key: "fx2cmd",
263
+ type: "fxCommand",
264
+ label: "FX2 Command",
265
+ description: "3-char command name for table FX slot 2."
266
+ },
267
+ {
268
+ x: 17,
269
+ width: 2,
270
+ key: "fx2val",
271
+ type: "fxValue",
272
+ label: "FX2 Value",
273
+ description: "Value for table FX2."
274
+ },
275
+ {
276
+ x: 20,
277
+ width: 3,
278
+ key: "fx3cmd",
279
+ type: "fxCommand",
280
+ label: "FX3 Command",
281
+ description: "3-char command name for table FX slot 3."
282
+ },
283
+ {
284
+ x: 23,
285
+ width: 2,
286
+ key: "fx3val",
287
+ type: "fxValue",
288
+ label: "FX3 Value",
289
+ description: "Value for table FX3."
290
+ }
291
+ ]
292
+ },
293
+ groove: {
294
+ title: "Groove View",
295
+ type: "grid",
296
+ description: "Defines the timing of each phrase step in ticks. Used to create swing, shuffle, triplets, and other rhythmic feels.",
297
+ rowField: {
298
+ x: 0,
299
+ width: 1,
300
+ parse: "hex",
301
+ type: "rowIndex",
302
+ key: "step",
303
+ description: "Groove step 0-F. The groove loops when a '--' entry is reached."
304
+ },
305
+ columns: [{
306
+ x: 2,
307
+ width: 2,
308
+ key: "ticks",
309
+ type: "ticks",
310
+ label: "Ticks (TIC)",
311
+ description: "Number of ticks this step takes. Default is 06 (at 24 PPQN = 1 sixteenth note). '00' skips the step."
312
+ }, {
313
+ x: 6,
314
+ width: 2,
315
+ key: "ppq",
316
+ type: "ppq",
317
+ label: "PPQ",
318
+ description: "Pulses Per Quarter note. Only present on groove row 0; absent on all other rows."
319
+ }]
320
+ },
321
+ instrumentpool: {
322
+ title: "Instrument Pool",
323
+ type: "grid",
324
+ description: "Lists all instrument slots with their mix routing. Each row shows the instrument name and its dry/FX send levels.",
325
+ rowField: {
326
+ x: 0,
327
+ width: 2,
328
+ parse: "hex",
329
+ type: "rowIndex",
330
+ key: "instIndex",
331
+ description: "Instrument slot index 00-7F."
332
+ },
333
+ columns: [
334
+ {
335
+ x: 3,
336
+ width: 12,
337
+ key: "name",
338
+ type: "instrumentName",
339
+ label: "Instrument Name",
340
+ description: "Name of the instrument in this slot (up to 12 chars). '------------' = empty slot."
341
+ },
342
+ {
343
+ x: 16,
344
+ width: 2,
345
+ key: "dry",
346
+ type: "volume",
347
+ label: "Dry (DRY)",
348
+ description: "Direct output volume for this instrument (hex 00-FF)."
349
+ },
350
+ {
351
+ x: 19,
352
+ width: 2,
353
+ key: "mx",
354
+ type: "volume",
355
+ label: "ModFX (MX)",
356
+ description: "ModFX send level (hex 00-FF)."
357
+ },
358
+ {
359
+ x: 22,
360
+ width: 2,
361
+ key: "de",
362
+ type: "volume",
363
+ label: "Delay (DE)",
364
+ description: "Delay send level (hex 00-FF)."
365
+ },
366
+ {
367
+ x: 25,
368
+ width: 2,
369
+ key: "rv",
370
+ type: "volume",
371
+ label: "Reverb (RV)",
372
+ description: "Reverb send level (hex 00-FF)."
373
+ },
374
+ {
375
+ x: 28,
376
+ width: 2,
377
+ key: "eq",
378
+ type: "eqSlot",
379
+ label: "EQ Slot (EQ)",
380
+ description: "EQ slot assignment. '--' = no EQ."
381
+ }
382
+ ]
383
+ }
384
+ },
385
+ fxCommands: {
386
+ sequencer: {
387
+ ARP: { description: "Arpeggio: plays 3 notes rapidly. X=first interval semitones, Y=second interval semitones." },
388
+ ARC: { description: "Arpeggio Config: X=mode, Y=speed in ticks." },
389
+ CHA: { description: "Chance: X=probability left of command (0=never, F=always), Y=probability right." },
390
+ DEL: { description: "Delay: in phrase delays entire row by XX ticks; in table delays table playhead." },
391
+ GRV: { description: "Groove: sets groove number XX for the current track." },
392
+ GGR: { description: "Global Groove: sets groove XX for all tracks." },
393
+ HOP: { description: "Hop: in phrase jumps to row Y of next phrase; HOPFF stops track. In table loops to row Y X times." },
394
+ INS: { description: "Instrument: changes active instrument to XX as an FX command." },
395
+ KIL: { description: "Kill: stops the playing instrument after XX ticks." },
396
+ RND: { description: "Random: randomises the preceding FX command. X=left range, Y=right range (0=none, F=full)." },
397
+ RNL: { description: "Randomise Left: randomises the FX command to the left." },
398
+ RET: { description: "Retrig: retriggers current row. Y≠0: retrig every Y ticks with X volume ramp. Y=0: single retrig after X ticks." },
399
+ REP: { description: "Repeat: repeats and increments the last FX command by XX each step." },
400
+ RTO: { description: "Repeat To: sets the min/max value that REP stops at." },
401
+ RMX: { description: "Remix: repositions the phrase playhead (Y) on tracks to the left (selected by X)." },
402
+ NTH: { description: "Nth Trigger: conditional trigger based on loop count." },
403
+ PSL: { description: "Pitch Slide (portamento): enables portamento for XX ticks." },
404
+ PBN: { description: "Pitch Bend: continuous pitch slide up (00-7F) or down (80-FF)." },
405
+ PVB: { description: "Vibrato: X=speed, Y=depth." },
406
+ PVX: { description: "Extreme Vibrato: like PVB but with higher range." },
407
+ SCA: { description: "Track Scale: X=key signature, Y=scale number for this track." },
408
+ SCG: { description: "Global Scale: X=key, Y=scale number for the whole song." },
409
+ SNG: { description: "Song Hop: moves this track's song position by XX rows relative to current." },
410
+ SED: { description: "Random Seed: sets the random seed XX for this track." },
411
+ TBL: { description: "Table: assigns table number XX to the current instrument." },
412
+ THO: { description: "Table Hop: jumps all table columns to position 0X." },
413
+ TIC: { description: "Table Tick: sets the table tick rate. In a table, each FX column can run independently." },
414
+ TBX: { description: "Aux Table: runs table XX in parallel with the instrument table. 00=stop aux table." },
415
+ TPO: { description: "Tempo: sets song BPM to XX (hex → decimal conversion shown in help text)." },
416
+ TSP: { description: "Global Transpose: transposes the entire song by XX semitones." },
417
+ NXT: { description: "Next Track Trigger: plays instrument XX on the next track using current note/velocity." },
418
+ OFF: { description: "Note Off: stops the playing instrument after XX ticks. Triggers ADSR release stage." },
419
+ MTT: { description: "Micro Time: adjusts row playback timing in sub-tick (1/8 tick) amounts." }
420
+ },
421
+ instrument: {
422
+ VOL: { description: "Volume offset (relative)." },
423
+ PIT: { description: "Pitch offset in semitones (relative)." },
424
+ FIN: { description: "Fine tune: pitch offset -1 to +1 semitones (relative)." },
425
+ EA1: { description: "Envelope 1 Amount offset." },
426
+ EA2: { description: "Envelope 2 Amount offset." },
427
+ AT1: { description: "Envelope 1 Attack time offset." },
428
+ AT2: { description: "Envelope 2 Attack time offset." },
429
+ HO1: { description: "Envelope 1 Hold time offset." },
430
+ HO2: { description: "Envelope 2 Hold time offset." },
431
+ DE1: { description: "Envelope 1 Decay time offset." },
432
+ DE2: { description: "Envelope 2 Decay time offset." },
433
+ ET1: { description: "Retrigger Envelope 1 (any value > 00 retriggers)." },
434
+ ET2: { description: "Retrigger Envelope 2." },
435
+ LA1: { description: "LFO 1 Amount offset." },
436
+ LA2: { description: "LFO 2 Amount offset." },
437
+ LF1: { description: "LFO 1 Frequency offset." },
438
+ LF2: { description: "LFO 2 Frequency offset." },
439
+ LT1: { description: "Retrigger LFO 1 (value sets phase offset)." },
440
+ LT2: { description: "Retrigger LFO 2." }
441
+ },
442
+ mixer: {
443
+ VMV: { description: "Main Volume: sets the main song output volume." },
444
+ VMX: { description: "ModFX Volume." },
445
+ VDE: { description: "Delay Volume." },
446
+ VRE: { description: "Reverb Volume." },
447
+ VT1: { description: "Track 1 Volume." },
448
+ VT2: { description: "Track 2 Volume." },
449
+ VT3: { description: "Track 3 Volume." },
450
+ VT4: { description: "Track 4 Volume." },
451
+ VT5: { description: "Track 5 Volume." },
452
+ VT6: { description: "Track 6 Volume." },
453
+ VT7: { description: "Track 7 Volume." },
454
+ VT8: { description: "Track 8 Volume." },
455
+ DJC: { description: "DJ Filter Cutoff." },
456
+ DJR: { description: "DJ Filter Resonance." },
457
+ DJT: { description: "DJ Filter Type." },
458
+ EQM: { description: "Assign main mix EQ slot." },
459
+ EQI: { description: "Assign current instrument EQ slot." }
460
+ }
461
+ }
462
+ }, i = r.fxCommands;
463
+ function a(e) {
464
+ let t = e.toUpperCase();
465
+ for (let e of Object.values(i)) if (t in e) return e[t];
466
+ }
467
+ var o = new Set([
468
+ "--",
469
+ "---",
470
+ "---00",
471
+ "----",
472
+ "-"
473
+ ]);
474
+ function s(e) {
475
+ return e ? o.has(e) || /^-+$/.test(e) : !0;
476
+ }
477
+ function c(e) {
478
+ let t = e.trim();
479
+ if (!t || s(t)) return null;
480
+ let n = parseInt(t, 16);
481
+ return Number.isNaN(n) ? null : n;
482
+ }
483
+ function l(e, t, n) {
484
+ return t >= e.length ? "" : e.slice(t, Math.min(t + n, e.length));
485
+ }
486
+ function u(e) {
487
+ if (!e) return {
488
+ viewId: null,
489
+ isUnsaved: !1
490
+ };
491
+ let t = e.trim(), n = t.endsWith("*"), r = (n ? t.slice(0, -1).trimEnd() : t).split(/\s+/), i = r[r.length - 1] ?? "";
492
+ return {
493
+ viewId: /^[0-9A-Fa-f]{1,2}$/.test(i) ? i.toUpperCase() : null,
494
+ isUnsaved: n
495
+ };
496
+ }
497
+ function d(e) {
498
+ return e.length > 0 && /^[^a-zA-Z0-9 ]/.test(e[0]) ? {
499
+ line: e.slice(1),
500
+ offset: 1
501
+ } : {
502
+ line: e,
503
+ offset: 0
504
+ };
505
+ }
506
+ function f(e, t) {
507
+ let n = l(t, e.x, e.width).trim(), r = s(n), i = [
508
+ "chainRef",
509
+ "phraseRef",
510
+ "velocity",
511
+ "instrumentRef",
512
+ "fxValue",
513
+ "transpose",
514
+ "ticks",
515
+ "volume",
516
+ "ppq",
517
+ "eqSlot",
518
+ "rowIndex"
519
+ ], a = ["ppq"], o = null;
520
+ if (!r && i.includes(e.type)) if (a.includes(e.type)) {
521
+ let e = parseInt(n, 10);
522
+ o = Number.isNaN(e) ? null : e;
523
+ } else o = c(n);
524
+ return {
525
+ key: e.key,
526
+ label: e.label,
527
+ type: e.type,
528
+ rawValue: n,
529
+ hexValue: o,
530
+ isEmpty: r,
531
+ meta: e.meta
532
+ };
533
+ }
534
+ function p(e, t) {
535
+ let n = l(e, t.x, t.width).trim();
536
+ if (!n) return null;
537
+ if (t.parse === "hex") return c(n);
538
+ let r = parseInt(n, 10);
539
+ return Number.isNaN(r) ? null : r;
540
+ }
541
+ function m(e, t) {
542
+ for (let n of e) if (t >= n.x && t < n.x + n.width) return n;
543
+ let n = null, r = 2;
544
+ for (let i of e) {
545
+ let e = Math.min(Math.abs(t - i.x), Math.abs(t - (i.x + i.width - 1)));
546
+ e < r && (r = e, n = i);
547
+ }
548
+ return n;
549
+ }
550
+ function h(e) {
551
+ let t = e.viewName;
552
+ if (!t) return null;
553
+ let n = r.views[t] ?? null, i = n?.type === "grid", a = n?.title ?? null, o = n?.description ?? null, { viewId: s, isUnsaved: c } = u(e.viewTitle);
554
+ if (!i || !n) return {
555
+ viewName: t,
556
+ viewTitle: a,
557
+ viewDescription: o,
558
+ viewId: s,
559
+ isUnsaved: c,
560
+ isGridView: !1,
561
+ row: null,
562
+ activeField: null
563
+ };
564
+ let l = e.currentLine;
565
+ if (!l) return {
566
+ viewName: t,
567
+ viewTitle: a,
568
+ viewDescription: o,
569
+ viewId: s,
570
+ isUnsaved: c,
571
+ isGridView: !0,
572
+ row: null,
573
+ activeField: null
574
+ };
575
+ let { line: h, offset: g } = d(l), _ = e.cursorPos ? e.cursorPos.x - g : 0, v = n.rowField ? p(h, n.rowField) : null, y = {};
576
+ for (let e of n.columns) y[e.key] = f(e, h);
577
+ let b = {
578
+ rowIndex: v,
579
+ rowKey: n.rowField?.key ?? "row",
580
+ fields: y
581
+ }, x = null;
582
+ if (e.cursorPos) {
583
+ let e = m(n.columns, _);
584
+ if (e) {
585
+ let n = y[e.key];
586
+ n && (x = {
587
+ ...n,
588
+ viewName: t,
589
+ rowIndex: v
590
+ });
591
+ }
592
+ }
593
+ return {
594
+ viewName: t,
595
+ viewTitle: a,
596
+ viewDescription: o,
597
+ viewId: s,
598
+ isUnsaved: c,
599
+ isGridView: !0,
600
+ row: b,
601
+ activeField: x
602
+ };
603
+ }
604
+ function g(e) {
605
+ if (!e.activeField) return e.viewTitle ?? e.viewName;
606
+ let { activeField: t, row: n } = e, r = [], i = _(t);
607
+ if (r.push(`${t.label}: ${i}`), t.type === "fxCommand" && !t.isEmpty) {
608
+ let e = a(t.rawValue);
609
+ e && r.push(`(${e.description})`);
610
+ }
611
+ if (t.type === "fxValue" && n) {
612
+ let e = t.key.replace("val", "cmd"), i = n.fields[e];
613
+ if (i && !i.isEmpty) {
614
+ let e = a(i.rawValue), t = e ? `${i.rawValue} (${e.description})` : i.rawValue;
615
+ r.push(`for ${t}`);
616
+ }
617
+ }
618
+ if (t.meta?.trackIndex != null && r.push(`Track ${t.meta.trackIndex}`), n?.rowIndex != null) {
619
+ let t = n.rowIndex.toString(16).toUpperCase().padStart(2, "0");
620
+ r.push(`${e.viewTitle ?? e.viewName} row ${t}`);
621
+ }
622
+ return r.join(" — ");
623
+ }
624
+ function _(e) {
625
+ if (e.isEmpty) return "(empty)";
626
+ switch (e.type) {
627
+ case "note": return e.rawValue === "OFF" ? "Note Off" : `Note ${e.rawValue}`;
628
+ case "transpose": {
629
+ if (e.hexValue == null) return e.rawValue;
630
+ if (e.hexValue === 0) return "±0 st";
631
+ let t = e.hexValue > 127 ? e.hexValue - 256 : e.hexValue;
632
+ return `${t > 0 ? "+" : ""}${t} st`;
633
+ }
634
+ case "velocity": return e.hexValue == null ? e.rawValue : `${e.rawValue}h (${e.hexValue} / 127 max)`;
635
+ case "chainRef":
636
+ case "phraseRef":
637
+ case "instrumentRef": return e.rawValue;
638
+ case "fxCommand": return e.rawValue;
639
+ case "fxValue": return e.hexValue == null ? e.rawValue : `${e.rawValue}h (dec ${e.hexValue})`;
640
+ case "ticks": return e.rawValue === "00" ? "00 (skip step)" : e.hexValue == null ? e.rawValue : `${e.rawValue}h (${e.hexValue} ticks)`;
641
+ case "volume": return e.rawValue;
642
+ default: return e.rawValue;
643
+ }
644
+ }
645
+ //#endregion
2
646
  //#region src/client.ts
3
- var r = () => ({
647
+ var v = () => ({
4
648
  viewName: null,
5
649
  viewTitle: null,
6
650
  minimapKey: null,
@@ -16,9 +660,9 @@ var r = () => ({
16
660
  fontMode: null,
17
661
  systemInfo: null,
18
662
  macroRunning: !1
19
- }), i = class {
663
+ }), y = class {
20
664
  constructor(e = {}) {
21
- this.connection = null, this.remoteHandle = null, this.localHandle = null, this.stateCallbacks = /* @__PURE__ */ new Set(), this.viewCallbacks = /* @__PURE__ */ new Set(), this.cursorCallbacks = /* @__PURE__ */ new Set(), this.textCallbacks = /* @__PURE__ */ new Set(), this.keyCallbacks = /* @__PURE__ */ new Set(), this._state = r(), this._isConnected = !1, this.config = e;
665
+ this.connection = null, this.remoteHandle = null, this.localHandle = null, this.stateCallbacks = /* @__PURE__ */ new Set(), this.viewCallbacks = /* @__PURE__ */ new Set(), this.cursorCallbacks = /* @__PURE__ */ new Set(), this.textCallbacks = /* @__PURE__ */ new Set(), this.keyCallbacks = /* @__PURE__ */ new Set(), this._state = v(), this._isConnected = !1, this.config = e;
22
666
  }
23
667
  get state() {
24
668
  return this._state;
@@ -88,6 +732,10 @@ var r = () => ({
88
732
  if (!this.remoteHandle) throw Error("M8 SDK client is not connected");
89
733
  return this.remoteHandle.call("setValueToInt", e);
90
734
  }
735
+ async setValueFloat(e) {
736
+ if (!this.remoteHandle) throw Error("M8 SDK client is not connected");
737
+ return this.remoteHandle.call("setValueFloat", e);
738
+ }
91
739
  async setNote(e) {
92
740
  if (!this.remoteHandle) throw Error("M8 SDK client is not connected");
93
741
  return this.remoteHandle.call("setNote", e);
@@ -138,13 +786,20 @@ var r = () => ({
138
786
  disconnect() {
139
787
  this.connection?.close(), this.connection = null, this.remoteHandle = null, this.localHandle = null, this._isConnected = !1, this.stateCallbacks.clear(), this.viewCallbacks.clear(), this.cursorCallbacks.clear(), this.textCallbacks.clear(), this.keyCallbacks.clear();
140
788
  }
789
+ getSemanticContext() {
790
+ return h(this._state);
791
+ }
792
+ describeContext() {
793
+ let e = h(this._state);
794
+ return e ? g(e) : null;
795
+ }
141
796
  };
142
- async function a(e = {}) {
143
- let t = new i(e);
797
+ async function b(e = {}) {
798
+ let t = new y(e);
144
799
  return await t.connect(), t;
145
800
  }
146
- function o(e = {}) {
147
- let t = new i(e);
801
+ function x(e = {}) {
802
+ let t = new y(e);
148
803
  return {
149
804
  client: t,
150
805
  connect: async () => {
@@ -152,11 +807,11 @@ function o(e = {}) {
152
807
  }
153
808
  };
154
809
  }
155
- var s = {
156
- createM8Client: a,
157
- createM8ClientSync: o
810
+ var S = {
811
+ createM8Client: b,
812
+ createM8ClientSync: x
158
813
  };
159
814
  //#endregion
160
- export { a as createM8Client, o as createM8ClientSync, s as default };
815
+ export { b as createM8Client, x as createM8ClientSync, S as default, g as describeContext, _ as formatFieldValue, h as getSemanticContext, a as lookupFxCommand };
161
816
 
162
817
  //# sourceMappingURL=index.js.map