@opendaw/studio-core 0.0.37 → 0.0.39

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 (62) hide show
  1. package/dist/AudioOfflineRenderer.d.ts.map +1 -1
  2. package/dist/AudioOfflineRenderer.js +4 -1
  3. package/dist/Engine.d.ts +2 -1
  4. package/dist/Engine.d.ts.map +1 -1
  5. package/dist/EngineFacade.d.ts +1 -0
  6. package/dist/EngineFacade.d.ts.map +1 -1
  7. package/dist/EngineFacade.js +3 -1
  8. package/dist/EngineWorklet.d.ts +1 -0
  9. package/dist/EngineWorklet.d.ts.map +1 -1
  10. package/dist/EngineWorklet.js +9 -2
  11. package/dist/RecordingWorklet.d.ts.map +1 -1
  12. package/dist/RecordingWorklet.js +12 -5
  13. package/dist/capture/CaptureMidi.d.ts.map +1 -1
  14. package/dist/capture/CaptureMidi.js +13 -13
  15. package/dist/capture/RecordAudio.d.ts +2 -2
  16. package/dist/capture/RecordAudio.d.ts.map +1 -1
  17. package/dist/clouds/CloudAuthManager.d.ts.map +1 -1
  18. package/dist/clouds/CloudAuthManager.js +10 -2
  19. package/dist/clouds/CloudBackupSamples.d.ts.map +1 -1
  20. package/dist/clouds/CloudBackupSamples.js +6 -1
  21. package/dist/index.d.ts +1 -7
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +1 -7
  24. package/dist/midi/MIDIMessageSubscriber.js +4 -4
  25. package/dist/midi/MidiDevices.d.ts +6 -2
  26. package/dist/midi/MidiDevices.d.ts.map +1 -1
  27. package/dist/midi/MidiDevices.js +11 -2
  28. package/dist/midi/SoftwareMIDIInput.d.ts +34 -0
  29. package/dist/midi/SoftwareMIDIInput.d.ts.map +1 -0
  30. package/dist/midi/SoftwareMIDIInput.js +80 -0
  31. package/dist/processors.js +3 -3
  32. package/dist/processors.js.map +3 -3
  33. package/dist/project/Project.d.ts +3 -3
  34. package/dist/project/Project.d.ts.map +1 -1
  35. package/dist/project/Project.js +3 -1
  36. package/dist/project/ProjectBundle.d.ts.map +1 -1
  37. package/dist/project/ProjectBundle.js +1 -1
  38. package/dist/project/ProjectEnv.d.ts +2 -2
  39. package/dist/project/ProjectEnv.d.ts.map +1 -1
  40. package/dist/samples/{MainThreadSampleLoader.d.ts → DefaultSampleLoader.d.ts} +4 -4
  41. package/dist/samples/DefaultSampleLoader.d.ts.map +1 -0
  42. package/dist/samples/{MainThreadSampleLoader.js → DefaultSampleLoader.js} +7 -2
  43. package/dist/samples/{MainThreadSampleManager.d.ts → DefaultSampleLoaderManager.d.ts} +4 -5
  44. package/dist/samples/DefaultSampleLoaderManager.d.ts.map +1 -0
  45. package/dist/samples/DefaultSampleLoaderManager.js +19 -0
  46. package/dist/samples/OpenSampleAPI.d.ts.map +1 -1
  47. package/dist/samples/OpenSampleAPI.js +3 -2
  48. package/dist/samples/P2PSampleProvider.d.ts +13 -0
  49. package/dist/samples/P2PSampleProvider.d.ts.map +1 -0
  50. package/dist/samples/P2PSampleProvider.js +350 -0
  51. package/dist/samples/SampleStorage.d.ts +7 -1
  52. package/dist/samples/SampleStorage.d.ts.map +1 -1
  53. package/dist/samples/SampleStorage.js +1 -1
  54. package/dist/samples/index.d.ts +9 -0
  55. package/dist/samples/index.d.ts.map +1 -0
  56. package/dist/samples/index.js +8 -0
  57. package/dist/workers-main.js +2 -2
  58. package/dist/workers-main.js.map +3 -3
  59. package/package.json +15 -14
  60. package/dist/samples/MainThreadSampleLoader.d.ts.map +0 -1
  61. package/dist/samples/MainThreadSampleManager.d.ts.map +0 -1
  62. package/dist/samples/MainThreadSampleManager.js +0 -22
