@opendaw/studio-core 0.0.43 → 0.0.45

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 (104) hide show
  1. package/dist/AssetService.d.ts +12 -2
  2. package/dist/AssetService.d.ts.map +1 -1
  3. package/dist/AssetService.js +46 -1
  4. package/dist/AudioOfflineRenderer.d.ts +1 -2
  5. package/dist/AudioOfflineRenderer.d.ts.map +1 -1
  6. package/dist/AudioOfflineRenderer.js +10 -3
  7. package/dist/EffectBox.d.ts +2 -2
  8. package/dist/EffectBox.d.ts.map +1 -1
  9. package/dist/EffectFactories.d.ts +6 -0
  10. package/dist/EffectFactories.d.ts.map +1 -1
  11. package/dist/EffectFactories.js +29 -24
  12. package/dist/EffectFactory.d.ts +1 -1
  13. package/dist/EffectFactory.d.ts.map +1 -1
  14. package/dist/EffectParameterDefaults.d.ts +5 -0
  15. package/dist/EffectParameterDefaults.d.ts.map +1 -0
  16. package/dist/EffectParameterDefaults.js +27 -0
  17. package/dist/Engine.d.ts +1 -1
  18. package/dist/Engine.d.ts.map +1 -1
  19. package/dist/EngineFacade.d.ts +1 -1
  20. package/dist/EngineFacade.d.ts.map +1 -1
  21. package/dist/EngineFacade.js +1 -1
  22. package/dist/EngineWorklet.d.ts +2 -2
  23. package/dist/EngineWorklet.d.ts.map +1 -1
  24. package/dist/EngineWorklet.js +3 -2
  25. package/dist/Preferences.d.ts +20 -0
  26. package/dist/Preferences.d.ts.map +1 -0
  27. package/dist/Preferences.js +46 -0
  28. package/dist/capture/CaptureDevices.js +3 -3
  29. package/dist/capture/RecordTrack.d.ts +2 -2
  30. package/dist/capture/RecordTrack.d.ts.map +1 -1
  31. package/dist/capture/Recording.d.ts +1 -1
  32. package/dist/capture/Recording.d.ts.map +1 -1
  33. package/dist/capture/Recording.js +1 -1
  34. package/dist/cloud/CloudAuthManager.d.ts +6 -2
  35. package/dist/cloud/CloudAuthManager.d.ts.map +1 -1
  36. package/dist/cloud/CloudAuthManager.js +12 -12
  37. package/dist/cloud/CloudBackup.js +1 -1
  38. package/dist/cloud/{CloudBackupSoundfont.d.ts → CloudBackupSoundfonts.d.ts} +1 -1
  39. package/dist/cloud/CloudBackupSoundfonts.d.ts.map +1 -0
  40. package/dist/cloud/{CloudBackupSoundfont.js → CloudBackupSoundfonts.js} +1 -1
  41. package/dist/dawproject/BuiltinDevices.d.ts.map +1 -1
  42. package/dist/dawproject/BuiltinDevices.js +3 -2
  43. package/dist/dawproject/{DawProjectImport.d.ts → DawProjectImporter.d.ts} +1 -1
  44. package/dist/dawproject/DawProjectImporter.d.ts.map +1 -0
  45. package/dist/dawproject/{DawProjectImport.js → DawProjectImporter.js} +17 -5
  46. package/dist/dawproject/DawProjectImporter.test.d.ts +2 -0
  47. package/dist/dawproject/DawProjectImporter.test.d.ts.map +1 -0
  48. package/dist/dawproject/{DawProjectImport.test.js → DawProjectImporter.test.js} +1 -1
  49. package/dist/dawproject/DawProjectService.js +1 -1
  50. package/dist/dawproject/index.d.ts +1 -1
  51. package/dist/dawproject/index.d.ts.map +1 -1
  52. package/dist/dawproject/index.js +1 -1
  53. package/dist/index.d.ts +1 -0
  54. package/dist/index.d.ts.map +1 -1
  55. package/dist/index.js +1 -0
  56. package/dist/midi/MIDILearning.d.ts +1 -1
  57. package/dist/midi/MIDILearning.d.ts.map +1 -1
  58. package/dist/midi/MIDILearning.js +22 -3
  59. package/dist/processors.js +27 -5
  60. package/dist/processors.js.map +4 -4
  61. package/dist/project/Project.d.ts +12 -8
  62. package/dist/project/Project.d.ts.map +1 -1
  63. package/dist/project/Project.js +45 -33
  64. package/dist/project/ProjectMigration.d.ts.map +1 -1
  65. package/dist/project/ProjectMigration.js +10 -1
  66. package/dist/project/Recovery.d.ts +9 -0
  67. package/dist/project/Recovery.d.ts.map +1 -0
  68. package/dist/project/Recovery.js +49 -0
  69. package/dist/project/index.d.ts +1 -0
  70. package/dist/project/index.d.ts.map +1 -1
  71. package/dist/project/index.js +1 -0
  72. package/dist/samples/OpenSampleAPI.d.ts.map +1 -1
  73. package/dist/samples/OpenSampleAPI.js +5 -3
  74. package/dist/samples/SampleService.d.ts +5 -2
  75. package/dist/samples/SampleService.d.ts.map +1 -1
  76. package/dist/samples/SampleService.js +12 -4
  77. package/dist/samples/SampleStorage.d.ts +1 -1
  78. package/dist/samples/SampleStorage.d.ts.map +1 -1
  79. package/dist/samples/SampleStorage.js +1 -1
  80. package/dist/soundfont/DefaultSoundfontLoader.d.ts +2 -1
  81. package/dist/soundfont/DefaultSoundfontLoader.d.ts.map +1 -1
  82. package/dist/soundfont/DefaultSoundfontLoader.js +14 -4
  83. package/dist/soundfont/DefaultSoundfontLoaderManager.d.ts +2 -1
  84. package/dist/soundfont/DefaultSoundfontLoaderManager.d.ts.map +1 -1
  85. package/dist/soundfont/DefaultSoundfontLoaderManager.js +1 -0
  86. package/dist/soundfont/OpenSoundfontAPI.d.ts.map +1 -1
  87. package/dist/soundfont/OpenSoundfontAPI.js +6 -4
  88. package/dist/soundfont/SoundfontService.d.ts +5 -2
  89. package/dist/soundfont/SoundfontService.d.ts.map +1 -1
  90. package/dist/soundfont/SoundfontService.js +18 -8
  91. package/dist/workers-main.js +2 -2
  92. package/dist/workers-main.js.map +4 -4
  93. package/dist/ysync/YService.d.ts.map +1 -1
  94. package/dist/ysync/YService.js +4 -2
  95. package/dist/ysync/YSync.d.ts.map +1 -1
  96. package/dist/ysync/YSync.js +79 -51
  97. package/package.json +49 -48
  98. package/dist/cloud/CloudBackupSoundfont.d.ts.map +0 -1
  99. package/dist/dawproject/DawProjectImport.d.ts.map +0 -1
  100. package/dist/dawproject/DawProjectImport.test.d.ts +0 -2
  101. package/dist/dawproject/DawProjectImport.test.d.ts.map +0 -1
  102. package/dist/env.d.ts +0 -6
  103. package/dist/env.d.ts.map +0 -1
  104. package/dist/env.js +0 -9
