@opendaw/studio-core 0.0.19 → 0.0.21

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 (110) hide show
  1. package/dist/AudioDevices.d.ts +8 -0
  2. package/dist/AudioDevices.d.ts.map +1 -0
  3. package/dist/AudioDevices.js +34 -0
  4. package/dist/AudioUnitOrdering.d.ts +3 -0
  5. package/dist/AudioUnitOrdering.d.ts.map +1 -0
  6. package/dist/AudioUnitOrdering.js +7 -0
  7. package/dist/EffectBox.d.ts +2 -2
  8. package/dist/EffectBox.d.ts.map +1 -1
  9. package/dist/Engine.d.ts +31 -10
  10. package/dist/Engine.d.ts.map +1 -1
  11. package/dist/EngineFacade.d.ts +22 -11
  12. package/dist/EngineFacade.d.ts.map +1 -1
  13. package/dist/EngineFacade.js +39 -22
  14. package/dist/EngineWorklet.d.ts +22 -13
  15. package/dist/EngineWorklet.d.ts.map +1 -1
  16. package/dist/EngineWorklet.js +47 -56
  17. package/dist/MeterWorklet.d.ts.map +1 -1
  18. package/dist/MeterWorklet.js +2 -2
  19. package/dist/MidiDevices.d.ts +12 -0
  20. package/dist/MidiDevices.d.ts.map +1 -0
  21. package/dist/MidiDevices.js +92 -0
  22. package/dist/Project.d.ts +14 -3
  23. package/dist/Project.d.ts.map +1 -1
  24. package/dist/Project.js +27 -4
  25. package/dist/ProjectApi.d.ts +0 -1
  26. package/dist/ProjectApi.d.ts.map +1 -1
  27. package/dist/ProjectApi.js +16 -11
  28. package/dist/ProjectMigration.d.ts.map +1 -1
  29. package/dist/ProjectMigration.js +20 -3
  30. package/dist/RecordingWorklet.d.ts +15 -3
  31. package/dist/RecordingWorklet.d.ts.map +1 -1
  32. package/dist/RecordingWorklet.js +111 -16
  33. package/dist/WorkerAgents.d.ts +2 -2
  34. package/dist/WorkerAgents.d.ts.map +1 -1
  35. package/dist/Worklets.d.ts +1 -1
  36. package/dist/Worklets.d.ts.map +1 -1
  37. package/dist/Worklets.js +2 -2
  38. package/dist/capture/Capture.d.ts +22 -0
  39. package/dist/capture/Capture.d.ts.map +1 -0
  40. package/dist/capture/Capture.js +32 -0
  41. package/dist/capture/CaptureAudio.d.ts +17 -0
  42. package/dist/capture/CaptureAudio.d.ts.map +1 -0
  43. package/dist/capture/CaptureAudio.js +106 -0
  44. package/dist/capture/CaptureManager.d.ts +12 -0
  45. package/dist/capture/CaptureManager.d.ts.map +1 -0
  46. package/dist/capture/CaptureManager.js +38 -0
  47. package/dist/capture/CaptureMidi.d.ts +13 -0
  48. package/dist/capture/CaptureMidi.d.ts.map +1 -0
  49. package/dist/capture/CaptureMidi.js +106 -0
  50. package/dist/capture/RecordAudio.d.ts +19 -0
  51. package/dist/capture/RecordAudio.d.ts.map +1 -0
  52. package/dist/capture/RecordAudio.js +66 -0
  53. package/dist/capture/RecordMidi.d.ts +13 -0
  54. package/dist/capture/RecordMidi.d.ts.map +1 -0
  55. package/dist/capture/RecordMidi.js +85 -0
  56. package/dist/capture/RecordTrack.d.ts +7 -0
  57. package/dist/capture/RecordTrack.d.ts.map +1 -0
  58. package/dist/capture/RecordTrack.js +23 -0
  59. package/dist/capture/Recording.d.ts +9 -0
  60. package/dist/capture/Recording.d.ts.map +1 -0
  61. package/dist/capture/Recording.js +65 -0
  62. package/dist/capture/RecordingContext.d.ts +10 -0
  63. package/dist/capture/RecordingContext.d.ts.map +1 -0
  64. package/dist/capture/RecordingContext.js +1 -0
  65. package/dist/dawproject/AudioUnitExportLayout.d.ts +10 -0
  66. package/dist/dawproject/AudioUnitExportLayout.d.ts.map +1 -0
  67. package/dist/dawproject/AudioUnitExportLayout.js +64 -0
  68. package/dist/dawproject/BuiltinDevices.d.ts +9 -0
  69. package/dist/dawproject/BuiltinDevices.d.ts.map +1 -0
  70. package/dist/dawproject/BuiltinDevices.js +70 -0
  71. package/dist/dawproject/{DawProjectIO.d.ts → DawProject.d.ts} +6 -4
  72. package/dist/dawproject/DawProject.d.ts.map +1 -0
  73. package/dist/dawproject/DawProject.js +48 -0
  74. package/dist/dawproject/DawProjectExporter.d.ts +7 -6
  75. package/dist/dawproject/DawProjectExporter.d.ts.map +1 -1
  76. package/dist/dawproject/DawProjectExporter.js +245 -22
  77. package/dist/dawproject/DawProjectExporter.test.js +38 -6
  78. package/dist/dawproject/DawProjectImport.d.ts +12 -0
  79. package/dist/dawproject/DawProjectImport.d.ts.map +1 -0
  80. package/dist/dawproject/DawProjectImport.js +389 -0
  81. package/dist/dawproject/DawProjectImport.test.js +6 -7
  82. package/dist/dawproject/DeviceIO.d.ts +8 -0
  83. package/dist/dawproject/DeviceIO.d.ts.map +1 -0
  84. package/dist/dawproject/DeviceIO.js +63 -0
  85. package/dist/index.d.ts +13 -3
  86. package/dist/index.d.ts.map +1 -1
  87. package/dist/index.js +13 -3
  88. package/dist/processors.js +3 -3
  89. package/dist/processors.js.map +4 -4
  90. package/dist/samples/MainThreadSampleLoader.d.ts +1 -0
  91. package/dist/samples/MainThreadSampleLoader.d.ts.map +1 -1
  92. package/dist/samples/MainThreadSampleLoader.js +10 -6
  93. package/dist/samples/MainThreadSampleManager.d.ts +5 -5
  94. package/dist/samples/MainThreadSampleManager.d.ts.map +1 -1
  95. package/dist/samples/MainThreadSampleManager.js +1 -0
  96. package/dist/samples/SampleProvider.d.ts +2 -2
  97. package/dist/samples/SampleProvider.d.ts.map +1 -1
  98. package/dist/samples/SampleStorage.d.ts.map +1 -1
  99. package/dist/samples/SampleStorage.js +2 -3
  100. package/dist/workers.js +2 -2
  101. package/dist/workers.js.map +4 -4
  102. package/package.json +15 -15
  103. package/dist/dawproject/DawProjectIO.d.ts.map +0 -1
  104. package/dist/dawproject/DawProjectIO.js +0 -31
  105. package/dist/dawproject/DawProjectImporter.d.ts +0 -12
  106. package/dist/dawproject/DawProjectImporter.d.ts.map +0 -1
  107. package/dist/dawproject/DawProjectImporter.js +0 -273
  108. package/dist/samples/SamplePeaks.d.ts +0 -6
  109. package/dist/samples/SamplePeaks.d.ts.map +0 -1
  110. package/dist/samples/SamplePeaks.js +0 -9
