@sudobility/music_drawing 0.0.33 → 0.0.35

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.
Files changed (63) hide show
  1. package/dist/canvas-renderer.d.ts +79 -4
  2. package/dist/canvas-renderer.d.ts.map +1 -1
  3. package/dist/canvas-renderer.js +245 -53
  4. package/dist/canvas-renderer.js.map +1 -1
  5. package/dist/cursor.d.ts +60 -0
  6. package/dist/cursor.d.ts.map +1 -0
  7. package/dist/cursor.js +157 -0
  8. package/dist/cursor.js.map +1 -0
  9. package/dist/index.d.ts +16 -0
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +16 -0
  12. package/dist/index.js.map +1 -1
  13. package/dist/keyboard-geometry.d.ts +50 -2
  14. package/dist/keyboard-geometry.d.ts.map +1 -1
  15. package/dist/keyboard-geometry.js +71 -2
  16. package/dist/keyboard-geometry.js.map +1 -1
  17. package/dist/keyboard-keys.d.ts +93 -0
  18. package/dist/keyboard-keys.d.ts.map +1 -0
  19. package/dist/keyboard-keys.js +60 -0
  20. package/dist/keyboard-keys.js.map +1 -0
  21. package/dist/layered-paint.d.ts +47 -0
  22. package/dist/layered-paint.d.ts.map +1 -0
  23. package/dist/layered-paint.js +22 -0
  24. package/dist/layered-paint.js.map +1 -0
  25. package/dist/pagination.d.ts +6 -2
  26. package/dist/pagination.d.ts.map +1 -1
  27. package/dist/pagination.js +4 -0
  28. package/dist/pagination.js.map +1 -1
  29. package/dist/playback-binding.d.ts +57 -0
  30. package/dist/playback-binding.d.ts.map +1 -0
  31. package/dist/playback-binding.js +110 -0
  32. package/dist/playback-binding.js.map +1 -0
  33. package/dist/playhead.d.ts.map +1 -1
  34. package/dist/playhead.js +22 -3
  35. package/dist/playhead.js.map +1 -1
  36. package/dist/press.d.ts +66 -0
  37. package/dist/press.d.ts.map +1 -0
  38. package/dist/press.js +64 -0
  39. package/dist/press.js.map +1 -0
  40. package/dist/print-plan.d.ts +64 -0
  41. package/dist/print-plan.d.ts.map +1 -0
  42. package/dist/print-plan.js +101 -0
  43. package/dist/print-plan.js.map +1 -0
  44. package/dist/render-theme.d.ts.map +1 -1
  45. package/dist/render-theme.js +11 -2
  46. package/dist/render-theme.js.map +1 -1
  47. package/dist/score-canvas.d.ts +280 -0
  48. package/dist/score-canvas.d.ts.map +1 -0
  49. package/dist/score-canvas.js +702 -0
  50. package/dist/score-canvas.js.map +1 -0
  51. package/dist/skia/index.d.ts +2 -0
  52. package/dist/skia/index.d.ts.map +1 -1
  53. package/dist/skia/index.js +1 -0
  54. package/dist/skia/index.js.map +1 -1
  55. package/dist/skia/skia-layers.d.ts +43 -0
  56. package/dist/skia/skia-layers.d.ts.map +1 -0
  57. package/dist/skia/skia-layers.js +24 -0
  58. package/dist/skia/skia-layers.js.map +1 -0
  59. package/dist/types.d.ts +13 -0
  60. package/dist/types.d.ts.map +1 -1
  61. package/dist/types.js +1 -1
  62. package/dist/types.js.map +1 -1
  63. package/package.json +3 -3
@@ -17,7 +17,7 @@
17
17
  * │C │D │E │F │G │
18
18
  * └──┴──┴──┴──┴──┘
19
19
  */
20
- import { FULL_KEYBOARD, gmPercussion, gmPercussionName, midiToPitch, pitchToString, } from '@sudobility/music_types';
20
+ import { FULL_KEYBOARD, gmPercussion, gmPercussionName, isNoteEvent, midiIsInRange, midiToPitch, pitchToMidi, pitchToString, trackKeyboardRange, trackRangeIsBinding, } from '@sudobility/music_types';
21
21
  /**
22
22
  * The 88-key piano — `FULL_KEYBOARD` **by identity**, not a second pair of
23
23
  * numbers that agrees with it today.
@@ -76,6 +76,20 @@ export const MIN_WHITE_KEY_WIDTH = 14;
76
76
  /** Black-key size, as a fraction of a white key. */
77
77
  export const BLACK_KEY_WIDTH_RATIO = 0.6;
78
78
  export const BLACK_KEY_HEIGHT_RATIO = 0.62;
79
+ /**
80
+ * A white key outside the instrument's compass: pale enough to read as a key,
81
+ * grey enough to tell apart from the playable ones beside it.
82
+ */
83
+ export const KEYBOARD_OUT_OF_RANGE_WHITE = '#e4e4e7';
84
+ /**
85
+ * A black key outside the instrument's compass.
86
+ *
87
+ * Its own colour because the white one alone left half the dimmed span looking
88
+ * playable: an out-of-range octave read as pale whites with ordinary black keys
89
+ * between them, and the blacks are exactly as unplayable. Still dark enough to
90
+ * read as a black key, so the keyboard's pattern is not broken.
91
+ */
92
+ export const KEYBOARD_OUT_OF_RANGE_BLACK = '#63636b';
79
93
  /** Height of one row of key labels, and so of the gutter a keyboard needs per row. */
80
94
  export const LABEL_ROW_HEIGHT = 12;
81
95
  /** True for the five black keys per octave (pitch classes 1, 3, 6, 8, 10). */
