@opendaw/studio-core 0.0.24 → 0.0.26
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.
- package/dist/AudioDevices.js +4 -4
- package/dist/AudioOfflineRenderer.d.ts +8 -0
- package/dist/AudioOfflineRenderer.d.ts.map +1 -0
- package/dist/AudioOfflineRenderer.js +88 -0
- package/dist/AudioWorklets.d.ts +1 -1
- package/dist/AudioWorklets.d.ts.map +1 -1
- package/dist/AudioWorklets.js +3 -2
- package/dist/FilePickerAcceptTypes.d.ts +8 -0
- package/dist/FilePickerAcceptTypes.d.ts.map +1 -0
- package/dist/FilePickerAcceptTypes.js +27 -0
- package/dist/WorkerAgents.d.ts +1 -1
- package/dist/WorkerAgents.d.ts.map +1 -1
- package/dist/WorkerAgents.js +3 -3
- package/dist/capture/CaptureAudio.d.ts.map +1 -1
- package/dist/capture/CaptureAudio.js +9 -4
- package/dist/capture/CaptureMidi.d.ts.map +1 -1
- package/dist/capture/CaptureMidi.js +5 -4
- package/dist/capture/Recording.d.ts.map +1 -1
- package/dist/capture/Recording.js +3 -3
- package/dist/index.d.ts +15 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -8
- package/dist/midi/MIDILearning.d.ts +26 -0
- package/dist/midi/MIDILearning.d.ts.map +1 -0
- package/dist/midi/MIDILearning.js +88 -0
- package/dist/midi/MIDIMessageSubscriber.d.ts +5 -0
- package/dist/midi/MIDIMessageSubscriber.d.ts.map +1 -0
- package/dist/midi/MIDIMessageSubscriber.js +40 -0
- package/dist/{MidiDevices.d.ts → midi/MidiDevices.d.ts} +2 -1
- package/dist/midi/MidiDevices.d.ts.map +1 -0
- package/dist/{MidiDevices.js → midi/MidiDevices.js} +16 -4
- package/dist/processors.js +3 -3
- package/dist/processors.js.map +4 -4
- package/dist/project/Project.d.ts +8 -1
- package/dist/project/Project.d.ts.map +1 -1
- package/dist/project/Project.js +14 -3
- package/dist/project/ProjectBundle.d.ts +1 -1
- package/dist/project/ProjectBundle.d.ts.map +1 -1
- package/dist/project/ProjectBundle.js +9 -11
- package/dist/project/ProjectEnv.d.ts +0 -7
- package/dist/project/ProjectEnv.d.ts.map +1 -1
- package/dist/project/ProjectProfile.js +3 -3
- package/dist/samples/OpenSampleAPI.d.ts +14 -0
- package/dist/samples/OpenSampleAPI.d.ts.map +1 -0
- package/dist/samples/OpenSampleAPI.js +109 -0
- package/dist/samples/SampleAPI.d.ts +10 -0
- package/dist/samples/SampleAPI.d.ts.map +1 -0
- package/dist/samples/SampleAPI.js +1 -0
- package/dist/samples/SampleImporter.d.ts +11 -0
- package/dist/samples/SampleImporter.d.ts.map +1 -0
- package/dist/samples/SampleImporter.js +1 -0
- package/dist/workers.js +2 -2
- package/dist/workers.js.map +4 -4
- package/package.json +14 -14
- package/dist/MidiDevices.d.ts.map +0 -1
@@ -10,6 +10,8 @@ import { CaptureDevices } from "../capture/CaptureDevices";
|
|
10
10
|
import { EngineFacade } from "../EngineFacade";
|
11
11
|
import { EngineWorklet } from "../EngineWorklet";
|
12
12
|
import { AudioWorklets } from "../AudioWorklets";
|
13
|
+
import { MIDILearning } from "../midi/MIDILearning";
|
14
|
+
import { ppqn } from "@opendaw/lib-dsp";
|
13
15
|
export type RestartWorklet = {
|
14
16
|
unload: Procedure<unknown>;
|
15
17
|
load: Procedure<EngineWorklet>;
|
@@ -33,10 +35,11 @@ export declare class Project implements BoxAdaptersContext, Terminable, Terminab
|
|
33
35
|
readonly userEditingManager: UserEditingManager;
|
34
36
|
readonly parameterFieldAdapters: ParameterFieldAdapters;
|
35
37
|
readonly liveStreamReceiver: LiveStreamReceiver;
|
38
|
+
readonly midiLearning: MIDILearning;
|
36
39
|
readonly mixer: Mixer;
|
37
40
|
readonly engine: EngineFacade;
|
38
41
|
private constructor();
|
39
|
-
startAudioWorklet(worklets: AudioWorklets, restart
|
42
|
+
startAudioWorklet(worklets: AudioWorklets, restart?: RestartWorklet): EngineWorklet;
|
40
43
|
startRecording(countIn?: boolean): void;
|
41
44
|
own<T extends Terminable>(terminable: T): T;
|
42
45
|
ownAll<T extends Terminable>(...terminables: Array<T>): void;
|
@@ -51,6 +54,10 @@ export declare class Project implements BoxAdaptersContext, Terminable, Terminab
|
|
51
54
|
get isMainThread(): boolean;
|
52
55
|
get liveStreamBroadcaster(): LiveStreamBroadcaster;
|
53
56
|
get skeleton(): ProjectDecoder.Skeleton;
|
57
|
+
merge(options: {
|
58
|
+
insert: ppqn;
|
59
|
+
}, ...projects: ReadonlyArray<Project>): Promise<Project>;
|
60
|
+
extractIntoNew(): Promise<Project>;
|
54
61
|
toArrayBuffer(): ArrayBufferLike;
|
55
62
|
copy(): Project;
|
56
63
|
terminate(): void;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"Project.d.ts","sourceRoot":"","sources":["../../src/project/Project.ts"],"names":[],"mappings":"AAAA,OAAO,EAIH,SAAS,
|
1
|
+
{"version":3,"file":"Project.d.ts","sourceRoot":"","sources":["../../src/project/Project.ts"],"names":[],"mappings":"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"}
|
package/dist/project/Project.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import { ByteArrayOutput, Option, panic, Terminator, UUID } from "@opendaw/lib-std";
|
1
|
+
import { ByteArrayOutput, Option, panic, safeExecute, Terminator, UUID } from "@opendaw/lib-std";
|
2
2
|
import { BoxGraph, Editing } from "@opendaw/lib-box";
|
3
3
|
import { AudioBusBox, AudioUnitBox, BoxIO, GrooveShuffleBox, RootBox, TimelineBox, UserInterfaceBox } from "@opendaw/studio-boxes";
|
4
4
|
import { BoxAdapters, IconSymbol, ParameterFieldAdapters, ProjectDecoder, RootBoxAdapter, TimelineBoxAdapter, UserEditingManager, VertexSelection } from "@opendaw/studio-adapters";
|
@@ -10,6 +10,7 @@ import { ProjectMigration } from "./ProjectMigration";
|
|
10
10
|
import { CaptureDevices } from "../capture/CaptureDevices";
|
11
11
|
import { EngineFacade } from "../EngineFacade";
|
12
12
|
import { Recording } from "../capture/Recording";
|
13
|
+
import { MIDILearning } from "../midi/MIDILearning";
|
13
14
|
// Main Entry Point for a Project
|
14
15
|
export class Project {
|
15
16
|
static new(env) {
|
@@ -75,6 +76,7 @@ export class Project {
|
|
75
76
|
userEditingManager;
|
76
77
|
parameterFieldAdapters;
|
77
78
|
liveStreamReceiver;
|
79
|
+
midiLearning;
|
78
80
|
mixer;
|
79
81
|
engine = new EngineFacade();
|
80
82
|
constructor(env, boxGraph, { rootBox, userInterfaceBox, masterBusBox, masterAudioUnit, timelineBox }) {
|
@@ -94,6 +96,7 @@ export class Project {
|
|
94
96
|
this.userEditingManager.follow(this.userInterfaceBox);
|
95
97
|
this.selection.switch(this.userInterfaceBox.selection);
|
96
98
|
this.liveStreamReceiver = this.#terminator.own(new LiveStreamReceiver());
|
99
|
+
this.midiLearning = this.#terminator.own(new MIDILearning(this));
|
97
100
|
this.captureDevices = this.#terminator.own(new CaptureDevices(this));
|
98
101
|
this.mixer = new Mixer(this.rootBoxAdapter.audioUnits);
|
99
102
|
console.debug(`Project was created on ${this.rootBoxAdapter.created.toString()}`);
|
@@ -107,9 +110,9 @@ export class Project {
|
|
107
110
|
// we will only accept the first error
|
108
111
|
engine.removeEventListener("error", handler);
|
109
112
|
engine.removeEventListener("processorerror", handler);
|
110
|
-
restart
|
113
|
+
safeExecute(restart?.unload, event);
|
111
114
|
lifecycle.terminate();
|
112
|
-
restart
|
115
|
+
safeExecute(restart?.load, this.startAudioWorklet(worklets, restart));
|
113
116
|
};
|
114
117
|
engine.addEventListener("error", handler);
|
115
118
|
engine.addEventListener("processorerror", handler);
|
@@ -148,6 +151,14 @@ export class Project {
|
|
148
151
|
}
|
149
152
|
};
|
150
153
|
}
|
154
|
+
merge(options, ...projects) {
|
155
|
+
// TODO
|
156
|
+
return Promise.reject("Not implemented");
|
157
|
+
}
|
158
|
+
extractIntoNew( /*Something ;)*/) {
|
159
|
+
// TODO
|
160
|
+
return Promise.reject("Not implemented");
|
161
|
+
}
|
151
162
|
toArrayBuffer() {
|
152
163
|
const output = ByteArrayOutput.create();
|
153
164
|
output.writeInt(ProjectDecoder.MAGIC_HEADER_OPEN);
|
@@ -3,6 +3,6 @@ import { ProjectEnv } from "./ProjectEnv";
|
|
3
3
|
import { ProjectProfile } from "./ProjectProfile";
|
4
4
|
export declare namespace ProjectBundle {
|
5
5
|
const encode: ({ uuid, project, meta, cover }: ProjectProfile, progress: MutableObservableValue<unitValue>) => Promise<ArrayBuffer>;
|
6
|
-
const decode: (env: ProjectEnv, arrayBuffer: ArrayBuffer,
|
6
|
+
const decode: (env: ProjectEnv, arrayBuffer: ArrayBuffer, openProfileUUID?: UUID.Format) => Promise<ProjectProfile>;
|
7
7
|
}
|
8
8
|
//# sourceMappingURL=ProjectBundle.d.ts.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"ProjectBundle.d.ts","sourceRoot":"","sources":["../../src/project/ProjectBundle.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,sBAAsB,EAAiB,SAAS,EAAE,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAInH,OAAO,EAAC,UAAU,EAAC,MAAM,cAAc,CAAA;AAEvC,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAA;AAM/C,yBAAiB,aAAa,CAAC;IACpB,MAAM,MAAM,GAAU,gCAA8B,cAAc,EAC5C,UAAU,sBAAsB,CAAC,SAAS,CAAC,KAAG,OAAO,CAAC,WAAW,CAuB7F,CAAA;IAEM,MAAM,MAAM,GAAU,KAAK,UAAU,EACf,aAAa,WAAW,EACxB,
|
1
|
+
{"version":3,"file":"ProjectBundle.d.ts","sourceRoot":"","sources":["../../src/project/ProjectBundle.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,sBAAsB,EAAiB,SAAS,EAAE,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAInH,OAAO,EAAC,UAAU,EAAC,MAAM,cAAc,CAAA;AAEvC,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAA;AAM/C,yBAAiB,aAAa,CAAC;IACpB,MAAM,MAAM,GAAU,gCAA8B,cAAc,EAC5C,UAAU,sBAAsB,CAAC,SAAS,CAAC,KAAG,OAAO,CAAC,WAAW,CAuB7F,CAAA;IAEM,MAAM,MAAM,GAAU,KAAK,UAAU,EACf,aAAa,WAAW,EACxB,kBAAkB,IAAI,CAAC,MAAM,KAAG,OAAO,CAAC,cAAc,CA0BlF,CAAA;CAyBJ"}
|
@@ -31,35 +31,33 @@ export var ProjectBundle;
|
|
31
31
|
progress.setValue(1.0);
|
32
32
|
return blob.arrayBuffer();
|
33
33
|
};
|
34
|
-
ProjectBundle.decode = async (env, arrayBuffer,
|
34
|
+
ProjectBundle.decode = async (env, arrayBuffer, openProfileUUID) => {
|
35
35
|
const { default: JSZip } = await import("jszip");
|
36
36
|
const zip = await JSZip.loadAsync(arrayBuffer);
|
37
37
|
if (await asDefined(zip.file("version")).async("text") !== "1") {
|
38
38
|
return panic("Unknown bundle version");
|
39
39
|
}
|
40
40
|
const bundleUUID = UUID.validate(await asDefined(zip.file("uuid")).async("uint8array"));
|
41
|
-
console.debug(UUID.toString(bundleUUID),
|
42
|
-
if (isDefined(
|
41
|
+
console.debug(UUID.toString(bundleUUID), openProfileUUID ? UUID.toString(openProfileUUID) : "none");
|
42
|
+
if (isDefined(openProfileUUID) && UUID.equals(openProfileUUID, bundleUUID)) {
|
43
43
|
return panic("Project is already open");
|
44
44
|
}
|
45
45
|
console.debug("loading samples...");
|
46
46
|
const samples = asDefined(zip.folder("samples"), "Could not find samples");
|
47
47
|
const promises = [];
|
48
48
|
samples.forEach((path, file) => {
|
49
|
-
if (
|
50
|
-
|
51
|
-
.async("arraybuffer")
|
52
|
-
.then(arrayBuffer => WorkerAgents.Opfs
|
53
|
-
.write(`${SampleStorage.Folder}/${path}`, new Uint8Array(arrayBuffer))));
|
49
|
+
if (file.dir) {
|
50
|
+
return;
|
54
51
|
}
|
52
|
+
promises.push(file.async("arraybuffer")
|
53
|
+
.then(arrayBuffer => WorkerAgents.Opfs
|
54
|
+
.write(`${SampleStorage.Folder}/${path}`, new Uint8Array(arrayBuffer))));
|
55
55
|
});
|
56
56
|
await Promise.all(promises);
|
57
57
|
const project = Project.load(env, await asDefined(zip.file(ProjectPaths.ProjectFile)).async("arraybuffer"));
|
58
58
|
const meta = JSON.parse(await asDefined(zip.file(ProjectPaths.ProjectMetaFile)).async("text"));
|
59
59
|
const coverFile = zip.file(ProjectPaths.ProjectCoverFile);
|
60
|
-
const cover =
|
61
|
-
? Option.wrap(await coverFile.async("arraybuffer"))
|
62
|
-
: Option.None;
|
60
|
+
const cover = Option.wrap(await coverFile?.async("arraybuffer"));
|
63
61
|
return new ProjectProfile(bundleUUID, project, meta, cover);
|
64
62
|
};
|
65
63
|
const pipeSampleLoaderInto = async (loader, zip) => {
|
@@ -1,15 +1,8 @@
|
|
1
1
|
import { SampleManager } from "@opendaw/studio-adapters";
|
2
2
|
import { AudioWorklets } from "../AudioWorklets";
|
3
3
|
export interface ProjectEnv {
|
4
|
-
dialogs?: ProjectEnv.Dialogs;
|
5
4
|
audioContext: AudioContext;
|
6
5
|
audioWorklets: AudioWorklets;
|
7
6
|
sampleManager: SampleManager;
|
8
7
|
}
|
9
|
-
export declare namespace ProjectEnv {
|
10
|
-
interface Dialogs {
|
11
|
-
info(headline: string, message: string, okText: string): Promise<void>;
|
12
|
-
approve(headline: string, message: string, approveText: string, cancelText: string): Promise<boolean>;
|
13
|
-
}
|
14
|
-
}
|
15
8
|
//# sourceMappingURL=ProjectEnv.d.ts.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"ProjectEnv.d.ts","sourceRoot":"","sources":["../../src/project/ProjectEnv.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,0BAA0B,CAAA;AACtD,OAAO,EAAC,aAAa,EAAC,MAAM,kBAAkB,CAAA;AAE9C,MAAM,WAAW,UAAU;IACvB,
|
1
|
+
{"version":3,"file":"ProjectEnv.d.ts","sourceRoot":"","sources":["../../src/project/ProjectEnv.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,0BAA0B,CAAA;AACtD,OAAO,EAAC,aAAa,EAAC,MAAM,kBAAkB,CAAA;AAE9C,MAAM,WAAW,UAAU;IACvB,YAAY,EAAE,YAAY,CAAA;IAC1B,aAAa,EAAE,aAAa,CAAA;IAC5B,aAAa,EAAE,aAAa,CAAA;CAC/B"}
|
@@ -36,9 +36,9 @@ export class ProjectProfile {
|
|
36
36
|
const uuid = UUID.generate();
|
37
37
|
const project = this.project.copy();
|
38
38
|
const meta = ProjectMeta.copy(this.meta);
|
39
|
-
const
|
40
|
-
await ProjectProfile.#writeFiles(
|
41
|
-
return Option.wrap(
|
39
|
+
const profile = new ProjectProfile(uuid, project, meta, Option.None, true);
|
40
|
+
await ProjectProfile.#writeFiles(profile);
|
41
|
+
return Option.wrap(profile);
|
42
42
|
}
|
43
43
|
else {
|
44
44
|
return ProjectProfile.#writeFiles(this).then(() => {
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import { Procedure, unitValue, UUID } from "@opendaw/lib-std";
|
2
|
+
import { AudioData, Sample, SampleMetaData } from "@opendaw/studio-adapters";
|
3
|
+
import { SampleAPI } from "@opendaw/studio-core";
|
4
|
+
export declare class OpenSampleAPI implements SampleAPI {
|
5
|
+
static readonly ApiRoot = "https://api.opendaw.studio/samples";
|
6
|
+
static readonly FileRoot = "https://assets.opendaw.studio/samples";
|
7
|
+
static fromAudioBuffer(buffer: AudioBuffer): AudioData;
|
8
|
+
all(): Promise<ReadonlyArray<Sample>>;
|
9
|
+
get(uuid: UUID.Format): Promise<Sample>;
|
10
|
+
load(context: AudioContext, uuid: UUID.Format, progress: Procedure<unitValue>): Promise<[AudioData, Sample]>;
|
11
|
+
upload(arrayBuffer: ArrayBuffer, metaData: SampleMetaData): Promise<void>;
|
12
|
+
allowsUpload(): boolean;
|
13
|
+
}
|
14
|
+
//# sourceMappingURL=OpenSampleAPI.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"OpenSampleAPI.d.ts","sourceRoot":"","sources":["../../src/samples/OpenSampleAPI.ts"],"names":[],"mappings":"AAAA,OAAO,EAKH,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;AAY9C,qBAAa,aAAc,YAAW,SAAS;IAC3C,MAAM,CAAC,QAAQ,CAAC,OAAO,wCAAuC;IAC9D,MAAM,CAAC,QAAQ,CAAC,QAAQ,2CAA0C;IAElE,MAAM,CAAC,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,SAAS;IAShD,GAAG,IAAI,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IAKrC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAQvC,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAkC5G,MAAM,CAAC,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAsC/E,YAAY,IAAI,OAAO;CAC1B"}
|
@@ -0,0 +1,109 @@
|
|
1
|
+
import { Arrays, asDefined, DefaultObservableValue, panic, RuntimeNotifier, tryCatch, UUID } from "@opendaw/lib-std";
|
2
|
+
import { network, Promises } from "@opendaw/lib-runtime";
|
3
|
+
const username = "openDAW";
|
4
|
+
const password = "prototype";
|
5
|
+
const base64Credentials = btoa(`${username}:${password}`);
|
6
|
+
const headers = {
|
7
|
+
method: "GET",
|
8
|
+
headers: { "Authorization": `Basic ${base64Credentials}` },
|
9
|
+
credentials: "include"
|
10
|
+
};
|
11
|
+
// Standard openDAW samples
|
12
|
+
export class OpenSampleAPI {
|
13
|
+
static ApiRoot = "https://api.opendaw.studio/samples";
|
14
|
+
static FileRoot = "https://assets.opendaw.studio/samples";
|
15
|
+
static fromAudioBuffer(buffer) {
|
16
|
+
return {
|
17
|
+
frames: Arrays.create(channel => buffer.getChannelData(channel), buffer.numberOfChannels),
|
18
|
+
sampleRate: buffer.sampleRate,
|
19
|
+
numberOfFrames: buffer.length,
|
20
|
+
numberOfChannels: buffer.numberOfChannels
|
21
|
+
};
|
22
|
+
}
|
23
|
+
async all() {
|
24
|
+
return Promises.retry(() => fetch(`${OpenSampleAPI.ApiRoot}/list.php`, headers)
|
25
|
+
.then(x => x.json(), () => []));
|
26
|
+
}
|
27
|
+
async get(uuid) {
|
28
|
+
const url = `${OpenSampleAPI.ApiRoot}/get.php?uuid=${UUID.toString(uuid)}`;
|
29
|
+
const sample = await Promises.retry(() => network.limitFetch(url, headers)
|
30
|
+
.then(x => x.json()))
|
31
|
+
.then(x => { if ("error" in x) {
|
32
|
+
return panic(x.error);
|
33
|
+
}
|
34
|
+
else {
|
35
|
+
return x;
|
36
|
+
} });
|
37
|
+
return Object.freeze({ ...sample, cloud: "cloud:openDAW" });
|
38
|
+
}
|
39
|
+
async load(context, uuid, progress) {
|
40
|
+
console.debug(`load ${UUID.toString(uuid)}`);
|
41
|
+
return this.get(uuid)
|
42
|
+
.then(({ uuid, name, bpm }) => Promises.retry(() => network
|
43
|
+
.limitFetch(`${OpenSampleAPI.FileRoot}/${uuid}`, headers))
|
44
|
+
.then(response => {
|
45
|
+
const total = parseInt(response.headers.get("Content-Length") ?? "0");
|
46
|
+
let loaded = 0;
|
47
|
+
return new Promise((resolve, reject) => {
|
48
|
+
const reader = asDefined(response.body, "No body in response").getReader();
|
49
|
+
const chunks = [];
|
50
|
+
const nextChunk = ({ done, value }) => {
|
51
|
+
if (done) {
|
52
|
+
resolve(new Blob(chunks).arrayBuffer());
|
53
|
+
}
|
54
|
+
else {
|
55
|
+
chunks.push(value);
|
56
|
+
loaded += value.length;
|
57
|
+
progress(loaded / total);
|
58
|
+
reader.read().then(nextChunk, reject);
|
59
|
+
}
|
60
|
+
};
|
61
|
+
reader.read().then(nextChunk, reject);
|
62
|
+
});
|
63
|
+
})
|
64
|
+
.then(arrayBuffer => context.decodeAudioData(arrayBuffer))
|
65
|
+
.then(audioBuffer => ([OpenSampleAPI.fromAudioBuffer(audioBuffer), {
|
66
|
+
uuid,
|
67
|
+
bpm,
|
68
|
+
name,
|
69
|
+
duration: audioBuffer.duration,
|
70
|
+
sample_rate: audioBuffer.sampleRate
|
71
|
+
}])));
|
72
|
+
}
|
73
|
+
async upload(arrayBuffer, metaData) {
|
74
|
+
const progress = new DefaultObservableValue(0.0);
|
75
|
+
const dialog = RuntimeNotifier.progress({ headline: "Uploading", progress });
|
76
|
+
const formData = new FormData();
|
77
|
+
Object.entries(metaData).forEach(([key, value]) => formData.set(key, String(value)));
|
78
|
+
const params = new URLSearchParams(location.search);
|
79
|
+
const accessKey = asDefined(params.get("access-key"), "Cannot upload without access-key.");
|
80
|
+
formData.set("key", accessKey);
|
81
|
+
formData.append("file", new Blob([arrayBuffer]));
|
82
|
+
console.log("upload data", Array.from(formData.entries()), arrayBuffer.byteLength);
|
83
|
+
const xhr = new XMLHttpRequest();
|
84
|
+
xhr.upload.addEventListener("progress", (event) => {
|
85
|
+
if (event.lengthComputable) {
|
86
|
+
progress.setValue(event.loaded / event.total);
|
87
|
+
}
|
88
|
+
});
|
89
|
+
xhr.onreadystatechange = () => {
|
90
|
+
if (xhr.readyState === 4) {
|
91
|
+
dialog.terminate();
|
92
|
+
if (xhr.status === 200) {
|
93
|
+
RuntimeNotifier.info({ message: xhr.responseText });
|
94
|
+
}
|
95
|
+
else {
|
96
|
+
const { status, value } = tryCatch(() => JSON.parse(xhr.responseText).message ?? "Unknown error message");
|
97
|
+
RuntimeNotifier.info({
|
98
|
+
headline: "Upload Failure",
|
99
|
+
message: status === "success" ? value : "Unknown error"
|
100
|
+
});
|
101
|
+
}
|
102
|
+
}
|
103
|
+
};
|
104
|
+
xhr.open("POST", `${OpenSampleAPI.ApiRoot}/upload.php`, true);
|
105
|
+
xhr.setRequestHeader("Authorization", `Basic ${base64Credentials}`);
|
106
|
+
xhr.send(formData);
|
107
|
+
}
|
108
|
+
allowsUpload() { return false; }
|
109
|
+
}
|
@@ -0,0 +1,10 @@
|
|
1
|
+
import { AudioData, Sample, SampleMetaData } from "@opendaw/studio-adapters";
|
2
|
+
import { Procedure, unitValue, UUID } from "@opendaw/lib-std";
|
3
|
+
export interface SampleAPI {
|
4
|
+
all(): Promise<ReadonlyArray<Sample>>;
|
5
|
+
get(uuid: UUID.Format): Promise<Sample>;
|
6
|
+
load(context: AudioContext, uuid: UUID.Format, progress: Procedure<unitValue>): Promise<[AudioData, Sample]>;
|
7
|
+
upload(arrayBuffer: ArrayBuffer, metaData: SampleMetaData): Promise<void>;
|
8
|
+
allowsUpload(): boolean;
|
9
|
+
}
|
10
|
+
//# sourceMappingURL=SampleAPI.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"SampleAPI.d.ts","sourceRoot":"","sources":["../../src/samples/SampleAPI.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAC,MAAM,0BAA0B,CAAA;AAC1E,OAAO,EAAC,SAAS,EAAE,SAAS,EAAE,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAE3D,MAAM,WAAW,SAAS;IACtB,GAAG,IAAI,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAA;IACrC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IACvC,IAAI,CAAC,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC,SAAS,CAAC,GAAG,OAAO,CAAC,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAA;IAC5G,MAAM,CAAC,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACzE,YAAY,IAAI,OAAO,CAAA;CAC1B"}
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1,11 @@
|
|
1
|
+
import { Progress, UUID } from "@opendaw/lib-std";
|
2
|
+
import { Sample } from "@opendaw/studio-adapters";
|
3
|
+
export type SampleImporter = {
|
4
|
+
importSample(sample: {
|
5
|
+
uuid: UUID.Format;
|
6
|
+
name: string;
|
7
|
+
arrayBuffer: ArrayBuffer;
|
8
|
+
progressHandler?: Progress.Handler;
|
9
|
+
}): Promise<Sample>;
|
10
|
+
};
|
11
|
+
//# sourceMappingURL=SampleImporter.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"SampleImporter.d.ts","sourceRoot":"","sources":["../../src/samples/SampleImporter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAE,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAC,MAAM,EAAC,MAAM,0BAA0B,CAAA;AAE/C,MAAM,MAAM,cAAc,GAAG;IACzB,YAAY,CAAC,MAAM,EAAE;QACjB,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,WAAW,CAAC;QACzB,eAAe,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAA;KACrC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;CACtB,CAAA"}
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|