@opendaw/studio-core 0.0.26 → 0.0.27
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/AudioOfflineRenderer.d.ts.map +1 -1
- package/dist/AudioOfflineRenderer.js +7 -3
- package/dist/Engine.d.ts +4 -4
- package/dist/Engine.d.ts.map +1 -1
- package/dist/EngineFacade.d.ts +4 -4
- package/dist/EngineFacade.d.ts.map +1 -1
- package/dist/EngineWorklet.d.ts +4 -4
- package/dist/EngineWorklet.d.ts.map +1 -1
- package/dist/RecordingWorklet.d.ts +1 -1
- package/dist/RecordingWorklet.d.ts.map +1 -1
- package/dist/RecordingWorklet.js +1 -1
- package/dist/WavFile.d.ts +10 -0
- package/dist/WavFile.d.ts.map +1 -0
- package/dist/WavFile.js +94 -0
- package/dist/WorkerAgents.d.ts +1 -1
- package/dist/WorkerAgents.d.ts.map +1 -1
- package/dist/WorkerAgents.js +15 -3
- package/dist/capture/Capture.d.ts +1 -1
- package/dist/capture/Capture.d.ts.map +1 -1
- package/dist/capture/CaptureAudio.js +1 -1
- package/dist/capture/CaptureDevices.d.ts +1 -1
- package/dist/capture/CaptureDevices.d.ts.map +1 -1
- package/dist/capture/CaptureMidi.js +1 -1
- package/dist/clouds/CloudAuthManager.d.ts +10 -0
- package/dist/clouds/CloudAuthManager.d.ts.map +1 -0
- package/dist/clouds/CloudAuthManager.js +195 -0
- package/dist/clouds/CloudBackup.d.ts +8 -0
- package/dist/clouds/CloudBackup.d.ts.map +1 -0
- package/dist/clouds/CloudBackup.js +55 -0
- package/dist/clouds/CloudBackupProjects.d.ts +10 -0
- package/dist/clouds/CloudBackupProjects.d.ts.map +1 -0
- package/dist/clouds/CloudBackupProjects.js +167 -0
- package/dist/clouds/CloudBackupSamples.d.ts +13 -0
- package/dist/clouds/CloudBackupSamples.d.ts.map +1 -0
- package/dist/clouds/CloudBackupSamples.js +129 -0
- package/dist/clouds/CloudHandler.d.ts +9 -0
- package/dist/clouds/CloudHandler.d.ts.map +1 -0
- package/dist/clouds/CloudHandler.js +1 -0
- package/dist/clouds/CloudService.d.ts +2 -0
- package/dist/clouds/CloudService.d.ts.map +1 -0
- package/dist/clouds/CloudService.js +1 -0
- package/dist/clouds/DropboxHandler.d.ts +12 -0
- package/dist/clouds/DropboxHandler.d.ts.map +1 -0
- package/dist/clouds/DropboxHandler.js +83 -0
- package/dist/clouds/GoogleDriveHandler.d.ts +12 -0
- package/dist/clouds/GoogleDriveHandler.d.ts.map +1 -0
- package/dist/clouds/GoogleDriveHandler.js +256 -0
- package/dist/dawproject/DawProject.d.ts +2 -2
- package/dist/dawproject/DawProject.d.ts.map +1 -1
- package/dist/dawproject/DawProjectExporter.js +2 -2
- package/dist/dawproject/DawProjectImport.d.ts +1 -1
- package/dist/dawproject/DawProjectImport.d.ts.map +1 -1
- package/dist/dawproject/DeviceIO.d.ts +1 -1
- package/dist/dawproject/DeviceIO.d.ts.map +1 -1
- package/dist/dawproject/DeviceIO.js +2 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/processors.js +3 -3
- package/dist/processors.js.map +4 -4
- package/dist/project/Project.d.ts +0 -5
- package/dist/project/Project.d.ts.map +1 -1
- package/dist/project/Project.js +4 -9
- package/dist/project/ProjectApi.d.ts +9 -1
- package/dist/project/ProjectApi.d.ts.map +1 -1
- package/dist/project/ProjectApi.js +67 -3
- package/dist/project/ProjectBundle.d.ts +1 -1
- package/dist/project/ProjectBundle.d.ts.map +1 -1
- package/dist/project/ProjectBundle.js +1 -1
- package/dist/project/ProjectPaths.d.ts +4 -4
- package/dist/project/ProjectPaths.d.ts.map +1 -1
- package/dist/project/ProjectProfile.d.ts +2 -2
- package/dist/project/ProjectProfile.d.ts.map +1 -1
- package/dist/project/ProjectSignals.d.ts +6 -0
- package/dist/project/ProjectSignals.d.ts.map +1 -0
- package/dist/project/ProjectSignals.js +4 -0
- package/dist/project/ProjectStorage.d.ts +23 -0
- package/dist/project/ProjectStorage.d.ts.map +1 -0
- package/dist/project/ProjectStorage.js +59 -0
- package/dist/samples/MainThreadSampleLoader.d.ts +2 -2
- package/dist/samples/MainThreadSampleLoader.d.ts.map +1 -1
- package/dist/samples/MainThreadSampleLoader.js +2 -3
- package/dist/samples/MainThreadSampleManager.d.ts +4 -4
- package/dist/samples/MainThreadSampleManager.d.ts.map +1 -1
- package/dist/samples/OpenSampleAPI.d.ts +4 -2
- package/dist/samples/OpenSampleAPI.d.ts.map +1 -1
- package/dist/samples/OpenSampleAPI.js +19 -2
- package/dist/samples/SampleAPI.d.ts +2 -2
- package/dist/samples/SampleAPI.d.ts.map +1 -1
- package/dist/samples/SampleImporter.d.ts +1 -1
- package/dist/samples/SampleImporter.d.ts.map +1 -1
- package/dist/samples/SampleProvider.d.ts +1 -1
- package/dist/samples/SampleProvider.d.ts.map +1 -1
- package/dist/samples/SampleStorage.d.ts +7 -5
- package/dist/samples/SampleStorage.d.ts.map +1 -1
- package/dist/samples/SampleStorage.js +31 -17
- package/dist/workers.js +2 -2
- package/dist/workers.js.map +4 -4
- package/package.json +14 -14
- package/dist/Wav.d.ts +0 -6
- package/dist/Wav.d.ts.map +0 -1
- package/dist/Wav.js +0 -46
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"AudioOfflineRenderer.d.ts","sourceRoot":"","sources":["../src/AudioOfflineRenderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiC,GAAG,EAAE,MAAM,EAAmC,MAAM,kBAAkB,CAAA;AAI9G,OAAO,EAAC,wBAAwB,EAAC,MAAM,0BAA0B,CAAA;AACjE,OAAO,EAAC,OAAO,EAAC,MAAM,mBAAmB,CAAA;AACzC,OAAO,EAAC,WAAW,EAAC,MAAM,uBAAuB,CAAA;AAIjD,yBAAiB,oBAAoB,CAAC;IAC3B,MAAM,KAAK,GAAU,QAAQ,OAAO,EACf,MAAM,WAAW,EACjB,wBAAwB,MAAM,CAAC,wBAAwB,CAAC,EACxD,aAAY,GAAY,KAAG,OAAO,CAAC,IAAI,CA4BlE,CAAA;
|
1
|
+
{"version":3,"file":"AudioOfflineRenderer.d.ts","sourceRoot":"","sources":["../src/AudioOfflineRenderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiC,GAAG,EAAE,MAAM,EAAmC,MAAM,kBAAkB,CAAA;AAI9G,OAAO,EAAC,wBAAwB,EAAC,MAAM,0BAA0B,CAAA;AACjE,OAAO,EAAC,OAAO,EAAC,MAAM,mBAAmB,CAAA;AACzC,OAAO,EAAC,WAAW,EAAC,MAAM,uBAAuB,CAAA;AAIjD,yBAAiB,oBAAoB,CAAC;IAC3B,MAAM,KAAK,GAAU,QAAQ,OAAO,EACf,MAAM,WAAW,EACjB,wBAAwB,MAAM,CAAC,wBAAwB,CAAC,EACxD,aAAY,GAAY,KAAG,OAAO,CAAC,IAAI,CA4BlE,CAAA;CAiDJ"}
|
@@ -3,7 +3,7 @@ import { PPQN } from "@opendaw/lib-dsp";
|
|
3
3
|
import { AnimationFrame, Files } from "@opendaw/lib-dom";
|
4
4
|
import { Promises, Wait } from "@opendaw/lib-runtime";
|
5
5
|
import { ExportStemsConfiguration } from "@opendaw/studio-adapters";
|
6
|
-
import {
|
6
|
+
import { WavFile } from "./WavFile";
|
7
7
|
import { AudioWorklets } from "./AudioWorklets";
|
8
8
|
export var AudioOfflineRenderer;
|
9
9
|
(function (AudioOfflineRenderer) {
|
@@ -48,7 +48,7 @@ export var AudioOfflineRenderer;
|
|
48
48
|
if (!approved) {
|
49
49
|
return;
|
50
50
|
}
|
51
|
-
const wavFile =
|
51
|
+
const wavFile = WavFile.encodeFloats(buffer);
|
52
52
|
const suggestedName = `${meta.name}.wav`;
|
53
53
|
const saveResult = await Promises.tryCatch(Files.save(wavFile, { suggestedName }));
|
54
54
|
if (saveResult.status === "rejected" && !Errors.isAbort(saveResult.error)) {
|
@@ -63,7 +63,11 @@ export var AudioOfflineRenderer;
|
|
63
63
|
for (let stemIndex = 0; stemIndex < numStems; stemIndex++) {
|
64
64
|
const l = buffer.getChannelData(stemIndex * 2);
|
65
65
|
const r = buffer.getChannelData(stemIndex * 2 + 1);
|
66
|
-
const file =
|
66
|
+
const file = WavFile.encodeFloats({
|
67
|
+
channels: [l, r],
|
68
|
+
sampleRate: buffer.sampleRate,
|
69
|
+
numFrames: buffer.length
|
70
|
+
});
|
67
71
|
zip.file(`${trackNames[stemIndex]}.wav`, file, { binary: true });
|
68
72
|
}
|
69
73
|
const arrayBuffer = await zip.generateAsync({
|
package/dist/Engine.d.ts
CHANGED
@@ -14,9 +14,9 @@ export interface Engine extends Terminable {
|
|
14
14
|
panic(): void;
|
15
15
|
noteSignal(signal: NoteSignal): void;
|
16
16
|
subscribeNotes(observer: Observer<NoteSignal>): Subscription;
|
17
|
-
ignoreNoteRegion(uuid: UUID.
|
18
|
-
scheduleClipPlay(clipIds: ReadonlyArray<UUID.
|
19
|
-
scheduleClipStop(trackIds: ReadonlyArray<UUID.
|
17
|
+
ignoreNoteRegion(uuid: UUID.Bytes): void;
|
18
|
+
scheduleClipPlay(clipIds: ReadonlyArray<UUID.Bytes>): void;
|
19
|
+
scheduleClipStop(trackIds: ReadonlyArray<UUID.Bytes>): void;
|
20
20
|
subscribeClipNotification(observer: Observer<ClipNotification>): Subscription;
|
21
21
|
get position(): ObservableValue<ppqn>;
|
22
22
|
get isPlaying(): ObservableValue<boolean>;
|
@@ -26,7 +26,7 @@ export interface Engine extends Terminable {
|
|
26
26
|
get playbackTimestamp(): ObservableValue<ppqn>;
|
27
27
|
get countInBeatsTotal(): ObservableValue<int>;
|
28
28
|
get countInBeatsRemaining(): ObservableValue<number>;
|
29
|
-
get markerState(): ObservableValue<Nullable<[UUID.
|
29
|
+
get markerState(): ObservableValue<Nullable<[UUID.Bytes, int]>>;
|
30
30
|
get project(): Project;
|
31
31
|
}
|
32
32
|
//# sourceMappingURL=Engine.d.ts.map
|
package/dist/Engine.d.ts.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"Engine.d.ts","sourceRoot":"","sources":["../src/Engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,kBAAkB,CAAA;AACrC,OAAO,EAAC,GAAG,EAAE,QAAQ,EAAE,eAAe,EAAE,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,IAAI,EAAC,MAAM,kBAAkB,CAAA;AACzG,OAAO,EAAC,gBAAgB,EAAE,UAAU,EAAC,MAAM,0BAA0B,CAAA;AACrE,OAAO,EAAC,OAAO,EAAC,MAAM,mBAAmB,CAAA;AAEzC,MAAM,WAAW,MAAO,SAAQ,UAAU;IACtC,IAAI,IAAI,IAAI,CAAA;IACZ,IAAI,IAAI,IAAI,CAAA;IACZ,WAAW,CAAC,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAA;IACjC,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;IACtC,aAAa,IAAI,IAAI,CAAA;IACrB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACxB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;IACxC,IAAI,IAAI,IAAI,CAAA;IACZ,KAAK,IAAI,IAAI,CAAA;IACb,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAA;IACpC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,YAAY,CAAA;IAC5D,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,
|
1
|
+
{"version":3,"file":"Engine.d.ts","sourceRoot":"","sources":["../src/Engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,kBAAkB,CAAA;AACrC,OAAO,EAAC,GAAG,EAAE,QAAQ,EAAE,eAAe,EAAE,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,IAAI,EAAC,MAAM,kBAAkB,CAAA;AACzG,OAAO,EAAC,gBAAgB,EAAE,UAAU,EAAC,MAAM,0BAA0B,CAAA;AACrE,OAAO,EAAC,OAAO,EAAC,MAAM,mBAAmB,CAAA;AAEzC,MAAM,WAAW,MAAO,SAAQ,UAAU;IACtC,IAAI,IAAI,IAAI,CAAA;IACZ,IAAI,IAAI,IAAI,CAAA;IACZ,WAAW,CAAC,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAA;IACjC,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;IACtC,aAAa,IAAI,IAAI,CAAA;IACrB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACxB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;IACxC,IAAI,IAAI,IAAI,CAAA;IACZ,KAAK,IAAI,IAAI,CAAA;IACb,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAA;IACpC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,YAAY,CAAA;IAC5D,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAA;IACxC,gBAAgB,CAAC,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAA;IAC1D,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAA;IAC3D,yBAAyB,CAAC,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,YAAY,CAAA;IAE7E,IAAI,QAAQ,IAAI,eAAe,CAAC,IAAI,CAAC,CAAA;IACrC,IAAI,SAAS,IAAI,eAAe,CAAC,OAAO,CAAC,CAAA;IACzC,IAAI,WAAW,IAAI,eAAe,CAAC,OAAO,CAAC,CAAA;IAC3C,IAAI,YAAY,IAAI,eAAe,CAAC,OAAO,CAAC,CAAA;IAC5C,IAAI,gBAAgB,IAAI,eAAe,CAAC,OAAO,CAAC,CAAA;IAChD,IAAI,iBAAiB,IAAI,eAAe,CAAC,IAAI,CAAC,CAAA;IAC9C,IAAI,iBAAiB,IAAI,eAAe,CAAC,GAAG,CAAC,CAAA;IAC7C,IAAI,qBAAqB,IAAI,eAAe,CAAC,MAAM,CAAC,CAAA;IACpD,IAAI,WAAW,IAAI,eAAe,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,CAAA;IAC/D,IAAI,OAAO,IAAI,OAAO,CAAA;CACzB"}
|
package/dist/EngineFacade.d.ts
CHANGED
@@ -23,7 +23,7 @@ export declare class EngineFacade implements Engine {
|
|
23
23
|
get playbackTimestamp(): ObservableValue<ppqn>;
|
24
24
|
get countInBeatsTotal(): ObservableValue<int>;
|
25
25
|
get countInBeatsRemaining(): ObservableValue<int>;
|
26
|
-
get markerState(): DefaultObservableValue<Nullable<[UUID.
|
26
|
+
get markerState(): DefaultObservableValue<Nullable<[UUID.Bytes, int]>>;
|
27
27
|
get project(): Project;
|
28
28
|
isReady(): Promise<void>;
|
29
29
|
queryLoadingComplete(): Promise<boolean>;
|
@@ -31,10 +31,10 @@ export declare class EngineFacade implements Engine {
|
|
31
31
|
sampleRate(): number;
|
32
32
|
subscribeClipNotification(observer: Observer<ClipNotification>): Subscription;
|
33
33
|
subscribeNotes(observer: Observer<NoteSignal>): Subscription;
|
34
|
-
ignoreNoteRegion(uuid: UUID.
|
34
|
+
ignoreNoteRegion(uuid: UUID.Bytes): void;
|
35
35
|
noteSignal(signal: NoteSignal): void;
|
36
|
-
scheduleClipPlay(clipIds: ReadonlyArray<UUID.
|
37
|
-
scheduleClipStop(trackIds: ReadonlyArray<UUID.
|
36
|
+
scheduleClipPlay(clipIds: ReadonlyArray<UUID.Bytes>): void;
|
37
|
+
scheduleClipStop(trackIds: ReadonlyArray<UUID.Bytes>): void;
|
38
38
|
terminate(): void;
|
39
39
|
}
|
40
40
|
//# sourceMappingURL=EngineFacade.d.ts.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"EngineFacade.d.ts","sourceRoot":"","sources":["../src/EngineFacade.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,sBAAsB,EACtB,GAAG,EACH,sBAAsB,EACtB,QAAQ,EACR,eAAe,EACf,QAAQ,EAER,YAAY,EAEZ,IAAI,EACP,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAC,IAAI,EAAC,MAAM,kBAAkB,CAAA;AACrC,OAAO,EAAC,gBAAgB,EAAE,UAAU,EAAC,MAAM,0BAA0B,CAAA;AACrE,OAAO,EAAC,MAAM,EAAC,MAAM,UAAU,CAAA;AAC/B,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAA;AAC7C,OAAO,EAAC,OAAO,EAAC,MAAM,mBAAmB,CAAA;AAEzC,qBAAa,YAAa,YAAW,MAAM;;;IAkBvC,UAAU,CAAC,OAAO,EAAE,aAAa;IAiBjC,aAAa,IAAI,IAAI;IAErB,cAAc,IAAI,IAAI;IAMtB,IAAI,IAAI,IAAI;IACZ,IAAI,CAAC,KAAK,GAAE,OAAe,GAAG,IAAI;IAClC,WAAW,CAAC,QAAQ,EAAE,IAAI,GAAG,IAAI;IACjC,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IACtC,aAAa,IAAI,IAAI;IAErB,IAAI,QAAQ,IAAI,eAAe,CAAC,IAAI,CAAC,CAAwB;IAC7D,IAAI,SAAS,IAAI,eAAe,CAAC,OAAO,CAAC,CAAyB;IAClE,IAAI,WAAW,IAAI,eAAe,CAAC,OAAO,CAAC,CAA2B;IACtE,IAAI,YAAY,IAAI,eAAe,CAAC,OAAO,CAAC,CAA4B;IACxE,IAAI,gBAAgB,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAgC;IACvF,IAAI,iBAAiB,IAAI,eAAe,CAAC,IAAI,CAAC,CAAiC;IAC/E,IAAI,iBAAiB,IAAI,eAAe,CAAC,GAAG,CAAC,CAAiC;IAC9E,IAAI,qBAAqB,IAAI,eAAe,CAAC,GAAG,CAAC,CAAqC;IACtF,IAAI,WAAW,IAAI,sBAAsB,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,
|
1
|
+
{"version":3,"file":"EngineFacade.d.ts","sourceRoot":"","sources":["../src/EngineFacade.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,sBAAsB,EACtB,GAAG,EACH,sBAAsB,EACtB,QAAQ,EACR,eAAe,EACf,QAAQ,EAER,YAAY,EAEZ,IAAI,EACP,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAC,IAAI,EAAC,MAAM,kBAAkB,CAAA;AACrC,OAAO,EAAC,gBAAgB,EAAE,UAAU,EAAC,MAAM,0BAA0B,CAAA;AACrE,OAAO,EAAC,MAAM,EAAC,MAAM,UAAU,CAAA;AAC/B,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAA;AAC7C,OAAO,EAAC,OAAO,EAAC,MAAM,mBAAmB,CAAA;AAEzC,qBAAa,YAAa,YAAW,MAAM;;;IAkBvC,UAAU,CAAC,OAAO,EAAE,aAAa;IAiBjC,aAAa,IAAI,IAAI;IAErB,cAAc,IAAI,IAAI;IAMtB,IAAI,IAAI,IAAI;IACZ,IAAI,CAAC,KAAK,GAAE,OAAe,GAAG,IAAI;IAClC,WAAW,CAAC,QAAQ,EAAE,IAAI,GAAG,IAAI;IACjC,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IACtC,aAAa,IAAI,IAAI;IAErB,IAAI,QAAQ,IAAI,eAAe,CAAC,IAAI,CAAC,CAAwB;IAC7D,IAAI,SAAS,IAAI,eAAe,CAAC,OAAO,CAAC,CAAyB;IAClE,IAAI,WAAW,IAAI,eAAe,CAAC,OAAO,CAAC,CAA2B;IACtE,IAAI,YAAY,IAAI,eAAe,CAAC,OAAO,CAAC,CAA4B;IACxE,IAAI,gBAAgB,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAgC;IACvF,IAAI,iBAAiB,IAAI,eAAe,CAAC,IAAI,CAAC,CAAiC;IAC/E,IAAI,iBAAiB,IAAI,eAAe,CAAC,GAAG,CAAC,CAAiC;IAC9E,IAAI,qBAAqB,IAAI,eAAe,CAAC,GAAG,CAAC,CAAqC;IACtF,IAAI,WAAW,IAAI,sBAAsB,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,CAA2B;IACjG,IAAI,OAAO,IAAI,OAAO,CAAmE;IAEzF,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IACxB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC;IAGxC,KAAK,IAAI,IAAI;IACb,UAAU,IAAI,MAAM;IACpB,yBAAyB,CAAC,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,YAAY;IAG7E,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,YAAY;IAG5D,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI;IAGxC,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAGpC,gBAAgB,CAAC,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI;IAG1D,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI;IAI3D,SAAS,IAAI,IAAI;CAIpB"}
|
package/dist/EngineWorklet.d.ts
CHANGED
@@ -22,15 +22,15 @@ export declare class EngineWorklet extends AudioWorkletNode implements Engine {
|
|
22
22
|
get position(): ObservableValue<ppqn>;
|
23
23
|
get playbackTimestamp(): MutableObservableValue<number>;
|
24
24
|
get metronomeEnabled(): MutableObservableValue<boolean>;
|
25
|
-
get markerState(): ObservableValue<Nullable<[UUID.
|
25
|
+
get markerState(): ObservableValue<Nullable<[UUID.Bytes, int]>>;
|
26
26
|
get project(): Project;
|
27
27
|
isReady(): Promise<void>;
|
28
28
|
queryLoadingComplete(): Promise<boolean>;
|
29
29
|
noteSignal(signal: NoteSignal): void;
|
30
30
|
subscribeNotes(observer: Observer<NoteSignal>): Subscription;
|
31
|
-
ignoreNoteRegion(uuid: UUID.
|
32
|
-
scheduleClipPlay(clipIds: ReadonlyArray<UUID.
|
33
|
-
scheduleClipStop(trackIds: ReadonlyArray<UUID.
|
31
|
+
ignoreNoteRegion(uuid: UUID.Bytes): void;
|
32
|
+
scheduleClipPlay(clipIds: ReadonlyArray<UUID.Bytes>): void;
|
33
|
+
scheduleClipStop(trackIds: ReadonlyArray<UUID.Bytes>): void;
|
34
34
|
subscribeClipNotification(observer: Observer<ClipNotification>): Subscription;
|
35
35
|
terminate(): void;
|
36
36
|
}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"EngineWorklet.d.ts","sourceRoot":"","sources":["../src/EngineWorklet.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,GAAG,EACH,sBAAsB,EAEtB,QAAQ,EACR,eAAe,EACf,QAAQ,EAER,YAAY,EAGZ,IAAI,EACP,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAC,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAIrC,OAAO,EAEH,gBAAgB,EAOhB,wBAAwB,EACxB,UAAU,EACb,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EAAC,OAAO,EAAC,MAAM,mBAAmB,CAAA;AACzC,OAAO,EAAC,MAAM,EAAC,MAAM,UAAU,CAAA;AAE/B,qBAAa,aAAc,SAAQ,gBAAiB,YAAW,MAAM;;IACjE,MAAM,CAAC,EAAE,EAAE,GAAG,CAAQ;IAEtB,QAAQ,CAAC,EAAE,SAAqB;gBAoBpB,OAAO,EAAE,gBAAgB,EACzB,OAAO,EAAE,OAAO,EAChB,mBAAmB,CAAC,EAAE,wBAAwB;IA8F1D,IAAI,IAAI,IAAI;IACZ,IAAI,CAAC,KAAK,GAAE,OAAe,GAAG,IAAI;IAClC,WAAW,CAAC,QAAQ,EAAE,IAAI,GAAG,IAAI;IACjC,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IACtC,aAAa,IAAI,IAAI;IACrB,KAAK,IAAI,IAAI;IAEb,IAAI,SAAS,IAAI,eAAe,CAAC,OAAO,CAAC,CAAyB;IAClE,IAAI,WAAW,IAAI,eAAe,CAAC,OAAO,CAAC,CAA2B;IACtE,IAAI,YAAY,IAAI,eAAe,CAAC,OAAO,CAAC,CAA4B;IACxE,IAAI,iBAAiB,IAAI,eAAe,CAAC,GAAG,CAAC,CAAiC;IAC9E,IAAI,qBAAqB,IAAI,eAAe,CAAC,MAAM,CAAC,CAAqC;IACzF,IAAI,QAAQ,IAAI,eAAe,CAAC,IAAI,CAAC,CAAwB;IAC7D,IAAI,iBAAiB,IAAI,sBAAsB,CAAC,MAAM,CAAC,CAAiC;IACxF,IAAI,gBAAgB,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAgC;IACvF,IAAI,WAAW,IAAI,eAAe,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,
|
1
|
+
{"version":3,"file":"EngineWorklet.d.ts","sourceRoot":"","sources":["../src/EngineWorklet.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,GAAG,EACH,sBAAsB,EAEtB,QAAQ,EACR,eAAe,EACf,QAAQ,EAER,YAAY,EAGZ,IAAI,EACP,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAC,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAIrC,OAAO,EAEH,gBAAgB,EAOhB,wBAAwB,EACxB,UAAU,EACb,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EAAC,OAAO,EAAC,MAAM,mBAAmB,CAAA;AACzC,OAAO,EAAC,MAAM,EAAC,MAAM,UAAU,CAAA;AAE/B,qBAAa,aAAc,SAAQ,gBAAiB,YAAW,MAAM;;IACjE,MAAM,CAAC,EAAE,EAAE,GAAG,CAAQ;IAEtB,QAAQ,CAAC,EAAE,SAAqB;gBAoBpB,OAAO,EAAE,gBAAgB,EACzB,OAAO,EAAE,OAAO,EAChB,mBAAmB,CAAC,EAAE,wBAAwB;IA8F1D,IAAI,IAAI,IAAI;IACZ,IAAI,CAAC,KAAK,GAAE,OAAe,GAAG,IAAI;IAClC,WAAW,CAAC,QAAQ,EAAE,IAAI,GAAG,IAAI;IACjC,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IACtC,aAAa,IAAI,IAAI;IACrB,KAAK,IAAI,IAAI;IAEb,IAAI,SAAS,IAAI,eAAe,CAAC,OAAO,CAAC,CAAyB;IAClE,IAAI,WAAW,IAAI,eAAe,CAAC,OAAO,CAAC,CAA2B;IACtE,IAAI,YAAY,IAAI,eAAe,CAAC,OAAO,CAAC,CAA4B;IACxE,IAAI,iBAAiB,IAAI,eAAe,CAAC,GAAG,CAAC,CAAiC;IAC9E,IAAI,qBAAqB,IAAI,eAAe,CAAC,MAAM,CAAC,CAAqC;IACzF,IAAI,QAAQ,IAAI,eAAe,CAAC,IAAI,CAAC,CAAwB;IAC7D,IAAI,iBAAiB,IAAI,sBAAsB,CAAC,MAAM,CAAC,CAAiC;IACxF,IAAI,gBAAgB,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAgC;IACvF,IAAI,WAAW,IAAI,eAAe,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,CAA2B;IAC1F,IAAI,OAAO,IAAI,OAAO,CAAuB;IAE7C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IACxB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC;IACxC,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IACpC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,YAAY;IAC5D,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI;IACxC,gBAAgB,CAAC,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI;IAI1D,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI;IAG3D,yBAAyB,CAAC,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,YAAY;IAQ7E,SAAS,IAAI,IAAI;CAIpB"}
|
@@ -3,7 +3,7 @@ import { Peaks } from "@opendaw/lib-fusion";
|
|
3
3
|
import { AudioData, RingBuffer, SampleLoader, SampleLoaderState } from "@opendaw/studio-adapters";
|
4
4
|
export declare class RecordingWorklet extends AudioWorkletNode implements Terminable, SampleLoader {
|
5
5
|
#private;
|
6
|
-
readonly uuid: UUID.
|
6
|
+
readonly uuid: UUID.Bytes;
|
7
7
|
constructor(context: BaseAudioContext, config: RingBuffer.Config, outputLatency: number);
|
8
8
|
own<T extends Terminable>(terminable: T): T;
|
9
9
|
limit(count: int): void;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"RecordingWorklet.d.ts","sourceRoot":"","sources":["../src/RecordingWorklet.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,GAAG,EAEH,QAAQ,EACR,MAAM,EAEN,YAAY,EACZ,UAAU,EAEV,IAAI,EACP,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAAC,KAAK,EAAc,MAAM,qBAAqB,CAAA;AACtD,OAAO,EACH,SAAS,EAET,UAAU,EACV,YAAY,EACZ,iBAAiB,EAEpB,MAAM,0BAA0B,CAAA;AAMjC,qBAAa,gBAAiB,SAAQ,gBAAiB,YAAW,UAAU,EAAE,YAAY;;IAGtF,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,
|
1
|
+
{"version":3,"file":"RecordingWorklet.d.ts","sourceRoot":"","sources":["../src/RecordingWorklet.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,GAAG,EAEH,QAAQ,EACR,MAAM,EAEN,YAAY,EACZ,UAAU,EAEV,IAAI,EACP,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAAC,KAAK,EAAc,MAAM,qBAAqB,CAAA;AACtD,OAAO,EACH,SAAS,EAET,UAAU,EACV,YAAY,EACZ,iBAAiB,EAEpB,MAAM,0BAA0B,CAAA;AAMjC,qBAAa,gBAAiB,SAAQ,gBAAiB,YAAW,UAAU,EAAE,YAAY;;IAGtF,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAkB;gBAa/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM;IA2BvF,GAAG,CAAC,CAAC,SAAS,UAAU,EAAE,UAAU,EAAE,CAAC,GAAG,CAAC;IAE3C,KAAK,CAAC,KAAK,EAAE,GAAG,GAAG,IAAI;IAEvB,aAAa,CAAC,KAAK,EAAE,GAAG,GAAG,IAAI;IAE/B,IAAI,cAAc,IAAI,GAAG,CAA6C;IACtE,IAAI,IAAI,IAAI,MAAM,CAAC,SAAS,CAAC,CAAoB;IACjD,IAAI,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,CAA6E;IACvG,IAAI,KAAK,IAAI,iBAAiB,CAAqB;IAEnD,UAAU,IAAI,IAAI;IAElB,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,iBAAiB,CAAC,GAAG,YAAY;IAQ9D,SAAS,IAAI,IAAI;IAMjB,QAAQ,IAAI,MAAM;CAkCrB"}
|
package/dist/RecordingWorklet.js
CHANGED
@@ -89,7 +89,7 @@ export class RecordingWorklet extends AudioWorkletNode {
|
|
89
89
|
const bpm = BPMTools.detect(frames[0], sample_rate);
|
90
90
|
const duration = totalSamples / sample_rate;
|
91
91
|
const meta = { name: "Recording", bpm, sample_rate, duration };
|
92
|
-
await SampleStorage.
|
92
|
+
await SampleStorage.saveSample(this.uuid, audioData, peaks, meta);
|
93
93
|
this.#setState({ type: "loaded" });
|
94
94
|
this.terminate();
|
95
95
|
}
|
@@ -0,0 +1,10 @@
|
|
1
|
+
export declare namespace WavFile {
|
2
|
+
type Audio = {
|
3
|
+
channels: ReadonlyArray<Float32Array>;
|
4
|
+
sampleRate: number;
|
5
|
+
numFrames: number;
|
6
|
+
};
|
7
|
+
const decodeFloats: (buffer: ArrayBuffer) => Audio;
|
8
|
+
const encodeFloats: (audio: Audio | AudioBuffer) => ArrayBuffer;
|
9
|
+
}
|
10
|
+
//# sourceMappingURL=WavFile.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"WavFile.d.ts","sourceRoot":"","sources":["../src/WavFile.ts"],"names":[],"mappings":"AAEA,yBAAiB,OAAO,CAAC;IAMrB,KAAY,KAAK,GAAG;QAChB,QAAQ,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;QACtC,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAA;KACpB,CAAA;IAEM,MAAM,YAAY,GAAI,QAAQ,WAAW,KAAG,KA2ClD,CAAA;IAEM,MAAM,YAAY,GAAI,OAAO,KAAK,GAAG,WAAW,KAAG,WAuCzD,CAAA;CACJ"}
|
package/dist/WavFile.js
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
import { Arrays, panic } from "@opendaw/lib-std";
|
2
|
+
export var WavFile;
|
3
|
+
(function (WavFile) {
|
4
|
+
const MAGIC_RIFF = 0x46464952;
|
5
|
+
const MAGIC_WAVE = 0x45564157;
|
6
|
+
const MAGIC_FMT = 0x20746d66;
|
7
|
+
const MAGIC_DATA = 0x61746164;
|
8
|
+
WavFile.decodeFloats = (buffer) => {
|
9
|
+
const view = new DataView(buffer);
|
10
|
+
if (view.getUint32(0, true) !== MAGIC_RIFF
|
11
|
+
|| view.getUint32(8, true) !== MAGIC_WAVE) {
|
12
|
+
return panic("Not a RIFF/WAVE file");
|
13
|
+
}
|
14
|
+
let fmtOffset = -1;
|
15
|
+
let dataOffset = -1;
|
16
|
+
let dataSize = 0;
|
17
|
+
for (let o = 12; o + 8 <= view.byteLength;) {
|
18
|
+
const id = view.getUint32(o, true);
|
19
|
+
const size = view.getUint32(o + 4, true);
|
20
|
+
const next = o + 8 + ((size + 1) & ~1);
|
21
|
+
if (id === MAGIC_FMT)
|
22
|
+
fmtOffset = o + 8;
|
23
|
+
if (id === MAGIC_DATA) {
|
24
|
+
dataOffset = o + 8;
|
25
|
+
dataSize = size;
|
26
|
+
}
|
27
|
+
o = next;
|
28
|
+
}
|
29
|
+
if (fmtOffset < 0 || dataOffset < 0) {
|
30
|
+
return panic("Missing fmt or data chunk");
|
31
|
+
}
|
32
|
+
const audioFormat = view.getUint16(fmtOffset, true); // 3 = IEEE float
|
33
|
+
const numChannels = view.getUint16(fmtOffset + 2, true);
|
34
|
+
const sampleRate = view.getUint32(fmtOffset + 4, true);
|
35
|
+
const blockAlign = view.getUint16(fmtOffset + 12, true);
|
36
|
+
const bitsPerSample = view.getUint16(fmtOffset + 14, true);
|
37
|
+
if (audioFormat !== 3 || bitsPerSample !== 32) {
|
38
|
+
return panic("Expected 32-bit float WAV (format 3)");
|
39
|
+
}
|
40
|
+
if (blockAlign !== numChannels * 4) {
|
41
|
+
return panic("Invalid block alignment");
|
42
|
+
}
|
43
|
+
const numFrames = Math.floor(dataSize / blockAlign);
|
44
|
+
const interleaved = new Float32Array(buffer, dataOffset, numFrames * numChannels);
|
45
|
+
const channels = Arrays.create(() => new Float32Array(numFrames), numChannels);
|
46
|
+
for (let i = 0, w = 0; i < numFrames; i++) {
|
47
|
+
for (let c = 0; c < numChannels; c++) {
|
48
|
+
channels[c][i] = interleaved[w++];
|
49
|
+
}
|
50
|
+
}
|
51
|
+
return { channels, sampleRate, numFrames };
|
52
|
+
};
|
53
|
+
WavFile.encodeFloats = (audio) => {
|
54
|
+
const bytesPerChannel = Float32Array.BYTES_PER_ELEMENT;
|
55
|
+
const sampleRate = audio.sampleRate;
|
56
|
+
let numFrames;
|
57
|
+
let numberOfChannels;
|
58
|
+
let channels;
|
59
|
+
if (audio instanceof AudioBuffer) {
|
60
|
+
channels = Arrays.create(index => audio.getChannelData(index), audio.numberOfChannels);
|
61
|
+
numFrames = audio.length;
|
62
|
+
numberOfChannels = audio.numberOfChannels;
|
63
|
+
}
|
64
|
+
else {
|
65
|
+
channels = audio.channels;
|
66
|
+
numFrames = audio.numFrames;
|
67
|
+
numberOfChannels = audio.channels.length;
|
68
|
+
}
|
69
|
+
const size = 44 + numFrames * numberOfChannels * bytesPerChannel;
|
70
|
+
const buf = new ArrayBuffer(size);
|
71
|
+
const view = new DataView(buf);
|
72
|
+
view.setUint32(0, MAGIC_RIFF, true);
|
73
|
+
view.setUint32(4, size - 8, true);
|
74
|
+
view.setUint32(8, MAGIC_WAVE, true);
|
75
|
+
view.setUint32(12, MAGIC_FMT, true);
|
76
|
+
view.setUint32(16, 16, true); // chunk length
|
77
|
+
view.setUint16(20, 3, true); // compression
|
78
|
+
view.setUint16(22, numberOfChannels, true);
|
79
|
+
view.setUint32(24, sampleRate, true);
|
80
|
+
view.setUint32(28, sampleRate * numberOfChannels * bytesPerChannel, true);
|
81
|
+
view.setUint16(32, numberOfChannels * bytesPerChannel, true);
|
82
|
+
view.setUint16(34, 8 * bytesPerChannel, true);
|
83
|
+
view.setUint32(36, MAGIC_DATA, true);
|
84
|
+
view.setUint32(40, numberOfChannels * numFrames * bytesPerChannel, true);
|
85
|
+
let w = 44;
|
86
|
+
for (let i = 0; i < numFrames; ++i) {
|
87
|
+
for (let j = 0; j < numberOfChannels; ++j) {
|
88
|
+
view.setFloat32(w, channels[j][i], true);
|
89
|
+
w += bytesPerChannel;
|
90
|
+
}
|
91
|
+
}
|
92
|
+
return view.buffer;
|
93
|
+
};
|
94
|
+
})(WavFile || (WavFile = {}));
|
package/dist/WorkerAgents.d.ts
CHANGED
@@ -2,7 +2,7 @@ import { Option } from "@opendaw/lib-std";
|
|
2
2
|
import type { OpfsProtocol, SamplePeakProtocol } from "@opendaw/lib-fusion";
|
3
3
|
import { Messenger } from "@opendaw/lib-runtime";
|
4
4
|
export declare class WorkerAgents {
|
5
|
-
static install(): void
|
5
|
+
static install(): Promise<void>;
|
6
6
|
static messenger: Option<Messenger>;
|
7
7
|
static get Peak(): SamplePeakProtocol;
|
8
8
|
static get Opfs(): OpfsProtocol;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"WorkerAgents.d.ts","sourceRoot":"","sources":["../src/WorkerAgents.ts"],"names":[],"mappings":"AAAA,OAAO,
|
1
|
+
{"version":3,"file":"WorkerAgents.d.ts","sourceRoot":"","sources":["../src/WorkerAgents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgC,MAAM,EAAY,MAAM,kBAAkB,CAAA;AACjF,OAAO,KAAK,EAAC,YAAY,EAAE,kBAAkB,EAAC,MAAM,qBAAqB,CAAA;AACzE,OAAO,EAAe,SAAS,EAAC,MAAM,sBAAsB,CAAA;AAI5D,qBAAa,YAAY;WACR,OAAO;IAgBpB,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,CAAc;IAGjD,MAAM,KAAK,IAAI,IAAI,kBAAkB,CAapC;IAGD,MAAM,KAAK,IAAI,IAAI,YAAY,CAS9B;CACJ"}
|
package/dist/WorkerAgents.js
CHANGED
@@ -7,12 +7,24 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
7
7
|
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
|
-
import { Lazy, Option } from "@opendaw/lib-std";
|
10
|
+
import { assert, Lazy, Option } from "@opendaw/lib-std";
|
11
11
|
import { Communicator, Messenger } from "@opendaw/lib-runtime";
|
12
12
|
const WorkerUrl = new URL("./workers.js", import.meta.url);
|
13
13
|
export class WorkerAgents {
|
14
|
-
static install() {
|
15
|
-
this.messenger
|
14
|
+
static async install() {
|
15
|
+
assert(this.messenger.isEmpty(), "WorkerAgents are already installed");
|
16
|
+
console.debug("WorkerAgents", WorkerUrl);
|
17
|
+
const message = Messenger.for(new Worker(WorkerUrl, { type: "module" }));
|
18
|
+
this.messenger = Option.wrap(message);
|
19
|
+
const { resolve, promise } = Promise.withResolvers();
|
20
|
+
const subscription = message.channel("initialize").subscribe(data => {
|
21
|
+
if (data === "ready") {
|
22
|
+
console.debug("WorkerAgents ready");
|
23
|
+
resolve();
|
24
|
+
subscription.terminate();
|
25
|
+
}
|
26
|
+
});
|
27
|
+
return promise;
|
16
28
|
}
|
17
29
|
static messenger = Option.None;
|
18
30
|
static get Peak() {
|
@@ -9,7 +9,7 @@ export declare abstract class Capture<BOX extends CaptureBox = CaptureBox> imple
|
|
9
9
|
abstract get deviceLabel(): Option<string>;
|
10
10
|
abstract prepareRecording(): Promise<void>;
|
11
11
|
abstract startRecording(): Terminable;
|
12
|
-
get uuid(): UUID.
|
12
|
+
get uuid(): UUID.Bytes;
|
13
13
|
get manager(): CaptureDevices;
|
14
14
|
get audioUnitBox(): AudioUnitBox;
|
15
15
|
get captureBox(): BOX;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"Capture.d.ts","sourceRoot":"","sources":["../../src/capture/Capture.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,sBAAsB,EACtB,MAAM,EACN,UAAU,EAEV,IAAI,EACP,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAC,YAAY,EAAC,MAAM,uBAAuB,CAAA;AAClD,OAAO,EAAC,UAAU,EAAC,MAAM,0BAA0B,CAAA;AACnD,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAA;AAE/C,8BAAsB,OAAO,CAAC,GAAG,SAAS,UAAU,GAAG,UAAU,CAAE,YAAW,UAAU;;IAUpF,SAAS,aAAa,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,GAAG;IAmB1F,QAAQ,KAAK,KAAK,IAAI,MAAM,CAAA;IAC5B,QAAQ,KAAK,WAAW,IAAI,MAAM,CAAC,MAAM,CAAC,CAAA;IAC1C,QAAQ,CAAC,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IAC1C,QAAQ,CAAC,cAAc,IAAI,UAAU;IAErC,IAAI,IAAI,IAAI,IAAI,CAAC,
|
1
|
+
{"version":3,"file":"Capture.d.ts","sourceRoot":"","sources":["../../src/capture/Capture.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,sBAAsB,EACtB,MAAM,EACN,UAAU,EAEV,IAAI,EACP,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAC,YAAY,EAAC,MAAM,uBAAuB,CAAA;AAClD,OAAO,EAAC,UAAU,EAAC,MAAM,0BAA0B,CAAA;AACnD,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAA;AAE/C,8BAAsB,OAAO,CAAC,GAAG,SAAS,UAAU,GAAG,UAAU,CAAE,YAAW,UAAU;;IAUpF,SAAS,aAAa,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,GAAG;IAmB1F,QAAQ,KAAK,KAAK,IAAI,MAAM,CAAA;IAC5B,QAAQ,KAAK,WAAW,IAAI,MAAM,CAAC,MAAM,CAAC,CAAA;IAC1C,QAAQ,CAAC,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IAC1C,QAAQ,CAAC,cAAc,IAAI,UAAU;IAErC,IAAI,IAAI,IAAI,IAAI,CAAC,KAAK,CAAyC;IAC/D,IAAI,OAAO,IAAI,cAAc,CAAuB;IACpD,IAAI,YAAY,IAAI,YAAY,CAA4B;IAC5D,IAAI,UAAU,IAAI,GAAG,CAA0B;IAC/C,IAAI,KAAK,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAqB;IACjE,IAAI,QAAQ,IAAI,sBAAsB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAwB;IAE9E,GAAG,CAAC,CAAC,SAAS,UAAU,EAAE,UAAU,EAAE,CAAC,GAAG,CAAC;IAC3C,MAAM,CAAC,CAAC,SAAS,UAAU,EAAE,GAAG,WAAW,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,IAAI;IACpE,SAAS,IAAI,IAAI;CACpB"}
|
@@ -11,7 +11,7 @@ export class CaptureAudio extends Capture {
|
|
11
11
|
constructor(manager, audioUnitBox, captureAudioBox) {
|
12
12
|
super(manager, audioUnitBox, captureAudioBox);
|
13
13
|
this.#stream = new MutableObservableOption();
|
14
|
-
this.#streamGenerator = Promises.
|
14
|
+
this.#streamGenerator = Promises.sequentialize(() => this.#updateStream());
|
15
15
|
this.ownAll(captureAudioBox.requestChannels.catchupAndSubscribe(owner => {
|
16
16
|
const channels = owner.getValue();
|
17
17
|
this.#requestChannels = channels === 1 || channels === 2 ? Option.wrap(channels) : Option.None;
|
@@ -5,7 +5,7 @@ export declare class CaptureDevices implements Terminable {
|
|
5
5
|
#private;
|
6
6
|
constructor(project: Project);
|
7
7
|
get project(): Project;
|
8
|
-
get(uuid: UUID.
|
8
|
+
get(uuid: UUID.Bytes): Option<Capture>;
|
9
9
|
setArm(subject: Capture, exclusive: boolean): void;
|
10
10
|
filterArmed(): ReadonlyArray<Capture>;
|
11
11
|
terminate(): void;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"CaptureDevices.d.ts","sourceRoot":"","sources":["../../src/capture/CaptureDevices.ts"],"names":[],"mappings":"AAAA,OAAO,
|
1
|
+
{"version":3,"file":"CaptureDevices.d.ts","sourceRoot":"","sources":["../../src/capture/CaptureDevices.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiC,MAAM,EAA2B,UAAU,EAAE,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAElH,OAAO,EAAC,OAAO,EAAC,MAAM,oBAAoB,CAAA;AAC1C,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAA;AAIjC,qBAAa,cAAe,YAAW,UAAU;;gBAKjC,OAAO,EAAE,OAAO;IAiB5B,IAAI,OAAO,IAAI,OAAO,CAAuB;IAE7C,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC;IAEtC,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,GAAG,IAAI;IAUlD,WAAW,IAAI,aAAa,CAAC,OAAO,CAAC;IAKrC,SAAS,IAAI,IAAI;CAKpB"}
|
@@ -14,7 +14,7 @@ export class CaptureMidi extends Capture {
|
|
14
14
|
#stream = Option.None;
|
15
15
|
constructor(manager, audioUnitBox, captureMidiBox) {
|
16
16
|
super(manager, audioUnitBox, captureMidiBox);
|
17
|
-
this.#streamGenerator = Promises.
|
17
|
+
this.#streamGenerator = Promises.sequentialize(() => this.#updateStream());
|
18
18
|
this.ownAll(captureMidiBox.channel.catchupAndSubscribe(async (owner) => {
|
19
19
|
const channel = owner.getValue();
|
20
20
|
this.#filterChannel = channel >= 0 ? Option.wrap(channel) : Option.None;
|
@@ -0,0 +1,10 @@
|
|
1
|
+
import { CloudHandler } from "./CloudHandler";
|
2
|
+
import { CloudService } from "./CloudService";
|
3
|
+
export declare class CloudAuthManager {
|
4
|
+
#private;
|
5
|
+
static create(): CloudAuthManager;
|
6
|
+
readonly id: number;
|
7
|
+
private constructor();
|
8
|
+
getHandler(service: CloudService): Promise<CloudHandler>;
|
9
|
+
}
|
10
|
+
//# sourceMappingURL=CloudAuthManager.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"CloudAuthManager.d.ts","sourceRoot":"","sources":["../../src/clouds/CloudAuthManager.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAA;AAE3C,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAA;AAE3C,qBAAa,gBAAgB;;IACzB,MAAM,CAAC,MAAM,IAAI,gBAAgB;IAqBjC,QAAQ,CAAC,EAAE,SAAyB;IAIpC,OAAO;IAED,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;CAmLjE"}
|
@@ -0,0 +1,195 @@
|
|
1
|
+
import { asDefined, Errors, isDefined, isNull, Maps, panic, RuntimeNotifier, TimeSpan } from "@opendaw/lib-std";
|
2
|
+
import { Promises } from "@opendaw/lib-runtime";
|
3
|
+
export class CloudAuthManager {
|
4
|
+
static create() { return new CloudAuthManager(); }
|
5
|
+
static async #createCodes() {
|
6
|
+
const array = new Uint8Array(32);
|
7
|
+
crypto.getRandomValues(array);
|
8
|
+
const codeVerifier = btoa(String.fromCharCode(...array))
|
9
|
+
.replace(/\+/g, "-")
|
10
|
+
.replace(/\//g, "_")
|
11
|
+
.replace(/=/g, "");
|
12
|
+
const encoder = new TextEncoder();
|
13
|
+
const data = encoder.encode(codeVerifier);
|
14
|
+
const digest = await crypto.subtle.digest("SHA-256", data);
|
15
|
+
const codeChallenge = btoa(String.fromCharCode(...new Uint8Array(digest)))
|
16
|
+
.replace(/\+/g, "-")
|
17
|
+
.replace(/\//g, "_")
|
18
|
+
.replace(/=/g, "");
|
19
|
+
return { codeVerifier, codeChallenge };
|
20
|
+
}
|
21
|
+
static #ID = 0;
|
22
|
+
id = CloudAuthManager.#ID++;
|
23
|
+
#memoizedHandlers = new Map();
|
24
|
+
constructor() { }
|
25
|
+
async getHandler(service) {
|
26
|
+
const memo = Maps.createIfAbsent(this.#memoizedHandlers, service, service => {
|
27
|
+
switch (service) {
|
28
|
+
case "Dropbox": {
|
29
|
+
return Promises.memoizeAsync(this.#oauthDropbox.bind(this), TimeSpan.hours(1));
|
30
|
+
}
|
31
|
+
case "GoogleDrive": {
|
32
|
+
return Promises.memoizeAsync(this.#oauthGoogle.bind(this), TimeSpan.hours(1));
|
33
|
+
}
|
34
|
+
default:
|
35
|
+
return panic(`Unsupported service: ${service}`);
|
36
|
+
}
|
37
|
+
});
|
38
|
+
const handler = await memo();
|
39
|
+
const { status } = await Promises.tryCatch(handler.alive());
|
40
|
+
if (status === "rejected") {
|
41
|
+
this.#memoizedHandlers.delete(service);
|
42
|
+
return this.getHandler(service);
|
43
|
+
}
|
44
|
+
console.debug(`Handler for '${service}' is alive`);
|
45
|
+
return handler;
|
46
|
+
}
|
47
|
+
async #oauthPkceFlow(config) {
|
48
|
+
const redirectUri = `${location.origin}/auth-callback.html`;
|
49
|
+
const { codeVerifier, codeChallenge } = await CloudAuthManager.#createCodes();
|
50
|
+
const params = new URLSearchParams({
|
51
|
+
client_id: config.clientId,
|
52
|
+
response_type: "code",
|
53
|
+
redirect_uri: redirectUri,
|
54
|
+
scope: config.scope,
|
55
|
+
code_challenge: codeChallenge,
|
56
|
+
code_challenge_method: "S256",
|
57
|
+
...(config.extraAuthParams ?? {})
|
58
|
+
});
|
59
|
+
const authUrl = `${config.authUrlBase}?${params.toString()}`;
|
60
|
+
console.debug("[CloudAuth] Opening auth window:", authUrl);
|
61
|
+
const authWindow = window.open(authUrl, "cloudAuth");
|
62
|
+
if (isNull(authWindow)) {
|
63
|
+
return Errors.warn("Failed to open authentication window. Please check popup blockers.");
|
64
|
+
}
|
65
|
+
const { resolve, reject, promise } = Promise.withResolvers();
|
66
|
+
const channel = new BroadcastChannel("auth-callback");
|
67
|
+
const dialog = RuntimeNotifier.progress({
|
68
|
+
headline: "Cloud Service",
|
69
|
+
message: "Please wait for authentication...",
|
70
|
+
cancel: () => reject("cancelled")
|
71
|
+
});
|
72
|
+
channel.onmessage = async (event) => {
|
73
|
+
const data = asDefined(event.data, "No data");
|
74
|
+
console.debug("[CloudAuth] Received via BroadcastChannel:", this.id, data);
|
75
|
+
if (data.type === "auth-callback" && isDefined(data.code)) {
|
76
|
+
console.debug("[CloudAuth] Processing code from BroadcastChannel...", data.type, data.code);
|
77
|
+
try {
|
78
|
+
const tokenParams = new URLSearchParams({
|
79
|
+
code: data.code,
|
80
|
+
grant_type: "authorization_code",
|
81
|
+
client_id: config.clientId,
|
82
|
+
redirect_uri: redirectUri,
|
83
|
+
code_verifier: codeVerifier,
|
84
|
+
...(config.extraTokenParams ?? {})
|
85
|
+
});
|
86
|
+
const response = await fetch(config.tokenUrl, {
|
87
|
+
method: "POST",
|
88
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
89
|
+
body: tokenParams.toString()
|
90
|
+
});
|
91
|
+
if (!response.ok) {
|
92
|
+
const errorText = await response.text();
|
93
|
+
console.error("[CloudAuth] Token exchange error:", errorText);
|
94
|
+
return panic(`Token exchange failed: ${response.statusText}`);
|
95
|
+
}
|
96
|
+
const dataJson = await response.json();
|
97
|
+
const accessToken = dataJson.access_token;
|
98
|
+
if (!accessToken) {
|
99
|
+
return panic("No access_token in token response");
|
100
|
+
}
|
101
|
+
resolve(await this.#createHandler(config.service, accessToken));
|
102
|
+
}
|
103
|
+
catch (err) {
|
104
|
+
console.debug("[CloudAuth] Token exchange failed:", err);
|
105
|
+
reject(err);
|
106
|
+
}
|
107
|
+
}
|
108
|
+
else if (data.type === "closed") {
|
109
|
+
console.debug("[CloudAuth] Callback window closed");
|
110
|
+
reject(null);
|
111
|
+
}
|
112
|
+
};
|
113
|
+
return promise.finally(() => {
|
114
|
+
console.debug("[CloudAuth] Closing auth window");
|
115
|
+
authWindow.close();
|
116
|
+
dialog.terminate();
|
117
|
+
channel.close();
|
118
|
+
});
|
119
|
+
}
|
120
|
+
async #oauthDropbox() {
|
121
|
+
return this.#oauthPkceFlow({
|
122
|
+
service: "dropbox",
|
123
|
+
clientId: "jtehjzxaxf3bf1l",
|
124
|
+
authUrlBase: "https://www.dropbox.com/oauth2/authorize",
|
125
|
+
tokenUrl: "https://api.dropboxapi.com/oauth2/token",
|
126
|
+
scope: "", // Dropbox scope is optional
|
127
|
+
extraAuthParams: {
|
128
|
+
token_access_type: "offline"
|
129
|
+
}
|
130
|
+
});
|
131
|
+
}
|
132
|
+
async #oauthGoogle() {
|
133
|
+
const clientId = "628747153367-gt1oqcn3trr9l9a7jhigja6l1t3f1oik.apps.googleusercontent.com";
|
134
|
+
const scope = "https://www.googleapis.com/auth/drive.appdata";
|
135
|
+
const redirectUri = `${location.origin}/auth-callback.html`;
|
136
|
+
const params = new URLSearchParams({
|
137
|
+
client_id: clientId,
|
138
|
+
response_type: "token",
|
139
|
+
redirect_uri: redirectUri,
|
140
|
+
scope,
|
141
|
+
include_granted_scopes: "true",
|
142
|
+
prompt: "consent"
|
143
|
+
});
|
144
|
+
const authUrl = `https://accounts.google.com/o/oauth2/v2/auth?${params.toString()}`;
|
145
|
+
console.debug("[CloudAuth] Opening auth window:", authUrl);
|
146
|
+
const authWindow = window.open(authUrl, "cloudAuth");
|
147
|
+
if (isNull(authWindow)) {
|
148
|
+
return Errors.warn("Failed to open authentication window. Please check popup blockers.");
|
149
|
+
}
|
150
|
+
const { resolve, reject, promise } = Promise.withResolvers();
|
151
|
+
const channel = new BroadcastChannel("auth-callback");
|
152
|
+
const dialog = RuntimeNotifier.progress({
|
153
|
+
headline: "Google Drive",
|
154
|
+
message: "Please authorize access to app data...",
|
155
|
+
cancel: () => reject("cancelled")
|
156
|
+
});
|
157
|
+
channel.onmessage = async (event) => {
|
158
|
+
const data = asDefined(event.data, "No data");
|
159
|
+
console.debug("[CloudAuth] Received via BroadcastChannel:", this.id, data);
|
160
|
+
if (data.type === "auth-callback" && isDefined(data.access_token)) {
|
161
|
+
try {
|
162
|
+
const accessToken = data.access_token;
|
163
|
+
resolve(await this.#createHandler("google", accessToken));
|
164
|
+
}
|
165
|
+
catch (err) {
|
166
|
+
reject(err);
|
167
|
+
}
|
168
|
+
}
|
169
|
+
else if (data.type === "closed") {
|
170
|
+
console.debug("[CloudAuth] Callback window closed");
|
171
|
+
reject(null);
|
172
|
+
}
|
173
|
+
};
|
174
|
+
return promise.finally(() => {
|
175
|
+
console.debug("[CloudAuth] Closing auth window");
|
176
|
+
authWindow.close();
|
177
|
+
dialog.terminate();
|
178
|
+
channel.close();
|
179
|
+
});
|
180
|
+
}
|
181
|
+
async #createHandler(service, token) {
|
182
|
+
switch (service) {
|
183
|
+
case "dropbox": {
|
184
|
+
const { DropboxHandler } = await import("./DropboxHandler");
|
185
|
+
return new DropboxHandler(token);
|
186
|
+
}
|
187
|
+
case "google": {
|
188
|
+
const { GoogleDriveHandler } = await import("./GoogleDriveHandler");
|
189
|
+
return new GoogleDriveHandler(token);
|
190
|
+
}
|
191
|
+
default:
|
192
|
+
return panic(`Handler not implemented for service: ${service}`);
|
193
|
+
}
|
194
|
+
}
|
195
|
+
}
|
@@ -0,0 +1,8 @@
|
|
1
|
+
import { CloudHandler } from "./CloudHandler";
|
2
|
+
import { CloudAuthManager } from "./CloudAuthManager";
|
3
|
+
import { CloudService } from "./CloudService";
|
4
|
+
export declare namespace CloudBackup {
|
5
|
+
const backup: (cloudAuthManager: CloudAuthManager, service: CloudService) => Promise<void>;
|
6
|
+
const backupWithHandler: (cloudHandler: CloudHandler, service: CloudService) => Promise<void>;
|
7
|
+
}
|
8
|
+
//# sourceMappingURL=CloudBackup.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"CloudBackup.d.ts","sourceRoot":"","sources":["../../src/clouds/CloudBackup.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAA;AAG3C,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAA;AACnD,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAA;AAG3C,yBAAiB,WAAW,CAAC;IAClB,MAAM,MAAM,GAAU,kBAAkB,gBAAgB,EAAE,SAAS,YAAY,kBA8BrF,CAAA;IAEM,MAAM,iBAAiB,GAAU,cAAc,YAAY,EAAE,SAAS,YAAY,kBAYxF,CAAA;CACJ"}
|