@@ -1 +1 @@
1
- {"version":3,"file":"AudioOfflineRenderer.d.ts","sourceRoot":"","sources":["../src/AudioOfflineRenderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiC,GAAG,EAAE,MAAM,EAAmC,MAAM,kBAAkB,CAAA;AAI9G,OAAO,EAAC,wBAAwB,EAAC,MAAM,0BAA0B,CAAA;AACjE,OAAO,EAAC,OAAO,EAAC,MAAM,mBAAmB,CAAA;AACzC,OAAO,EAAC,WAAW,EAAC,MAAM,uBAAuB,CAAA;AAIjD,yBAAiB,oBAAoB,CAAC;IAC3B,MAAM,KAAK,GAAU,QAAQ,OAAO,EACf,MAAM,WAAW,EACjB,wBAAwB,MAAM,CAAC,wBAAwB,CAAC,EACxD,aAAY,GAAY,KAAG,OAAO,CAAC,IAAI,CA+BlE,CAAA;CAiDJ"}
1
+ {"version":3,"file":"AudioOfflineRenderer.d.ts","sourceRoot":"","sources":["../src/AudioOfflineRenderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiC,GAAG,EAAE,MAAM,EAAmC,MAAM,kBAAkB,CAAA;AAI9G,OAAO,EAAC,wBAAwB,EAAC,MAAM,0BAA0B,CAAA;AACjE,OAAO,EAAC,OAAO,EAAC,MAAM,mBAAmB,CAAA;AACzC,OAAO,EAAC,WAAW,EAAC,MAAM,uBAAuB,CAAA;AAIjD,yBAAiB,oBAAoB,CAAC;IAC3B,MAAM,KAAK,GAAU,QAAQ,OAAO,EACf,MAAM,WAAW,EACjB,wBAAwB,MAAM,CAAC,wBAAwB,CAAC,EACxD,aAAY,GAAY,KAAG,OAAO,CAAC,IAAI,CAgClE,CAAA;CAiDJ"}
@@ -8,8 +8,11 @@ import { AudioWorklets } from "./AudioWorklets";
8
8
  export var AudioOfflineRenderer;
9
9
  (function (AudioOfflineRenderer) {
10
10
  AudioOfflineRenderer.start = async (source, meta, optExportConfiguration, sampleRate = 48_000) => {
11
- const project = source.copy();
12
11
  const numStems = ExportStemsConfiguration.countStems(optExportConfiguration);
12
+ if (numStems === 0) {
13
+ return panic("Nothing to export");
14
+ }
15
+ const project = source.copy();
13
16
  const progress = new DefaultObservableValue(0.0);
14
17
  const dialog = RuntimeNotifier.progress({ headline: "Rendering...", progress });
15
18
  project.boxGraph.beginTransaction();
package/dist/Engine.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { ppqn } from "@opendaw/lib-dsp";
2
- import { int, Nullable, ObservableValue, Observer, Subscription, Terminable, UUID } from "@opendaw/lib-std";
2
+ import { int, MutableObservableValue, Nullable, ObservableValue, Observer, Subscription, Terminable, UUID } from "@opendaw/lib-std";
3
3
  import { ClipNotification, NoteSignal } from "@opendaw/studio-adapters";
4
4
  import { Project } from "./project/Project";
5
5
  export interface Engine extends Terminable {
@@ -24,6 +24,7 @@ export interface Engine extends Terminable {
24
24
  get isCountingIn(): ObservableValue<boolean>;
25
25
  get metronomeEnabled(): ObservableValue<boolean>;
26
26
  get playbackTimestamp(): ObservableValue<ppqn>;
27
+ get playbackTimestampEnabled(): MutableObservableValue<boolean>;
27
28
  get countInBeatsTotal(): ObservableValue<int>;
28
29
  get countInBeatsRemaining(): ObservableValue<number>;
29
30
  get markerState(): ObservableValue<Nullable<[UUID.Bytes, int]>>;
@@ -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,EAAC,GAAG,EAAE,QAAQ,EAAE,eAAe,EAAE,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,IAAI,EAAC,MAAM,kBAAkB,CAAA;AACzG,OAAO,EAAC,gBAAgB,EAAE,UAAU,EAAC,MAAM,0BAA0B,CAAA;AACrE,OAAO,EAAC,OAAO,EAAC,MAAM,mBAAmB,CAAA;AAEzC,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,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAA;IACpC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,YAAY,CAAA;IAC5D,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAA;IACxC,gBAAgB,CAAC,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAA;IAC1D,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAA;IAC3D,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,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,CAAA;IAC/D,IAAI,OAAO,IAAI,OAAO,CAAA;CACzB"}
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,GAAG,EACH,sBAAsB,EACtB,QAAQ,EACR,eAAe,EACf,QAAQ,EACR,YAAY,EACZ,UAAU,EACV,IAAI,EACP,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAC,gBAAgB,EAAE,UAAU,EAAC,MAAM,0BAA0B,CAAA;AACrE,OAAO,EAAC,OAAO,EAAC,MAAM,mBAAmB,CAAA;AAEzC,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,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAA;IACpC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,YAAY,CAAA;IAC5D,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAA;IACxC,gBAAgB,CAAC,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAA;IAC1D,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAA;IAC3D,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,wBAAwB,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAA;IAC/D,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,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,CAAA;IAC/D,IAAI,OAAO,IAAI,OAAO,CAAA;CACzB"}
@@ -21,6 +21,7 @@ export declare class EngineFacade implements Engine {
21
21
  get isCountingIn(): ObservableValue<boolean>;
22
22
  get metronomeEnabled(): MutableObservableValue<boolean>;
23
23
  get playbackTimestamp(): ObservableValue<ppqn>;
24
+ get playbackTimestampEnabled(): MutableObservableValue<boolean>;
24
25
  get countInBeatsTotal(): ObservableValue<int>;
25
26
  get countInBeatsRemaining(): ObservableValue<int>;
26
27
  get markerState(): DefaultObservableValue<Nullable<[UUID.Bytes, int]>>;
@@ -1 +1 @@
1
- {"version":3,"file":"EngineFacade.d.ts","sourceRoot":"","sources":["../src/EngineFacade.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,sBAAsB,EACtB,GAAG,EACH,sBAAsB,EACtB,QAAQ,EACR,eAAe,EACf,QAAQ,EAER,YAAY,EAEZ,IAAI,EACP,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAC,IAAI,EAAC,MAAM,kBAAkB,CAAA;AACrC,OAAO,EAAC,gBAAgB,EAAE,UAAU,EAAC,MAAM,0BAA0B,CAAA;AACrE,OAAO,EAAC,MAAM,EAAC,MAAM,UAAU,CAAA;AAC/B,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAA;AAC7C,OAAO,EAAC,OAAO,EAAC,MAAM,mBAAmB,CAAA;AAEzC,qBAAa,YAAa,YAAW,MAAM;;;IAkBvC,UAAU,CAAC,OAAO,EAAE,aAAa;IAiBjC,aAAa,IAAI,IAAI;IAErB,cAAc,IAAI,IAAI;IAMtB,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,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,CAA2B;IACjG,IAAI,OAAO,IAAI,OAAO,CAAmE;IAEzF,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,UAAU,CAAC,GAAG,YAAY;IAG5D,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI;IAGxC,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAGpC,gBAAgB,CAAC,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI;IAG1D,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI;IAI3D,SAAS,IAAI,IAAI;CAIpB"}
1
+ {"version":3,"file":"EngineFacade.d.ts","sourceRoot":"","sources":["../src/EngineFacade.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,sBAAsB,EACtB,GAAG,EACH,sBAAsB,EACtB,QAAQ,EACR,eAAe,EACf,QAAQ,EAER,YAAY,EAEZ,IAAI,EACP,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAC,IAAI,EAAC,MAAM,kBAAkB,CAAA;AACrC,OAAO,EAAC,gBAAgB,EAAE,UAAU,EAAC,MAAM,0BAA0B,CAAA;AACrE,OAAO,EAAC,MAAM,EAAC,MAAM,UAAU,CAAA;AAC/B,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAA;AAC7C,OAAO,EAAC,OAAO,EAAC,MAAM,mBAAmB,CAAA;AAEzC,qBAAa,YAAa,YAAW,MAAM;;;IAmBvC,UAAU,CAAC,OAAO,EAAE,aAAa;IAmBjC,aAAa,IAAI,IAAI;IAErB,cAAc,IAAI,IAAI;IAMtB,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,wBAAwB,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAwC;IACvG,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,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,CAA2B;IACjG,IAAI,OAAO,IAAI,OAAO,CAAmE;IAEzF,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,UAAU,CAAC,GAAG,YAAY;IAG5D,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI;IAGxC,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAGpC,gBAAgB,CAAC,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI;IAG1D,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI;IAI3D,SAAS,IAAI,IAAI;CAIpB"}
@@ -3,6 +3,7 @@ export class EngineFacade {
3
3
  #terminator = new Terminator();
4
4
  #lifecycle = this.#terminator.own(new Terminator());
5
5
  #playbackTimestamp = new DefaultObservableValue(0.0);
6
+ #playbackTimestampEnabled = new DefaultObservableValue(true);
6
7
  #countInBeatsTotal = new DefaultObservableValue(4);
7
8
  #countInBeatsRemaining = new DefaultObservableValue(0);
8
9
  #position = new DefaultObservableValue(0.0);
@@ -16,7 +17,7 @@ export class EngineFacade {
16
17
  setWorklet(worklet) {
17
18
  this.#worklet = Option.wrap(worklet);
18
19
  this.#lifecycle.terminate();
19
- this.#lifecycle.ownAll(worklet.playbackTimestamp.catchupAndSubscribe(owner => this.#playbackTimestamp.setValue(owner.getValue())), worklet.countInBeatsTotal.catchupAndSubscribe(owner => this.#countInBeatsTotal.setValue(owner.getValue())), worklet.countInBeatsRemaining.catchupAndSubscribe(owner => this.#countInBeatsRemaining.setValue(owner.getValue())), worklet.position.catchupAndSubscribe(owner => this.#position.setValue(owner.getValue())), worklet.isPlaying.catchupAndSubscribe(owner => this.#isPlaying.setValue(owner.getValue())), worklet.isRecording.catchupAndSubscribe(owner => this.#isRecording.setValue(owner.getValue())), worklet.isCountingIn.catchupAndSubscribe(owner => this.#isCountingIn.setValue(owner.getValue())), worklet.metronomeEnabled.catchupAndSubscribe(owner => this.#metronomeEnabled.setValue(owner.getValue())), worklet.markerState.catchupAndSubscribe(owner => this.#markerState.setValue(owner.getValue())), this.metronomeEnabled.catchupAndSubscribe(owner => worklet.metronomeEnabled.setValue(owner.getValue())));
20
+ this.#lifecycle.ownAll(worklet.playbackTimestamp.catchupAndSubscribe(owner => this.#playbackTimestamp.setValue(owner.getValue())), worklet.playbackTimestampEnabled.catchupAndSubscribe(owner => this.#playbackTimestampEnabled.setValue(owner.getValue())), worklet.countInBeatsTotal.catchupAndSubscribe(owner => this.#countInBeatsTotal.setValue(owner.getValue())), worklet.countInBeatsRemaining.catchupAndSubscribe(owner => this.#countInBeatsRemaining.setValue(owner.getValue())), worklet.position.catchupAndSubscribe(owner => this.#position.setValue(owner.getValue())), worklet.isPlaying.catchupAndSubscribe(owner => this.#isPlaying.setValue(owner.getValue())), worklet.isRecording.catchupAndSubscribe(owner => this.#isRecording.setValue(owner.getValue())), worklet.isCountingIn.catchupAndSubscribe(owner => this.#isCountingIn.setValue(owner.getValue())), worklet.metronomeEnabled.catchupAndSubscribe(owner => this.#metronomeEnabled.setValue(owner.getValue())), worklet.markerState.catchupAndSubscribe(owner => this.#markerState.setValue(owner.getValue())), this.#metronomeEnabled.catchupAndSubscribe(owner => worklet.metronomeEnabled.setValue(owner.getValue())), this.#playbackTimestampEnabled.catchupAndSubscribe(owner => worklet.playbackTimestampEnabled.setValue(owner.getValue())));
20
21
  }
21
22
  assertWorklet() { this.#worklet.unwrap("No worklet available"); }
22
23
  releaseWorklet() {
@@ -35,6 +36,7 @@ export class EngineFacade {
35
36
  get isCountingIn() { return this.#isCountingIn; }
36
37
  get metronomeEnabled() { return this.#metronomeEnabled; }
37
38
  get playbackTimestamp() { return this.#playbackTimestamp; }
39
+ get playbackTimestampEnabled() { return this.#playbackTimestampEnabled; }
38
40
  get countInBeatsTotal() { return this.#countInBeatsTotal; }
39
41
  get countInBeatsRemaining() { return this.#countInBeatsRemaining; }
40
42
  get markerState() { return this.#markerState; }
@@ -21,6 +21,7 @@ export declare class EngineWorklet extends AudioWorkletNode implements Engine {
21
21
  get countInBeatsRemaining(): ObservableValue<number>;
22
22
  get position(): ObservableValue<ppqn>;
23
23
  get playbackTimestamp(): MutableObservableValue<number>;
24
+ get playbackTimestampEnabled(): MutableObservableValue<boolean>;
24
25
  get metronomeEnabled(): MutableObservableValue<boolean>;
25
26
  get markerState(): ObservableValue<Nullable<[UUID.Bytes, int]>>;
26
27
  get project(): Project;
@@ -1 +1 @@
1
- {"version":3,"file":"EngineWorklet.d.ts","sourceRoot":"","sources":["../src/EngineWorklet.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,GAAG,EACH,sBAAsB,EAEtB,QAAQ,EACR,eAAe,EACf,QAAQ,EAER,YAAY,EAGZ,IAAI,EACP,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAC,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAIrC,OAAO,EAEH,gBAAgB,EAOhB,wBAAwB,EACxB,UAAU,EACV,gBAAgB,EACnB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EAAC,OAAO,EAAC,MAAM,mBAAmB,CAAA;AACzC,OAAO,EAAC,MAAM,EAAC,MAAM,UAAU,CAAA;AAE/B,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,EAC9C,OAAO,CAAC,EAAE,gBAAgB;IA+FtC,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,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,CAA2B;IAC1F,IAAI,OAAO,IAAI,OAAO,CAAuB;IAE7C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IACxB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC;IACxC,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IACpC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,YAAY;IAC5D,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI;IACxC,gBAAgB,CAAC,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI;IAI1D,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI;IAG3D,yBAAyB,CAAC,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,YAAY;IAQ7E,SAAS,IAAI,IAAI;CAIpB"}
1
+ {"version":3,"file":"EngineWorklet.d.ts","sourceRoot":"","sources":["../src/EngineWorklet.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,GAAG,EACH,sBAAsB,EAEtB,QAAQ,EACR,eAAe,EACf,QAAQ,EAER,YAAY,EAGZ,IAAI,EACP,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAC,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAIrC,OAAO,EAEH,gBAAgB,EAOhB,wBAAwB,EACxB,UAAU,EACV,gBAAgB,EACnB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EAAC,OAAO,EAAC,MAAM,mBAAmB,CAAA;AACzC,OAAO,EAAC,MAAM,EAAC,MAAM,UAAU,CAAA;AAE/B,qBAAa,aAAc,SAAQ,gBAAiB,YAAW,MAAM;;IACjE,MAAM,CAAC,EAAE,EAAE,GAAG,CAAQ;IAEtB,QAAQ,CAAC,EAAE,SAAqB;gBAqBpB,OAAO,EAAE,gBAAgB,EACzB,OAAO,EAAE,OAAO,EAChB,mBAAmB,CAAC,EAAE,wBAAwB,EAC9C,OAAO,CAAC,EAAE,gBAAgB;IAsGtC,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,wBAAwB,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAwC;IACvG,IAAI,gBAAgB,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAgC;IACvF,IAAI,WAAW,IAAI,eAAe,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,CAA2B;IAC1F,IAAI,OAAO,IAAI,OAAO,CAAuB;IAE7C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IACxB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC;IACxC,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IACpC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,YAAY;IAC5D,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI;IACxC,gBAAgB,CAAC,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI;IAI1D,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI;IAG3D,yBAAyB,CAAC,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,YAAY;IAQ7E,SAAS,IAAI,IAAI;CAIpB"}
@@ -9,6 +9,7 @@ export class EngineWorklet extends AudioWorkletNode {
9
9
  #terminator = new Terminator();
10
10
  #project;
11
11
  #playbackTimestamp = new DefaultObservableValue(0.0);
12
+ #playbackTimestampEnabled = new DefaultObservableValue(true);
12
13
  #position = new DefaultObservableValue(0.0);
13
14
  #isPlaying = new DefaultObservableValue(false);
14
15
  #isRecording = new DefaultObservableValue(false);
@@ -57,7 +58,12 @@ export class EngineWorklet extends AudioWorkletNode {
57
58
  setPosition(position) { dispatcher.dispatchAndForget(this.setPosition, position); }
58
59
  startRecording(countIn) { dispatcher.dispatchAndForget(this.startRecording, countIn); }
59
60
  stopRecording() { dispatcher.dispatchAndForget(this.stopRecording); }
60
- setMetronomeEnabled(enabled) { dispatcher.dispatchAndForget(this.setMetronomeEnabled, enabled); }
61
+ setMetronomeEnabled(enabled) {
62
+ dispatcher.dispatchAndForget(this.setMetronomeEnabled, enabled);
63
+ }
64
+ setPlaybackTimestampEnabled(enabled) {
65
+ dispatcher.dispatchAndForget(this.setPlaybackTimestampEnabled, enabled);
66
+ }
61
67
  queryLoadingComplete() {
62
68
  return dispatcher.dispatchAndReturn(this.queryLoadingComplete);
63
69
  }
@@ -104,7 +110,7 @@ export class EngineWorklet extends AudioWorkletNode {
104
110
  },
105
111
  switchMarkerState: (state) => this.#markerState.setValue(state)
106
112
  });
107
- 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())));
113
+ 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())), this.#playbackTimestampEnabled.catchupAndSubscribe(owner => this.#commands.setPlaybackTimestampEnabled(owner.getValue())));
108
114
  }
109
115
  play() { this.#commands.play(); }
110
116
  stop(reset = false) { this.#commands.stop(reset); }
@@ -119,6 +125,7 @@ export class EngineWorklet extends AudioWorkletNode {
119
125
  get countInBeatsRemaining() { return this.#countInBeatsRemaining; }
120
126
  get position() { return this.#position; }
121
127
  get playbackTimestamp() { return this.#playbackTimestamp; }
128
+ get playbackTimestampEnabled() { return this.#playbackTimestampEnabled; }
122
129
  get metronomeEnabled() { return this.#metronomeEnabled; }
123
130
  get markerState() { return this.#markerState; }
124
131
  get project() { return this.#project; }
@@ -1 +1 @@
1
- {"version":3,"file":"RecordingWorklet.d.ts","sourceRoot":"","sources":["../src/RecordingWorklet.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,GAAG,EAEH,QAAQ,EACR,MAAM,EAEN,YAAY,EACZ,UAAU,EAEV,IAAI,EACP,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAAC,KAAK,EAAc,MAAM,qBAAqB,CAAA;AACtD,OAAO,EACH,SAAS,EAET,UAAU,EACV,YAAY,EACZ,iBAAiB,EAEpB,MAAM,0BAA0B,CAAA;AAMjC,qBAAa,gBAAiB,SAAQ,gBAAiB,YAAW,UAAU,EAAE,YAAY;;IAGtF,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAkB;gBAa/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM;IA2BvF,GAAG,CAAC,CAAC,SAAS,UAAU,EAAE,UAAU,EAAE,CAAC,GAAG,CAAC;IAE3C,KAAK,CAAC,KAAK,EAAE,GAAG,GAAG,IAAI;IAEvB,aAAa,CAAC,KAAK,EAAE,GAAG,GAAG,IAAI;IAE/B,IAAI,cAAc,IAAI,GAAG,CAA6C;IACtE,IAAI,IAAI,IAAI,MAAM,CAAC,SAAS,CAAC,CAAoB;IACjD,IAAI,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,CAA6E;IACvG,IAAI,KAAK,IAAI,iBAAiB,CAAqB;IAEnD,UAAU,IAAI,IAAI;IAElB,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,iBAAiB,CAAC,GAAG,YAAY;IAQ9D,SAAS,IAAI,IAAI;IAMjB,QAAQ,IAAI,MAAM;CAkCrB"}
1
+ {"version":3,"file":"RecordingWorklet.d.ts","sourceRoot":"","sources":["../src/RecordingWorklet.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,GAAG,EAEH,QAAQ,EACR,MAAM,EAGN,YAAY,EACZ,UAAU,EAEV,IAAI,EACP,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAAC,KAAK,EAAc,MAAM,qBAAqB,CAAA;AACtD,OAAO,EACH,SAAS,EAET,UAAU,EACV,YAAY,EACZ,iBAAiB,EAEpB,MAAM,0BAA0B,CAAA;AAMjC,qBAAa,gBAAiB,SAAQ,gBAAiB,YAAW,UAAU,EAAE,YAAY;;IAGtF,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAkB;gBAa/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM;IA2BvF,GAAG,CAAC,CAAC,SAAS,UAAU,EAAE,UAAU,EAAE,CAAC,GAAG,CAAC;IAE3C,KAAK,CAAC,KAAK,EAAE,GAAG,GAAG,IAAI;IAEvB,aAAa,CAAC,KAAK,EAAE,GAAG,GAAG,IAAI;IAE/B,IAAI,cAAc,IAAI,GAAG,CAA6C;IACtE,IAAI,IAAI,IAAI,MAAM,CAAC,SAAS,CAAC,CAAoB;IACjD,IAAI,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,CAA6E;IACvG,IAAI,KAAK,IAAI,iBAAiB,CAAqB;IAEnD,UAAU,IAAI,IAAI;IAElB,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,iBAAiB,CAAC,GAAG,YAAY;IAQ9D,SAAS,IAAI,IAAI;IAMjB,QAAQ,IAAI,MAAM;CAyCrB"}
@@ -1,8 +1,8 @@
1
- import { ByteArrayInput, Notifier, Option, Progress, Terminable, Terminator, UUID } from "@opendaw/lib-std";
1
+ import { ByteArrayInput, Notifier, Option, panic, Progress, Terminable, Terminator, UUID } from "@opendaw/lib-std";
2
2
  import { BPMTools } from "@opendaw/lib-dsp";
3
3
  import { SamplePeaks } from "@opendaw/lib-fusion";
4
4
  import { mergeChunkPlanes, RingBuffer } from "@opendaw/studio-adapters";
5
- import { SampleStorage } from "./samples/SampleStorage";
5
+ import { SampleStorage } from "./samples";
6
6
  import { RenderQuantum } from "./RenderQuantum";
7
7
  import { Workers } from "./Workers";
8
8
  import { PeaksWriter } from "./PeaksWriter";
@@ -68,7 +68,7 @@ export class RecordingWorklet extends AudioWorkletNode {
68
68
  this.#isRecording = false;
69
69
  this.#reader.stop();
70
70
  if (this.#output.length === 0) {
71
- return;
71
+ return panic("No recording data available");
72
72
  }
73
73
  const totalSamples = this.#limitSamples;
74
74
  const sample_rate = this.context.sampleRate;
@@ -88,10 +88,17 @@ export class RecordingWorklet extends AudioWorkletNode {
88
88
  this.#peaks = Option.wrap(SamplePeaks.from(new ByteArrayInput(peaks)));
89
89
  const bpm = BPMTools.detect(frames[0], sample_rate);
90
90
  const duration = totalSamples / sample_rate;
91
- const meta = { name: "Recording", bpm, sample_rate, duration };
92
- await SampleStorage.saveSample(this.uuid, audioData, peaks, meta);
91
+ const meta = { name: "Recording", bpm, sample_rate, duration, origin: "recording" };
92
+ const sample = {
93
+ uuid: this.uuid,
94
+ audio: audioData,
95
+ peaks: peaks,
96
+ meta
97
+ };
98
+ await SampleStorage.saveSample(sample);
93
99
  this.#setState({ type: "loaded" });
94
100
  this.terminate();
101
+ return sample;
95
102
  }
96
103
  #setState(value) {
97
104
  this.#state = value;
@@ -1 +1 @@
1
- {"version":3,"file":"CaptureMidi.d.ts","sourceRoot":"","sources":["../../src/capture/CaptureMidi.ts"],"names":[],"mappings":"AAAA,OAAO,EAQH,QAAQ,EACR,MAAM,EACN,YAAY,EACZ,UAAU,EACb,MAAM,kBAAkB,CAAA;AAIzB,OAAO,EAAC,YAAY,EAAE,cAAc,EAAC,MAAM,uBAAuB,CAAA;AAClE,OAAO,EAAC,UAAU,EAAC,MAAM,0BAA0B,CAAA;AAEnD,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAA;AACjC,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAA;AAI/C,qBAAa,WAAY,SAAQ,OAAO,CAAC,cAAc,CAAC;;gBAOxC,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,cAAc;IA8B/F,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAEhC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,YAAY;IAE5D,IAAI,KAAK,IAAI,MAAM,CAgBlB;IAED,IAAI,WAAW,IAAI,MAAM,CAAC,MAAM,CAAC,CAIhC;IAEK,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IAuBvC,cAAc,IAAI,UAAU;CAgD/B"}
1
+ {"version":3,"file":"CaptureMidi.d.ts","sourceRoot":"","sources":["../../src/capture/CaptureMidi.ts"],"names":[],"mappings":"AAAA,OAAO,EAQH,QAAQ,EACR,MAAM,EACN,YAAY,EACZ,UAAU,EACb,MAAM,kBAAkB,CAAA;AAIzB,OAAO,EAAC,YAAY,EAAE,cAAc,EAAC,MAAM,uBAAuB,CAAA;AAClE,OAAO,EAAC,UAAU,EAAC,MAAM,0BAA0B,CAAA;AAEnD,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAA;AACjC,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAA;AAI/C,qBAAa,WAAY,SAAQ,OAAO,CAAC,cAAc,CAAC;;gBAOxC,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,cAAc;IA+B/F,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAEhC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,YAAY;IAE5D,IAAI,KAAK,IAAI,MAAM,CAgBlB;IAED,IAAI,WAAW,IAAI,MAAM,CAAC,MAAM,CAAC,CAIhC;IAEK,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IAuBvC,cAAc,IAAI,UAAU;CAgD/B"}
@@ -33,33 +33,33 @@ export class CaptureMidi extends Capture {
33
33
  else {
34
34
  this.#stopStream();
35
35
  }
36
- }), this.#notifier.subscribe((signal) => manager.project.engine.noteSignal(signal)));
36
+ }), this.#notifier.subscribe((signal) => manager.project.engine.noteSignal(signal)), Terminable.create(() => this.#stopStream()));
37
37
  }
38
38
  notify(signal) { this.#notifier.notify(signal); }
39
39
  subscribeNotes(observer) { return this.#notifier.subscribe(observer); }
40
40
  get label() {
41
- return MidiDevices.get().mapOr(midiAccess => this.deviceId.getValue().match({
41
+ return MidiDevices.get().mapOr(() => this.deviceId.getValue().match({
42
42
  none: () => this.armed.getValue() ? this.#filterChannel.match({
43
43
  none: () => `Listening to all devices`,
44
44
  some: channel => `Listening to all devices on channel '${channel}'`
45
45
  }) : "Arm to listen to MIDI device...",
46
46
  some: id => {
47
- const device = midiAccess.inputs.get(id);
48
- if (isUndefined(device)) {
47
+ const device = MidiDevices.findInputDeviceById(id);
48
+ if (device.isEmpty()) {
49
49
  return `⚠️ Could not find device with id '${id}'`;
50
50
  }
51
- const deviceName = device.name ?? "Unknown device";
51
+ const deviceName = device.unwrapOrUndefined()?.name ?? "Unknown device";
52
52
  return this.#filterChannel.match({
53
53
  none: () => `Listening to ${deviceName}`,
54
- some: channel => `Listening to ${deviceName} on channel '${channel}'`
54
+ some: channel => `Listening to ${deviceName} on channel #${channel + 1}`
55
55
  });
56
56
  }
57
57
  }), "MIDI not available");
58
58
  }
59
59
  get deviceLabel() {
60
60
  return this.deviceId.getValue()
61
- .flatMap(deviceId => MidiDevices.inputs()
62
- .map(inputs => inputs.find(input => input.id === deviceId)?.name));
61
+ .flatMap(deviceId => MidiDevices.findInputDeviceById(deviceId)
62
+ .map(device => device.name));
63
63
  }
64
64
  async prepareRecording() {
65
65
  if (MidiDevices.get().isEmpty()) {
@@ -70,7 +70,7 @@ export class CaptureMidi extends Capture {
70
70
  return Errors.warn("MIDI not available");
71
71
  }
72
72
  }
73
- const optInputs = MidiDevices.inputs();
73
+ const optInputs = MidiDevices.inputDevices();
74
74
  if (optInputs.isEmpty()) {
75
75
  return Errors.warn("MIDI not available");
76
76
  }
@@ -87,16 +87,16 @@ export class CaptureMidi extends Capture {
87
87
  }
88
88
  }
89
89
  startRecording() {
90
- const availableMidiDevices = MidiDevices.inputs();
91
- assert(availableMidiDevices.nonEmpty(), "No MIDI input devices found");
90
+ const availableInputDevices = MidiDevices.inputDevices();
91
+ assert(availableInputDevices.nonEmpty(), "No MIDI input devices found");
92
92
  return RecordMidi.start({ notifier: this.#notifier, project: this.manager.project, capture: this });
93
93
  }
94
94
  async #updateStream() {
95
95
  if (MidiDevices.get().isEmpty()) {
96
96
  await MidiDevices.requestPermission();
97
97
  }
98
- const availableMidiDevices = MidiDevices.inputs();
99
- const available = availableMidiDevices.unwrap();
98
+ const availableInputDevices = MidiDevices.inputDevices();
99
+ const available = availableInputDevices.unwrap();
100
100
  const capturing = this.deviceId.getValue().match({
101
101
  none: () => available,
102
102
  some: id => available.filter(device => id === device.id)
@@ -1,5 +1,5 @@
1
1
  import { Terminable } from "@opendaw/lib-std";
2
- import { SampleManager } from "@opendaw/studio-adapters";
2
+ import { SampleLoaderManager } from "@opendaw/studio-adapters";
3
3
  import { Project } from "../project/Project";
4
4
  import { RecordingWorklet } from "../RecordingWorklet";
5
5
  import { Capture } from "./Capture";
@@ -7,7 +7,7 @@ export declare namespace RecordAudio {
7
7
  type RecordAudioContext = {
8
8
  recordingWorklet: RecordingWorklet;
9
9
  mediaStream: MediaStream;
10
- sampleManager: SampleManager;
10
+ sampleManager: SampleLoaderManager;
11
11
  audioContext: AudioContext;
12
12
  project: Project;
13
13
  capture: Capture;
@@ -1 +1 @@
1
- {"version":3,"file":"RecordAudio.d.ts","sourceRoot":"","sources":["../../src/capture/RecordAudio.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2C,UAAU,EAAmB,MAAM,kBAAkB,CAAA;AAGvG,OAAO,EAAC,aAAa,EAAY,MAAM,0BAA0B,CAAA;AACjE,OAAO,EAAC,OAAO,EAAC,MAAM,oBAAoB,CAAA;AAC1C,OAAO,EAAC,gBAAgB,EAAC,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAA;AAIjC,yBAAiB,WAAW,CAAC;IACzB,KAAK,kBAAkB,GAAG;QACtB,gBAAgB,EAAE,gBAAgB,CAAA;QAClC,WAAW,EAAE,WAAW,CAAA;QACxB,aAAa,EAAE,aAAa,CAAA;QAC5B,YAAY,EAAE,YAAY,CAAA;QAC1B,OAAO,EAAE,OAAO,CAAA;QAChB,OAAO,EAAE,OAAO,CAAA;QAChB,MAAM,EAAE,MAAM,CAAA;KACjB,CAAA;IAED,MAAM,CAAC,MAAM,KAAK,GACd,0FAAwF,kBAAkB,KACxG,UAqEL,CAAA;;CACJ"}
1
+ {"version":3,"file":"RecordAudio.d.ts","sourceRoot":"","sources":["../../src/capture/RecordAudio.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2C,UAAU,EAAmB,MAAM,kBAAkB,CAAA;AAGvG,OAAO,EAAC,mBAAmB,EAAY,MAAM,0BAA0B,CAAA;AACvE,OAAO,EAAC,OAAO,EAAC,MAAM,oBAAoB,CAAA;AAC1C,OAAO,EAAC,gBAAgB,EAAC,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAA;AAIjC,yBAAiB,WAAW,CAAC;IACzB,KAAK,kBAAkB,GAAG;QACtB,gBAAgB,EAAE,gBAAgB,CAAA;QAClC,WAAW,EAAE,WAAW,CAAA;QACxB,aAAa,EAAE,mBAAmB,CAAA;QAClC,YAAY,EAAE,YAAY,CAAA;QAC1B,OAAO,EAAE,OAAO,CAAA;QAChB,OAAO,EAAE,OAAO,CAAA;QAChB,MAAM,EAAE,MAAM,CAAA;KACjB,CAAA;IAED,MAAM,CAAC,MAAM,KAAK,GACd,0FAAwF,kBAAkB,KACxG,UAqEL,CAAA;;CACJ"}
@@ -1 +1 @@
1
- {"version":3,"file":"CloudAuthManager.d.ts","sourceRoot":"","sources":["../../src/clouds/CloudAuthManager.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAA;AAC3C,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAA;AAI3C,qBAAa,gBAAgB;;IACzB,MAAM,CAAC,MAAM,IAAI,gBAAgB;IAqBjC,QAAQ,CAAC,EAAE,SAAyB;IAIpC,OAAO;IAED,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;CAiLjE"}
1
+ {"version":3,"file":"CloudAuthManager.d.ts","sourceRoot":"","sources":["../../src/clouds/CloudAuthManager.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAA;AAC3C,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAA;AAI3C,qBAAa,gBAAgB;;IACzB,MAAM,CAAC,MAAM,IAAI,gBAAgB;IAqBjC,QAAQ,CAAC,EAAE,SAAyB;IAIpC,OAAO;IAED,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;CAuLjE"}
@@ -71,10 +71,15 @@ export class CloudAuthManager {
71
71
  message: "Please wait for authentication...",
72
72
  cancel: () => reject("cancelled")
73
73
  });
74
+ let handled = false;
74
75
  channel.onmessage = async (event) => {
75
76
  const data = asDefined(event.data, "No data");
76
77
  console.debug("[CloudAuth] Received via BroadcastChannel:", this.id, data);
77
78
  if (data.type === "auth-callback" && isDefined(data.code)) {
79
+ if (handled) {
80
+ return;
81
+ }
82
+ handled = true;
78
83
  console.debug("[CloudAuth] Processing code from BroadcastChannel...", data.type, data.code);
79
84
  try {
80
85
  const tokenParams = new URLSearchParams({
@@ -108,8 +113,11 @@ export class CloudAuthManager {
108
113
  }
109
114
  }
110
115
  else if (data.type === "closed") {
111
- console.debug("[CloudAuth] Callback window closed");
112
- reject(null);
116
+ // Only reject if we did not already start handling a code
117
+ if (!handled) {
118
+ console.debug("[CloudAuth] Callback window closed before code received");
119
+ reject(null);
120
+ }
113
121
  }
114
122
  };
115
123
  return promise.finally(() => {
@@ -1 +1 @@
1
- {"version":3,"file":"CloudBackupSamples.d.ts","sourceRoot":"","sources":["../../src/clouds/CloudBackupSamples.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,SAAS,EAAE,QAAQ,EAAmB,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAGlG,OAAO,EAAY,MAAM,EAAC,MAAM,0BAA0B,CAAA;AAG1D,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAA;AAM3C,qBAAa,kBAAkB;;IAC3B,MAAM,CAAC,QAAQ,CAAC,UAAU,aAAY;IACtC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,SAAkC;IACnE,MAAM,CAAC,QAAQ,CAAC,eAAe,GAAI,aAAW,MAAM,EAAE,aAAW,MAAM,aAAY;IAEnF,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,GAAG,MAAM;WAE5B,KAAK,CAAC,YAAY,EAAE,YAAY,EAC1B,QAAQ,EAAE,QAAQ,CAAC,OAAO,EAC1B,GAAG,EAAE,SAAS,CAAC,MAAM,CAAC;IAgBzC,OAAO;CAsHV"}
1
+ {"version":3,"file":"CloudBackupSamples.d.ts","sourceRoot":"","sources":["../../src/clouds/CloudBackupSamples.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,SAAS,EAAE,QAAQ,EAAmB,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAGlG,OAAO,EAAY,MAAM,EAAC,MAAM,0BAA0B,CAAA;AAG1D,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAA;AAM3C,qBAAa,kBAAkB;;IAC3B,MAAM,CAAC,QAAQ,CAAC,UAAU,aAAY;IACtC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,SAAkC;IACnE,MAAM,CAAC,QAAQ,CAAC,eAAe,GAAI,aAAW,MAAM,EAAE,aAAW,MAAM,aAAY;IAEnF,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,GAAG,MAAM;WAE5B,KAAK,CAAC,YAAY,EAAE,YAAY,EAC1B,QAAQ,EAAE,QAAQ,CAAC,OAAO,EAC1B,GAAG,EAAE,SAAS,CAAC,MAAM,CAAC;IAgBzC,OAAO;CA2HV"}
@@ -114,7 +114,12 @@ export class CloudBackupSamples {
114
114
  };
115
115
  const shifts = SamplePeaks.findBestFit(audioData.numberOfFrames);
116
116
  const peaks = await Workers.Peak.generateAsync(Progress.Empty, shifts, audioData.frames, audioData.numberOfFrames, audioData.numberOfChannels);
117
- await SampleStorage.saveSample(UUID.parse(sample.uuid), audioData, peaks, sample);
117
+ await SampleStorage.saveSample({
118
+ uuid: UUID.parse(sample.uuid),
119
+ audio: audioData,
120
+ peaks: peaks,
121
+ meta: sample
122
+ });
118
123
  return sample;
119
124
  }));
120
125
  this.#log("Download samples complete.");
package/dist/index.d.ts CHANGED
@@ -18,13 +18,7 @@ export * from "./project/ProjectPaths";
18
18
  export * from "./project/ProjectProfile";
19
19
  export * from "./project/ProjectSignals";
20
20
  export * from "./project/ProjectStorage";
21
- export * from "./samples/SampleStorage";
22
- export * from "./samples/MainThreadSampleLoader";
23
- export * from "./samples/MainThreadSampleManager";
24
- export * from "./samples/OpenSampleAPI";
25
- export * from "./samples/SampleAPI";
26
- export * from "./samples/SampleImporter";
27
- export * from "./samples/SampleProvider";
21
+ export * from "./samples/index";
28
22
  export * from "./sync-log/Commit";
29
23
  export * from "./sync-log/SyncLogReader";
30
24
  export * from "./sync-log/SyncLogWriter";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA;AACjC,cAAc,wBAAwB,CAAA;AACtC,cAAc,uBAAuB,CAAA;AACrC,cAAc,0BAA0B,CAAA;AACxC,cAAc,qBAAqB,CAAA;AAEnC,cAAc,yBAAyB,CAAA;AACvC,cAAc,iCAAiC,CAAA;AAC/C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,+BAA+B,CAAA;AAE7C,cAAc,oBAAoB,CAAA;AAClC,cAAc,qBAAqB,CAAA;AAEnC,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA;AACpC,cAAc,yBAAyB,CAAA;AACvC,cAAc,sBAAsB,CAAA;AACpC,cAAc,uBAAuB,CAAA;AACrC,cAAc,wBAAwB,CAAA;AACtC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AAExC,cAAc,yBAAyB,CAAA;AACvC,cAAc,kCAAkC,CAAA;AAChD,cAAc,mCAAmC,CAAA;AACjD,cAAc,yBAAyB,CAAA;AACvC,cAAc,qBAAqB,CAAA;AACnC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AAExC,cAAc,mBAAmB,CAAA;AACjC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AAExC,cAAc,2BAA2B,CAAA;AACzC,cAAc,uBAAuB,CAAA;AACrC,cAAc,sBAAsB,CAAA;AAEpC,cAAc,oBAAoB,CAAA;AAElC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,wBAAwB,CAAA;AACtC,cAAc,qBAAqB,CAAA;AACnC,cAAc,cAAc,CAAA;AAC5B,cAAc,UAAU,CAAA;AACxB,cAAc,aAAa,CAAA;AAC3B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,mBAAmB,CAAA;AACjC,cAAc,UAAU,CAAA;AACxB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,yBAAyB,CAAA;AACvC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,uBAAuB,CAAA;AACrC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,SAAS,CAAA;AACvB,cAAc,eAAe,CAAA;AAC7B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,WAAW,CAAA;AACzB,cAAc,WAAW,CAAA;AACzB,cAAc,iBAAiB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA;AACjC,cAAc,wBAAwB,CAAA;AACtC,cAAc,uBAAuB,CAAA;AACrC,cAAc,0BAA0B,CAAA;AACxC,cAAc,qBAAqB,CAAA;AAEnC,cAAc,yBAAyB,CAAA;AACvC,cAAc,iCAAiC,CAAA;AAC/C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,+BAA+B,CAAA;AAE7C,cAAc,oBAAoB,CAAA;AAClC,cAAc,qBAAqB,CAAA;AAEnC,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA;AACpC,cAAc,yBAAyB,CAAA;AACvC,cAAc,sBAAsB,CAAA;AACpC,cAAc,uBAAuB,CAAA;AACrC,cAAc,wBAAwB,CAAA;AACtC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AAExC,cAAc,iBAAiB,CAAA;AAE/B,cAAc,mBAAmB,CAAA;AACjC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AAExC,cAAc,2BAA2B,CAAA;AACzC,cAAc,uBAAuB,CAAA;AACrC,cAAc,sBAAsB,CAAA;AAEpC,cAAc,oBAAoB,CAAA;AAElC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,wBAAwB,CAAA;AACtC,cAAc,qBAAqB,CAAA;AACnC,cAAc,cAAc,CAAA;AAC5B,cAAc,UAAU,CAAA;AACxB,cAAc,aAAa,CAAA;AAC3B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,mBAAmB,CAAA;AACjC,cAAc,UAAU,CAAA;AACxB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,yBAAyB,CAAA;AACvC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,uBAAuB,CAAA;AACrC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,SAAS,CAAA;AACvB,cAAc,eAAe,CAAA;AAC7B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,WAAW,CAAA;AACzB,cAAc,WAAW,CAAA;AACzB,cAAc,iBAAiB,CAAA"}
package/dist/index.js CHANGED
@@ -18,13 +18,7 @@ export * from "./project/ProjectPaths";
18
18
  export * from "./project/ProjectProfile";
19
19
  export * from "./project/ProjectSignals";
20
20
  export * from "./project/ProjectStorage";
21
- export * from "./samples/SampleStorage";
22
- export * from "./samples/MainThreadSampleLoader";
23
- export * from "./samples/MainThreadSampleManager";
24
- export * from "./samples/OpenSampleAPI";
25
- export * from "./samples/SampleAPI";
26
- export * from "./samples/SampleImporter";
27
- export * from "./samples/SampleProvider";
21
+ export * from "./samples/index";
28
22
  export * from "./sync-log/Commit";
29
23
  export * from "./sync-log/SyncLogReader";
30
24
  export * from "./sync-log/SyncLogWriter";
@@ -3,7 +3,7 @@ import { Events } from "@opendaw/lib-dom";
3
3
  import { MidiData } from "@opendaw/lib-midi";
4
4
  export class MIDIMessageSubscriber {
5
5
  static subscribeMessageEvents(access, observer, channel) {
6
- const listen = (input) => isDefined(channel)
6
+ const listenToMIDIMessages = (input) => isDefined(channel)
7
7
  ? Events.subscribe(input, "midimessage", (event) => {
8
8
  if (event.data === null || MidiData.readChannel(event.data) !== channel) {
9
9
  return;
@@ -11,7 +11,7 @@ export class MIDIMessageSubscriber {
11
11
  observer(event);
12
12
  }) : Events.subscribe(input, "midimessage", observer);
13
13
  const connections = Array.from(access.inputs.values())
14
- .map(input => ([input, listen(input)]));
14
+ .map(input => ([input, listenToMIDIMessages(input)]));
15
15
  const stateSubscription = Events.subscribe(access, "statechange", (event) => {
16
16
  const port = event.port;
17
17
  if (!isInstanceOf(port, MIDIInput)) {
@@ -19,14 +19,14 @@ export class MIDIMessageSubscriber {
19
19
  }
20
20
  for (const [input, subscription] of connections) {
21
21
  if (input === port) {
22
- // Well, this is strange, but if you start listening to a midi-input initially,
22
+ // Well, this seems odd, but if you start listening to a midi-input initially,
23
23
  // it will change its state to 'connected', so we clean up the first old subscriptions.
24
24
  subscription.terminate();
25
25
  break;
26
26
  }
27
27
  }
28
28
  if (port.state === "connected") {
29
- connections.push([port, listen(port)]);
29
+ connections.push([port, listenToMIDIMessages(port)]);
30
30
  }
31
31
  });
32
32
  return {
@@ -1,12 +1,16 @@
1
1
  import { byte, MutableObservableValue, ObservableOption, Observer, Option, Subscription } from "@opendaw/lib-std";
2
+ import { SoftwareMIDIInput } from "./SoftwareMIDIInput";
2
3
  export declare class MidiDevices {
3
4
  #private;
4
5
  static canRequestMidiAccess(): boolean;
6
+ static readonly softwareMIDIInput: SoftwareMIDIInput;
5
7
  static requestPermission(): Promise<undefined>;
6
8
  static get(): ObservableOption<MIDIAccess>;
7
9
  static subscribeMessageEvents(observer: Observer<MIDIMessageEvent>, channel?: byte): Subscription;
8
- static inputs(): Option<ReadonlyArray<MIDIInput>>;
9
- static outputs(): Option<ReadonlyArray<MIDIOutput>>;
10
+ static inputDevices(): Option<ReadonlyArray<MIDIInput>>;
11
+ static findInputDeviceById(id: string): Option<MIDIInput>;
12
+ static externalInputDevices(): Option<ReadonlyArray<MIDIInput>>;
13
+ static externalOutputDevices(): Option<ReadonlyArray<MIDIOutput>>;
10
14
  static panic(): void;
11
15
  static available(): MutableObservableValue<boolean>;
12
16
  }
@@ -1 +1 @@
1
- {"version":3,"file":"MidiDevices.d.ts","sourceRoot":"","sources":["../../src/midi/MidiDevices.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,IAAI,EAIJ,sBAAsB,EAEtB,gBAAgB,EAEhB,QAAQ,EACR,MAAM,EACN,YAAY,EAEf,MAAM,kBAAkB,CAAA;AAKzB,qBAAa,WAAW;;IACpB,MAAM,CAAC,oBAAoB,IAAI,OAAO;WAIzB,iBAAiB;IAiB9B,MAAM,CAAC,GAAG,IAAI,gBAAgB,CAAC,UAAU,CAAC;IAE1C,MAAM,CAAC,sBAAsB,CAAC,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC,EAAE,IAAI,GAAG,YAAY;IAWjG,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"}
1
+ {"version":3,"file":"MidiDevices.d.ts","sourceRoot":"","sources":["../../src/midi/MidiDevices.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,IAAI,EAIJ,sBAAsB,EAEtB,gBAAgB,EAEhB,QAAQ,EACR,MAAM,EACN,YAAY,EAEf,MAAM,kBAAkB,CAAA;AAIzB,OAAO,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAA;AAErD,qBAAa,WAAW;;IACpB,MAAM,CAAC,oBAAoB,IAAI,OAAO;IAEtC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAA0B;WAIjE,iBAAiB;IAiB9B,MAAM,CAAC,GAAG,IAAI,gBAAgB,CAAC,UAAU,CAAC;IAE1C,MAAM,CAAC,sBAAsB,CAAC,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC,EAAE,IAAI,GAAG,YAAY;IAWjG,MAAM,CAAC,YAAY,IAAI,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;IAKvD,MAAM,CAAC,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC;IAIzD,MAAM,CAAC,oBAAoB,IAAI,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;IAI/D,MAAM,CAAC,qBAAqB,IAAI,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;IAIjE,MAAM,CAAC,KAAK,IAAI,IAAI;IAkBpB,MAAM,CAAC,SAAS,IAAI,sBAAsB,CAAC,OAAO,CAAC;CAqCtD"}
@@ -11,8 +11,10 @@ import { Errors, Lazy, MutableObservableOption, MutableObservableValue, Notifier
11
11
  import { MidiData } from "@opendaw/lib-midi";
12
12
  import { Promises } from "@opendaw/lib-runtime";
13
13
  import { MIDIMessageSubscriber } from "./MIDIMessageSubscriber";
14
+ import { SoftwareMIDIInput } from "./SoftwareMIDIInput";
14
15
  export class MidiDevices {
15
16
  static canRequestMidiAccess() { return "requestMIDIAccess" in navigator; }
17
+ static softwareMIDIInput = new SoftwareMIDIInput();
16
18
  static #memoizedRequest = Promises.memoizeAsync(() => navigator.requestMIDIAccess({ sysex: false }));
17
19
  static async requestPermission() {
18
20
  if (this.canRequestMidiAccess()) {
@@ -41,10 +43,17 @@ export class MidiDevices {
41
43
  some: midi => MIDIMessageSubscriber.subscribeMessageEvents(midi, observer, channel)
42
44
  });
43
45
  }
44
- static inputs() {
46
+ static inputDevices() {
47
+ return this.externalInputDevices()
48
+ .map((inputs) => Array.from(inputs.values()).concat(this.softwareMIDIInput));
49
+ }
50
+ static findInputDeviceById(id) {
51
+ return this.inputDevices().map(inputs => inputs.find(input => input.id === id));
52
+ }
53
+ static externalInputDevices() {
45
54
  return this.get().map(({ inputs }) => Array.from(inputs.values()));
46
55
  }
47
- static outputs() {
56
+ static externalOutputDevices() {
48
57
  return this.get().map(({ outputs }) => Array.from(outputs.values()));
49
58
  }
50
59
  static panic() {
@@ -0,0 +1,34 @@
1
+ import { byte, int, Nullable, ObservableValue, unitValue } from "@opendaw/lib-std";
2
+ type OnMidiMessage = Nullable<(this: MIDIInput, ev: MIDIMessageEvent) => any>;
3
+ type OnStateChange = Nullable<(this: MIDIPort, ev: MIDIConnectionEvent) => any>;
4
+ export declare class SoftwareMIDIInput implements MIDIInput {
5
+ #private;
6
+ readonly manufacturer: string | null;
7
+ readonly connection: MIDIPortConnectionState;
8
+ readonly id: string;
9
+ readonly name: string | null;
10
+ readonly state: MIDIPortDeviceState;
11
+ readonly type: MIDIPortType;
12
+ readonly version: string | null;
13
+ onstatechange: OnStateChange;
14
+ constructor();
15
+ get onmidimessage(): OnMidiMessage;
16
+ set onmidimessage(value: OnMidiMessage);
17
+ get countListeners(): ObservableValue<int>;
18
+ sendNoteOn(note: byte, velocity?: unitValue): void;
19
+ sendNoteOff(note: byte): void;
20
+ releaseAllNotes(): void;
21
+ hasActiveNote(note: byte): boolean;
22
+ hasActiveNotes(): boolean;
23
+ get channel(): byte;
24
+ set channel(value: byte);
25
+ open(): Promise<MIDIPort>;
26
+ close(): Promise<MIDIPort>;
27
+ addEventListener<K extends keyof MIDIInputEventMap>(type: K, listener: (this: MIDIInput, ev: MIDIInputEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
28
+ addEventListener<K extends keyof MIDIPortEventMap>(type: K, listener: (this: MIDIPort, ev: MIDIPortEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
29
+ dispatchEvent(event: MIDIMessageEvent): boolean;
30
+ removeEventListener<K extends keyof MIDIInputEventMap>(type: K, listener: (this: MIDIInput, ev: MIDIInputEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
31
+ removeEventListener<K extends keyof MIDIPortEventMap>(type: K, listener: (this: MIDIPort, ev: MIDIPortEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
32
+ }
33
+ export {};
34
+ //# sourceMappingURL=SoftwareMIDIInput.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SoftwareMIDIInput.d.ts","sourceRoot":"","sources":["../../src/midi/SoftwareMIDIInput.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,IAAI,EAGJ,GAAG,EAEH,QAAQ,EACR,eAAe,EAEf,SAAS,EACZ,MAAM,kBAAkB,CAAA;AAGzB,KAAK,aAAa,GAAG,QAAQ,CAAC,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,gBAAgB,KAAK,GAAG,CAAC,CAAA;AAE7E,KAAK,aAAa,GAAG,QAAQ,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,mBAAmB,KAAK,GAAG,CAAC,CAAA;AAE/E,qBAAa,iBAAkB,YAAW,SAAS;;IAC/C,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAY;IAChD,QAAQ,CAAC,UAAU,EAAE,uBAAuB,CAAS;IACrD,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAwB;IAC3C,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAsB;IAClD,QAAQ,CAAC,KAAK,EAAE,mBAAmB,CAAc;IACjD,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAU;IACrC,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAU;IAMzC,aAAa,EAAE,aAAa,CAAO;;IAWnC,IAAI,aAAa,IAAI,aAAa,CAA6B;IAC/D,IAAI,aAAa,CAAC,KAAK,EAAE,aAAa,EAGrC;IAED,IAAI,cAAc,IAAI,eAAe,CAAC,GAAG,CAAC,CAA8B;IAExE,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,GAAE,SAAe,GAAG,IAAI;IAOvD,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAO7B,eAAe,IAAI,IAAI;IAKvB,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO;IAClC,cAAc,IAAI,OAAO;IAEzB,IAAI,OAAO,IAAI,IAAI,CAAuB;IAC1C,IAAI,OAAO,CAAC,KAAK,EAAE,IAAI,EAItB;IAED,IAAI,IAAI,OAAO,CAAC,QAAQ,CAAC;IACzB,KAAK,IAAI,OAAO,CAAC,QAAQ,CAAC;IAC1B,gBAAgB,CAAC,CAAC,SAAS,MAAM,iBAAiB,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,uBAAuB,GAAG,IAAI;IAC7K,gBAAgB,CAAC,CAAC,SAAS,MAAM,gBAAgB,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,uBAAuB,GAAG,IAAI;IAK1K,aAAa,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO;IAI/C,mBAAmB,CAAC,CAAC,SAAS,MAAM,iBAAiB,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,oBAAoB,GAAG,IAAI;IAC7K,mBAAmB,CAAC,CAAC,SAAS,MAAM,gBAAgB,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,OAAO,CAAC,EAAE,OAAO,GAAG,oBAAoB,GAAG,IAAI;CAc7K"}