@@ -98,7 +112,9 @@ export function keyboardWidth(whiteKeyWidth, range = FULL_RANGE) {
98
112
  * and the blacks land on top of the whites they overlap, with no z-index
99
113
  * bookkeeping.
100
114
  */
101
- export function computeKeys(whiteKeyWidth, whiteKeyHeight, range = FULL_RANGE, naming = 'pitch') {
115
+ export function computeKeys(whiteKeyWidth, whiteKeyHeight, range = FULL_RANGE, naming = 'pitch',
116
+ /** What the instrument can play; keys outside it are `outOfRange`. Null marks none. */
117
+ playable = null) {
102
118
  const whites = [];
103
119
  const blacks = [];
104
120
  const blackWidth = whiteKeyWidth * BLACK_KEY_WIDTH_RATIO;
@@ -120,6 +136,7 @@ export function computeKeys(whiteKeyWidth, whiteKeyHeight, range = FULL_RANGE, n
120
136
  ? noteLabel(midi)
121
137
  : null;
122
138
  const name = drums ? gmPercussionName(midi) : noteLabel(midi);
139
+ const outOfRange = playable !== null && !midiIsInRange(midi, playable);
123
140
  if (isBlackKey(midi)) {
124
141
  blacks.push({
125
142
  midi,
@@ -134,6 +151,7 @@ export function computeKeys(whiteKeyWidth, whiteKeyHeight, range = FULL_RANGE, n
134
151
  name,
135
152
  // Second row: clear of the white keys and of their labels.
136
153
  labelTop: whiteKeyHeight + 1 + LABEL_ROW_HEIGHT,
154
+ outOfRange,
137
155
  });
138
156
  }
139
157
  else {
@@ -146,10 +164,61 @@ export function computeKeys(whiteKeyWidth, whiteKeyHeight, range = FULL_RANGE, n
146
164
  label,
147
165
  name,
148
166
  labelTop: whiteKeyHeight + 1,
167
+ outOfRange,
149
168
  });
150
169
  whiteIndex += 1;
151
170
  }
152
171
  }
153
172
  return [...whites, ...blacks];
154
173
  }
174
+ /** The whole MIDI note range, which an imported part may use past the piano's ends. */
175
+ const MIDI_MIN = 0;
176
+ const MIDI_MAX = 127;
177
+ /**
178
+ * The keyboard for a track: its instrument's compass, widened to reach every
179
+ * note the track actually holds.
180
+ *
181
+ * Widened because a part can hold notes its instrument cannot play — an
182
+ * imported sub-octave bass layer is the usual one — and a keyboard that stopped
183
+ * at the compass lit no key at all for them. The widened keys are marked
184
+ * `outOfRange` through `playable`, which does not widen: they show what is
185
+ * there, they are not an invitation to write more of it. Both apps call this,
186
+ * so they draw the same keys and refuse the same presses.
187
+ */
188
+ export function trackKeyboardSpan(track) {
189
+ const compass = trackKeyboardRange(track);
190
+ let min = compass.min;
191
+ let max = compass.max;
192
+ for (const measure of track.measures) {
193
+ for (const voice of measure.voices) {
194
+ for (const event of voice.events) {
195
+ if (!isNoteEvent(event))
196
+ continue;
197
+ const midi = pitchToMidi(event.pitch);
198
+ if (midi < min)
199
+ min = midi;
200
+ if (midi > max)
201
+ max = midi;
202
+ }
203
+ }
204
+ }
205
+ // The compass itself keeps the 88-key snapping. Past it, the keyboard follows
206
+ // the notes as far as MIDI goes: an imported sub-bass reaches below A0, and
207
+ // stopping at the piano's end would light nothing for exactly those notes.
208
+ let { min: from, max: to } = snapToWhiteKeys(compass);
209
+ if (min < from) {
210
+ from = min;
211
+ while (from > MIDI_MIN && isBlackKey(from))
212
+ from -= 1;
213
+ }
214
+ if (max > to) {
215
+ to = max;
216
+ while (to < MIDI_MAX && isBlackKey(to))
217
+ to += 1;
218
+ }
219
+ return {
220
+ range: { min: from, max: to },
221
+ playable: trackRangeIsBinding(track) ? compass : null,
222
+ };
223
+ }
155
224
  //# sourceMappingURL=keyboard-geometry.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"keyboard-geometry.js","sourceRoot":"","sources":["../src/keyboard-geometry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EACL,aAAa,EACb,YAAY,EACZ,gBAAgB,EAChB,WAAW,EACX,aAAa,GAEd,MAAM,yBAAyB,CAAC;AAejC;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,UAAU,GAAkB,aAAa,CAAC;AAEvD,sDAAsD;AACtD,MAAM,CAAC,MAAM,iBAAiB,GAAG,aAAa,CAAC,GAAG,CAAC;AACnD,wBAAwB;AACxB,MAAM,CAAC,MAAM,iBAAiB,GAAG,aAAa,CAAC,GAAG,CAAC;AACnD,4EAA4E;AAC5E,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,CAAC;AAElC;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,eAAe,CAAC,KAAoB;IAClD,IAAI,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IACtE,IAAI,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IACtE,OAAO,GAAG,GAAG,aAAa,CAAC,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC;QAAE,GAAG,IAAI,CAAC,CAAC;IAC5D,OAAO,GAAG,GAAG,aAAa,CAAC,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC;QAAE,GAAG,IAAI,CAAC,CAAC;IAC5D,4EAA4E;IAC5E,OAAO,UAAU,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,GAAG;QAAE,GAAG,IAAI,CAAC,CAAC;IAC9C,OAAO,UAAU,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,GAAG;QAAE,GAAG,IAAI,CAAC,CAAC;IAC9C,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AACtB,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,aAAa,CAAC,QAAuB,UAAU;IAC7D,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,IAAI,IAAI,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,IAAI,KAAK,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC;QACrD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,KAAK,IAAI,CAAC,CAAC;IACpC,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,EAAE,CAAC;AAEtC,oDAAoD;AACpD,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAG,CAAC;AACzC,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,CAAC;AAuC3C,sFAAsF;AACtF,MAAM,CAAC,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAWnC,8EAA8E;AAC9E,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,MAAM,UAAU,GAAG,CAAC,CAAC,IAAI,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC;IAC3C,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;AAC/C,CAAC;AAED,kIAAkI;AAClI,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,OAAO,aAAa,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,aAAa,CAC3B,aAAqB,EACrB,QAAuB,UAAU;IAEjC,OAAO,aAAa,CAAC,KAAK,CAAC,GAAG,aAAa,CAAC;AAC9C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,WAAW,CACzB,aAAqB,EACrB,cAAsB,EACtB,QAAuB,UAAU,EACjC,SAAoB,OAAO;IAE3B,MAAM,MAAM,GAAe,EAAE,CAAC;IAC9B,MAAM,MAAM,GAAe,EAAE,CAAC;IAC9B,MAAM,UAAU,GAAG,aAAa,GAAG,qBAAqB,CAAC;IACzD,MAAM,WAAW,GAAG,cAAc,GAAG,sBAAsB,CAAC;IAC5D,MAAM,KAAK,GAAG,MAAM,KAAK,YAAY,CAAC;IAEtC,2EAA2E;IAC3E,uEAAuE;IACvE,6CAA6C;IAC7C,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,KAAK,IAAI,IAAI,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,IAAI,KAAK,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,EAAE,CAAC;QACxD,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;QAChC,MAAM,UAAU,GACd,KAAK,CAAC,UAAU,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,IAAI,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC;QACvE,2EAA2E;QAC3E,2EAA2E;QAC3E,4CAA4C;QAC5C,MAAM,KAAK,GAAG,KAAK;YACjB,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,KAAK,IAAI,IAAI,CAAC;YACrC,CAAC,CAAC,UAAU;gBACV,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC;gBACjB,CAAC,CAAC,IAAI,CAAC;QACX,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAE9D,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACrB,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI;gBACJ,OAAO,EAAE,IAAI;gBACb,CAAC,EAAE,UAAU,GAAG,aAAa,GAAG,UAAU,GAAG,CAAC;gBAC9C,KAAK,EAAE,UAAU;gBACjB,MAAM,EAAE,WAAW;gBACnB,sEAAsE;gBACtE,uEAAuE;gBACvE,8CAA8C;gBAC9C,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;gBAC3B,IAAI;gBACJ,2DAA2D;gBAC3D,QAAQ,EAAE,cAAc,GAAG,CAAC,GAAG,gBAAgB;aAChD,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI;gBACJ,OAAO,EAAE,KAAK;gBACd,CAAC,EAAE,UAAU,GAAG,aAAa;gBAC7B,KAAK,EAAE,aAAa;gBACpB,MAAM,EAAE,cAAc;gBACtB,KAAK;gBACL,IAAI;gBACJ,QAAQ,EAAE,cAAc,GAAG,CAAC;aAC7B,CAAC,CAAC;YACH,UAAU,IAAI,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC;AAChC,CAAC"}
1
+ {"version":3,"file":"keyboard-geometry.js","sourceRoot":"","sources":["../src/keyboard-geometry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * The keyboard for a track, in one call: which keys, how big, what they are
3
+ * called, and where their labels go.
4
+ *
5
+ * Each of those was already a shared function — `trackKeyboardSpan`,
6
+ * `computeKeys`, `keyboardLabelSemitones`/`relabelKeys` — but the *composition*
7
+ * was written out in both apps, and the two compositions disagreed: the native
8
+ * app never relabelled a transposing part in written pitch, laid its labels
9
+ * inside the keys rather than in a gutter, recomputed black-key heights from
10
+ * the ratio, and fitted the width where the web scrolled. A keyboard is the
11
+ * sum of those decisions, so the sum lives here too.
12
+ *
13
+ * Web's rules are the reference: the height handed in is the whole panel, the
14
+ * label gutter comes out of it, and a drum kit's gutter is two rows because its
15
+ * black keys are named as well.
16
+ */
17
+ import type { PitchDisplay, Track } from '@sudobility/music_types';
18
+ import { type KeyNaming, type KeyboardRange, type PianoKey } from './keyboard-geometry.js';
19
+ import type { MidiRange } from '@sudobility/music_types';
20
+ import type { RenderTheme } from './types.js';
21
+ /**
22
+ * Room below the keys for a pitched keyboard's one row of C/F labels.
23
+ *
24
+ * A little more than `LABEL_ROW_HEIGHT`, so the label clears the key's bottom
25
+ * edge instead of touching it.
26
+ */
27
+ export declare const PITCH_LABEL_GUTTER = 14;
28
+ /** A playable white key. */
29
+ export declare const KEYBOARD_WHITE = "#fbfbfd";
30
+ /** A playable black key. */
31
+ export declare const KEYBOARD_BLACK = "#1f1f23";
32
+ /**
33
+ * How the keys meet the width they are given.
34
+ *
35
+ * - `'scroll'` (web, the default): keys fill the width but never shrink below
36
+ * `MIN_WHITE_KEY_WIDTH`; past that the keyboard is wider than its panel and
37
+ * the panel scrolls. On a desktop a narrow window should not turn 88 keys
38
+ * into slivers nobody can click.
39
+ * - `'width'` (native): the whole range always fits. On a phone a keyboard you
40
+ * have to scroll is one you cannot play a two-handed chord on, and a finger
41
+ * presses a sliver more reliably than a pointer does.
42
+ */
43
+ export type KeyboardFit = 'scroll' | 'width';
44
+ export type KeyboardKeysOptions = {
45
+ /** Available width. */
46
+ width: number;
47
+ /** The whole panel's height, label gutter included. */
48
+ height: number;
49
+ /** The active track; null or absent draws the whole piano with nothing marked. */
50
+ track: Pick<Track, 'clef' | 'midiProgram' | 'measures'> | null | undefined;
51
+ /** What the staff shows; moves the lettering of a transposing part. Default concert. */
52
+ pitchDisplay?: PitchDisplay;
53
+ fit?: KeyboardFit;
54
+ };
55
+ export type KeyboardKeys = {
56
+ /** The keys drawn, snapped to whole white keys. */
57
+ range: KeyboardRange;
58
+ /** What the instrument can play, or null when nothing is marked. */
59
+ playable: MidiRange | null;
60
+ naming: KeyNaming;
61
+ /** Whites first, then blacks — render in order and the blacks land on top. Each carries its own height and label position. */
62
+ keys: PianoKey[];
63
+ /** Height reserved under the white keys for labels. */
64
+ labelGutter: number;
65
+ /** A white key's height: `height − labelGutter`. */
66
+ keyHeight: number;
67
+ whiteKeyWidth: number;
68
+ /** The keyboard's total width — of `range`, not of the 88-key piano. */
69
+ width: number;
70
+ };
71
+ /**
72
+ * Everything a keyboard view needs to draw `track`'s keys into a box.
73
+ *
74
+ * Cheap enough to call per render (it walks the track's notes once) but it
75
+ * returns fresh arrays, so memoize on its inputs where the keys are reconciled.
76
+ */
77
+ export declare function keyboardKeys({ width, height, track, pitchDisplay, fit, }: KeyboardKeysOptions): KeyboardKeys;
78
+ /** What is happening to a key right now. */
79
+ export type KeyState = {
80
+ /** Sounding in playback, or held down. */
81
+ lit: boolean;
82
+ /** A pitch of the one selected chord. */
83
+ selected: boolean;
84
+ };
85
+ /**
86
+ * The fill for `key`.
87
+ *
88
+ * Sounding wins over selected — it is the more transient signal, and a key
89
+ * that is both should show what is happening now — and either wins over the
90
+ * out-of-range dimming, which is a standing fact about the instrument.
91
+ */
92
+ export declare function keyboardKeyFill(key: Pick<PianoKey, 'isBlack' | 'outOfRange'>, state: KeyState, theme: RenderTheme): string;
93
+ //# sourceMappingURL=keyboard-keys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyboard-keys.d.ts","sourceRoot":"","sources":["../src/keyboard-keys.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EAWL,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,KAAK,QAAQ,EACd,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAErC,4BAA4B;AAC5B,eAAO,MAAM,cAAc,YAAY,CAAC;AACxC,4BAA4B;AAC5B,eAAO,MAAM,cAAc,YAAY,CAAC;AAExC;;;;;;;;;;GAUG;AACH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,OAAO,CAAC;AAE7C,MAAM,MAAM,mBAAmB,GAAG;IAChC,uBAAuB;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,MAAM,EAAE,MAAM,CAAC;IACf,kFAAkF;IAClF,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,GAAG,UAAU,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC;IAC3E,wFAAwF;IACxF,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,GAAG,CAAC,EAAE,WAAW,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,mDAAmD;IACnD,KAAK,EAAE,aAAa,CAAC;IACrB,oEAAoE;IACpE,QAAQ,EAAE,SAAS,GAAG,IAAI,CAAC;IAC3B,MAAM,EAAE,SAAS,CAAC;IAClB,8HAA8H;IAC9H,IAAI,EAAE,QAAQ,EAAE,CAAC;IACjB,uDAAuD;IACvD,WAAW,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,MAAM,EACN,KAAK,EACL,YAAwB,EACxB,GAAc,GACf,EAAE,mBAAmB,GAAG,YAAY,CAiCpC;AAED,4CAA4C;AAC5C,MAAM,MAAM,QAAQ,GAAG;IACrB,0CAA0C;IAC1C,GAAG,EAAE,OAAO,CAAC;IACb,yCAAyC;IACzC,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,IAAI,CAAC,QAAQ,EAAE,SAAS,GAAG,YAAY,CAAC,EAC7C,KAAK,EAAE,QAAQ,EACf,KAAK,EAAE,WAAW,GACjB,MAAM,CAMR"}
@@ -0,0 +1,60 @@
1
+ import { FULL_RANGE, KEYBOARD_OUT_OF_RANGE_BLACK, KEYBOARD_OUT_OF_RANGE_WHITE, LABEL_ROW_HEIGHT, MIN_WHITE_KEY_WIDTH, computeKeys, keyboardWidth, snapToWhiteKeys, trackKeyboardSpan, whiteKeyCount, } from './keyboard-geometry.js';
2
+ import { keyboardLabelSemitones, relabelKeys } from './keyboard-labels.js';
3
+ /**
4
+ * Room below the keys for a pitched keyboard's one row of C/F labels.
5
+ *
6
+ * A little more than `LABEL_ROW_HEIGHT`, so the label clears the key's bottom
7
+ * edge instead of touching it.
8
+ */
9
+ export const PITCH_LABEL_GUTTER = 14;
10
+ /** A playable white key. */
11
+ export const KEYBOARD_WHITE = '#fbfbfd';
12
+ /** A playable black key. */
13
+ export const KEYBOARD_BLACK = '#1f1f23';
14
+ /**
15
+ * Everything a keyboard view needs to draw `track`'s keys into a box.
16
+ *
17
+ * Cheap enough to call per render (it walks the track's notes once) but it
18
+ * returns fresh arrays, so memoize on its inputs where the keys are reconciled.
19
+ */
20
+ export function keyboardKeys({ width, height, track, pitchDisplay = 'concert', fit = 'scroll', }) {
21
+ const span = track
22
+ ? trackKeyboardSpan(track)
23
+ : { range: snapToWhiteKeys(FULL_RANGE), playable: null };
24
+ const { range, playable } = span;
25
+ // On a percussion track `midiProgram` is a kit and every key is a drum.
26
+ const naming = track?.clef === 'percussion' ? 'percussion' : 'pitch';
27
+ // A kit names its black keys too, on a second row under the first.
28
+ const labelGutter = naming === 'percussion' ? LABEL_ROW_HEIGHT * 2 : PITCH_LABEL_GUTTER;
29
+ const keyHeight = Math.max(1, height - labelGutter);
30
+ const fitted = width / Math.max(1, whiteKeyCount(range));
31
+ const whiteKeyWidth = fit === 'width' ? fitted : Math.max(MIN_WHITE_KEY_WIDTH, fitted);
32
+ const keys = relabelKeys(computeKeys(whiteKeyWidth, keyHeight, range, naming, playable), keyboardLabelSemitones(track, pitchDisplay));
33
+ return {
34
+ range,
35
+ playable,
36
+ naming,
37
+ keys,
38
+ labelGutter,
39
+ keyHeight,
40
+ whiteKeyWidth,
41
+ width: keyboardWidth(whiteKeyWidth, range),
42
+ };
43
+ }
44
+ /**
45
+ * The fill for `key`.
46
+ *
47
+ * Sounding wins over selected — it is the more transient signal, and a key
48
+ * that is both should show what is happening now — and either wins over the
49
+ * out-of-range dimming, which is a standing fact about the instrument.
50
+ */
51
+ export function keyboardKeyFill(key, state, theme) {
52
+ if (state.lit)
53
+ return theme.keyboardLit ?? theme.notePlaying;
54
+ if (state.selected)
55
+ return theme.keyboardSelected ?? theme.noteSelected;
56
+ if (key.isBlack)
57
+ return key.outOfRange ? KEYBOARD_OUT_OF_RANGE_BLACK : KEYBOARD_BLACK;
58
+ return key.outOfRange ? KEYBOARD_OUT_OF_RANGE_WHITE : KEYBOARD_WHITE;
59
+ }
60
+ //# sourceMappingURL=keyboard-keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"keyboard-keys.js","sourceRoot":"","sources":["../src/keyboard-keys.ts"],"names":[],"mappings":"AAiBA,OAAO,EACL,UAAU,EACV,2BAA2B,EAC3B,2BAA2B,EAC3B,gBAAgB,EAChB,mBAAmB,EACnB,WAAW,EACX,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,aAAa,GAId,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,sBAAsB,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAI3E;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,CAAC;AAErC,4BAA4B;AAC5B,MAAM,CAAC,MAAM,cAAc,GAAG,SAAS,CAAC;AACxC,4BAA4B;AAC5B,MAAM,CAAC,MAAM,cAAc,GAAG,SAAS,CAAC;AA4CxC;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,EAC3B,KAAK,EACL,MAAM,EACN,KAAK,EACL,YAAY,GAAG,SAAS,EACxB,GAAG,GAAG,QAAQ,GACM;IACpB,MAAM,IAAI,GAAG,KAAK;QAChB,CAAC,CAAC,iBAAiB,CAAC,KAAK,CAAC;QAC1B,CAAC,CAAC,EAAE,KAAK,EAAE,eAAe,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC3D,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC;IAEjC,wEAAwE;IACxE,MAAM,MAAM,GACV,KAAK,EAAE,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC;IACxD,mEAAmE;IACnE,MAAM,WAAW,GACf,MAAM,KAAK,YAAY,CAAC,CAAC,CAAC,gBAAgB,GAAG,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC;IACtE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,WAAW,CAAC,CAAC;IAEpD,MAAM,MAAM,GAAG,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC;IACzD,MAAM,aAAa,GACjB,GAAG,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC;IAEnE,MAAM,IAAI,GAAG,WAAW,CACtB,WAAW,CAAC,aAAa,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAC9D,sBAAsB,CAAC,KAAK,EAAE,YAAY,CAAC,CAC5C,CAAC;IAEF,OAAO;QACL,KAAK;QACL,QAAQ;QACR,MAAM;QACN,IAAI;QACJ,WAAW;QACX,SAAS;QACT,aAAa;QACb,KAAK,EAAE,aAAa,CAAC,aAAa,EAAE,KAAK,CAAC;KAC3C,CAAC;AACJ,CAAC;AAUD;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAC7B,GAA6C,EAC7C,KAAe,EACf,KAAkB;IAElB,IAAI,KAAK,CAAC,GAAG;QAAE,OAAO,KAAK,CAAC,WAAW,IAAI,KAAK,CAAC,WAAW,CAAC;IAC7D,IAAI,KAAK,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAC,gBAAgB,IAAI,KAAK,CAAC,YAAY,CAAC;IACxE,IAAI,GAAG,CAAC,OAAO;QACb,OAAO,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,cAAc,CAAC;IACvE,OAAO,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,cAAc,CAAC;AACvE,CAAC"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Painting a frame as a cached base with the active track's notes over it.
3
+ *
4
+ * During playback the only thing a repaint changes is which of the active
5
+ * track's notes are lit (`noteColorsFor`), so redrawing the whole window for
6
+ * it — every stave, clef, beam and notehead of every visible track — is almost
7
+ * entirely wasted. The renderer draws a frame as two layers (see
8
+ * `CanvasRenderOptions.layer`); this keeps the base from the last paint and
9
+ * redraws only the overlay while nothing else has changed.
10
+ *
11
+ * What counts as "nothing else" is the canvas's call, not this module's: the
12
+ * `ScoreCanvas` passes a `baseVersion` that moves whenever anything but the lit
13
+ * notes changes — the score, the view, the scroll, the active track, the
14
+ * selection. This compares versions and nothing more.
15
+ *
16
+ * Platform-free. A host supplies the two things only it can do: record into an
17
+ * offscreen layer (an offscreen canvas on the web, an `SkPicture` in Skia) and
18
+ * put a layer on screen with more drawing over it.
19
+ */
20
+ import type { CanvasRenderOptions, CanvasRenderResult, CanvasScoreRenderer } from './canvas-renderer.js';
21
+ import type { DrawingContext2D } from './drawing-context.js';
22
+ import type { Score } from '@sudobility/music_types';
23
+ export type LayerCompositor<Layer> = {
24
+ /**
25
+ * Draw into an offscreen layer the size of the visible canvas and return it.
26
+ *
27
+ * May reuse and return the previous layer: it is never shown again once a
28
+ * new one is recorded.
29
+ */
30
+ record(draw: (ctx: DrawingContext2D) => void, previous: Layer | null): Layer;
31
+ /**
32
+ * Show `base` on the visible surface with an identity transform, then run
33
+ * `drawOverlay` over it on the same context.
34
+ */
35
+ present(base: Layer, drawOverlay: (ctx: DrawingContext2D) => void): void;
36
+ };
37
+ /** What `ScoreCanvas` tells a surface about the frame it is asking for. */
38
+ export type PaintFrame = {
39
+ /**
40
+ * Moves whenever anything a base depends on has changed; equal means only
41
+ * the lit notes differ from the last paint.
42
+ */
43
+ baseVersion: number;
44
+ };
45
+ export type LayeredPaint = (score: Score, options: CanvasRenderOptions, frame?: PaintFrame) => CanvasRenderResult | null;
46
+ export declare function createLayeredPaint<Layer>(renderer: CanvasScoreRenderer, compositor: LayerCompositor<Layer>): LayeredPaint;
47
+ //# sourceMappingURL=layered-paint.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layered-paint.d.ts","sourceRoot":"","sources":["../src/layered-paint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,KAAK,EACV,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACpB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAErD,MAAM,MAAM,eAAe,CAAC,KAAK,IAAI;IACnC;;;;;OAKG;IACH,MAAM,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,IAAI,EAAE,QAAQ,EAAE,KAAK,GAAG,IAAI,GAAG,KAAK,CAAC;IAC7E;;;OAGG;IACH,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,IAAI,GAAG,IAAI,CAAC;CAC1E,CAAC;AAEF,2EAA2E;AAC3E,MAAM,MAAM,UAAU,GAAG;IACvB;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,CACzB,KAAK,EAAE,KAAK,EACZ,OAAO,EAAE,mBAAmB,EAC5B,KAAK,CAAC,EAAE,UAAU,KACf,kBAAkB,GAAG,IAAI,CAAC;AAE/B,wBAAgB,kBAAkB,CAAC,KAAK,EACtC,QAAQ,EAAE,mBAAmB,EAC7B,UAAU,EAAE,eAAe,CAAC,KAAK,CAAC,GACjC,YAAY,CA0Bd"}
@@ -0,0 +1,22 @@
1
+ export function createLayeredPaint(renderer, compositor) {
2
+ let base = null;
3
+ let version = null;
4
+ return (score, options, frame) => {
5
+ // Without a version there is no telling what changed, so the base is
6
+ // always re-recorded: correct, and exactly the old cost plus a composite.
7
+ let shown = base;
8
+ if (shown === null ||
9
+ frame === undefined ||
10
+ frame.baseVersion !== version) {
11
+ shown = compositor.record(ctx => renderer.render(score, ctx, { ...options, layer: 'base' }), base);
12
+ base = shown;
13
+ version = frame?.baseVersion ?? null;
14
+ }
15
+ let result = null;
16
+ compositor.present(shown, ctx => {
17
+ result = renderer.render(score, ctx, { ...options, layer: 'overlay' });
18
+ });
19
+ return result;
20
+ };
21
+ }
22
+ //# sourceMappingURL=layered-paint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"layered-paint.js","sourceRoot":"","sources":["../src/layered-paint.ts"],"names":[],"mappings":"AAyDA,MAAM,UAAU,kBAAkB,CAChC,QAA6B,EAC7B,UAAkC;IAElC,IAAI,IAAI,GAAiB,IAAI,CAAC;IAC9B,IAAI,OAAO,GAAkB,IAAI,CAAC;IAElC,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAC/B,qEAAqE;QACrE,0EAA0E;QAC1E,IAAI,KAAK,GAAG,IAAI,CAAC;QACjB,IACE,KAAK,KAAK,IAAI;YACd,KAAK,KAAK,SAAS;YACnB,KAAK,CAAC,WAAW,KAAK,OAAO,EAC7B,CAAC;YACD,KAAK,GAAG,UAAU,CAAC,MAAM,CACvB,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,EACjE,IAAI,CACL,CAAC;YACF,IAAI,GAAG,KAAK,CAAC;YACb,OAAO,GAAG,KAAK,EAAE,WAAW,IAAI,IAAI,CAAC;QACvC,CAAC;QACD,IAAI,MAAM,GAA8B,IAAI,CAAC;QAC7C,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE;YAC9B,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE,GAAG,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QACzE,CAAC,CAAC,CAAC;QACH,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;AACJ,CAAC"}
@@ -1,7 +1,11 @@
1
1
  import type { Track } from '@sudobility/music_types';
2
2
  import type { LayoutPlan } from './layout.js';
3
- export type PaperSize = 'a4' | 'letter' | 'legal';
4
- export type PaperOrientation = 'portrait' | 'landscape';
3
+ /** The papers a score prints on, in the order a picker offers them. */
4
+ export declare const PAPER_SIZES: readonly ["a4", "letter", "legal"];
5
+ export type PaperSize = (typeof PAPER_SIZES)[number];
6
+ /** Portrait first: it is the default and what almost every part is. */
7
+ export declare const PAPER_ORIENTATIONS: readonly ["portrait", "landscape"];
8
+ export type PaperOrientation = (typeof PAPER_ORIENTATIONS)[number];
5
9
  /** Portrait dimensions in millimetres; landscape swaps them. */
6
10
  export declare const PAPER_DIMENSIONS_MM: Record<PaperSize, {
7
11
  width: number;
@@ -1 +1 @@
1
- {"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../src/pagination.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAW,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,UAAU,EAAgB,MAAM,aAAa,CAAC;AAE5D,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,QAAQ,GAAG,OAAO,CAAC;AAClD,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG,WAAW,CAAC;AAExD,gEAAgE;AAChE,eAAO,MAAM,mBAAmB,EAAE,MAAM,CACtC,SAAS,EACT;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAKlC,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,KAAK,CAAC;AAEjC;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,SAAS,EAChB,WAAW,EAAE,gBAAgB,EAC7B,YAAY,EAAE,MAAM,EACpB,QAAQ,GAAE,MAAuB,GAChC,MAAM,CAOR;AAED,2EAA2E;AAC3E,MAAM,MAAM,SAAS,GAAG;IAAE,aAAa,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAOpD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,IAAI,CAAC;AA6B/B;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,KAAK,EACZ,eAAe,EAAE,MAAM,GACtB,MAAM,CAQR;AA8BD;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CACtB,IAAI,EAAE,UAAU,EAChB,UAAU,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,KAAK,GAChB,SAAS,EAAE,CA+Bb"}
1
+ {"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../src/pagination.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAW,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,UAAU,EAAgB,MAAM,aAAa,CAAC;AAE5D,uEAAuE;AACvE,eAAO,MAAM,WAAW,oCAAqC,CAAC;AAC9D,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAErD,uEAAuE;AACvE,eAAO,MAAM,kBAAkB,oCAAqC,CAAC;AACrE,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnE,gEAAgE;AAChE,eAAO,MAAM,mBAAmB,EAAE,MAAM,CACtC,SAAS,EACT;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAKlC,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,KAAK,CAAC;AAEjC;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,SAAS,EAChB,WAAW,EAAE,gBAAgB,EAC7B,YAAY,EAAE,MAAM,EACpB,QAAQ,GAAE,MAAuB,GAChC,MAAM,CAOR;AAED,2EAA2E;AAC3E,MAAM,MAAM,SAAS,GAAG;IAAE,aAAa,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAOpD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,IAAI,CAAC;AA6B/B;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,KAAK,EACZ,eAAe,EAAE,MAAM,GACtB,MAAM,CAQR;AA8BD;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CACtB,IAAI,EAAE,UAAU,EAChB,UAAU,EAAE,MAAM,EAClB,SAAS,CAAC,EAAE,KAAK,GAChB,SAAS,EAAE,CA+Bb"}
@@ -10,6 +10,10 @@
10
10
  * of a phrase costs a real player a hand.
11
11
  */
12
12
  import { isSilentMeasure } from '@sudobility/music_types';
13
+ /** The papers a score prints on, in the order a picker offers them. */
14
+ export const PAPER_SIZES = ['a4', 'letter', 'legal'];
15
+ /** Portrait first: it is the default and what almost every part is. */
16
+ export const PAPER_ORIENTATIONS = ['portrait', 'landscape'];
13
17
  /** Portrait dimensions in millimetres; landscape swaps them. */
14
18
  export const PAPER_DIMENSIONS_MM = {
15
19
  a4: { width: 210, height: 297 },
@@ -1 +1 @@
1
- {"version":3,"file":"pagination.js","sourceRoot":"","sources":["../src/pagination.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAO1D,gEAAgE;AAChE,MAAM,CAAC,MAAM,mBAAmB,GAG5B;IACF,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE;IAC/B,MAAM,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,eAAe;IACxD,KAAK,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,eAAe;CACxD,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAC;AAEjC;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAC9B,KAAgB,EAChB,WAA6B,EAC7B,YAAoB,EACpB,WAAmB,cAAc;IAEjC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;IACrD,MAAM,SAAS,GAAG,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;IAC9D,MAAM,QAAQ,GAAG,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;IAC7D,OAAO,CACL,CAAC,YAAY,GAAG,CAAC,QAAQ,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,GAAG,CAAC,SAAS,GAAG,CAAC,GAAG,QAAQ,CAAC,CACxE,CAAC;AACJ,CAAC;AAKD,oEAAoE;AACpE,SAAS,YAAY,CAAC,MAAoB;IACxC,OAAO,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC;AAC3C,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC;AAE/B,sFAAsF;AACtF,SAAS,OAAO,CAAC,OAAgB;IAC/B,OAAO,OAAO,CAAC,qBAAqB,IAAI,CAAC,CAAC;AAC5C,CAAC;AAED,2CAA2C;AAC3C,SAAS,gBAAgB,CAAC,KAAY,EAAE,OAA0B;IAChE,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAChD,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3C,IAAI,CAAC,OAAO,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC;YAAE,MAAM;QACjD,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,6CAA6C;AAC7C,SAAS,eAAe,CAAC,KAAY,EAAE,OAA0B;IAC/D,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACtC,IAAI,CAAC,OAAO,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC;YAAE,MAAM;QACjD,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAC1B,IAAgB,EAChB,KAAY,EACZ,eAAuB;IAEvB,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,GAAG,CAAC,CAAC,CAAC;IAC/C,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI;QAAE,OAAO,CAAC,CAAC;IAC7B,OAAO,CACL,gBAAgB,CAAC,KAAK,EAAE,IAAI,CAAC,cAAc,CAAC;QAC5C,eAAe,CAAC,KAAK,EAAE,IAAI,CAAC,cAAc,CAAC,CAC5C,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,SAAS,QAAQ,CACf,IAAgB,EAChB,KAAY,EACZ,KAAa,EACb,SAAiB;IAEjB,IAAI,IAAI,GAAG,SAAS,CAAC;IACrB,IAAI,SAAS,GAAG,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,GAAG,CAAC,CAAC,CAAC;IAEzD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,EAAE,SAAS,GAAG,aAAa,CAAC,CAAC;IAChE,KAAK,IAAI,GAAG,GAAG,SAAS,GAAG,CAAC,EAAE,GAAG,IAAI,QAAQ,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;QACxD,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC;QACjD,IAAI,KAAK,GAAG,SAAS,EAAE,CAAC;YACtB,IAAI,GAAG,GAAG,CAAC;YACX,SAAS,GAAG,KAAK,CAAC;QACpB,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,QAAQ,CACtB,IAAgB,EAChB,UAAkB,EAClB,SAAiB;IAEjB,MAAM,KAAK,GAAgB,EAAE,CAAC;IAC9B,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,OAAO,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACnC,IAAI,GAAG,GAAG,KAAK,CAAC;QAChB,IAAI,IAAI,GAAG,CAAC,CAAC;QAEb,OAAO,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YACjC,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;YAC/C,wEAAwE;YACxE,yCAAyC;YACzC,IAAI,GAAG,GAAG,KAAK,IAAI,IAAI,GAAG,MAAM,GAAG,UAAU;gBAAE,MAAM;YACrD,IAAI,IAAI,MAAM,CAAC;YACf,GAAG,IAAI,CAAC,CAAC;QACX,CAAC;QAED,yEAAyE;QACzE,yEAAyE;QACzE,qEAAqE;QACrE,IAAI,SAAS,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YAC3C,GAAG,GAAG,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;QAC9C,CAAC;QAED,MAAM,aAAa,GAAa,EAAE,CAAC;QACnC,KAAK,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC;YAAE,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC3D,KAAK,CAAC,IAAI,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC;QAC9B,KAAK,GAAG,GAAG,CAAC;IACd,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
1
+ {"version":3,"file":"pagination.js","sourceRoot":"","sources":["../src/pagination.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAI1D,uEAAuE;AACvE,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAU,CAAC;AAG9D,uEAAuE;AACvE,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,UAAU,EAAE,WAAW,CAAU,CAAC;AAGrE,gEAAgE;AAChE,MAAM,CAAC,MAAM,mBAAmB,GAG5B;IACF,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE;IAC/B,MAAM,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,eAAe;IACxD,KAAK,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,eAAe;CACxD,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,EAAE,CAAC;AAEjC;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAC9B,KAAgB,EAChB,WAA6B,EAC7B,YAAoB,EACpB,WAAmB,cAAc;IAEjC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAC;IACrD,MAAM,SAAS,GAAG,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;IAC9D,MAAM,QAAQ,GAAG,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;IAC7D,OAAO,CACL,CAAC,YAAY,GAAG,CAAC,QAAQ,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,GAAG,CAAC,SAAS,GAAG,CAAC,GAAG,QAAQ,CAAC,CACxE,CAAC;AACJ,CAAC;AAKD,oEAAoE;AACpE,SAAS,YAAY,CAAC,MAAoB;IACxC,OAAO,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC;AAC3C,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC;AAE/B,sFAAsF;AACtF,SAAS,OAAO,CAAC,OAAgB;IAC/B,OAAO,OAAO,CAAC,qBAAqB,IAAI,CAAC,CAAC;AAC5C,CAAC;AAED,2CAA2C;AAC3C,SAAS,gBAAgB,CAAC,KAAY,EAAE,OAA0B;IAChE,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAChD,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3C,IAAI,CAAC,OAAO,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC;YAAE,MAAM;QACjD,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,6CAA6C;AAC7C,SAAS,eAAe,CAAC,KAAY,EAAE,OAA0B;IAC/D,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QACtC,IAAI,CAAC,OAAO,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC;YAAE,MAAM;QACjD,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAC1B,IAAgB,EAChB,KAAY,EACZ,eAAuB;IAEvB,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,GAAG,CAAC,CAAC,CAAC;IAC/C,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI;QAAE,OAAO,CAAC,CAAC;IAC7B,OAAO,CACL,gBAAgB,CAAC,KAAK,EAAE,IAAI,CAAC,cAAc,CAAC;QAC5C,eAAe,CAAC,KAAK,EAAE,IAAI,CAAC,cAAc,CAAC,CAC5C,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,SAAS,QAAQ,CACf,IAAgB,EAChB,KAAY,EACZ,KAAa,EACb,SAAiB;IAEjB,IAAI,IAAI,GAAG,SAAS,CAAC;IACrB,IAAI,SAAS,GAAG,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,GAAG,CAAC,CAAC,CAAC;IAEzD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,EAAE,SAAS,GAAG,aAAa,CAAC,CAAC;IAChE,KAAK,IAAI,GAAG,GAAG,SAAS,GAAG,CAAC,EAAE,GAAG,IAAI,QAAQ,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;QACxD,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC;QACjD,IAAI,KAAK,GAAG,SAAS,EAAE,CAAC;YACtB,IAAI,GAAG,GAAG,CAAC;YACX,SAAS,GAAG,KAAK,CAAC;QACpB,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,QAAQ,CACtB,IAAgB,EAChB,UAAkB,EAClB,SAAiB;IAEjB,MAAM,KAAK,GAAgB,EAAE,CAAC;IAC9B,IAAI,KAAK,GAAG,CAAC,CAAC;IAEd,OAAO,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACnC,IAAI,GAAG,GAAG,KAAK,CAAC;QAChB,IAAI,IAAI,GAAG,CAAC,CAAC;QAEb,OAAO,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YACjC,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;YAC/C,wEAAwE;YACxE,yCAAyC;YACzC,IAAI,GAAG,GAAG,KAAK,IAAI,IAAI,GAAG,MAAM,GAAG,UAAU;gBAAE,MAAM;YACrD,IAAI,IAAI,MAAM,CAAC;YACf,GAAG,IAAI,CAAC,CAAC;QACX,CAAC;QAED,yEAAyE;QACzE,yEAAyE;QACzE,qEAAqE;QACrE,IAAI,SAAS,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YAC3C,GAAG,GAAG,QAAQ,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;QAC9C,CAAC;QAED,MAAM,aAAa,GAAa,EAAE,CAAC;QACnC,KAAK,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC;YAAE,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC3D,KAAK,CAAC,IAAI,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC;QAC9B,KAAK,GAAG,GAAG,CAAC;IACd,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Playback → the score canvas, in one place both apps share.
3
+ *
4
+ * Watches the shared playhead (`IMusicPosition`) and the player's sounding
5
+ * notes and drives a `ScoreCanvas` with them: the cursor, the lit notes, and
6
+ * following the music. The rules below used to live separately in the web
7
+ * app's caret and in the native app's, and disagreed.
8
+ *
9
+ * **The cursor is described, not written per frame.** While playing, the
10
+ * binding hands the canvas a motion (a tick, when it was true, and a rate) and
11
+ * re-describes it only when the reports disagree with it by more than
12
+ * `DRIFT_SECONDS`, or the tempo has measurably changed. Between those the
13
+ * surface moves the line on its own.
14
+ */
15
+ import type { IMusicPosition, SoundingNote } from '@sudobility/music_types';
16
+ import type { CursorMotion } from './cursor.js';
17
+ /** Re-describe the motion when the line would be further than this from the reports. */
18
+ export declare const DRIFT_SECONDS = 0.04;
19
+ /** What the binding needs from the canvas — `ScoreCanvas` satisfies it. */
20
+ export type PlaybackCanvasTarget = {
21
+ setCursorTick(tick: number): void;
22
+ animateCursor(motion: CursorMotion): void;
23
+ setPlayingNotes(notes: readonly SoundingNote[]): void;
24
+ scrollToFollow(tick: number): void;
25
+ measureIndexAt(tick: number): number | null;
26
+ writtenTicksPerSecond(tick: number): number;
27
+ /** How long lit notes take to draw here; see `ScoreCanvas.highlightLatencySeconds`. */
28
+ subscribeHighlightLatency?(listener: (seconds: number) => void): () => void;
29
+ };
30
+ export type PlaybackBindingOptions = {
31
+ position: IMusicPosition;
32
+ /** The player's sounding-notes subscription; returns an unsubscribe. */
33
+ onSounding?: (listener: (notes: readonly SoundingNote[]) => void) => () => void;
34
+ /**
35
+ * Run `work` once the current burst of notifications is over — a microtask
36
+ * (`queueMicrotask`) on every host.
37
+ *
38
+ * A single engine call can notify several times, and only the end state means
39
+ * anything: stopping homes the position to 0 while it still reports playing,
40
+ * then reports stopped. Decided notification by notification, that homing
41
+ * reads as the music moving to bar 1 and the view scrolls there; decided once
42
+ * the call is over, it is a stop, and stopping is not a navigation.
43
+ */
44
+ defer: (work: () => void) => void;
45
+ /**
46
+ * The player's `setSoundingRenderDelay`: told how long lit notes take to
47
+ * draw on this host, so it publishes them that far ahead and they land with
48
+ * the sound rather than behind it.
49
+ */
50
+ setSoundingRenderDelay?: (seconds: number) => void;
51
+ /** Whether the view follows the playhead. Default true. */
52
+ follow?: boolean;
53
+ /** `performance.now()` — passed in, since this package names no host global. */
54
+ now: () => number;
55
+ };
56
+ export declare function bindPlaybackToCanvas(canvas: PlaybackCanvasTarget, { position, defer, onSounding, setSoundingRenderDelay, follow, now, }: PlaybackBindingOptions): () => void;
57
+ //# sourceMappingURL=playback-binding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"playback-binding.d.ts","sourceRoot":"","sources":["../src/playback-binding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,wFAAwF;AACxF,eAAO,MAAM,aAAa,OAAO,CAAC;AAQlC,2EAA2E;AAC3E,MAAM,MAAM,oBAAoB,GAAG;IACjC,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,aAAa,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAAC;IAC1C,eAAe,CAAC,KAAK,EAAE,SAAS,YAAY,EAAE,GAAG,IAAI,CAAC;IACtD,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC5C,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5C,uFAAuF;IACvF,yBAAyB,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CAC7E,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,EAAE,cAAc,CAAC;IACzB,wEAAwE;IACxE,UAAU,CAAC,EAAE,CACX,QAAQ,EAAE,CAAC,KAAK,EAAE,SAAS,YAAY,EAAE,KAAK,IAAI,KAC/C,MAAM,IAAI,CAAC;IAChB;;;;;;;;;OASG;IACH,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IAClC;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACnD,2DAA2D;IAC3D,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,gFAAgF;IAChF,GAAG,EAAE,MAAM,MAAM,CAAC;CACnB,CAAC;AAEF,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,oBAAoB,EAC5B,EACE,QAAQ,EACR,KAAK,EACL,UAAU,EACV,sBAAsB,EACtB,MAAa,EACb,GAAG,GACJ,EAAE,sBAAsB,GACxB,MAAM,IAAI,CA6GZ"}
@@ -0,0 +1,110 @@
1
+ /** Re-describe the motion when the line would be further than this from the reports. */
2
+ export const DRIFT_SECONDS = 0.04;
3
+ /** The shortest span a rate measurement is trusted over. */
4
+ const RATE_WINDOW_SECONDS = 0.25;
5
+ /** A tempo change smaller than this is measurement noise… */
6
+ const RATE_CHANGE = 0.05;
7
+ /** …and it is judged only over a span long enough to tell. */
8
+ const RATE_CHANGE_WINDOW_SECONDS = 1;
9
+ export function bindPlaybackToCanvas(canvas, { position, defer, onSounding, setSoundingRenderDelay, follow = true, now, }) {
10
+ let motion = null;
11
+ let wasPlaying = position.isPlaying;
12
+ let rateWindow = null;
13
+ let rate = 0;
14
+ let followedMeasure = null;
15
+ const describe = (next) => {
16
+ motion = next;
17
+ canvas.animateCursor(next);
18
+ };
19
+ const followTo = (tick) => {
20
+ if (!follow)
21
+ return;
22
+ const measure = canvas.measureIndexAt(tick);
23
+ // 14. Once per bar.
24
+ if (measure === null || measure === followedMeasure)
25
+ return;
26
+ followedMeasure = measure;
27
+ canvas.scrollToFollow(tick);
28
+ };
29
+ const wake = () => {
30
+ const tick = position.tick;
31
+ const at = now();
32
+ const playing = position.isPlaying;
33
+ const transportChanged = playing !== wasPlaying;
34
+ wasPlaying = playing;
35
+ if (!playing) {
36
+ rateWindow = null;
37
+ if (!motion || motion.ticksPerSecond !== 0 || motion.tick !== tick) {
38
+ motion = { tick, atMs: at, ticksPerSecond: 0 };
39
+ canvas.setCursorTick(tick);
40
+ }
41
+ // 15. Stopping or pausing is not a navigation; a seek while stopped is.
42
+ if (transportChanged)
43
+ followedMeasure = null;
44
+ else
45
+ followTo(tick);
46
+ return;
47
+ }
48
+ followTo(tick);
49
+ if (transportChanged || !rateWindow || tick < rateWindow.tick) {
50
+ // Just started, or jumped back: nothing measured yet belongs to this run.
51
+ rate = canvas.writtenTicksPerSecond(tick);
52
+ rateWindow = { tick, at };
53
+ describe({ tick, atMs: at, ticksPerSecond: rate });
54
+ return;
55
+ }
56
+ const span = (at - rateWindow.at) / 1000;
57
+ const measured = span >= RATE_WINDOW_SECONDS ? (tick - rateWindow.tick) / span : 0;
58
+ if (rate <= 0 || !motion) {
59
+ if (measured <= 0)
60
+ return;
61
+ rate = measured;
62
+ rateWindow = { tick, at };
63
+ describe({ tick, atMs: at, ticksPerSecond: rate });
64
+ return;
65
+ }
66
+ const expected = motion.tick + (motion.ticksPerSecond * (at - motion.atMs)) / 1000;
67
+ const drifted = Math.abs(expected - tick) > rate * DRIFT_SECONDS;
68
+ const retimed = span >= RATE_CHANGE_WINDOW_SECONDS &&
69
+ measured > 0 &&
70
+ Math.abs(measured - rate) > rate * RATE_CHANGE;
71
+ if (drifted || retimed) {
72
+ // The measurement window restarts only once it has produced a rate:
73
+ // restarting it on every correction would keep it too short to measure,
74
+ // and a transport running at another speed would be re-anchored at the
75
+ // wrong rate forever.
76
+ if (measured > 0) {
77
+ rate = measured;
78
+ rateWindow = { tick, at };
79
+ }
80
+ describe({ tick, atMs: at, ticksPerSecond: rate });
81
+ }
82
+ };
83
+ let queued = false;
84
+ let disposed = false;
85
+ const unsubscribePosition = position.subscribe(() => {
86
+ if (queued)
87
+ return;
88
+ queued = true;
89
+ defer(() => {
90
+ queued = false;
91
+ if (!disposed)
92
+ wake();
93
+ });
94
+ });
95
+ const unsubscribeLatency = setSoundingRenderDelay && canvas.subscribeHighlightLatency
96
+ ? canvas.subscribeHighlightLatency(setSoundingRenderDelay)
97
+ : undefined;
98
+ const unsubscribeSounding = onSounding?.(notes => canvas.setPlayingNotes(notes));
99
+ // The cursor starts where the playhead is, without scrolling anywhere.
100
+ canvas.setCursorTick(position.tick);
101
+ motion = { tick: position.tick, atMs: now(), ticksPerSecond: 0 };
102
+ followedMeasure = canvas.measureIndexAt(position.tick);
103
+ return () => {
104
+ disposed = true;
105
+ unsubscribePosition();
106
+ unsubscribeSounding?.();
107
+ unsubscribeLatency?.();
108
+ };
109
+ }
110
+ //# sourceMappingURL=playback-binding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"playback-binding.js","sourceRoot":"","sources":["../src/playback-binding.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"playhead.d.ts","sourceRoot":"","sources":["../src/playhead.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,KAAK,EACV,oBAAoB,EAGrB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,KAAK,EAAE,UAAU,EAAgB,MAAM,aAAa,CAAC;AAE5D;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GAAG,WAAW,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;AAEtE,MAAM,MAAM,aAAa,GAAG;IAC1B,mCAAmC;IACnC,CAAC,EAAE,MAAM,CAAC;IACV,yGAAyG;IACzG,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAqMF;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,MAAM,EACZ,aAAa,CAAC,EAAE,aAAa,GAC5B,aAAa,GAAG,IAAI,CAiDtB;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,KAAK,EACZ,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,aAAa,CAAC,EAAE,aAAa,GAC5B,MAAM,GAAG,IAAI,CA2Cf"}
1
+ {"version":3,"file":"playhead.d.ts","sourceRoot":"","sources":["../src/playhead.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,KAAK,EACV,oBAAoB,EAGrB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,KAAK,EAAE,UAAU,EAAgB,MAAM,aAAa,CAAC;AAE5D;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GAAG,WAAW,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC;AAEtE,MAAM,MAAM,aAAa,GAAG;IAC1B,mCAAmC;IACnC,CAAC,EAAE,MAAM,CAAC;IACV,yGAAyG;IACzG,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AA8NF;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,MAAM,EACZ,aAAa,CAAC,EAAE,aAAa,GAC5B,aAAa,GAAG,IAAI,CAkDtB;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,UAAU,EAChB,KAAK,EAAE,KAAK,EACZ,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,aAAa,CAAC,EAAE,aAAa,GAC5B,MAAM,GAAG,IAAI,CA6Cf"}