@@ -1,33 +1,36 @@
1
- import { Procedure, Terminable, TerminableOwner, Terminator } from "@opendaw/lib-std";
2
- import { BoxGraph, Editing } from "@opendaw/lib-box";
1
+ import { Func, Procedure, Terminable, TerminableOwner, Terminator } from "@opendaw/lib-std";
2
+ import { BoxEditing, BoxGraph } from "@opendaw/lib-box";
3
3
  import { AudioBusBox, AudioUnitBox, BoxIO, RootBox, TimelineBox, UserInterfaceBox } from "@opendaw/studio-boxes";
4
4
  import { BoxAdapters, BoxAdaptersContext, ClipSequencing, ParameterFieldAdapters, ProcessorOptions, ProjectSkeleton, RootBoxAdapter, SampleLoaderManager, SoundfontLoaderManager, TimelineBoxAdapter, UserEditingManager, VertexSelection } from "@opendaw/studio-adapters";
5
5
  import { LiveStreamBroadcaster, LiveStreamReceiver } from "@opendaw/lib-fusion";
6
6
  import { ProjectEnv } from "./ProjectEnv";
7
7
  import { Mixer } from "../Mixer";
8
8
  import { ProjectApi } from "./ProjectApi";
9
- import { CaptureDevices } from "../capture/CaptureDevices";
9
+ import { CaptureDevices } from "../capture";
10
10
  import { EngineFacade } from "../EngineFacade";
11
11
  import { EngineWorklet } from "../EngineWorklet";
12
- import { MIDILearning } from "../midi/MIDILearning";
12
+ import { MIDILearning } from "../midi";
13
13
  export type RestartWorklet = {
14
- unload: Procedure<unknown>;
14
+ unload: Func<unknown, Promise<unknown>>;
15
15
  load: Procedure<EngineWorklet>;
16
16
  };