@@ -0,0 +1,8 @@
1
+ export declare class AudioDevices {
2
+ #private;
3
+ static requestPermission(): Promise<undefined>;
4
+ static requestStream(constraints: MediaTrackConstraints): Promise<MediaStream>;
5
+ static updateInputList(): Promise<undefined>;
6
+ static get inputs(): ReadonlyArray<MediaDeviceInfo>;
7
+ }
8
+ //# sourceMappingURL=AudioDevices.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AudioDevices.d.ts","sourceRoot":"","sources":["../src/AudioDevices.ts"],"names":[],"mappings":"AAIA,qBAAa,YAAY;;WACR,iBAAiB;WAQjB,aAAa,CAAC,WAAW,EAAE,qBAAqB,GAAG,OAAO,CAAC,WAAW,CAAC;WAavE,eAAe;IAY5B,MAAM,KAAK,MAAM,IAAI,aAAa,CAAC,eAAe,CAAC,CAAsB;CAC5E"}
@@ -0,0 +1,34 @@
1
+ import { Promises } from "@opendaw/lib-runtime";
2
+ import { Arrays, isInstanceOf, warn } from "@opendaw/lib-std";
3
+ import { ConstrainDOM } from "@opendaw/lib-dom";
4
+ export class AudioDevices {
5
+ static async requestPermission() {
6
+ const { status, value: stream } = await Promises.tryCatch(navigator.mediaDevices.getUserMedia({ audio: true }));
7
+ if (status === "rejected") {
8
+ return warn("Could not request permission.");
9
+ }
10
+ stream.getTracks().forEach(track => track.stop());
11
+ await this.updateInputList();
12
+ }
13
+ static async requestStream(constraints) {
14
+ const { status, value: stream, error } = await Promises.tryCatch(navigator.mediaDevices.getUserMedia({ audio: constraints }));
15
+ if (status === "rejected") {
16
+ return warn(isInstanceOf(error, OverconstrainedError) ?
17
+ error.constraint === "deviceId"
18
+ ? `Could not find device with id: '${ConstrainDOM.resolveString(constraints.deviceId)}'`
19
+ : error.constraint
20
+ : String(error));
21
+ }
22
+ return stream;
23
+ }
24
+ static async updateInputList() {
25
+ this.#inputs = Arrays.empty();
26
+ const { status, value: devices } = await Promises.tryCatch(navigator.mediaDevices.enumerateDevices());
27
+ if (status === "rejected") {
28
+ return warn("Could not enumerate devices.");
29
+ }
30
+ this.#inputs = devices.filter(device => device.kind === "audioinput" && device.deviceId !== "" && device.groupId !== "");
31
+ }
32
+ static #inputs = Arrays.empty();
33
+ static get inputs() { return this.#inputs; }
34
+ }
@@ -0,0 +1,3 @@
1
+ import { int } from "@opendaw/lib-std";
2
+ export declare const AudioUnitOrdering: Record<string, int>;
3
+ //# sourceMappingURL=AudioUnitOrdering.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AudioUnitOrdering.d.ts","sourceRoot":"","sources":["../src/AudioUnitOrdering.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,GAAG,EAAC,MAAM,kBAAkB,CAAA;AAGpC,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAKxC,CAAA"}
@@ -0,0 +1,7 @@
1
+ import { AudioUnitType } from "@opendaw/studio-enums";
2
+ export const AudioUnitOrdering = {
3
+ [AudioUnitType.Instrument]: 0,
4
+ [AudioUnitType.Aux]: 1,
5
+ [AudioUnitType.Bus]: 2,
6
+ [AudioUnitType.Output]: 3
7
+ };
@@ -1,3 +1,3 @@
1
- import { ArpeggioDeviceBox, DelayDeviceBox, ModularDeviceBox, PitchDeviceBox, RevampDeviceBox, ReverbDeviceBox, StereoToolDeviceBox, ZeitgeistDeviceBox } from "@opendaw/studio-boxes";
2
- export type EffectBox = ArpeggioDeviceBox | PitchDeviceBox | ZeitgeistDeviceBox | DelayDeviceBox | ReverbDeviceBox | RevampDeviceBox | StereoToolDeviceBox | ModularDeviceBox;
1
+ import { ArpeggioDeviceBox, DelayDeviceBox, ModularDeviceBox, PitchDeviceBox, RevampDeviceBox, ReverbDeviceBox, StereoToolDeviceBox, UnknownAudioEffectDeviceBox, UnknownMidiEffectDeviceBox, ZeitgeistDeviceBox } from "@opendaw/studio-boxes";
2
+ export type EffectBox = ArpeggioDeviceBox | PitchDeviceBox | ZeitgeistDeviceBox | UnknownMidiEffectDeviceBox | DelayDeviceBox | ReverbDeviceBox | RevampDeviceBox | StereoToolDeviceBox | ModularDeviceBox | UnknownAudioEffectDeviceBox;
3
3
  //# sourceMappingURL=EffectBox.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"EffectBox.d.ts","sourceRoot":"","sources":["../src/EffectBox.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,eAAe,EACf,mBAAmB,EACnB,kBAAkB,EACrB,MAAM,uBAAuB,CAAA;AAE9B,MAAM,MAAM,SAAS,GACf,iBAAiB,GAAG,cAAc,GAAG,kBAAkB,GACvD,cAAc,GAAG,eAAe,GAAG,eAAe,GAAG,mBAAmB,GAAG,gBAAgB,CAAA"}
1
+ {"version":3,"file":"EffectBox.d.ts","sourceRoot":"","sources":["../src/EffectBox.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,eAAe,EACf,eAAe,EACf,mBAAmB,EACnB,2BAA2B,EAC3B,0BAA0B,EAC1B,kBAAkB,EACrB,MAAM,uBAAuB,CAAA;AAE9B,MAAM,MAAM,SAAS,GACf,iBAAiB,GAAG,cAAc,GAAG,kBAAkB,GAAG,0BAA0B,GACpF,cAAc,GAAG,eAAe,GAAG,eAAe,GAAG,mBAAmB,GACxE,gBAAgB,GAAG,2BAA2B,CAAA"}
package/dist/Engine.d.ts CHANGED
@@ -1,21 +1,42 @@
1
1
  import { ppqn } from "@opendaw/lib-dsp";
2
- import { byte, DefaultObservableValue, int, MutableObservableValue, Nullable, ObservableValue, Observer, Subscription, unitValue, UUID } from "@opendaw/lib-std";
2
+ import { byte, int, Nullable, ObservableValue, Observer, Subscription, Terminable, unitValue, UUID } from "@opendaw/lib-std";
3
3
  import { ClipNotification } from "@opendaw/studio-adapters";
4
- export interface Engine {
5
- position(): ObservableValue<ppqn>;
6
- isPlaying(): MutableObservableValue<boolean>;
7
- isRecording(): MutableObservableValue<boolean>;
8
- metronomeEnabled(): MutableObservableValue<boolean>;
4
+ import { Project } from "./Project";
5
+ export type NoteTrigger = {
6
+ type: "note-on";
7
+ uuid: UUID.Format;
8
+ pitch: byte;
9
+ velocity: unitValue;
10
+ } | {
11
+ type: "note-off";
12
+ uuid: UUID.Format;
13
+ pitch: byte;
14
+ };
15
+ export interface Engine extends Terminable {
16
+ play(): void;
17
+ stop(): void;
18
+ setPosition(position: ppqn): void;
19
+ startRecording(countIn: boolean): void;
20
+ stopRecording(): void;
9
21
  isReady(): Promise<void>;
10
22
  queryLoadingComplete(): Promise<boolean>;
11
23
  stop(): void;
12
24
  panic(): void;
13
25
  noteOn(uuid: UUID.Format, pitch: byte, velocity: unitValue): void;
14
26
  noteOff(uuid: UUID.Format, pitch: byte): void;
15
- scheduleClipPlay(...clipIds: ReadonlyArray<UUID.Format>): void;
16
- scheduleClipStop(...trackIds: ReadonlyArray<UUID.Format>): void;
17
- requestPosition(position: ppqn): void;
27
+ subscribeNotes(observer: Observer<NoteTrigger>): Subscription;
28
+ scheduleClipPlay(clipIds: ReadonlyArray<UUID.Format>): void;
29
+ scheduleClipStop(trackIds: ReadonlyArray<UUID.Format>): void;
18
30
  subscribeClipNotification(observer: Observer<ClipNotification>): Subscription;
19
- markerState(): DefaultObservableValue<Nullable<[UUID.Format, int]>>;
31
+ get position(): ObservableValue<ppqn>;
32
+ get isPlaying(): ObservableValue<boolean>;
33
+ get isRecording(): ObservableValue<boolean>;
34
+ get isCountingIn(): ObservableValue<boolean>;
35
+ get metronomeEnabled(): ObservableValue<boolean>;
36
+ get playbackTimestamp(): ObservableValue<ppqn>;
37
+ get countInBeatsTotal(): ObservableValue<int>;
38
+ get countInBeatsRemaining(): ObservableValue<number>;
39
+ get markerState(): ObservableValue<Nullable<[UUID.Format, int]>>;
40
+ get project(): Project;
20
41
  }
21
42
  //# sourceMappingURL=Engine.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Engine.d.ts","sourceRoot":"","sources":["../src/Engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,kBAAkB,CAAA;AACrC,OAAO,EACH,IAAI,EACJ,sBAAsB,EACtB,GAAG,EACH,sBAAsB,EACtB,QAAQ,EACR,eAAe,EACf,QAAQ,EACR,YAAY,EACZ,SAAS,EACT,IAAI,EACP,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAC,gBAAgB,EAAC,MAAM,0BAA0B,CAAA;AAEzD,MAAM,WAAW,MAAM;IACnB,QAAQ,IAAI,eAAe,CAAC,IAAI,CAAC,CAAA;IACjC,SAAS,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAA;IAC5C,WAAW,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAA;IAC9C,gBAAgB,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAA;IACnD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACxB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;IACxC,IAAI,IAAI,IAAI,CAAA;IACZ,KAAK,IAAI,IAAI,CAAA;IACb,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,GAAG,IAAI,CAAA;IACjE,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,GAAG,IAAI,CAAA;IAC7C,gBAAgB,CAAC,GAAG,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAAA;IAC9D,gBAAgB,CAAC,GAAG,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAAA;IAC/D,eAAe,CAAC,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAA;IACrC,yBAAyB,CAAC,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,YAAY,CAAA;IAC7E,WAAW,IAAI,sBAAsB,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAA;CACtE"}
1
+ {"version":3,"file":"Engine.d.ts","sourceRoot":"","sources":["../src/Engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,kBAAkB,CAAA;AACrC,OAAO,EACH,IAAI,EACJ,GAAG,EACH,QAAQ,EACR,eAAe,EACf,QAAQ,EACR,YAAY,EACZ,UAAU,EACV,SAAS,EACT,IAAI,EACP,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAC,gBAAgB,EAAC,MAAM,0BAA0B,CAAA;AACzD,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAA;AAEjC,MAAM,MAAM,WAAW,GACjB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC;IAAC,KAAK,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,SAAS,CAAA;CAAE,GACxE;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC;IAAC,KAAK,EAAE,IAAI,CAAA;CAAE,CAAA;AAE1D,MAAM,WAAW,MAAO,SAAQ,UAAU;IACtC,IAAI,IAAI,IAAI,CAAA;IACZ,IAAI,IAAI,IAAI,CAAA;IACZ,WAAW,CAAC,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAA;IACjC,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;IACtC,aAAa,IAAI,IAAI,CAAA;IACrB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACxB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;IACxC,IAAI,IAAI,IAAI,CAAA;IACZ,KAAK,IAAI,IAAI,CAAA;IACb,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,GAAG,IAAI,CAAA;IACjE,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,GAAG,IAAI,CAAA;IAC7C,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,YAAY,CAAA;IAC7D,gBAAgB,CAAC,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAAA;IAC3D,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAAA;IAC5D,yBAAyB,CAAC,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,YAAY,CAAA;IAE7E,IAAI,QAAQ,IAAI,eAAe,CAAC,IAAI,CAAC,CAAA;IACrC,IAAI,SAAS,IAAI,eAAe,CAAC,OAAO,CAAC,CAAA;IACzC,IAAI,WAAW,IAAI,eAAe,CAAC,OAAO,CAAC,CAAA;IAC3C,IAAI,YAAY,IAAI,eAAe,CAAC,OAAO,CAAC,CAAA;IAC5C,IAAI,gBAAgB,IAAI,eAAe,CAAC,OAAO,CAAC,CAAA;IAChD,IAAI,iBAAiB,IAAI,eAAe,CAAC,IAAI,CAAC,CAAA;IAC9C,IAAI,iBAAiB,IAAI,eAAe,CAAC,GAAG,CAAC,CAAA;IAC7C,IAAI,qBAAqB,IAAI,eAAe,CAAC,MAAM,CAAC,CAAA;IACpD,IAAI,WAAW,IAAI,eAAe,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAA;IAChE,IAAI,OAAO,IAAI,OAAO,CAAA;CACzB"}
@@ -1,28 +1,39 @@
1
1
  import { byte, DefaultObservableValue, int, MutableObservableValue, Nullable, ObservableValue, Observer, Subscription, unitValue, UUID } from "@opendaw/lib-std";
2
2
  import { ppqn } from "@opendaw/lib-dsp";
3
3
  import { ClipNotification } from "@opendaw/studio-adapters";
4
- import { Engine } from "./Engine";
4
+ import { Engine, NoteTrigger } from "./Engine";
5
5
  import { EngineWorklet } from "./EngineWorklet";
6
+ import { Project } from "./Project";
6
7
  export declare class EngineFacade implements Engine {
7
8
  #private;
9
+ constructor();
8
10
  setClient(client: EngineWorklet): void;
9
- playbackTimestamp(): MutableObservableValue<ppqn>;
10
- position(): ObservableValue<ppqn>;
11
- isPlaying(): MutableObservableValue<boolean>;
12
- isRecording(): MutableObservableValue<boolean>;
13
- metronomeEnabled(): MutableObservableValue<boolean>;
14
- markerState(): DefaultObservableValue<Nullable<[UUID.Format, int]>>;
11
+ releaseClient(): void;
12
+ play(): void;
13
+ stop(reset?: boolean): void;
14
+ setPosition(position: ppqn): void;
15
+ startRecording(countIn: boolean): void;
16
+ stopRecording(): void;
17
+ get position(): ObservableValue<ppqn>;
18
+ get isPlaying(): ObservableValue<boolean>;
19
+ get isRecording(): ObservableValue<boolean>;
20
+ get isCountingIn(): ObservableValue<boolean>;
21
+ get metronomeEnabled(): MutableObservableValue<boolean>;
22
+ get playbackTimestamp(): ObservableValue<ppqn>;
23
+ get countInBeatsTotal(): ObservableValue<int>;
24
+ get countInBeatsRemaining(): ObservableValue<int>;
25
+ get markerState(): DefaultObservableValue<Nullable<[UUID.Format, int]>>;
26
+ get project(): Project;
15
27
  isReady(): Promise<void>;
16
28
  queryLoadingComplete(): Promise<boolean>;
17
- stop(): void;
18
29
  panic(): void;
19
30
  sampleRate(): number;
20
31
  subscribeClipNotification(observer: Observer<ClipNotification>): Subscription;
32
+ subscribeNotes(observer: Observer<NoteTrigger>): Subscription;
21
33
  noteOn(uuid: UUID.Format, pitch: byte, velocity: unitValue): void;
22
34
  noteOff(uuid: UUID.Format, pitch: byte): void;
23
- scheduleClipPlay(...clipIds: ReadonlyArray<UUID.Format>): void;
24
- scheduleClipStop(...trackIds: ReadonlyArray<UUID.Format>): void;
25
- requestPosition(position: ppqn): void;
35
+ scheduleClipPlay(clipIds: ReadonlyArray<UUID.Format>): void;
36
+ scheduleClipStop(trackIds: ReadonlyArray<UUID.Format>): void;
26
37
  terminate(): void;
27
38
  }
28
39
  //# sourceMappingURL=EngineFacade.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"EngineFacade.d.ts","sourceRoot":"","sources":["../src/EngineFacade.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,IAAI,EACJ,sBAAsB,EACtB,GAAG,EACH,sBAAsB,EACtB,QAAQ,EACR,eAAe,EACf,QAAQ,EAER,YAAY,EAEZ,SAAS,EACT,IAAI,EACP,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAC,IAAI,EAAC,MAAM,kBAAkB,CAAA;AACrC,OAAO,EAAC,gBAAgB,EAAC,MAAM,0BAA0B,CAAA;AACzD,OAAO,EAAC,MAAM,EAAC,MAAM,UAAU,CAAA;AAC/B,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAA;AAE7C,qBAAa,YAAa,YAAW,MAAM;;IAWvC,SAAS,CAAC,MAAM,EAAE,aAAa;IAuB/B,iBAAiB,IAAI,sBAAsB,CAAC,IAAI,CAAC;IACjD,QAAQ,IAAI,eAAe,CAAC,IAAI,CAAC;IACjC,SAAS,IAAI,sBAAsB,CAAC,OAAO,CAAC;IAC5C,WAAW,IAAI,sBAAsB,CAAC,OAAO,CAAC;IAC9C,gBAAgB,IAAI,sBAAsB,CAAC,OAAO,CAAC;IACnD,WAAW,IAAI,sBAAsB,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IACnE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IACxB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC;IAGxC,IAAI,IAAI,IAAI;IACZ,KAAK,IAAI,IAAI;IACb,UAAU,IAAI,MAAM;IACpB,yBAAyB,CAAC,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,YAAY;IAG7E,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,GAAG,IAAI;IAGjE,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,GAAG,IAAI;IAC7C,gBAAgB,CAAC,GAAG,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI;IAC9D,gBAAgB,CAAC,GAAG,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI;IAC/D,eAAe,CAAC,QAAQ,EAAE,IAAI,GAAG,IAAI;IAErC,SAAS,IAAI,IAAI;CAKpB"}
1
+ {"version":3,"file":"EngineFacade.d.ts","sourceRoot":"","sources":["../src/EngineFacade.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,IAAI,EACJ,sBAAsB,EACtB,GAAG,EACH,sBAAsB,EACtB,QAAQ,EACR,eAAe,EACf,QAAQ,EAER,YAAY,EAEZ,SAAS,EACT,IAAI,EACP,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAC,IAAI,EAAC,MAAM,kBAAkB,CAAA;AACrC,OAAO,EAAC,gBAAgB,EAAC,MAAM,0BAA0B,CAAA;AACzD,OAAO,EAAC,MAAM,EAAE,WAAW,EAAC,MAAM,UAAU,CAAA;AAC5C,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAA;AAC7C,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAA;AAEjC,qBAAa,YAAa,YAAW,MAAM;;;IAkBvC,SAAS,CAAC,MAAM,EAAE,aAAa;IAiB/B,aAAa,IAAI,IAAI;IAMrB,IAAI,IAAI,IAAI;IACZ,IAAI,CAAC,KAAK,GAAE,OAAe,GAAG,IAAI;IAClC,WAAW,CAAC,QAAQ,EAAE,IAAI,GAAG,IAAI;IACjC,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IACtC,aAAa,IAAI,IAAI;IAErB,IAAI,QAAQ,IAAI,eAAe,CAAC,IAAI,CAAC,CAAwB;IAC7D,IAAI,SAAS,IAAI,eAAe,CAAC,OAAO,CAAC,CAAyB;IAClE,IAAI,WAAW,IAAI,eAAe,CAAC,OAAO,CAAC,CAA2B;IACtE,IAAI,YAAY,IAAI,eAAe,CAAC,OAAO,CAAC,CAA4B;IACxE,IAAI,gBAAgB,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAgC;IACvF,IAAI,iBAAiB,IAAI,eAAe,CAAC,IAAI,CAAC,CAAiC;IAC/E,IAAI,iBAAiB,IAAI,eAAe,CAAC,GAAG,CAAC,CAAiC;IAC9E,IAAI,qBAAqB,IAAI,eAAe,CAAC,GAAG,CAAC,CAAqC;IACtF,IAAI,WAAW,IAAI,sBAAsB,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAA2B;IAClG,IAAI,OAAO,IAAI,OAAO,CAAkD;IAExE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IACxB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC;IAGxC,KAAK,IAAI,IAAI;IACb,UAAU,IAAI,MAAM;IACpB,yBAAyB,CAAC,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,YAAY;IAG7E,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,YAAY;IAG7D,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,GAAG,IAAI;IAGjE,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,GAAG,IAAI;IAC7C,gBAAgB,CAAC,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI;IAG3D,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI;IAI5D,SAAS,IAAI,IAAI;CAIpB"}
@@ -1,50 +1,67 @@
1
1
  import { DefaultObservableValue, Option, Terminator } from "@opendaw/lib-std";
2
2
  export class EngineFacade {
3
3
  #terminator = new Terminator();
4
+ #lifecycle = this.#terminator.own(new Terminator());
4
5
  #playbackTimestamp = new DefaultObservableValue(0.0);
6
+ #countInBeatsTotal = new DefaultObservableValue(4);
7
+ #countInBeatsRemaining = new DefaultObservableValue(0);
5
8
  #position = new DefaultObservableValue(0.0);
6
9
  #isPlaying = new DefaultObservableValue(false);
7
10
  #isRecording = new DefaultObservableValue(false);
11
+ #isCountingIn = new DefaultObservableValue(false);
8
12
  #metronomeEnabled = new DefaultObservableValue(false);
9
13
  #markerState = new DefaultObservableValue(null);
10
14
  #client = Option.None;
15
+ constructor() { }
11
16
  setClient(client) {
12
17
  this.#client = Option.wrap(client);
13
- this.#terminator.terminate();
14
- this.#terminator.ownAll(client.playbackTimestamp().subscribe(owner => this.#playbackTimestamp.setValue(owner.getValue())), client.position().subscribe(owner => this.#position.setValue(owner.getValue())), client.isPlaying().subscribe(owner => this.#isPlaying.setValue(owner.getValue())), client.isRecording().subscribe(owner => this.#isRecording.setValue(owner.getValue())), client.metronomeEnabled().subscribe(owner => this.#metronomeEnabled.setValue(owner.getValue())), client.markerState().subscribe(owner => this.#markerState.setValue(owner.getValue())), this.position().subscribe(owner => client.position().setValue(owner.getValue())), this.isPlaying().subscribe(owner => client.isPlaying().setValue(owner.getValue())), this.isRecording().subscribe(owner => client.isRecording().setValue(owner.getValue())), this.metronomeEnabled().subscribe(owner => client.metronomeEnabled().setValue(owner.getValue())));
15
- this.#playbackTimestamp.setValue(client.playbackTimestamp().getValue());
16
- this.#position.setValue(client.position().getValue());
17
- this.#isPlaying.setValue(client.isPlaying().getValue());
18
- this.#isRecording.setValue(client.isRecording().getValue());
19
- this.#metronomeEnabled.setValue(client.metronomeEnabled().getValue());
20
- this.#markerState.setValue(client.markerState().getValue());
21
- }
22
- playbackTimestamp() { return this.#playbackTimestamp; }
23
- position() { return this.#position; }
24
- isPlaying() { return this.#isPlaying; }
25
- isRecording() { return this.#isRecording; }
26
- metronomeEnabled() { return this.#metronomeEnabled; }
27
- markerState() { return this.#markerState; }
18
+ this.#lifecycle.terminate();
19
+ this.#lifecycle.ownAll(client.playbackTimestamp.catchupAndSubscribe(owner => this.#playbackTimestamp.setValue(owner.getValue())), client.countInBeatsTotal.catchupAndSubscribe(owner => this.#countInBeatsTotal.setValue(owner.getValue())), client.countInBeatsRemaining.catchupAndSubscribe(owner => this.#countInBeatsRemaining.setValue(owner.getValue())), client.position.catchupAndSubscribe(owner => this.#position.setValue(owner.getValue())), client.isPlaying.catchupAndSubscribe(owner => this.#isPlaying.setValue(owner.getValue())), client.isRecording.catchupAndSubscribe(owner => this.#isRecording.setValue(owner.getValue())), client.isCountingIn.catchupAndSubscribe(owner => this.#isCountingIn.setValue(owner.getValue())), client.metronomeEnabled.catchupAndSubscribe(owner => this.#metronomeEnabled.setValue(owner.getValue())), client.markerState.catchupAndSubscribe(owner => this.#markerState.setValue(owner.getValue())), this.metronomeEnabled.catchupAndSubscribe(owner => client.metronomeEnabled.setValue(owner.getValue())));
20
+ }
21
+ releaseClient() {
22
+ this.#lifecycle.terminate();
23
+ this.#client.ifSome(client => client.terminate());
24
+ this.#client = Option.None;
25
+ }
26
+ play() { this.#client.ifSome(client => client.play()); }
27
+ stop(reset = false) { this.#client.ifSome(client => client.stop(reset)); }
28
+ setPosition(position) { this.#client.ifSome(client => client.setPosition(position)); }
29
+ startRecording(countIn) { this.#client.ifSome(client => client.startRecording(countIn)); }
30
+ stopRecording() { this.#client.ifSome(client => client.stopRecording()); }
31
+ get position() { return this.#position; }
32
+ get isPlaying() { return this.#isPlaying; }
33
+ get isRecording() { return this.#isRecording; }
34
+ get isCountingIn() { return this.#isCountingIn; }
35
+ get metronomeEnabled() { return this.#metronomeEnabled; }
36
+ get playbackTimestamp() { return this.#playbackTimestamp; }
37
+ get countInBeatsTotal() { return this.#countInBeatsTotal; }
38
+ get countInBeatsRemaining() { return this.#countInBeatsRemaining; }
39
+ get markerState() { return this.#markerState; }
40
+ get project() { return this.#client.unwrap("No engine").project; }
28
41
  isReady() { return this.#client.mapOr(client => client.isReady(), Promise.resolve()); }
29
42
  queryLoadingComplete() {
30
43
  return this.#client.mapOr(client => client.queryLoadingComplete(), Promise.resolve(false));
31
44
  }
32
- stop() { this.#client.ifSome(client => client.stop()); }
33
45
  panic() { this.#client.ifSome(client => client.panic()); }
34
46
  sampleRate() { return this.#client.isEmpty() ? 44_100 : this.#client.unwrap().context.sampleRate; }
35
47
  subscribeClipNotification(observer) {
36
- return this.#client.unwrap().subscribeClipNotification(observer);
48
+ return this.#client.unwrap("No engine").subscribeClipNotification(observer);
49
+ }
50
+ subscribeNotes(observer) {
51
+ return this.#client.unwrap("No engine").subscribeNotes(observer);
37
52
  }
38
53
  noteOn(uuid, pitch, velocity) {
39
54
  this.#client.unwrap("No engine").noteOn(uuid, pitch, velocity);
40
55
  }
41
56
  noteOff(uuid, pitch) { this.#client.unwrap("No engine").noteOff(uuid, pitch); }
42
- scheduleClipPlay(...clipIds) { this.#client.unwrap("No engine").scheduleClipPlay(...clipIds); }
43
- scheduleClipStop(...trackIds) { this.#client.unwrap("No engine").scheduleClipStop(...trackIds); }
44
- requestPosition(position) { this.#client.unwrap("No engine").requestPosition(position); }
57
+ scheduleClipPlay(clipIds) {
58
+ this.#client.unwrap("No engine").scheduleClipPlay(clipIds);
59
+ }
60
+ scheduleClipStop(trackIds) {
61
+ this.#client.unwrap("No engine").scheduleClipStop(trackIds);
62
+ }
45
63
  terminate() {
64
+ this.releaseClient();
46
65
  this.#terminator.terminate();
47
- this.#client.ifSome(client => client.terminate());
48
- this.#client = Option.None;
49
66
  }
50
67
  }
@@ -1,28 +1,37 @@
1
- import { byte, DefaultObservableValue, int, MutableObservableValue, Nullable, Observer, Subscription, unitValue, UUID } from "@opendaw/lib-std";
1
+ import { byte, int, MutableObservableValue, Nullable, ObservableValue, Observer, Subscription, unitValue, UUID } from "@opendaw/lib-std";
2
2
  import { ppqn } from "@opendaw/lib-dsp";
3
3
  import { ClipNotification, ExportStemsConfiguration } from "@opendaw/studio-adapters";
4
4
  import { Project } from "./Project";
5
- export declare class EngineWorklet extends AudioWorkletNode {
5
+ import { Engine, NoteTrigger } from "./Engine";
6
+ export declare class EngineWorklet extends AudioWorkletNode implements Engine {
6
7
  #private;
7
8
  static ID: int;
8
9
  readonly id: number;
9
- constructor(context: BaseAudioContext, project: Readonly<Project>, exportConfiguration?: ExportStemsConfiguration);
10
- stop(): void;
10
+ constructor(context: BaseAudioContext, project: Project, exportConfiguration?: ExportStemsConfiguration);
11
+ play(): void;
12
+ stop(reset?: boolean): void;
13
+ setPosition(position: ppqn): void;
14
+ startRecording(countIn: boolean): void;
15
+ stopRecording(): void;
11
16
  panic(): void;
12
- isPlaying(): MutableObservableValue<boolean>;
13
- isRecording(): MutableObservableValue<boolean>;
14
- playbackTimestamp(): DefaultObservableValue<number>;
15
- position(): MutableObservableValue<ppqn>;
16
- metronomeEnabled(): DefaultObservableValue<boolean>;
17
+ get isPlaying(): ObservableValue<boolean>;
18
+ get isRecording(): ObservableValue<boolean>;
19
+ get isCountingIn(): ObservableValue<boolean>;
20
+ get countInBeatsTotal(): ObservableValue<int>;
21
+ get countInBeatsRemaining(): ObservableValue<number>;
22
+ get position(): ObservableValue<ppqn>;
23
+ get playbackTimestamp(): MutableObservableValue<number>;
24
+ get metronomeEnabled(): MutableObservableValue<boolean>;
25
+ get markerState(): ObservableValue<Nullable<[UUID.Format, int]>>;
26
+ get project(): Project;
17
27
  isReady(): Promise<void>;
18
28
  queryLoadingComplete(): Promise<boolean>;
19
29
  noteOn(uuid: UUID.Format, pitch: byte, velocity: unitValue): void;
20
30
  noteOff(uuid: UUID.Format, pitch: byte): void;
21
- scheduleClipPlay(...clipIds: ReadonlyArray<UUID.Format>): void;
22
- scheduleClipStop(...trackIds: ReadonlyArray<UUID.Format>): void;
23
- requestPosition(position: ppqn): void;
31
+ subscribeNotes(observer: Observer<NoteTrigger>): Subscription;
32
+ scheduleClipPlay(clipIds: ReadonlyArray<UUID.Format>): void;
33
+ scheduleClipStop(trackIds: ReadonlyArray<UUID.Format>): void;
24
34
  subscribeClipNotification(observer: Observer<ClipNotification>): Subscription;
25
- markerState(): DefaultObservableValue<Nullable<[UUID.Format, int]>>;
26
35
  terminate(): void;
27
36
  }
28
37
  //# sourceMappingURL=EngineWorklet.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"EngineWorklet.d.ts","sourceRoot":"","sources":["../src/EngineWorklet.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,IAAI,EACJ,sBAAsB,EACtB,GAAG,EACH,sBAAsB,EAEtB,QAAQ,EACR,QAAQ,EAER,YAAY,EAGZ,SAAS,EACT,IAAI,EACP,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAC,IAAI,EAAC,MAAM,kBAAkB,CAAA;AACrC,OAAO,EAEH,gBAAgB,EAOhB,wBAAwB,EAC3B,MAAM,0BAA0B,CAAA;AAKjC,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAA;AAEjC,qBAAa,aAAc,SAAQ,gBAAgB;;IAC/C,MAAM,CAAC,EAAE,EAAE,GAAG,CAAQ;IAEtB,QAAQ,CAAC,EAAE,SAAqB;gBAgBpB,OAAO,EAAE,gBAAgB,EACzB,OAAO,EAAE,QAAQ,CAAC,OAAO,CAAC,EAC1B,mBAAmB,CAAC,EAAE,wBAAwB;IA2G1D,IAAI,IAAI,IAAI;IASZ,KAAK,IAAI,IAAI;IACb,SAAS,IAAI,sBAAsB,CAAC,OAAO,CAAC;IAC5C,WAAW,IAAI,sBAAsB,CAAC,OAAO,CAAC;IAC9C,iBAAiB,IAAI,sBAAsB,CAAC,MAAM,CAAC;IACnD,QAAQ,IAAI,sBAAsB,CAAC,IAAI,CAAC;IACxC,gBAAgB,IAAI,sBAAsB,CAAC,OAAO,CAAC;IACnD,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IACxB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC;IACxC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,GAAG,IAAI;IACjE,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,GAAG,IAAI;IAC7C,gBAAgB,CAAC,GAAG,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI;IAK9D,gBAAgB,CAAC,GAAG,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI;IAG/D,eAAe,CAAC,QAAQ,EAAE,IAAI,GAAG,IAAI;IAIrC,yBAAyB,CAAC,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,YAAY;IAQ7E,WAAW,IAAI,sBAAsB,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IAInE,SAAS,IAAI,IAAI;CAKpB"}
1
+ {"version":3,"file":"EngineWorklet.d.ts","sourceRoot":"","sources":["../src/EngineWorklet.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,IAAI,EAEJ,GAAG,EACH,sBAAsB,EAEtB,QAAQ,EACR,eAAe,EACf,QAAQ,EAER,YAAY,EAGZ,SAAS,EACT,IAAI,EACP,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAC,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAIrC,OAAO,EAEH,gBAAgB,EAOhB,wBAAwB,EAC3B,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAA;AACjC,OAAO,EAAC,MAAM,EAAE,WAAW,EAAC,MAAM,UAAU,CAAA;AAE5C,qBAAa,aAAc,SAAQ,gBAAiB,YAAW,MAAM;;IACjE,MAAM,CAAC,EAAE,EAAE,GAAG,CAAQ;IAEtB,QAAQ,CAAC,EAAE,SAAqB;gBAoBpB,OAAO,EAAE,gBAAgB,EACzB,OAAO,EAAE,OAAO,EAChB,mBAAmB,CAAC,EAAE,wBAAwB;IAgG1D,IAAI,IAAI,IAAI;IACZ,IAAI,CAAC,KAAK,GAAE,OAAe,GAAG,IAAI;IAClC,WAAW,CAAC,QAAQ,EAAE,IAAI,GAAG,IAAI;IACjC,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IACtC,aAAa,IAAI,IAAI;IACrB,KAAK,IAAI,IAAI;IAEb,IAAI,SAAS,IAAI,eAAe,CAAC,OAAO,CAAC,CAAyB;IAClE,IAAI,WAAW,IAAI,eAAe,CAAC,OAAO,CAAC,CAA2B;IACtE,IAAI,YAAY,IAAI,eAAe,CAAC,OAAO,CAAC,CAA4B;IACxE,IAAI,iBAAiB,IAAI,eAAe,CAAC,GAAG,CAAC,CAAiC;IAC9E,IAAI,qBAAqB,IAAI,eAAe,CAAC,MAAM,CAAC,CAAqC;IACzF,IAAI,QAAQ,IAAI,eAAe,CAAC,IAAI,CAAC,CAAwB;IAC7D,IAAI,iBAAiB,IAAI,sBAAsB,CAAC,MAAM,CAAC,CAAiC;IACxF,IAAI,gBAAgB,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAgC;IACvF,IAAI,WAAW,IAAI,eAAe,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAA2B;IAC3F,IAAI,OAAO,IAAI,OAAO,CAAuB;IAE7C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IACxB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC;IACxC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,GAAG,IAAI;IAIjE,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,IAAI,GAAG,IAAI;IAI7C,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,WAAW,CAAC,GAAG,YAAY;IAC7D,gBAAgB,CAAC,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI;IAI3D,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI;IAG5D,yBAAyB,CAAC,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,YAAY;IAQ7E,SAAS,IAAI,IAAI;CAIpB"}
@@ -1,30 +1,37 @@
1
1
  import { Arrays, DefaultObservableValue, Notifier, Option, SyncStream, Terminator, UUID } from "@opendaw/lib-std";
2
- import { EngineStateSchema, ExportStemsConfiguration } from "@opendaw/studio-adapters";
3
2
  import { SyncSource } from "@opendaw/lib-box";
4
3
  import { AnimationFrame } from "@opendaw/lib-dom";
5
4
  import { Communicator, Messenger } from "@opendaw/lib-runtime";
5
+ import { EngineStateSchema, ExportStemsConfiguration } from "@opendaw/studio-adapters";
6
6
  export class EngineWorklet extends AudioWorkletNode {
7
7
  static ID = 0 | 0;
8
8
  id = EngineWorklet.ID++;
9
9
  #terminator = new Terminator();
10
+ #project;
10
11
  #playbackTimestamp = new DefaultObservableValue(0.0);
11
12
  #position = new DefaultObservableValue(0.0);
12
13
  #isPlaying = new DefaultObservableValue(false);
13
14
  #isRecording = new DefaultObservableValue(false);
15
+ #isCountingIn = new DefaultObservableValue(false);
16
+ #countInBeatsTotal = new DefaultObservableValue(4);
17
+ #countInBeatsRemaining = new DefaultObservableValue(0);
14
18
  #metronomeEnabled = new DefaultObservableValue(false);
15
19
  #markerState = new DefaultObservableValue(null);
16
20
  #notifyClipNotification;
21
+ #notifyNoteTrigger;
17
22
  #playingClips;
18
23
  #commands;
19
24
  #isReady;
20
- #ignoreUpdates = false;
21
25
  constructor(context, project, exportConfiguration) {
22
- console.debug("constructor");
23
26
  const numberOfChannels = ExportStemsConfiguration.countStems(Option.wrap(exportConfiguration)) * 2;
24
27
  const reader = SyncStream.reader(EngineStateSchema(), state => {
25
- this.#ignoreUpdates = true;
26
- this.#position.setValue(state.position);
27
- this.#ignoreUpdates = false;
28
+ this.#isPlaying.setValue(state.isPlaying);
29
+ this.#isRecording.setValue(state.isRecording);
30
+ this.#isCountingIn.setValue(state.isCountingIn);
31
+ this.#countInBeatsTotal.setValue(state.countInBeatsTotal);
32
+ this.#countInBeatsRemaining.setValue(state.countInBeatsRemaining);
33
+ this.#playbackTimestamp.setValue(state.playbackTimestamp);
34
+ this.#position.setValue(state.position); // This must be the last to handle the state values before
28
35
  });
29
36
  super(context, "engine-processor", {
30
37
  numberOfInputs: 0,
@@ -38,15 +45,18 @@ export class EngineWorklet extends AudioWorkletNode {
38
45
  });
39
46
  const { resolve, promise } = Promise.withResolvers();
40
47
  const messenger = Messenger.for(this.port);
48
+ this.#project = project;
41
49
  this.#isReady = promise;
42
50
  this.#notifyClipNotification = this.#terminator.own(new Notifier());
51
+ this.#notifyNoteTrigger = this.#terminator.own(new Notifier());
43
52
  this.#playingClips = [];
44
53
  this.#commands = this.#terminator.own(Communicator.sender(messenger.channel("engine-commands"), dispatcher => new class {
45
- setPlaying(value) { dispatcher.dispatchAndForget(this.setPlaying, value); }
46
- setRecording(value) { dispatcher.dispatchAndForget(this.setRecording, value); }
54
+ play() { dispatcher.dispatchAndForget(this.play); }
55
+ stop(reset) { dispatcher.dispatchAndForget(this.stop, reset); }
47
56
  setPosition(position) { dispatcher.dispatchAndForget(this.setPosition, position); }
57
+ startRecording(countIn) { dispatcher.dispatchAndForget(this.startRecording, countIn); }
58
+ stopRecording() { dispatcher.dispatchAndForget(this.stopRecording); }
48
59
  setMetronomeEnabled(enabled) { dispatcher.dispatchAndForget(this.setMetronomeEnabled, enabled); }
49
- stopAndReset() { dispatcher.dispatchAndForget(this.stopAndReset); }
50
60
  queryLoadingComplete() {
51
61
  return dispatcher.dispatchAndReturn(this.queryLoadingComplete);
52
62
  }
@@ -70,7 +80,7 @@ export class EngineWorklet extends AudioWorkletNode {
70
80
  ready: () => resolve(),
71
81
  fetchAudio: (uuid) => {
72
82
  return new Promise((resolve, reject) => {
73
- const handler = project.audioManager.getOrCreate(uuid);
83
+ const handler = project.sampleManager.getOrCreate(uuid);
74
84
  handler.subscribe(state => {
75
85
  if (state.type === "error") {
76
86
  reject(state.reason);
@@ -95,57 +105,42 @@ export class EngineWorklet extends AudioWorkletNode {
95
105
  },
96
106
  switchMarkerState: (state) => this.#markerState.setValue(state)
97
107
  });
98
- this.#terminator.ownAll(AnimationFrame.add(() => reader.tryRead()), project.liveStreamReceiver.connect(messenger.channel("engine-live-data")), new SyncSource(project.boxGraph, messenger.channel("engine-sync"), false), this.#isPlaying.catchupAndSubscribe(owner => {
99
- const isPlaying = owner.getValue();
100
- if (isPlaying) {
101
- this.#commands.setPosition(this.#playbackTimestamp.getValue());
102
- }
103
- else if (this.#isRecording.getValue()) {
104
- this.#isRecording.setValue(false);
105
- }
106
- this.#commands.setPlaying(isPlaying);
107
- }), this.#isRecording.subscribe(owner => {
108
- const willRecord = owner.getValue();
109
- this.#commands.setPlaying(willRecord);
110
- this.#commands.setRecording(willRecord);
111
- }), this.#metronomeEnabled.catchupAndSubscribe(owner => this.#commands.setMetronomeEnabled(owner.getValue())), this.#position.catchupAndSubscribe(owner => {
112
- if (!this.#ignoreUpdates) {
113
- this.#commands.setPosition(owner.getValue());
114
- }
115
- }));
116
- }
117
- stop() {
118
- if (!this.#isPlaying.getValue() && this.#position.getValue() === 0.0) {
119
- this.#commands.stopAndReset();
120
- }
121
- else {
122
- this.#isRecording.setValue(false);
123
- this.#isPlaying.setValue(false);
124
- this.requestPosition(0.0);
125
- }
108
+ this.#terminator.ownAll(AnimationFrame.add(() => reader.tryRead()), project.liveStreamReceiver.connect(messenger.channel("engine-live-data")), new SyncSource(project.boxGraph, messenger.channel("engine-sync"), false), this.#metronomeEnabled.catchupAndSubscribe(owner => this.#commands.setMetronomeEnabled(owner.getValue())));
126
109
  }
110
+ play() { this.#commands.play(); }
111
+ stop(reset = false) { this.#commands.stop(reset); }
112
+ setPosition(position) { this.#commands.setPosition(position); }
113
+ startRecording(countIn) { this.#commands.startRecording(countIn); }
114
+ stopRecording() { this.#commands.stopRecording(); }
127
115
  panic() { this.#commands.panic(); }
128
- isPlaying() { return this.#isPlaying; }
129
- isRecording() { return this.#isRecording; }
130
- playbackTimestamp() { return this.#playbackTimestamp; }
131
- position() { return this.#position; }
132
- metronomeEnabled() { return this.#metronomeEnabled; }
116
+ get isPlaying() { return this.#isPlaying; }
117
+ get isRecording() { return this.#isRecording; }
118
+ get isCountingIn() { return this.#isCountingIn; }
119
+ get countInBeatsTotal() { return this.#countInBeatsTotal; }
120
+ get countInBeatsRemaining() { return this.#countInBeatsRemaining; }
121
+ get position() { return this.#position; }
122
+ get playbackTimestamp() { return this.#playbackTimestamp; }
123
+ get metronomeEnabled() { return this.#metronomeEnabled; }
124
+ get markerState() { return this.#markerState; }
125
+ get project() { return this.#project; }
133
126
  isReady() { return this.#isReady; }
134
127
  queryLoadingComplete() { return this.#commands.queryLoadingComplete(); }
135
- noteOn(uuid, pitch, velocity) { this.#commands.noteOn(uuid, pitch, velocity); }
136
- noteOff(uuid, pitch) { this.#commands.noteOff(uuid, pitch); }
137
- scheduleClipPlay(...clipIds) {
128
+ noteOn(uuid, pitch, velocity) {
129
+ this.#commands.noteOn(uuid, pitch, velocity);
130
+ this.#notifyNoteTrigger.notify({ type: "note-on", uuid, pitch, velocity });
131
+ }
132
+ noteOff(uuid, pitch) {
133
+ this.#commands.noteOff(uuid, pitch);
134
+ this.#notifyNoteTrigger.notify({ type: "note-off", uuid, pitch });
135
+ }
136
+ subscribeNotes(observer) { return this.#notifyNoteTrigger.subscribe(observer); }
137
+ scheduleClipPlay(clipIds) {
138
138
  this.#notifyClipNotification.notify({ type: "waiting", clips: clipIds });
139
139
  this.#commands.scheduleClipPlay(clipIds);
140
- this.#isPlaying.setValue(true); // must be second, since they might be executed in different blocks
141
140
  }
142
- scheduleClipStop(...trackIds) {
141
+ scheduleClipStop(trackIds) {
143
142
  this.#commands.scheduleClipStop(trackIds);
144
143
  }
145
- requestPosition(position) {
146
- this.#playbackTimestamp.setValue(position);
147
- this.#commands.setPosition(position);
148
- }
149
144
  subscribeClipNotification(observer) {
150
145
  observer({
151
146
  type: "sequencing",
@@ -153,11 +148,7 @@ export class EngineWorklet extends AudioWorkletNode {
153
148
  });
154
149
  return this.#notifyClipNotification.subscribe(observer);
155
150
  }
156
- markerState() {
157
- return this.#markerState;
158
- }
159
151
  terminate() {
160
- console.debug(`terminate EngineClient id: ${this.id}`);
161
152
  this.#terminator.terminate();
162
153
  this.disconnect();
163
154
  }
@@ -1 +1 @@
1
- {"version":3,"file":"MeterWorklet.d.ts","sourceRoot":"","sources":["../src/MeterWorklet.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,GAAG,EAAY,QAAQ,EAAU,YAAY,EAAc,UAAU,EAAa,MAAM,kBAAkB,CAAA;AAIlH,MAAM,MAAM,UAAU,GAAG;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,GAAG,EAAE,YAAY,CAAA;CAAE,CAAA;AAElE,qBAAa,YAAa,SAAQ,gBAAiB,YAAW,UAAU;;gBAIxD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,GAAG;IAmB5D,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,YAAY;IAEvD,SAAS,IAAI,IAAI;CACpB"}
1
+ {"version":3,"file":"MeterWorklet.d.ts","sourceRoot":"","sources":["../src/MeterWorklet.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,GAAG,EAAY,QAAQ,EAAU,YAAY,EAAc,UAAU,EAAa,MAAM,kBAAkB,CAAA;AAIlH,MAAM,MAAM,UAAU,GAAG;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,GAAG,EAAE,YAAY,CAAA;CAAE,CAAA;AAElE,qBAAa,YAAa,SAAQ,gBAAiB,YAAW,UAAU;;gBAIxD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,GAAG;IAqB5D,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,YAAY;IACvD,SAAS,IAAI,IAAI;CACpB"}
@@ -2,7 +2,7 @@ import { Notifier, Schema, SyncStream, Terminator } from "@opendaw/lib-std";
2
2
  import { AnimationFrame } from "@opendaw/lib-dom";
3
3
  export class MeterWorklet extends AudioWorkletNode {
4
4
  #terminator = new Terminator();
5
- #notifier = new Notifier();
5
+ #notifier = this.#terminator.own(new Notifier());
6
6
  constructor(context, numberOfChannels) {
7
7
  const receiver = SyncStream.reader(Schema.createBuilder({
8
8
  peak: Schema.floats(numberOfChannels),
@@ -19,7 +19,7 @@ export class MeterWorklet extends AudioWorkletNode {
19
19
  valueDecay: 0.200
20
20
  }
21
21
  });
22
- this.#terminator.own(AnimationFrame.add(() => receiver.tryRead()));
22
+ this.#terminator.ownAll(AnimationFrame.add(() => receiver.tryRead()));
23
23
  }
24
24
  subscribe(observer) { return this.#notifier.subscribe(observer); }
25
25
  terminate() { this.#terminator.terminate(); }
@@ -0,0 +1,12 @@
1
+ import { MutableObservableValue, ObservableOption, Option } from "@opendaw/lib-std";
2
+ export declare class MidiDevices {
3
+ #private;
4
+ static canRequestMidiAccess(): boolean;
5
+ static requestPermission(): Promise<undefined>;
6
+ static get(): ObservableOption<MIDIAccess>;
7
+ static inputs(): Option<ReadonlyArray<MIDIInput>>;
8
+ static outputs(): Option<ReadonlyArray<MIDIOutput>>;
9
+ static panic(): void;
10
+ static available(): MutableObservableValue<boolean>;
11
+ }
12
+ //# sourceMappingURL=MidiDevices.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MidiDevices.d.ts","sourceRoot":"","sources":["../src/MidiDevices.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,sBAAsB,EAEtB,gBAAgB,EAGhB,MAAM,EAGT,MAAM,kBAAkB,CAAA;AAIzB,qBAAa,WAAW;;IACpB,MAAM,CAAC,oBAAoB,IAAI,OAAO;WAEzB,iBAAiB;IAiB9B,MAAM,CAAC,GAAG,IAAI,gBAAgB,CAAC,UAAU,CAAC;IAE1C,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;IAIjD,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;IAInD,MAAM,CAAC,KAAK,IAAI,IAAI;IAkBpB,MAAM,CAAC,SAAS,IAAI,sBAAsB,CAAC,OAAO,CAAC;CAqCtD"}