@opendaw/studio-core 0.0.42 → 0.0.44

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 (46) hide show
  1. package/dist/AssetService.d.ts +28 -0
  2. package/dist/AssetService.d.ts.map +1 -0
  3. package/dist/AssetService.js +94 -0
  4. package/dist/EngineWorklet.d.ts +1 -1
  5. package/dist/EngineWorklet.d.ts.map +1 -1
  6. package/dist/capture/CaptureDevices.js +1 -1
  7. package/dist/cloud/CloudAuthManager.d.ts +6 -2
  8. package/dist/cloud/CloudAuthManager.d.ts.map +1 -1
  9. package/dist/cloud/CloudAuthManager.js +12 -11
  10. package/dist/cloud/CloudBackup.js +1 -1
  11. package/dist/cloud/{CloudBackupSoundfont.d.ts → CloudBackupSoundfonts.d.ts} +1 -1
  12. package/dist/cloud/CloudBackupSoundfonts.d.ts.map +1 -0
  13. package/dist/cloud/{CloudBackupSoundfont.js → CloudBackupSoundfonts.js} +1 -1
  14. package/dist/dawproject/DawProjectService.js +1 -1
  15. package/dist/processors.js +27 -5
  16. package/dist/processors.js.map +4 -4
  17. package/dist/project/Project.d.ts +2 -2
  18. package/dist/project/Project.d.ts.map +1 -1
  19. package/dist/project/Project.js +2 -3
  20. package/dist/samples/OpenSampleAPI.d.ts.map +1 -1
  21. package/dist/samples/OpenSampleAPI.js +5 -3
  22. package/dist/samples/SampleService.d.ts +10 -13
  23. package/dist/samples/SampleService.d.ts.map +1 -1
  24. package/dist/samples/SampleService.js +20 -43
  25. package/dist/samples/SampleStorage.d.ts +1 -1
  26. package/dist/samples/SampleStorage.d.ts.map +1 -1
  27. package/dist/samples/SampleStorage.js +1 -1
  28. package/dist/soundfont/DefaultSoundfontLoader.d.ts +2 -1
  29. package/dist/soundfont/DefaultSoundfontLoader.d.ts.map +1 -1
  30. package/dist/soundfont/DefaultSoundfontLoader.js +14 -4
  31. package/dist/soundfont/DefaultSoundfontLoaderManager.d.ts +2 -1
  32. package/dist/soundfont/DefaultSoundfontLoaderManager.d.ts.map +1 -1
  33. package/dist/soundfont/DefaultSoundfontLoaderManager.js +1 -0
  34. package/dist/soundfont/OpenSoundfontAPI.d.ts.map +1 -1
  35. package/dist/soundfont/OpenSoundfontAPI.js +6 -4
  36. package/dist/soundfont/SoundfontService.d.ts +10 -13
  37. package/dist/soundfont/SoundfontService.d.ts.map +1 -1
  38. package/dist/soundfont/SoundfontService.js +33 -52
  39. package/dist/workers-main.js +2 -2
  40. package/dist/workers-main.js.map +3 -3
  41. package/dist/ysync/YService.d.ts.map +1 -1
  42. package/dist/ysync/YService.js +4 -3
  43. package/dist/ysync/YSync.d.ts.map +1 -1
  44. package/dist/ysync/YSync.js +79 -51
  45. package/package.json +17 -16
  46. package/dist/cloud/CloudBackupSoundfont.d.ts.map +0 -1
@@ -6,10 +6,10 @@ 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
14
  unload: Procedure<unknown>;
15
15
  load: Procedure<EngineWorklet>;
@@ -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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"}
@@ -7,10 +7,9 @@ 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";
15
14
  // Main Entry Point for a Project