17
+ export type ProjectCreateOptions = {
18
+ noDefaultUser?: boolean;
19
+ };
17
20
  export declare class Project implements BoxAdaptersContext, Terminable, TerminableOwner {
18
21
  #private;
19
- static new(env: ProjectEnv): Project;
22
+ static new(env: ProjectEnv, options?: ProjectCreateOptions): Project;
20
23
  static load(env: ProjectEnv, arrayBuffer: ArrayBuffer): Project;
21
24
  static skeleton(env: ProjectEnv, skeleton: ProjectSkeleton): Project;
22
25
  readonly boxGraph: BoxGraph<BoxIO.TypeMap>;
23
26
  readonly rootBox: RootBox;
24
- readonly userInterfaceBox: UserInterfaceBox;
27
+ readonly userInterfaceBoxes: ReadonlyArray<UserInterfaceBox>;
25
28
  readonly masterBusBox: AudioBusBox;
26
29
  readonly masterAudioUnit: AudioUnitBox;
27
30
  readonly timelineBox: TimelineBox;
28
31
  readonly api: ProjectApi;
29
32
  readonly captureDevices: CaptureDevices;
30
- readonly editing: Editing;
33
+ readonly editing: BoxEditing;
31
34
  readonly selection: VertexSelection;
32
35
  readonly boxAdapters: BoxAdapters;
33
36
  readonly userEditingManager: UserEditingManager;
@@ -39,6 +42,7 @@ export declare class Project implements BoxAdaptersContext, Terminable, Terminab
39
42
  private constructor();
40
43
  startAudioWorklet(restart?: RestartWorklet, options?: ProcessorOptions): EngineWorklet;
41
44
  startRecording(countIn?: boolean): void;
45
+ follow(box: UserInterfaceBox): void;
42
46
  own<T extends Terminable>(terminable: T): T;
43
47
  ownAll<T extends Terminable>(...terminables: Array<T>): void;
44
48
  spawn(): Terminator;
@@ -1 +1 @@
1
- {"version":3,"file":"Project.d.ts","sourceRoot":"","sources":["../../src/project/Project.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Project.d.ts","sourceRoot":"","sources":["../../src/project/Project.ts"],"names":[],"mappings":"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"}
@@ -1,20 +1,20 @@
1
1
  import { Arrays, ByteArrayOutput, Option, panic, safeExecute, Terminator, UUID } from "@opendaw/lib-std";
2
- import { BoxGraph, Editing } from "@opendaw/lib-box";
3
- import { AudioBusBox, AudioUnitBox, BoxIO, GrooveShuffleBox, RootBox, TimelineBox, UserInterfaceBox } from "@opendaw/studio-boxes";
2
+ import { BoxEditing, BoxGraph } from "@opendaw/lib-box";
3
+ import { AudioBusBox, AudioUnitBox, BoxIO, CompressorDeviceBox, GrooveShuffleBox, RootBox, TimelineBox, UserInterfaceBox } from "@opendaw/studio-boxes";
4
4
  import { BoxAdapters, IconSymbol, ParameterFieldAdapters, ProjectDecoder, RootBoxAdapter, TimelineBoxAdapter, UnionBoxTypes, UserEditingManager, VertexSelection } from "@opendaw/studio-adapters";
5
5
  import { LiveStreamReceiver } from "@opendaw/lib-fusion";
6
6
  import { AudioUnitType } from "@opendaw/studio-enums";
7
7
  import { Mixer } from "../Mixer";
8
8
  import { ProjectApi } from "./ProjectApi";
9
9
  import { ProjectMigration } from "./ProjectMigration";
10
- import { CaptureDevices } from "../capture/CaptureDevices";
10
+ import { CaptureDevices, Recording } from "../capture";
11
11
  import { EngineFacade } from "../EngineFacade";
12
- import { Recording } from "../capture/Recording";
13
- import { MIDILearning } from "../midi/MIDILearning";
12
+ import { MIDILearning } from "../midi";
14
13
  import { ProjectValidation } from "./ProjectValidation";
14
+ import { Preferences } from "../Preferences";
15
15
  // Main Entry Point for a Project
16
16
  export class Project {
17
- static new(env) {
17
+ static new(env, options) {
18
18
  const boxGraph = new BoxGraph(Option.wrap(BoxIO.create));
19
19
  const isoString = new Date().toISOString();
20
20
  console.debug(`New Project created on ${isoString}`);
@@ -26,29 +26,42 @@ export class Project {
26
26
  box.groove.refer(grooveShuffleBox);
27
27
  box.created.setValue(isoString);
28
28
  });
29
- const userInterfaceBox = UserInterfaceBox.create(boxGraph, UUID.generate());
30
- const masterBusBox = AudioBusBox.create(boxGraph, UUID.generate(), box => {
29
+ const primaryAudioBus = AudioBusBox.create(boxGraph, UUID.generate(), box => {
31
30
  box.collection.refer(rootBox.audioBusses);
32
31
  box.label.setValue("Output");
33
32
  box.icon.setValue(IconSymbol.toName(IconSymbol.SpeakerHeadphone));
34
33
  box.color.setValue(/*Colors.blue*/ "hsl(189, 100%, 65%)"); // TODO
35
34
  });
36
- const masterAudioUnit = AudioUnitBox.create(boxGraph, UUID.generate(), box => {
35
+ const primaryAudioOutputUnit = AudioUnitBox.create(boxGraph, UUID.generate(), box => {
37
36
  box.type.setValue(AudioUnitType.Output);
38
37
  box.collection.refer(rootBox.audioUnits);
39
38
  box.output.refer(rootBox.outputDevice);
40
39
  box.index.setValue(0);
41
40
  });
41
+ if (Preferences.values["auto-create-output-compressor"]) {
42
+ CompressorDeviceBox.create(boxGraph, UUID.generate(), box => {
43
+ box.label.setValue("Compressor");
44
+ box.index.setValue(0);
45
+ box.host.refer(primaryAudioOutputUnit.audioEffects);
46
+ box.threshold.setValue(0);
47
+ box.ratio.setValue(24);
48
+ });
49
+ }
42
50
  const timelineBox = TimelineBox.create(boxGraph, UUID.generate());
43
51
  rootBox.timeline.refer(timelineBox.root);
44
- userInterfaceBox.root.refer(rootBox.users);
45
- masterBusBox.output.refer(masterAudioUnit.input);
52
+ primaryAudioBus.output.refer(primaryAudioOutputUnit.input);
53
+ const userInterfaceBoxes = [];
54
+ if (options?.noDefaultUser !== true) {
55
+ const userInterfaceBox = UserInterfaceBox.create(boxGraph, UUID.generate());
56
+ userInterfaceBox.root.refer(rootBox.users);
57
+ userInterfaceBoxes.push(userInterfaceBox);
58
+ }
46
59
  boxGraph.endTransaction();
47
60
  return new Project(env, boxGraph, {
48
61
  rootBox,
49
- userInterfaceBox,
50
- masterBusBox,
51
- masterAudioUnit,
62
+ primaryAudioBus,
63
+ primaryAudioOutputUnit,
64
+ userInterfaceBoxes,
52
65
  timelineBox
53
66
  });
54
67
  }
@@ -64,7 +77,7 @@ export class Project {
64
77
  #env;
65
78
  boxGraph;
66
79
  rootBox;
67
- userInterfaceBox;
80
+ userInterfaceBoxes;
68
81
  masterBusBox;
69
82
  masterAudioUnit;
70
83
  timelineBox;
@@ -79,26 +92,28 @@ export class Project {
79
92
  midiLearning;
80
93
  mixer;
81
94
  engine = new EngineFacade();
82
- constructor(env, boxGraph, { rootBox, userInterfaceBox, masterBusBox, masterAudioUnit, timelineBox }) {
95
+ constructor(env, boxGraph, { rootBox, userInterfaceBoxes, primaryAudioBus, primaryAudioOutputUnit, timelineBox }) {
83
96
  this.#env = env;
84
97
  this.boxGraph = boxGraph;
85
98
  this.rootBox = rootBox;
86
- this.userInterfaceBox = userInterfaceBox;
87
- this.masterBusBox = masterBusBox;
88
- this.masterAudioUnit = masterAudioUnit;
99
+ this.userInterfaceBoxes = userInterfaceBoxes;
100
+ this.masterBusBox = primaryAudioBus;
101
+ this.masterAudioUnit = primaryAudioOutputUnit;
89
102
  this.timelineBox = timelineBox;
90
103
  this.api = new ProjectApi(this);
91
- this.editing = new Editing(this.boxGraph);
104
+ this.editing = new BoxEditing(this.boxGraph);
92
105
  this.selection = new VertexSelection(this.editing, this.boxGraph);
93
106
  this.parameterFieldAdapters = new ParameterFieldAdapters();
94
107
  this.boxAdapters = this.#terminator.own(new BoxAdapters(this));
95
108
  this.userEditingManager = new UserEditingManager(this.editing);
96
- this.userEditingManager.follow(this.userInterfaceBox);
97
- this.selection.switch(this.userInterfaceBox.selection);
98
109
  this.liveStreamReceiver = this.#terminator.own(new LiveStreamReceiver());
99
110
  this.midiLearning = this.#terminator.own(new MIDILearning(this));
100
111
  this.captureDevices = this.#terminator.own(new CaptureDevices(this));
101
112
  this.mixer = new Mixer(this.rootBoxAdapter.audioUnits);
113
+ // TODO We are probably doing that from the outside
114
+ if (this.userInterfaceBoxes.length > 0) {
115
+ this.follow(this.userInterfaceBoxes[0]);
116
+ }
102
117
  console.debug(`Project was created on ${this.rootBoxAdapter.created.toString()}`);
103
118
  }
104
119
  startAudioWorklet(restart, options) {
@@ -110,8 +125,8 @@ export class Project {
110
125
  // we will only accept the first error
111
126
  engine.removeEventListener("error", handler);
112
127
  engine.removeEventListener("processorerror", handler);
113
- safeExecute(restart?.unload, event);
114
128
  lifecycle.terminate();
129
+ await safeExecute(restart?.unload, event);
115
130
  safeExecute(restart?.load, this.startAudioWorklet(restart));
116
131
  };
117
132
  engine.addEventListener("error", handler);
@@ -127,6 +142,10 @@ export class Project {
127
142
  }
128
143
  Recording.start(this, countIn).finally();
129
144
  }
145
+ follow(box) {
146
+ this.userEditingManager.follow(box);
147
+ this.selection.switch(box.selection);
148
+ }
130
149
  own(terminable) { return this.#terminator.own(terminable); }
131
150
  ownAll(...terminables) { return this.#terminator.ownAll(...terminables); }
132
151
  spawn() { return this.#terminator.spawn(); }
@@ -146,9 +165,9 @@ export class Project {
146
165
  mandatoryBoxes: {
147
166
  rootBox: this.rootBox,
148
167
  timelineBox: this.timelineBox,
149
- masterBusBox: this.masterBusBox,
150
- masterAudioUnit: this.masterAudioUnit,
151
- userInterfaceBox: this.userInterfaceBox
168
+ primaryAudioBus: this.masterBusBox,
169
+ primaryAudioOutputUnit: this.masterAudioUnit,
170
+ userInterfaceBoxes: this.userInterfaceBoxes
152
171
  }
153
172
  };
154
173
  }
@@ -156,16 +175,9 @@ export class Project {
156
175
  const output = ByteArrayOutput.create();
157
176
  output.writeInt(ProjectDecoder.MAGIC_HEADER_OPEN);
158
177
  output.writeInt(ProjectDecoder.FORMAT_VERSION);
159
- // store all boxes
160
178
  const boxGraphChunk = this.boxGraph.toArrayBuffer();
161
179
  output.writeInt(boxGraphChunk.byteLength);
162
180
  output.writeBytes(new Int8Array(boxGraphChunk));
163
- // store mandatory boxes' addresses
164
- UUID.toDataOutput(output, this.rootBox.address.uuid);
165
- UUID.toDataOutput(output, this.userInterfaceBox.address.uuid);
166
- UUID.toDataOutput(output, this.masterBusBox.address.uuid);
167
- UUID.toDataOutput(output, this.masterAudioUnit.address.uuid);
168
- UUID.toDataOutput(output, this.timelineBox.address.uuid);
169
181
  return output.toArrayBuffer();
170
182
  }
171
183
  copy(env) {
@@ -1 +1 @@
1
- {"version":3,"file":"ProjectMigration.d.ts","sourceRoot":"","sources":["../../src/project/ProjectMigration.ts"],"names":[],"mappings":"AAYA,OAAO,EAAC,eAAe,EAAC,MAAM,0BAA0B,CAAA;AAExD,qBAAa,gBAAgB;IACzB,MAAM,CAAC,OAAO,CAAC,EAAC,QAAQ,EAAE,cAAc,EAAC,EAAE,eAAe,GAAG,IAAI;CAmEpE"}
1
+ {"version":3,"file":"ProjectMigration.d.ts","sourceRoot":"","sources":["../../src/project/ProjectMigration.ts"],"names":[],"mappings":"AAaA,OAAO,EAAC,eAAe,EAAC,MAAM,0BAA0B,CAAA;AAExD,qBAAa,gBAAgB;IACzB,MAAM,CAAC,OAAO,CAAC,EAAC,QAAQ,EAAE,cAAc,EAAC,EAAE,eAAe,GAAG,IAAI;CA4EpE"}
@@ -1,5 +1,5 @@
1
1
  import { CaptureAudioBox, CaptureMidiBox, GrooveShuffleBox, ValueEventCurveBox } from "@opendaw/studio-boxes";
2
- import { asDefined, asInstanceOf, UUID } from "@opendaw/lib-std";
2
+ import { asDefined, asInstanceOf, clamp, UUID } from "@opendaw/lib-std";
3
3
  import { AudioUnitType } from "@opendaw/studio-enums";
4
4
  export class ProjectMigration {
5
5
  static migrate({ boxGraph, mandatoryBoxes }) {
@@ -70,6 +70,15 @@ export class ProjectMigration {
70
70
  }));
71
71
  box.capture.refer(captureBox);
72
72
  boxGraph.endTransaction();
73
+ },
74
+ visitRevampDeviceBox: (box) => {
75
+ // Clamp order in RevampDeviceBox to 0-3
76
+ // The older version stored the actual order,
77
+ // but the new version only stores indices, so 4 is not valid anymore
78
+ boxGraph.beginTransaction();
79
+ box.lowPass.order.setValue(clamp(box.lowPass.order.getValue(), 0, 3));
80
+ box.highPass.order.setValue(clamp(box.highPass.order.getValue(), 0, 3));
81
+ boxGraph.endTransaction();
73
82
  }
74
83
  }));
75
84
  }
@@ -0,0 +1,9 @@
1
+ import { Option, Provider } from "@opendaw/lib-std";
2
+ import { ProjectEnv, ProjectProfile } from "../";
3
+ export declare class Recovery {
4
+ #private;
5
+ constructor(projectProfileService: Provider<Option<ProjectProfile>>, env: ProjectEnv);
6
+ restoreProfile(): Promise<Option<ProjectProfile>>;
7
+ createBackupCommand(): Option<Provider<Promise<void>>>;
8
+ }
9
+ //# sourceMappingURL=Recovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Recovery.d.ts","sourceRoot":"","sources":["../../src/project/Recovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAE,QAAQ,EAAO,MAAM,kBAAkB,CAAA;AAEvD,OAAO,EAAU,UAAU,EAAe,cAAc,EAAU,MAAM,KAAK,CAAA;AAE7E,qBAAa,QAAQ;;gBAML,qBAAqB,EAAE,QAAQ,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,EAAE,GAAG,EAAE,UAAU;IAK9E,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;IAsBvD,mBAAmB,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;CAgBzD"}
@@ -0,0 +1,49 @@
1
+ import { Option, UUID } from "@opendaw/lib-std";
2
+ import { Promises } from "@opendaw/lib-runtime";
3
+ import { Project, ProjectProfile, Workers } from "../";
4
+ export class Recovery {
5
+ static #RESTORE_FILE_PATH = ".backup";
6
+ #projectProfileProvider;
7
+ #env;
8
+ constructor(projectProfileService, env) {
9
+ this.#projectProfileProvider = projectProfileService;
10
+ this.#env = env;
11
+ }
12
+ async restoreProfile() {
13
+ const backupResult = await Promises.tryCatch(Workers.Opfs.list(Recovery.#RESTORE_FILE_PATH));
14
+ if (backupResult.status === "rejected" || backupResult.value.length === 0) {
15
+ return Option.None;
16
+ }
17
+ const readResult = await Promises.tryCatch(Promise.all([
18
+ Workers.Opfs.read(`${Recovery.#RESTORE_FILE_PATH}/uuid`)
19
+ .then(x => UUID.validateBytes(x)),
20
+ Workers.Opfs.read(`${Recovery.#RESTORE_FILE_PATH}/project.od`)
21
+ .then(x => Project.load(this.#env, x.buffer)),
22
+ Workers.Opfs.read(`${Recovery.#RESTORE_FILE_PATH}/meta.json`)
23
+ .then(x => JSON.parse(new TextDecoder().decode(x.buffer))),
24
+ Workers.Opfs.read(`${Recovery.#RESTORE_FILE_PATH}/saved`)
25
+ .then(x => x.at(0) === 1)
26
+ ]));
27
+ const deleteResult = await Promises.tryCatch(Workers.Opfs.delete(Recovery.#RESTORE_FILE_PATH));
28
+ console.debug(`delete backup: "${deleteResult.status}"`);
29
+ if (readResult.status === "rejected") {
30
+ return Option.None;
31
+ }
32
+ const [uuid, project, meta, saved] = readResult.value;
33
+ const profile = new ProjectProfile(uuid, project, meta, Option.None, saved);
34
+ console.debug(`restore ${profile}, saved: ${saved}`);
35
+ return Option.wrap(profile);
36
+ }
37
+ createBackupCommand() {
38
+ return this.#projectProfileProvider().map((profile) => async () => {
39
+ console.debug("backup project");
40
+ const { project, meta, uuid } = profile;
41
+ return Promises.tryCatch(Promise.all([
42
+ Workers.Opfs.write(`${Recovery.#RESTORE_FILE_PATH}/uuid`, uuid),
43
+ Workers.Opfs.write(`${Recovery.#RESTORE_FILE_PATH}/project.od`, new Uint8Array(project.toArrayBuffer())),
44
+ Workers.Opfs.write(`${Recovery.#RESTORE_FILE_PATH}/meta.json`, new TextEncoder().encode(JSON.stringify(meta))),
45
+ Workers.Opfs.write(`${Recovery.#RESTORE_FILE_PATH}/saved`, new Uint8Array([profile.saved() ? 1 : 0]))
46
+ ])).then(result => console.debug(`backup result: ${result.status}`));
47
+ });
48
+ }
49
+ }
@@ -7,4 +7,5 @@ export * from "./ProjectPaths";
7
7
  export * from "./ProjectProfile";
8
8
  export * from "./ProjectSignals";
9
9
  export * from "./ProjectStorage";
10
+ export * from "./Recovery";
10
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/project/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAC5B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA;AAC5B,cAAc,eAAe,CAAA;AAC7B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/project/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAC5B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA;AAC5B,cAAc,eAAe,CAAA;AAC7B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,YAAY,CAAA"}
@@ -7,3 +7,4 @@ export * from "./ProjectPaths";
7
7
  export * from "./ProjectProfile";
8
8
  export * from "./ProjectSignals";
9
9
  export * from "./ProjectStorage";
10
+ export * from "./Recovery";
@@ -1 +1 @@
1
- {"version":3,"file":"OpenSampleAPI.d.ts","sourceRoot":"","sources":["../../src/samples/OpenSampleAPI.ts"],"names":[],"mappings":"AAAA,OAAO,EAMH,SAAS,EAGT,SAAS,EACT,IAAI,EACP,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAC,MAAM,0BAA0B,CAAA;AAC1E,OAAO,EAAC,SAAS,EAAC,MAAM,sBAAsB,CAAA;AAI9C,qBAAa,aAAc,YAAW,SAAS;IAC3C,MAAM,CAAC,QAAQ,CAAC,OAAO,wCAAuC;IAC9D,MAAM,CAAC,QAAQ,CAAC,QAAQ,2CAA0C;IAGlE,MAAM,CAAC,GAAG,IAAI,aAAa;IAE3B,MAAM,CAAC,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS;IAStD,OAAO;IAED,GAAG,IAAI,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IAKrC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC;IAQtC,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAmC3G,MAAM,CAAC,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAsC/E,YAAY,IAAI,OAAO;CAC1B"}
1
+ {"version":3,"file":"OpenSampleAPI.d.ts","sourceRoot":"","sources":["../../src/samples/OpenSampleAPI.ts"],"names":[],"mappings":"AAAA,OAAO,EAMH,SAAS,EAGT,SAAS,EACT,IAAI,EACP,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAC,MAAM,0BAA0B,CAAA;AAC1E,OAAO,EAAC,SAAS,EAAC,MAAM,sBAAsB,CAAA;AAK9C,qBAAa,aAAc,YAAW,SAAS;IAC3C,MAAM,CAAC,QAAQ,CAAC,OAAO,wCAAuC;IAC9D,MAAM,CAAC,QAAQ,CAAC,QAAQ,2CAA0C;IAGlE,MAAM,CAAC,GAAG,IAAI,aAAa;IAE3B,MAAM,CAAC,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS;IAStD,OAAO;IAED,GAAG,IAAI,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IAKrC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC;IAQtC,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAmC3G,MAAM,CAAC,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAoC/E,YAAY,IAAI,OAAO;CAC1B"}
@@ -9,7 +9,9 @@ var __metadata = (this && this.__metadata) || function (k, v) {
9
9
  };
10
10
  import { Arrays, asDefined, DefaultObservableValue, Lazy, panic, RuntimeNotifier, tryCatch, UUID } from "@opendaw/lib-std";
11
11
  import { network, Promises } from "@opendaw/lib-runtime";
12
+ import { Sample } from "@opendaw/studio-adapters";
12
13
  import { base64Credentials, OpenDAWHeaders } from "../OpenDAWHeaders";
14
+ import { z } from "zod";
13
15
  // Standard openDAW samples (considered to be non-removable)
14
16
  export class OpenSampleAPI {
15
17
  static ApiRoot = "https://api.opendaw.studio/samples";
@@ -25,13 +27,13 @@ export class OpenSampleAPI {
25
27
  }
26
28
  constructor() { }
27
29
  async all() {
28
- return Promises.retry(() => fetch(`${OpenSampleAPI.ApiRoot}/list.php`, OpenDAWHeaders)
29
- .then(x => x.json(), () => []));
30
+ return Promises.guardedRetry(() => fetch(`${OpenSampleAPI.ApiRoot}/list.php`, OpenDAWHeaders)
31
+ .then(x => x.json().then(x => z.array(Sample).parse(x)), () => []), (_error, count) => count < 10);
30
32
  }
31
33
  async get(uuid) {
32
34
  const url = `${OpenSampleAPI.ApiRoot}/get.php?uuid=${UUID.toString(uuid)}`;
33
35
  const sample = await Promises.retry(() => network.limitFetch(url, OpenDAWHeaders)
34
- .then(x => x.json()))
36
+ .then(x => x.json().then(x => Sample.parse(x))))
35
37
  .then(x => { if ("error" in x) {
36
38
  return panic(x.error);
37
39
  }
@@ -1,12 +1,15 @@
1
- import { Procedure } from "@opendaw/lib-std";
1
+ import { Class, Procedure } from "@opendaw/lib-std";
2
+ import { Box } from "@opendaw/lib-box";
2
3
  import { Sample } from "@opendaw/studio-adapters";
3
4
  import { AssetService } from "../AssetService";
4
5
  export declare class SampleService extends AssetService<Sample> {
5
6
  readonly audioContext: AudioContext;
6
7
  protected readonly namePlural: string;
7
8
  protected readonly nameSingular: string;
9
+ protected readonly boxType: Class<Box>;
10
+ protected readonly filePickerOptions: FilePickerOptions;
8
11
  constructor(audioContext: AudioContext, onUpdate: Procedure<Sample>);
9
- browse(multiple: boolean): Promise<ReadonlyArray<Sample>>;
10
12
  importFile({ uuid, name, arrayBuffer, progressHandler }: AssetService.ImportArgs): Promise<Sample>;
13
+ protected collectAllFiles(): Promise<ReadonlyArray<Sample>>;
11
14
  }
12
15
  //# sourceMappingURL=SampleService.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SampleService.d.ts","sourceRoot":"","sources":["../../src/samples/SampleService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,SAAS,EAAiB,MAAM,kBAAkB,CAAA;AAI/E,OAAO,EAAY,MAAM,EAAiB,MAAM,0BAA0B,CAAA;AAE1E,OAAO,EAAC,YAAY,EAAC,MAAM,iBAAiB,CAAA;AAE5C,qBAAa,aAAc,SAAQ,YAAY,CAAC,MAAM,CAAC;IAIvC,QAAQ,CAAC,YAAY,EAAE,YAAY;IAH/C,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAY;IACjD,SAAS,CAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAW;gBAE7B,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,CAAC,MAAM,CAAC;IAItE,MAAM,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IAIzD,UAAU,CAAC,EAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,eAAgC,EAAC,EACzD,YAAY,CAAC,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;CAoC/D"}
1
+ {"version":3,"file":"SampleService.d.ts","sourceRoot":"","sources":["../../src/samples/SampleService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,EAAe,SAAS,EAAiB,MAAM,kBAAkB,CAAA;AACtF,OAAO,EAAC,GAAG,EAAC,MAAM,kBAAkB,CAAA;AAKpC,OAAO,EAAY,MAAM,EAAiB,MAAM,0BAA0B,CAAA;AAC1E,OAAO,EAAC,YAAY,EAAC,MAAM,iBAAiB,CAAA;AAM5C,qBAAa,aAAc,SAAQ,YAAY,CAAC,MAAM,CAAC;IAMvC,QAAQ,CAAC,YAAY,EAAE,YAAY;IAL/C,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAY;IACjD,SAAS,CAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAW;IAClD,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,CAAe;IACrD,SAAS,CAAC,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAAiC;gBAEnE,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,CAAC,MAAM,CAAC;IAItE,UAAU,CAAC,EAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,eAAgC,EAAC,EACzD,YAAY,CAAC,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;cAqC5C,eAAe,IAAI,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;CAKpE"}
@@ -2,19 +2,22 @@ import { Arrays, isUndefined, Progress, UUID } from "@opendaw/lib-std";
2
2
  import { estimateBpm } from "@opendaw/lib-dsp";
3
3
  import { Promises } from "@opendaw/lib-runtime";
4
4
  import { SamplePeaks } from "@opendaw/lib-fusion";
5
- import { FilePickerAcceptTypes, SampleStorage, Workers } from "../index";
5
+ import { AudioFileBox } from "@opendaw/studio-boxes";
6
6
  import { AssetService } from "../AssetService";
7
+ import { FilePickerAcceptTypes } from "../FilePickerAcceptTypes";
8
+ import { Workers } from "../Workers";
9
+ import { SampleStorage } from "./SampleStorage";
10
+ import { OpenSampleAPI } from "./OpenSampleAPI";
7
11
  export class SampleService extends AssetService {
8
12
  audioContext;
9
13
  namePlural = "Samples";
10
14
  nameSingular = "Sample";
15
+ boxType = AudioFileBox;
16
+ filePickerOptions = FilePickerAcceptTypes.WavFiles;
11
17
  constructor(audioContext, onUpdate) {
12
18
  super(onUpdate);
13
19
  this.audioContext = audioContext;
14
20
  }
15
- async browse(multiple) {
16
- return this.browseFiles(multiple, FilePickerAcceptTypes.WavFiles);
17
- }
18
21
  async importFile({ uuid, name, arrayBuffer, progressHandler = Progress.Empty }) {
19
22
  console.debug(`importSample '${name}' (${arrayBuffer.byteLength >> 10}kb)`);
20
23
  console.time("UUID.sha256");
@@ -48,4 +51,9 @@ export class SampleService extends AssetService {
48
51
  this.onUpdate(sample);
49
52
  return sample;
50
53
  }
54
+ async collectAllFiles() {
55
+ const stock = await OpenSampleAPI.get().all();
56
+ const local = await SampleStorage.get().list();
57
+ return Arrays.merge(stock, local, (sample, { uuid }) => sample.uuid === uuid);
58
+ }
51
59
  }
@@ -13,7 +13,7 @@ export declare namespace SampleStorage {
13
13
  export declare class SampleStorage extends Storage<Sample, SampleMetaData, SampleStorage.NewSample, [AudioData, Peaks, SampleMetaData]> {
14
14
  static readonly Folder = "samples/v2";
15
15
  static get(): SampleStorage;
16
- static clean(): Promise<void>;
16
+ static cleanDeprecated(): Promise<void>;
17
17
  private constructor();
18
18
  save({ uuid, audio, peaks, meta }: SampleStorage.NewSample): Promise<void>;
19
19
  updateSampleMeta(uuid: UUID.Bytes, meta: SampleMetaData): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"SampleStorage.d.ts","sourceRoot":"","sources":["../../src/samples/SampleStorage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkC,IAAI,EAAC,MAAM,kBAAkB,CAAA;AACtE,OAAO,EAAC,KAAK,EAAc,MAAM,qBAAqB,CAAA;AACtD,OAAO,EAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAC,MAAM,0BAA0B,CAAA;AAG1E,OAAO,EAAC,OAAO,EAAC,MAAM,YAAY,CAAA;AAElC,yBAAiB,aAAa,CAAC;IAC3B,KAAY,SAAS,GAAG;QACpB,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC;QACjB,KAAK,EAAE,SAAS,CAAC;QACjB,KAAK,EAAE,WAAW,CAAC;QACnB,IAAI,EAAE,cAAc,CAAA;KACvB,CAAA;CACJ;AAED,qBAAa,aAAc,SAAQ,OAAO,CAAC,MAAM,EAAE,cAAc,EAAE,aAAa,CAAC,SAAS,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;IAC3H,MAAM,CAAC,QAAQ,CAAC,MAAM,gBAAe;IAGrC,MAAM,CAAC,GAAG,IAAI,aAAa;WAEd,KAAK;IAElB,OAAO;IAED,IAAI,CAAC,EAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAC,EAAE,aAAa,CAAC,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAexE,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAKvE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;CAgB5E"}
1
+ {"version":3,"file":"SampleStorage.d.ts","sourceRoot":"","sources":["../../src/samples/SampleStorage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkC,IAAI,EAAC,MAAM,kBAAkB,CAAA;AACtE,OAAO,EAAC,KAAK,EAAc,MAAM,qBAAqB,CAAA;AACtD,OAAO,EAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAC,MAAM,0BAA0B,CAAA;AAG1E,OAAO,EAAC,OAAO,EAAC,MAAM,YAAY,CAAA;AAElC,yBAAiB,aAAa,CAAC;IAC3B,KAAY,SAAS,GAAG;QACpB,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC;QACjB,KAAK,EAAE,SAAS,CAAC;QACjB,KAAK,EAAE,WAAW,CAAC;QACnB,IAAI,EAAE,cAAc,CAAA;KACvB,CAAA;CACJ;AAED,qBAAa,aAAc,SAAQ,OAAO,CAAC,MAAM,EAAE,cAAc,EAAE,aAAa,CAAC,SAAS,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;IAC3H,MAAM,CAAC,QAAQ,CAAC,MAAM,gBAAe;IAGrC,MAAM,CAAC,GAAG,IAAI,aAAa;WAEd,eAAe;IAE5B,OAAO;IAED,IAAI,CAAC,EAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAC,EAAE,aAAa,CAAC,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAexE,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAKvE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;CAgB5E"}
@@ -15,7 +15,7 @@ import { Storage } from "../Storage";
15
15
  export class SampleStorage extends Storage {
16
16
  static Folder = "samples/v2";
17
17
  static get() { return new SampleStorage(); }
18
- static async clean() { Workers.Opfs.delete("samples/v1").catch(EmptyExec); }
18
+ static async cleanDeprecated() { Workers.Opfs.delete("samples/v1").catch(EmptyExec); }
19
19
  constructor() { super(SampleStorage.Folder); }
20
20
  async save({ uuid, audio, peaks, meta }) {
21
21
  const path = `${this.folder}/${UUID.toString(uuid)}`;
@@ -1,11 +1,12 @@
1
1
  import { Observer, Option, Subscription, UUID } from "@opendaw/lib-std";
2
2
  import { SoundfontLoader, SoundfontLoaderState, SoundfontMetaData } from "@opendaw/studio-adapters";
3
3
  import { DefaultSoundfontLoaderManager } from "./DefaultSoundfontLoaderManager";
4
- import { SoundFont2 } from "soundfont2";
4
+ import type { SoundFont2 } from "soundfont2";
5
5
  export declare class DefaultSoundfontLoader implements SoundfontLoader {
6
6
  #private;
7
7
  constructor(manager: DefaultSoundfontLoaderManager, uuid: UUID.Bytes);
8
8
  subscribe(observer: Observer<SoundfontLoaderState>): Subscription;
9
+ invalidate(): void;
9
10
  get uuid(): UUID.Bytes;
10
11
  get soundfont(): Option<SoundFont2>;
11
12
  get meta(): Option<SoundfontMetaData>;
@@ -1 +1 @@
1
- {"version":3,"file":"DefaultSoundfontLoader.d.ts","sourceRoot":"","sources":["../../src/soundfont/DefaultSoundfontLoader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,QAAQ,EAAE,MAAM,EAAY,YAAY,EAAc,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAErG,OAAO,EAAC,eAAe,EAAE,oBAAoB,EAAE,iBAAiB,EAAC,MAAM,0BAA0B,CAAA;AACjG,OAAO,EAAC,6BAA6B,EAAC,MAAM,iCAAiC,CAAA;AAE7E,OAAO,EAAC,UAAU,EAAC,MAAM,YAAY,CAAA;AAErC,qBAAa,sBAAuB,YAAW,eAAe;;gBAU9C,OAAO,EAAE,6BAA6B,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK;IAQpE,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,oBAAoB,CAAC,GAAG,YAAY;IAQjE,IAAI,IAAI,IAAI,IAAI,CAAC,KAAK,CAAoB;IAC1C,IAAI,SAAS,IAAI,MAAM,CAAC,UAAU,CAAC,CAAyB;IAC5D,IAAI,IAAI,IAAI,MAAM,CAAC,iBAAiB,CAAC,CAAoB;IACzD,IAAI,KAAK,IAAI,oBAAoB,CAAqB;IAEtD,QAAQ,IAAI,MAAM;CA0CrB"}
1
+ {"version":3,"file":"DefaultSoundfontLoader.d.ts","sourceRoot":"","sources":["../../src/soundfont/DefaultSoundfontLoader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,QAAQ,EAAE,MAAM,EAAY,YAAY,EAAc,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAErG,OAAO,EAAC,eAAe,EAAE,oBAAoB,EAAE,iBAAiB,EAAC,MAAM,0BAA0B,CAAA;AACjG,OAAO,EAAC,6BAA6B,EAAC,MAAM,iCAAiC,CAAA;AAE7E,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,YAAY,CAAA;AAE1C,qBAAa,sBAAuB,YAAW,eAAe;;gBAY9C,OAAO,EAAE,6BAA6B,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK;IAQpE,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,oBAAoB,CAAC,GAAG,YAAY;IAQjE,UAAU,IAAI,IAAI;IAOlB,IAAI,IAAI,IAAI,IAAI,CAAC,KAAK,CAAoB;IAC1C,IAAI,SAAS,IAAI,MAAM,CAAC,UAAU,CAAC,CAAyB;IAC5D,IAAI,IAAI,IAAI,MAAM,CAAC,iBAAiB,CAAC,CAAoB;IACzD,IAAI,KAAK,IAAI,oBAAoB,CAAqB;IAEtD,QAAQ,IAAI,MAAM;CA+CrB"}
@@ -1,11 +1,11 @@
1
1
  import { Notifier, Option, Terminable, UUID } from "@opendaw/lib-std";
2
2
  import { Promises } from "@opendaw/lib-runtime";
3
3
  import { SoundfontStorage } from "./SoundfontStorage";
4
- import { SoundFont2 } from "soundfont2";
5
4
  export class DefaultSoundfontLoader {
6
5
  #manager;
7
6
  #uuid;
8
7
  #notifier;
8
+ #soundFont2 = Promises.memoizeAsync(() => import("soundfont2"));
9
9
  #meta = Option.None;
10
10
  #soundfont = Option.None;
11
11
  #state = { type: "progress", progress: 0.0 };
@@ -22,6 +22,12 @@ export class DefaultSoundfontLoader {
22
22
  }
23
23
  return this.#notifier.subscribe(observer);
24
24
  }
25
+ invalidate() {
26
+ this.#state = { type: "progress", progress: 0.0 };
27
+ this.#meta = Option.None;
28
+ this.#soundfont = Option.None;
29
+ this.#get();
30
+ }
25
31
  get uuid() { return this.#uuid; }
26
32
  get soundfont() { return this.#soundfont; }
27
33
  get meta() { return this.#meta; }
@@ -32,8 +38,8 @@ export class DefaultSoundfontLoader {
32
38
  this.#notifier.notify(this.#state);
33
39
  }
34
40
  #get() {
35
- SoundfontStorage.get().load(this.#uuid).then(([file, meta]) => {
36
- this.#soundfont = Option.wrap(new SoundFont2(new Uint8Array(file)));
41
+ SoundfontStorage.get().load(this.#uuid).then(async ([file, meta]) => {
42
+ this.#soundfont = Option.wrap(await this.#createSoundFont2(file));
37
43
  this.#meta = Option.wrap(meta);
38
44
  this.#setState({ type: "loaded" });
39
45
  }, (error) => {
@@ -57,7 +63,7 @@ export class DefaultSoundfontLoader {
57
63
  const [file, meta] = fetchResult.value;
58
64
  const storeResult = await Promises.tryCatch(SoundfontStorage.get().save({ uuid: this.#uuid, file, meta }));
59
65
  if (storeResult.status === "resolved") {
60
- this.#soundfont = Option.wrap(new SoundFont2(new Uint8Array(file)));
66
+ this.#soundfont = Option.wrap(await this.#createSoundFont2(file));
61
67
  this.#meta = Option.wrap(meta);
62
68
  this.#setState({ type: "loaded" });
63
69
  }
@@ -66,4 +72,8 @@ export class DefaultSoundfontLoader {
66
72
  this.#setState({ type: "error", reason: "N/A" });
67
73
  }
68
74
  }
75
+ async #createSoundFont2(buffer) {
76
+ const { SoundFont2 } = await this.#soundFont2();
77
+ return new SoundFont2(new Uint8Array(buffer));
78
+ }
69
79
  }
@@ -1,11 +1,12 @@
1
1
  import { Progress, UUID } from "@opendaw/lib-std";
2
- import { SoundfontProvider } from "./SoundfontProvider";
3
2
  import { SoundfontLoader, SoundfontLoaderManager, SoundfontMetaData } from "@opendaw/studio-adapters";
3
+ import { SoundfontProvider } from "./SoundfontProvider";
4
4
  export declare class DefaultSoundfontLoaderManager implements SoundfontLoaderManager, SoundfontProvider {
5
5
  #private;
6
6
  constructor(provider: SoundfontProvider);
7
7
  fetch(uuid: UUID.Bytes, progress: Progress.Handler): Promise<[ArrayBuffer, SoundfontMetaData]>;
8
8
  remove(uuid: UUID.Bytes): void;
9
9
  getOrCreate(uuid: UUID.Bytes): SoundfontLoader;
10
+ invalidate(uuid: UUID.Bytes): void;
10
11
  }
11
12
  //# sourceMappingURL=DefaultSoundfontLoaderManager.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"DefaultSoundfontLoaderManager.d.ts","sourceRoot":"","sources":["../../src/soundfont/DefaultSoundfontLoaderManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAa,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAE1D,OAAO,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAA;AACrD,OAAO,EAAC,eAAe,EAAE,sBAAsB,EAAE,iBAAiB,EAAC,MAAM,0BAA0B,CAAA;AAGnG,qBAAa,6BAA8B,YAAW,sBAAsB,EAAE,iBAAiB;;gBAI/E,QAAQ,EAAE,iBAAiB;IAKvC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,CAAC,OAAO,GAAG,OAAO,CAAC,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAC;IAI9F,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK;IAEvB,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,eAAe;CAGjD"}
1
+ {"version":3,"file":"DefaultSoundfontLoaderManager.d.ts","sourceRoot":"","sources":["../../src/soundfont/DefaultSoundfontLoaderManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAa,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAC1D,OAAO,EAAC,eAAe,EAAE,sBAAsB,EAAE,iBAAiB,EAAC,MAAM,0BAA0B,CAAA;AAEnG,OAAO,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAA;AAErD,qBAAa,6BAA8B,YAAW,sBAAsB,EAAE,iBAAiB;;gBAI/E,QAAQ,EAAE,iBAAiB;IAKvC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,CAAC,OAAO,GAAG,OAAO,CAAC,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAC;IAI9F,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK;IAEvB,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,eAAe;IAI9C,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK;CAC9B"}
@@ -14,4 +14,5 @@ export class DefaultSoundfontLoaderManager {
14
14
  getOrCreate(uuid) {
15
15
  return this.#loaders.getOrCreate(uuid, uuid => new DefaultSoundfontLoader(this, uuid));
16
16
  }
17
+ invalidate(uuid) { this.#loaders.opt(uuid).ifSome(loader => loader.invalidate()); }
17
18
  }
@@ -1 +1 @@
1
- {"version":3,"file":"OpenSoundfontAPI.d.ts","sourceRoot":"","sources":["../../src/soundfont/OpenSoundfontAPI.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,SAAS,EAAmB,SAAS,EAAE,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAC7F,OAAO,EAAC,SAAS,EAAE,iBAAiB,EAAC,MAAM,0BAA0B,CAAA;AAIrE,qBAAa,gBAAgB;;IACzB,MAAM,CAAC,QAAQ,CAAC,OAAO,2CAA0C;IACjE,MAAM,CAAC,QAAQ,CAAC,QAAQ,8CAA6C;IAGrE,MAAM,CAAC,GAAG,IAAI,gBAAgB;IAU9B,OAAO;IAED,GAAG,IAAI,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;IAExC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC;IAMzC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAC;CA0B1G"}
1
+ {"version":3,"file":"OpenSoundfontAPI.d.ts","sourceRoot":"","sources":["../../src/soundfont/OpenSoundfontAPI.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,SAAS,EAAmB,SAAS,EAAE,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAC7F,OAAO,EAAC,SAAS,EAAE,iBAAiB,EAAC,MAAM,0BAA0B,CAAA;AAKrE,qBAAa,gBAAgB;;IACzB,MAAM,CAAC,QAAQ,CAAC,OAAO,2CAA0C;IACjE,MAAM,CAAC,QAAQ,CAAC,QAAQ,8CAA6C;IAGrE,MAAM,CAAC,GAAG,IAAI,gBAAgB;IAW9B,OAAO;IAED,GAAG,IAAI,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;IAExC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC;IAMzC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,SAAS,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,CAAC,WAAW,EAAE,iBAAiB,CAAC,CAAC;CAyB1G"}