16
15
  export class Project {
@@ -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,18 +1,15 @@
1
- import { Procedure, Progress, UUID } 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
- export declare namespace SampleService {
4
- type ImportArgs = {
5
- uuid?: UUID.Bytes;
6
- name: string;
7
- arrayBuffer: ArrayBuffer;
8
- progressHandler?: Progress.Handler;
9
- };
10
- }
11
- export declare class SampleService {
4
+ import { AssetService } from "../AssetService";
5
+ export declare class SampleService extends AssetService<Sample> {
12
6
  readonly audioContext: AudioContext;
13
- readonly onUpdate: Procedure<Sample>;
7
+ protected readonly namePlural: string;
8
+ protected readonly nameSingular: string;
9
+ protected readonly boxType: Class<Box>;
10
+ protected readonly filePickerOptions: FilePickerOptions;
14
11
  constructor(audioContext: AudioContext, onUpdate: Procedure<Sample>);
15
- browseForSamples(multiple: boolean): Promise<void>;
16
- importSample({ uuid, name, arrayBuffer, progressHandler }: SampleService.ImportArgs): Promise<Sample>;
12
+ importFile({ uuid, name, arrayBuffer, progressHandler }: AssetService.ImportArgs): Promise<Sample>;
13
+ protected collectAllFiles(): Promise<ReadonlyArray<Sample>>;
17
14
  }
18
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,EAKH,SAAS,EACT,QAAQ,EAER,IAAI,EACP,MAAM,kBAAkB,CAAA;AAKzB,OAAO,EAAY,MAAM,EAAiB,MAAM,0BAA0B,CAAA;AAG1E,yBAAiB,aAAa,CAAC;IAC3B,KAAY,UAAU,GAAG;QACrB,IAAI,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,WAAW,CAAC;QACzB,eAAe,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAA;KACrC,CAAA;CACJ;AAED,qBAAa,aAAa;IACV,QAAQ,CAAC,YAAY,EAAE,YAAY;IAAE,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,MAAM,CAAC;gBAAhE,YAAY,EAAE,YAAY,EAAW,QAAQ,EAAE,SAAS,CAAC,MAAM,CAAC;IAE/E,gBAAgB,CAAC,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAiClD,YAAY,CAAC,EAAC,IAAI,EAAE,IAAI,EAAE,WAAW,EAAE,eAAgC,EAAC,EACzD,aAAa,CAAC,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;CAoClE"}
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"}
@@ -1,52 +1,24 @@
1
- import { Arrays, DefaultObservableValue, Errors, panic, Progress, RuntimeNotifier, UUID } from "@opendaw/lib-std";
1
+ import { Arrays, isUndefined, Progress, UUID } from "@opendaw/lib-std";
2
2
  import { estimateBpm } from "@opendaw/lib-dsp";
3
- import { Files } from "@opendaw/lib-dom";
4
3
  import { Promises } from "@opendaw/lib-runtime";
5
4
  import { SamplePeaks } from "@opendaw/lib-fusion";
6
- import { FilePickerAcceptTypes, SampleStorage, Workers } from "../index";
7
- export class SampleService {
5
+ import { AudioFileBox } from "@opendaw/studio-boxes";
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";
11
+ export class SampleService extends AssetService {
8
12
  audioContext;
9
- onUpdate;
13
+ namePlural = "Samples";
14
+ nameSingular = "Sample";
15
+ boxType = AudioFileBox;
16
+ filePickerOptions = FilePickerAcceptTypes.WavFiles;
10
17
  constructor(audioContext, onUpdate) {
18
+ super(onUpdate);
11
19
  this.audioContext = audioContext;
12
- this.onUpdate = onUpdate;
13
20
  }
14
- async browseForSamples(multiple) {
15
- const { error, status, value: files } = await Promises.tryCatch(Files.open({ ...FilePickerAcceptTypes.WavFiles, multiple }));
16
- if (status === "rejected") {
17
- if (Errors.isAbort(error)) {
18
- return;
19
- }
20
- else {
21
- return panic(String(error));
22
- }
23
- }
24
- const progress = new DefaultObservableValue(0.0);
25
- const dialog = RuntimeNotifier.progress({
26
- headline: `Importing ${files.length === 1 ? "Sample" : "Samples"}...`, progress
27
- });
28
- const progressHandler = Progress.split(value => progress.setValue(value), files.length);
29
- const rejected = [];
30
- for (const [index, file] of files.entries()) {
31
- const arrayBuffer = await file.arrayBuffer();
32
- const { status, error } = await Promises.tryCatch(this.importSample({
33
- name: file.name,
34
- arrayBuffer: arrayBuffer,
35
- progressHandler: progressHandler[index]
36
- }));
37
- if (status === "rejected") {
38
- rejected.push(String(error));
39
- }
40
- }
41
- dialog.terminate();
42
- if (rejected.length > 0) {
43
- await RuntimeNotifier.info({
44
- headline: "Sample Import Issues",
45
- message: `${rejected.join(", ")} could not be imported.`
46
- });
47
- }
48
- }
49
- async importSample({ uuid, name, arrayBuffer, progressHandler = Progress.Empty }) {
21
+ async importFile({ uuid, name, arrayBuffer, progressHandler = Progress.Empty }) {
50
22
  console.debug(`importSample '${name}' (${arrayBuffer.byteLength >> 10}kb)`);
51
23
  console.time("UUID.sha256");
52
24
  uuid ??= await UUID.sha256(arrayBuffer); // Must run before decodeAudioData laster, because it will detach the ArrayBuffer
@@ -69,7 +41,7 @@ export class SampleService {
69
41
  const peaks = await Workers.Peak.generateAsync(progressHandler, shifts, audioData.frames, audioData.numberOfFrames, audioData.numberOfChannels);
70
42
  const meta = {
71
43
  bpm: estimateBpm(audioBuffer.duration),
72
- name: name.substring(0, name.lastIndexOf(".")),
44
+ name: isUndefined(name) ? "Unnnamed" : name.substring(0, name.lastIndexOf(".")),
73
45
  duration: audioBuffer.duration,
74
46
  sample_rate: audioBuffer.sampleRate,
75
47
  origin: "import"
@@ -79,4 +51,9 @@ export class SampleService {
79
51
  this.onUpdate(sample);
80
52
  return sample;
81
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
+ }
82
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"}
@@ -8,18 +8,21 @@ var __metadata = (this && this.__metadata) || function (k, v) {
8
8
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
9
  };
10
10
  import { asDefined, Lazy, RuntimeNotifier, UUID } from "@opendaw/lib-std";
11
+ import { Soundfont } from "@opendaw/studio-adapters";
11
12
  import { OpenDAWHeaders } from "../OpenDAWHeaders";
12
13
  import { Promises } from "@opendaw/lib-runtime";
14
+ import { z } from "zod";
13
15
  export class OpenSoundfontAPI {
14
16
  static ApiRoot = "https://api.opendaw.studio/soundfonts";
15
17
  static FileRoot = "https://assets.opendaw.studio/soundfonts";
16
18
  static get() { return new OpenSoundfontAPI(); }
17
- #memoized = Promises.memoizeAsync(() => Promises.retry(() => fetch(`${OpenSoundfontAPI.ApiRoot}/list.json`, OpenDAWHeaders)
19
+ #memoized = Promises.memoizeAsync(() => Promises.guardedRetry(() => fetch(`${OpenSoundfontAPI.ApiRoot}/list.json`, OpenDAWHeaders)
18
20
  .then(x => x.json())
21
+ .then(x => z.array(Soundfont).parse(x))
19
22
  .catch(reason => RuntimeNotifier.info({
20
23
  headline: "OpenSoundfont API",
21
24
  message: `Could not connect to OpenSoundfont API\nReason: '${reason}'`
22
- }).then(() => []))));
25
+ }).then(() => [])), (_error, count) => count < 10));
23
26
  constructor() { }
24
27
  async all() { return this.#memoized(); }
25
28
  async get(uuid) {
@@ -32,7 +35,6 @@ export class OpenSoundfontAPI {
32
35
  const url = `${OpenSoundfontAPI.FileRoot}/${soundfont.uuid}`;
33
36
  return fetch(url, OpenDAWHeaders)
34
37
  .then(response => {
35
- const total = parseInt(response.headers.get("Content-Length") ?? "0");
36
38
  let loaded = 0;
37
39
  return new Promise((resolve, reject) => {
38
40
  const reader = asDefined(response.body, "No body in response").getReader();
@@ -44,7 +46,7 @@ export class OpenSoundfontAPI {
44
46
  else {
45
47
  chunks.push(value);
46
48
  loaded += value.length;
47
- progress(loaded / total);
49
+ progress(loaded / soundfont.size);
48
50
  reader.read().then(nextChunk, reject);
49
51
  }
50
52
  };
@@ -1,20 +1,17 @@
1
- import { Option, Procedure, Progress, UUID } from "@opendaw/lib-std";
1
+ import { Class, Option, Procedure } from "@opendaw/lib-std";
2
+ import { Box } from "@opendaw/lib-box";
2
3
  import { Soundfont } from "@opendaw/studio-adapters";
3
- export declare namespace SoundfontService {
4
- type ImportArgs = {
5
- uuid?: UUID.Bytes;
6
- arrayBuffer: ArrayBuffer;
7
- progressHandler?: Progress.Handler;
8
- };
9
- }
10
- export declare class SoundfontService {
4
+ import { AssetService } from "../AssetService";
5
+ export declare class SoundfontService extends AssetService<Soundfont> {
11
6
  #private;
12
- readonly onUpdate: Procedure<Soundfont>;
7
+ protected readonly namePlural: string;
8
+ protected readonly nameSingular: string;
9
+ protected readonly boxType: Class<Box>;
10
+ protected readonly filePickerOptions: FilePickerOptions;
13
11
  constructor(onUpdate: Procedure<Soundfont>);
14
12
  get local(): Option<ReadonlyArray<Soundfont>>;
15
13
  get remote(): Option<ReadonlyArray<Soundfont>>;
16
- browseForSoundfont(multiple?: boolean): Promise<ReadonlyArray<Soundfont>>;
17
- importSoundfont({ uuid, arrayBuffer }: SoundfontService.ImportArgs): Promise<Soundfont>;
18
- deleteSoundfont(uuid: UUID.Bytes): Promise<void>;
14
+ importFile({ uuid, arrayBuffer }: AssetService.ImportArgs): Promise<Soundfont>;
15
+ protected collectAllFiles(): Promise<ReadonlyArray<Soundfont>>;
19
16
  }
20
17
  //# sourceMappingURL=SoundfontService.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SoundfontService.d.ts","sourceRoot":"","sources":["../../src/soundfont/SoundfontService.ts"],"names":[],"mappings":"AAAA,OAAO,EAIH,MAAM,EAEN,SAAS,EACT,QAAQ,EAER,IAAI,EACP,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EAAC,SAAS,EAAoB,MAAM,0BAA0B,CAAA;AAMrE,yBAAiB,gBAAgB,CAAC;IAC9B,KAAY,UAAU,GAAG;QACrB,IAAI,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC;QAClB,WAAW,EAAE,WAAW,CAAC;QACzB,eAAe,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAA;KACrC,CAAA;CACJ;AAED,qBAAa,gBAAgB;;IAIb,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,SAAS,CAAC;gBAA9B,QAAQ,EAAE,SAAS,CAAC,SAAS,CAAC;IAUnD,IAAI,KAAK,IAAI,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAqB;IAClE,IAAI,MAAM,IAAI,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAsB;IAE9D,kBAAkB,CAAC,QAAQ,GAAE,OAAe,GAAG,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;IA+BhF,eAAe,CAAC,EAAC,IAAI,EAAE,WAAW,EAAC,EAAE,gBAAgB,CAAC,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC;IAiCrF,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;CAGzD"}
1
+ {"version":3,"file":"SoundfontService.d.ts","sourceRoot":"","sources":["../../src/soundfont/SoundfontService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,EAAE,MAAM,EAAS,SAAS,EAAwB,MAAM,kBAAkB,CAAA;AAC/F,OAAO,EAAC,GAAG,EAAC,MAAM,kBAAkB,CAAA;AAGpC,OAAO,EAAC,SAAS,EAAoB,MAAM,0BAA0B,CAAA;AAIrE,OAAO,EAAC,YAAY,EAAC,MAAM,iBAAiB,CAAA;AAG5C,qBAAa,gBAAiB,SAAQ,YAAY,CAAC,SAAS,CAAC;;IACzD,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAe;IACpD,SAAS,CAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAc;IACrD,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,CAAmB;IACzD,SAAS,CAAC,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAAuC;gBAOlF,QAAQ,EAAE,SAAS,CAAC,SAAS,CAAC;IAY1C,IAAI,KAAK,IAAI,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAqB;IAClE,IAAI,MAAM,IAAI,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,CAAsB;IAE9D,UAAU,CAAC,EAAC,IAAI,EAAE,WAAW,EAAC,EAAE,YAAY,CAAC,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC;cA2ClE,eAAe,IAAI,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;CAUvE"}
@@ -1,16 +1,20 @@
1
- import { Arrays, DefaultObservableValue, Errors, Option, panic, Progress, RuntimeNotifier, UUID } from "@opendaw/lib-std";
2
- import { Files } from "@opendaw/lib-dom";
3
- import { Promises } from "@opendaw/lib-runtime";
4
- import { SoundFont2 } from "soundfont2";
1
+ import { Arrays, Option, panic, RuntimeNotifier, UUID } from "@opendaw/lib-std";
2
+ import { Promises, Wait } from "@opendaw/lib-runtime";
3
+ import { SoundfontFileBox } from "@opendaw/studio-boxes";
5
4
  import { SoundfontStorage } from "./SoundfontStorage";
6
5
  import { FilePickerAcceptTypes } from "../FilePickerAcceptTypes";
7
6
  import { OpenSoundfontAPI } from "./OpenSoundfontAPI";
8
- export class SoundfontService {
9
- onUpdate;
7
+ import { AssetService } from "../AssetService";
8
+ export class SoundfontService extends AssetService {
9
+ namePlural = "Soundfonts";
10
+ nameSingular = "Soundfont";
11
+ boxType = SoundfontFileBox;
12
+ filePickerOptions = FilePickerAcceptTypes.SoundfontFiles;
13
+ #soundFont2 = Promises.memoizeAsync(() => import("soundfont2"));
10
14
  #local = Option.None;
11
15
  #remote = Option.None;
12
16
  constructor(onUpdate) {
13
- this.onUpdate = onUpdate;
17
+ super(onUpdate);
14
18
  Promise.all([
15
19
  SoundfontStorage.get().list(),
16
20
  OpenSoundfontAPI.get().all()
@@ -21,78 +25,55 @@ export class SoundfontService {
21
25
  }
22
26
  get local() { return this.#local; }
23
27
  get remote() { return this.#remote; }
24
- async browseForSoundfont(multiple = false) {
25
- const { error, status, value: files } = await Promises.tryCatch(Files.open({ ...FilePickerAcceptTypes.SoundfontFiles, multiple }));
26
- if (status === "rejected") {
27
- if (Errors.isAbort(error)) {
28
- return [];
29
- }
30
- else {
31
- return panic(String(error));
32
- }
33
- }
34
- const progress = new DefaultObservableValue(0.0);
35
- const dialog = RuntimeNotifier.progress({
36
- headline: `Importing ${files.length === 1 ? "Soundfont" : "Soundfonts"}...`, progress
37
- });
38
- const progressHandler = Progress.split(value => progress.setValue(value), files.length);
39
- const soundfonts = [];
40
- const rejected = [];
41
- for (const [index, file] of files.entries()) {
42
- const arrayBuffer = await file.arrayBuffer();
43
- const { status, value, error } = await Promises.tryCatch(this.importSoundfont({
44
- arrayBuffer,
45
- progressHandler: progressHandler[index]
46
- }));
47
- if (status === "rejected") {
48
- rejected.push(String(error));
49
- }
50
- else {
51
- soundfonts.push(value);
52
- }
53
- }
54
- dialog.terminate();
55
- if (rejected.length > 0) {
56
- await RuntimeNotifier.info({
57
- headline: "Soundfont Import Issues",
58
- message: `${rejected.join(", ")} could not be imported.`
59
- });
60
- }
61
- return soundfonts;
62
- }
63
- async importSoundfont({ uuid, arrayBuffer }) {
28
+ async importFile({ uuid, arrayBuffer }) {
64
29
  if (this.#local.isEmpty()) {
65
30
  return panic("Local soundfont storage has not been read.");
66
31
  }
67
32
  if (arrayBuffer.byteLength > (1 << 24)) {
68
33
  await RuntimeNotifier.approve({
69
34
  headline: "Soundfont Import",
70
- message: `The soundfont you are trying to import is ${(arrayBuffer.byteLength >> 20)}mb. This may cause memory issues. Do you want to continue?`,
35
+ message: `The soundfont you are trying to import is ${(arrayBuffer.byteLength >> 20)}mb. This may cause memory issues. Do you really want to continue?`,
71
36
  approveText: "Import",
72
37
  cancelText: "Cancel"
73
38
  });
74
39
  }
40
+ const updater = RuntimeNotifier.progress({ headline: `Import ${this.nameSingular}` });
41
+ await Wait.frame();
75
42
  console.debug(`importSoundfont (${arrayBuffer.byteLength >> 10}kb)`);
76
43
  console.time("UUID.sha256");
77
44
  uuid ??= await UUID.sha256(arrayBuffer);
78
45
  console.timeEnd("UUID.sha256");
79
- const soundFont2 = new SoundFont2(new Uint8Array(arrayBuffer));
46
+ console.time("SoundFont2");
47
+ const { status, value: soundFont2, error } = await Promises.tryCatch(this.#createSoundFont2(arrayBuffer));
48
+ console.timeEnd("SoundFont2");
49
+ if (status === "rejected") {
50
+ updater.terminate();
51
+ return panic(error);
52
+ }
80
53
  const meta = {
81
54
  name: soundFont2.metaData.name,
55
+ size: arrayBuffer.byteLength,
82
56
  url: "unknown",
83
57
  license: soundFont2.metaData.copyright ?? "No license provided",
84
58
  origin: "import"
85
59
  };
86
60
  await SoundfontStorage.get().save({ uuid, file: arrayBuffer, meta });
87
61
  const soundfont = { uuid: UUID.toString(uuid), ...meta };
88
- this.onUpdate(soundfont);
89
62
  const list = this.#local.unwrap();
90
63
  if (!list.some(other => other.uuid === soundfont.uuid)) {
91
64
  list.push(soundfont);
92
65
  }
66
+ this.onUpdate(soundfont);
67
+ updater.terminate();
93
68
  return soundfont;
94
69
  }
95
- async deleteSoundfont(uuid) {
96
- return SoundfontStorage.get().deleteItem(uuid);
70
+ async collectAllFiles() {
71
+ const stock = await OpenSoundfontAPI.get().all();
72
+ const local = await SoundfontStorage.get().list();
73
+ return Arrays.merge(stock, local, (a, b) => a.uuid === b.uuid);
74
+ }
75
+ async #createSoundFont2(buffer) {
76
+ const { SoundFont2 } = await this.#soundFont2();
77
+ return new SoundFont2(new Uint8Array(buffer));
97
78
  }
98
79
  }