@opendaw/studio-core 0.0.36 → 0.0.38
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 +4 -1
- package/dist/AudioWorklets.d.ts +6 -2
- package/dist/AudioWorklets.d.ts.map +1 -1
- package/dist/AudioWorklets.js +2 -2
- package/dist/Engine.d.ts +2 -1
- package/dist/Engine.d.ts.map +1 -1
- package/dist/EngineFacade.d.ts +1 -0
- package/dist/EngineFacade.d.ts.map +1 -1
- package/dist/EngineFacade.js +3 -1
- package/dist/EngineWorklet.d.ts +3 -2
- package/dist/EngineWorklet.d.ts.map +1 -1
- package/dist/EngineWorklet.js +12 -4
- package/dist/FilePickerAcceptTypes.d.ts +1 -0
- package/dist/FilePickerAcceptTypes.d.ts.map +1 -1
- package/dist/FilePickerAcceptTypes.js +4 -0
- package/dist/RecordingWorklet.d.ts.map +1 -1
- package/dist/RecordingWorklet.js +12 -5
- package/dist/capture/CaptureMidi.js +12 -12
- package/dist/capture/RecordAudio.d.ts +2 -2
- package/dist/capture/RecordAudio.d.ts.map +1 -1
- package/dist/clouds/CloudAuthManager.d.ts.map +1 -1
- package/dist/clouds/CloudAuthManager.js +10 -2
- package/dist/clouds/CloudBackup.d.ts +1 -1
- package/dist/clouds/CloudBackup.d.ts.map +1 -1
- package/dist/clouds/CloudBackup.js +41 -1
- package/dist/clouds/CloudBackupSamples.d.ts.map +1 -1
- package/dist/clouds/CloudBackupSamples.js +6 -1
- package/dist/index.d.ts +2 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -7
- package/dist/midi/MIDIMessageSubscriber.js +4 -4
- package/dist/midi/MidiDevices.d.ts +6 -2
- package/dist/midi/MidiDevices.d.ts.map +1 -1
- package/dist/midi/MidiDevices.js +11 -2
- package/dist/midi/SoftwareMIDIInput.d.ts +27 -0
- package/dist/midi/SoftwareMIDIInput.d.ts.map +1 -0
- package/dist/midi/SoftwareMIDIInput.js +42 -0
- package/dist/processors.js +3 -3
- package/dist/processors.js.map +4 -4
- package/dist/project/Project.d.ts +5 -4
- package/dist/project/Project.d.ts.map +1 -1
- package/dist/project/Project.js +21 -5
- package/dist/project/ProjectBundle.d.ts.map +1 -1
- package/dist/project/ProjectBundle.js +1 -1
- package/dist/project/ProjectEnv.d.ts +2 -2
- package/dist/project/ProjectEnv.d.ts.map +1 -1
- package/dist/samples/{MainThreadSampleLoader.d.ts → DefaultSampleLoader.d.ts} +4 -4
- package/dist/samples/DefaultSampleLoader.d.ts.map +1 -0
- package/dist/samples/{MainThreadSampleLoader.js → DefaultSampleLoader.js} +7 -2
- package/dist/samples/{MainThreadSampleManager.d.ts → DefaultSampleLoaderManager.d.ts} +4 -5
- package/dist/samples/DefaultSampleLoaderManager.d.ts.map +1 -0
- package/dist/samples/DefaultSampleLoaderManager.js +19 -0
- package/dist/samples/OpenSampleAPI.d.ts.map +1 -1
- package/dist/samples/OpenSampleAPI.js +3 -2
- package/dist/samples/P2PSampleProvider.d.ts +13 -0
- package/dist/samples/P2PSampleProvider.d.ts.map +1 -0
- package/dist/samples/P2PSampleProvider.js +350 -0
- package/dist/samples/SampleStorage.d.ts +7 -1
- package/dist/samples/SampleStorage.d.ts.map +1 -1
- package/dist/samples/SampleStorage.js +1 -1
- package/dist/samples/index.d.ts +9 -0
- package/dist/samples/index.d.ts.map +1 -0
- package/dist/samples/index.js +8 -0
- package/dist/ui/TimelineRange.d.ts +49 -0
- package/dist/ui/TimelineRange.d.ts.map +1 -0
- package/dist/ui/TimelineRange.js +83 -0
- package/dist/workers-main.js +2 -2
- package/dist/workers-main.js.map +3 -3
- package/package.json +19 -15
- package/dist/samples/MainThreadSampleLoader.d.ts.map +0 -1
- package/dist/samples/MainThreadSampleManager.d.ts.map +0 -1
- package/dist/samples/MainThreadSampleManager.js +0 -22
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"AudioOfflineRenderer.d.ts","sourceRoot":"","sources":["../src/AudioOfflineRenderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiC,GAAG,EAAE,MAAM,EAAmC,MAAM,kBAAkB,CAAA;AAI9G,OAAO,EAAC,wBAAwB,EAAC,MAAM,0BAA0B,CAAA;AACjE,OAAO,EAAC,OAAO,EAAC,MAAM,mBAAmB,CAAA;AACzC,OAAO,EAAC,WAAW,EAAC,MAAM,uBAAuB,CAAA;AAIjD,yBAAiB,oBAAoB,CAAC;IAC3B,MAAM,KAAK,GAAU,QAAQ,OAAO,EACf,MAAM,WAAW,EACjB,wBAAwB,MAAM,CAAC,wBAAwB,CAAC,EACxD,aAAY,GAAY,KAAG,OAAO,CAAC,IAAI,
|
1
|
+
{"version":3,"file":"AudioOfflineRenderer.d.ts","sourceRoot":"","sources":["../src/AudioOfflineRenderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiC,GAAG,EAAE,MAAM,EAAmC,MAAM,kBAAkB,CAAA;AAI9G,OAAO,EAAC,wBAAwB,EAAC,MAAM,0BAA0B,CAAA;AACjE,OAAO,EAAC,OAAO,EAAC,MAAM,mBAAmB,CAAA;AACzC,OAAO,EAAC,WAAW,EAAC,MAAM,uBAAuB,CAAA;AAIjD,yBAAiB,oBAAoB,CAAC;IAC3B,MAAM,KAAK,GAAU,QAAQ,OAAO,EACf,MAAM,WAAW,EACjB,wBAAwB,MAAM,CAAC,wBAAwB,CAAC,EACxD,aAAY,GAAY,KAAG,OAAO,CAAC,IAAI,CA+BlE,CAAA;CAiDJ"}
|
@@ -20,7 +20,10 @@ export var AudioOfflineRenderer;
|
|
20
20
|
const context = new OfflineAudioContext(numStems * 2, numSamples, sampleRate);
|
21
21
|
const durationInSeconds = numSamples / sampleRate;
|
22
22
|
const worklets = await AudioWorklets.createFor(context);
|
23
|
-
const engineWorklet = worklets.createEngine(
|
23
|
+
const engineWorklet = worklets.createEngine({
|
24
|
+
project: project,
|
25
|
+
exportConfiguration: optExportConfiguration.unwrapOrUndefined()
|
26
|
+
});
|
24
27
|
engineWorklet.play();
|
25
28
|
engineWorklet.connect(context.destination);
|
26
29
|
await engineWorklet.isReady();
|
package/dist/AudioWorklets.d.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { int } from "@opendaw/lib-std";
|
2
|
-
import { ExportStemsConfiguration } from "@opendaw/studio-adapters";
|
2
|
+
import { ExportStemsConfiguration, ProcessorOptions } from "@opendaw/studio-adapters";
|
3
3
|
import { Project } from "./project/Project";
|
4
4
|
import { EngineWorklet } from "./EngineWorklet";
|
5
5
|
import { MeterWorklet } from "./MeterWorklet";
|
@@ -12,7 +12,11 @@ export declare class AudioWorklets {
|
|
12
12
|
constructor(context: BaseAudioContext);
|
13
13
|
get context(): BaseAudioContext;
|
14
14
|
createMeter(numberOfChannels: int): MeterWorklet;
|
15
|
-
createEngine(project
|
15
|
+
createEngine({ project, exportConfiguration, options }: {
|
16
|
+
project: Project;
|
17
|
+
exportConfiguration?: ExportStemsConfiguration;
|
18
|
+
options?: ProcessorOptions;
|
19
|
+
}): EngineWorklet;
|
16
20
|
createRecording(numberOfChannels: int, numChunks: int, outputLatency: number): RecordingWorklet;
|
17
21
|
}
|
18
22
|
//# sourceMappingURL=AudioWorklets.d.ts.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"AudioWorklets.d.ts","sourceRoot":"","sources":["../src/AudioWorklets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,GAAG,EAAS,MAAM,kBAAkB,CAAA;AACvD,OAAO,EAAC,wBAAwB,EAAa,MAAM,0BAA0B,CAAA;
|
1
|
+
{"version":3,"file":"AudioWorklets.d.ts","sourceRoot":"","sources":["../src/AudioWorklets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,GAAG,EAAS,MAAM,kBAAkB,CAAA;AACvD,OAAO,EAAC,wBAAwB,EAAE,gBAAgB,EAAa,MAAM,0BAA0B,CAAA;AAC/F,OAAO,EAAC,OAAO,EAAC,MAAM,mBAAmB,CAAA;AACzC,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAA;AAC7C,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAA;AAC3C,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAA;AAGnD,qBAAa,aAAa;;IACtB,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;WAOpB,SAAS,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAAC,aAAa,CAAC;IAQzE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,gBAAgB,GAAG,aAAa;gBAMxC,OAAO,EAAE,gBAAgB;IAErC,IAAI,OAAO,IAAI,gBAAgB,CAAuB;IAEtD,WAAW,CAAC,gBAAgB,EAAE,GAAG,GAAG,YAAY;IAIhD,YAAY,CAAC,EAAC,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAC,EAAE;QAClD,OAAO,EAAE,OAAO,CAAC;QACjB,mBAAmB,CAAC,EAAE,wBAAwB,CAAC;QAC/C,OAAO,CAAC,EAAE,gBAAgB,CAAA;KAC7B,GAAG,aAAa;IAIjB,eAAe,CAAC,gBAAgB,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,GAAG,gBAAgB;CAOlG"}
|
package/dist/AudioWorklets.js
CHANGED
@@ -24,8 +24,8 @@ export class AudioWorklets {
|
|
24
24
|
createMeter(numberOfChannels) {
|
25
25
|
return new MeterWorklet(this.#context, numberOfChannels);
|
26
26
|
}
|
27
|
-
createEngine(project, exportConfiguration) {
|
28
|
-
return new EngineWorklet(this.#context, project, exportConfiguration);
|
27
|
+
createEngine({ project, exportConfiguration, options }) {
|
28
|
+
return new EngineWorklet(this.#context, project, exportConfiguration, options);
|
29
29
|
}
|
30
30
|
createRecording(numberOfChannels, numChunks, outputLatency) {
|
31
31
|
const audioBytes = numberOfChannels * numChunks * RenderQuantum * Float32Array.BYTES_PER_ELEMENT;
|
package/dist/Engine.d.ts
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { ppqn } from "@opendaw/lib-dsp";
|
2
|
-
import { int, Nullable, ObservableValue, Observer, Subscription, Terminable, UUID } from "@opendaw/lib-std";
|
2
|
+
import { int, MutableObservableValue, Nullable, ObservableValue, Observer, Subscription, Terminable, UUID } from "@opendaw/lib-std";
|
3
3
|
import { ClipNotification, NoteSignal } from "@opendaw/studio-adapters";
|
4
4
|
import { Project } from "./project/Project";
|
5
5
|
export interface Engine extends Terminable {
|
@@ -24,6 +24,7 @@ export interface Engine extends Terminable {
|
|
24
24
|
get isCountingIn(): ObservableValue<boolean>;
|
25
25
|
get metronomeEnabled(): ObservableValue<boolean>;
|
26
26
|
get playbackTimestamp(): ObservableValue<ppqn>;
|
27
|
+
get playbackTimestampEnabled(): MutableObservableValue<boolean>;
|
27
28
|
get countInBeatsTotal(): ObservableValue<int>;
|
28
29
|
get countInBeatsRemaining(): ObservableValue<number>;
|
29
30
|
get markerState(): ObservableValue<Nullable<[UUID.Bytes, int]>>;
|
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,
|
1
|
+
{"version":3,"file":"Engine.d.ts","sourceRoot":"","sources":["../src/Engine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAC,MAAM,kBAAkB,CAAA;AACrC,OAAO,EACH,GAAG,EACH,sBAAsB,EACtB,QAAQ,EACR,eAAe,EACf,QAAQ,EACR,YAAY,EACZ,UAAU,EACV,IAAI,EACP,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAC,gBAAgB,EAAE,UAAU,EAAC,MAAM,0BAA0B,CAAA;AACrE,OAAO,EAAC,OAAO,EAAC,MAAM,mBAAmB,CAAA;AAEzC,MAAM,WAAW,MAAO,SAAQ,UAAU;IACtC,IAAI,IAAI,IAAI,CAAA;IACZ,IAAI,IAAI,IAAI,CAAA;IACZ,WAAW,CAAC,QAAQ,EAAE,IAAI,GAAG,IAAI,CAAA;IACjC,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;IACtC,aAAa,IAAI,IAAI,CAAA;IACrB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACxB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;IACxC,IAAI,IAAI,IAAI,CAAA;IACZ,KAAK,IAAI,IAAI,CAAA;IACb,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAAA;IACpC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,YAAY,CAAA;IAC5D,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI,CAAA;IACxC,gBAAgB,CAAC,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAA;IAC1D,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAA;IAC3D,yBAAyB,CAAC,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,YAAY,CAAA;IAE7E,IAAI,QAAQ,IAAI,eAAe,CAAC,IAAI,CAAC,CAAA;IACrC,IAAI,SAAS,IAAI,eAAe,CAAC,OAAO,CAAC,CAAA;IACzC,IAAI,WAAW,IAAI,eAAe,CAAC,OAAO,CAAC,CAAA;IAC3C,IAAI,YAAY,IAAI,eAAe,CAAC,OAAO,CAAC,CAAA;IAC5C,IAAI,gBAAgB,IAAI,eAAe,CAAC,OAAO,CAAC,CAAA;IAChD,IAAI,iBAAiB,IAAI,eAAe,CAAC,IAAI,CAAC,CAAA;IAC9C,IAAI,wBAAwB,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAA;IAC/D,IAAI,iBAAiB,IAAI,eAAe,CAAC,GAAG,CAAC,CAAA;IAC7C,IAAI,qBAAqB,IAAI,eAAe,CAAC,MAAM,CAAC,CAAA;IACpD,IAAI,WAAW,IAAI,eAAe,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,CAAA;IAC/D,IAAI,OAAO,IAAI,OAAO,CAAA;CACzB"}
|
package/dist/EngineFacade.d.ts
CHANGED
@@ -21,6 +21,7 @@ export declare class EngineFacade implements Engine {
|
|
21
21
|
get isCountingIn(): ObservableValue<boolean>;
|
22
22
|
get metronomeEnabled(): MutableObservableValue<boolean>;
|
23
23
|
get playbackTimestamp(): ObservableValue<ppqn>;
|
24
|
+
get playbackTimestampEnabled(): MutableObservableValue<boolean>;
|
24
25
|
get countInBeatsTotal(): ObservableValue<int>;
|
25
26
|
get countInBeatsRemaining(): ObservableValue<int>;
|
26
27
|
get markerState(): DefaultObservableValue<Nullable<[UUID.Bytes, int]>>;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"EngineFacade.d.ts","sourceRoot":"","sources":["../src/EngineFacade.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,sBAAsB,EACtB,GAAG,EACH,sBAAsB,EACtB,QAAQ,EACR,eAAe,EACf,QAAQ,EAER,YAAY,EAEZ,IAAI,EACP,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAC,IAAI,EAAC,MAAM,kBAAkB,CAAA;AACrC,OAAO,EAAC,gBAAgB,EAAE,UAAU,EAAC,MAAM,0BAA0B,CAAA;AACrE,OAAO,EAAC,MAAM,EAAC,MAAM,UAAU,CAAA;AAC/B,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAA;AAC7C,OAAO,EAAC,OAAO,EAAC,MAAM,mBAAmB,CAAA;AAEzC,qBAAa,YAAa,YAAW,MAAM;;;
|
1
|
+
{"version":3,"file":"EngineFacade.d.ts","sourceRoot":"","sources":["../src/EngineFacade.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,sBAAsB,EACtB,GAAG,EACH,sBAAsB,EACtB,QAAQ,EACR,eAAe,EACf,QAAQ,EAER,YAAY,EAEZ,IAAI,EACP,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAC,IAAI,EAAC,MAAM,kBAAkB,CAAA;AACrC,OAAO,EAAC,gBAAgB,EAAE,UAAU,EAAC,MAAM,0BAA0B,CAAA;AACrE,OAAO,EAAC,MAAM,EAAC,MAAM,UAAU,CAAA;AAC/B,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAA;AAC7C,OAAO,EAAC,OAAO,EAAC,MAAM,mBAAmB,CAAA;AAEzC,qBAAa,YAAa,YAAW,MAAM;;;IAmBvC,UAAU,CAAC,OAAO,EAAE,aAAa;IAmBjC,aAAa,IAAI,IAAI;IAErB,cAAc,IAAI,IAAI;IAMtB,IAAI,IAAI,IAAI;IACZ,IAAI,CAAC,KAAK,GAAE,OAAe,GAAG,IAAI;IAClC,WAAW,CAAC,QAAQ,EAAE,IAAI,GAAG,IAAI;IACjC,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IACtC,aAAa,IAAI,IAAI;IAErB,IAAI,QAAQ,IAAI,eAAe,CAAC,IAAI,CAAC,CAAwB;IAC7D,IAAI,SAAS,IAAI,eAAe,CAAC,OAAO,CAAC,CAAyB;IAClE,IAAI,WAAW,IAAI,eAAe,CAAC,OAAO,CAAC,CAA2B;IACtE,IAAI,YAAY,IAAI,eAAe,CAAC,OAAO,CAAC,CAA4B;IACxE,IAAI,gBAAgB,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAgC;IACvF,IAAI,iBAAiB,IAAI,eAAe,CAAC,IAAI,CAAC,CAAiC;IAC/E,IAAI,wBAAwB,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAwC;IACvG,IAAI,iBAAiB,IAAI,eAAe,CAAC,GAAG,CAAC,CAAiC;IAC9E,IAAI,qBAAqB,IAAI,eAAe,CAAC,GAAG,CAAC,CAAqC;IACtF,IAAI,WAAW,IAAI,sBAAsB,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,CAA2B;IACjG,IAAI,OAAO,IAAI,OAAO,CAAmE;IAEzF,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IACxB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC;IAGxC,KAAK,IAAI,IAAI;IACb,UAAU,IAAI,MAAM;IACpB,yBAAyB,CAAC,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,YAAY;IAG7E,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,YAAY;IAG5D,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI;IAGxC,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAGpC,gBAAgB,CAAC,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI;IAG1D,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI;IAI3D,SAAS,IAAI,IAAI;CAIpB"}
|
package/dist/EngineFacade.js
CHANGED
@@ -3,6 +3,7 @@ export class EngineFacade {
|
|
3
3
|
#terminator = new Terminator();
|
4
4
|
#lifecycle = this.#terminator.own(new Terminator());
|
5
5
|
#playbackTimestamp = new DefaultObservableValue(0.0);
|
6
|
+
#playbackTimestampEnabled = new DefaultObservableValue(true);
|
6
7
|
#countInBeatsTotal = new DefaultObservableValue(4);
|
7
8
|
#countInBeatsRemaining = new DefaultObservableValue(0);
|
8
9
|
#position = new DefaultObservableValue(0.0);
|
@@ -16,7 +17,7 @@ export class EngineFacade {
|
|
16
17
|
setWorklet(worklet) {
|
17
18
|
this.#worklet = Option.wrap(worklet);
|
18
19
|
this.#lifecycle.terminate();
|
19
|
-
this.#lifecycle.ownAll(worklet.playbackTimestamp.catchupAndSubscribe(owner => this.#playbackTimestamp.setValue(owner.getValue())), worklet.countInBeatsTotal.catchupAndSubscribe(owner => this.#countInBeatsTotal.setValue(owner.getValue())), worklet.countInBeatsRemaining.catchupAndSubscribe(owner => this.#countInBeatsRemaining.setValue(owner.getValue())), worklet.position.catchupAndSubscribe(owner => this.#position.setValue(owner.getValue())), worklet.isPlaying.catchupAndSubscribe(owner => this.#isPlaying.setValue(owner.getValue())), worklet.isRecording.catchupAndSubscribe(owner => this.#isRecording.setValue(owner.getValue())), worklet.isCountingIn.catchupAndSubscribe(owner => this.#isCountingIn.setValue(owner.getValue())), worklet.metronomeEnabled.catchupAndSubscribe(owner => this.#metronomeEnabled.setValue(owner.getValue())), worklet.markerState.catchupAndSubscribe(owner => this.#markerState.setValue(owner.getValue())), this
|
20
|
+
this.#lifecycle.ownAll(worklet.playbackTimestamp.catchupAndSubscribe(owner => this.#playbackTimestamp.setValue(owner.getValue())), worklet.playbackTimestampEnabled.catchupAndSubscribe(owner => this.#playbackTimestampEnabled.setValue(owner.getValue())), worklet.countInBeatsTotal.catchupAndSubscribe(owner => this.#countInBeatsTotal.setValue(owner.getValue())), worklet.countInBeatsRemaining.catchupAndSubscribe(owner => this.#countInBeatsRemaining.setValue(owner.getValue())), worklet.position.catchupAndSubscribe(owner => this.#position.setValue(owner.getValue())), worklet.isPlaying.catchupAndSubscribe(owner => this.#isPlaying.setValue(owner.getValue())), worklet.isRecording.catchupAndSubscribe(owner => this.#isRecording.setValue(owner.getValue())), worklet.isCountingIn.catchupAndSubscribe(owner => this.#isCountingIn.setValue(owner.getValue())), worklet.metronomeEnabled.catchupAndSubscribe(owner => this.#metronomeEnabled.setValue(owner.getValue())), worklet.markerState.catchupAndSubscribe(owner => this.#markerState.setValue(owner.getValue())), this.#metronomeEnabled.catchupAndSubscribe(owner => worklet.metronomeEnabled.setValue(owner.getValue())), this.#playbackTimestampEnabled.catchupAndSubscribe(owner => worklet.playbackTimestampEnabled.setValue(owner.getValue())));
|
20
21
|
}
|
21
22
|
assertWorklet() { this.#worklet.unwrap("No worklet available"); }
|
22
23
|
releaseWorklet() {
|
@@ -35,6 +36,7 @@ export class EngineFacade {
|
|
35
36
|
get isCountingIn() { return this.#isCountingIn; }
|
36
37
|
get metronomeEnabled() { return this.#metronomeEnabled; }
|
37
38
|
get playbackTimestamp() { return this.#playbackTimestamp; }
|
39
|
+
get playbackTimestampEnabled() { return this.#playbackTimestampEnabled; }
|
38
40
|
get countInBeatsTotal() { return this.#countInBeatsTotal; }
|
39
41
|
get countInBeatsRemaining() { return this.#countInBeatsRemaining; }
|
40
42
|
get markerState() { return this.#markerState; }
|
package/dist/EngineWorklet.d.ts
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
import { int, MutableObservableValue, Nullable, ObservableValue, Observer, Subscription, UUID } from "@opendaw/lib-std";
|
2
2
|
import { ppqn } from "@opendaw/lib-dsp";
|
3
|
-
import { ClipNotification, ExportStemsConfiguration, NoteSignal } from "@opendaw/studio-adapters";
|
3
|
+
import { ClipNotification, ExportStemsConfiguration, NoteSignal, ProcessorOptions } from "@opendaw/studio-adapters";
|
4
4
|
import { Project } from "./project/Project";
|
5
5
|
import { Engine } from "./Engine";
|
6
6
|
export declare class EngineWorklet extends AudioWorkletNode implements Engine {
|
7
7
|
#private;
|
8
8
|
static ID: int;
|
9
9
|
readonly id: number;
|
10
|
-
constructor(context: BaseAudioContext, project: Project, exportConfiguration?: ExportStemsConfiguration);
|
10
|
+
constructor(context: BaseAudioContext, project: Project, exportConfiguration?: ExportStemsConfiguration, options?: ProcessorOptions);
|
11
11
|
play(): void;
|
12
12
|
stop(reset?: boolean): void;
|
13
13
|
setPosition(position: ppqn): void;
|
@@ -21,6 +21,7 @@ export declare class EngineWorklet extends AudioWorkletNode implements Engine {
|
|
21
21
|
get countInBeatsRemaining(): ObservableValue<number>;
|
22
22
|
get position(): ObservableValue<ppqn>;
|
23
23
|
get playbackTimestamp(): MutableObservableValue<number>;
|
24
|
+
get playbackTimestampEnabled(): MutableObservableValue<boolean>;
|
24
25
|
get metronomeEnabled(): MutableObservableValue<boolean>;
|
25
26
|
get markerState(): ObservableValue<Nullable<[UUID.Bytes, int]>>;
|
26
27
|
get project(): Project;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"EngineWorklet.d.ts","sourceRoot":"","sources":["../src/EngineWorklet.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,GAAG,EACH,sBAAsB,EAEtB,QAAQ,EACR,eAAe,EACf,QAAQ,EAER,YAAY,EAGZ,IAAI,EACP,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAC,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAIrC,OAAO,EAEH,gBAAgB,EAOhB,wBAAwB,EACxB,UAAU,
|
1
|
+
{"version":3,"file":"EngineWorklet.d.ts","sourceRoot":"","sources":["../src/EngineWorklet.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,GAAG,EACH,sBAAsB,EAEtB,QAAQ,EACR,eAAe,EACf,QAAQ,EAER,YAAY,EAGZ,IAAI,EACP,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAC,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAIrC,OAAO,EAEH,gBAAgB,EAOhB,wBAAwB,EACxB,UAAU,EACV,gBAAgB,EACnB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EAAC,OAAO,EAAC,MAAM,mBAAmB,CAAA;AACzC,OAAO,EAAC,MAAM,EAAC,MAAM,UAAU,CAAA;AAE/B,qBAAa,aAAc,SAAQ,gBAAiB,YAAW,MAAM;;IACjE,MAAM,CAAC,EAAE,EAAE,GAAG,CAAQ;IAEtB,QAAQ,CAAC,EAAE,SAAqB;gBAqBpB,OAAO,EAAE,gBAAgB,EACzB,OAAO,EAAE,OAAO,EAChB,mBAAmB,CAAC,EAAE,wBAAwB,EAC9C,OAAO,CAAC,EAAE,gBAAgB;IAsGtC,IAAI,IAAI,IAAI;IACZ,IAAI,CAAC,KAAK,GAAE,OAAe,GAAG,IAAI;IAClC,WAAW,CAAC,QAAQ,EAAE,IAAI,GAAG,IAAI;IACjC,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IACtC,aAAa,IAAI,IAAI;IACrB,KAAK,IAAI,IAAI;IAEb,IAAI,SAAS,IAAI,eAAe,CAAC,OAAO,CAAC,CAAyB;IAClE,IAAI,WAAW,IAAI,eAAe,CAAC,OAAO,CAAC,CAA2B;IACtE,IAAI,YAAY,IAAI,eAAe,CAAC,OAAO,CAAC,CAA4B;IACxE,IAAI,iBAAiB,IAAI,eAAe,CAAC,GAAG,CAAC,CAAiC;IAC9E,IAAI,qBAAqB,IAAI,eAAe,CAAC,MAAM,CAAC,CAAqC;IACzF,IAAI,QAAQ,IAAI,eAAe,CAAC,IAAI,CAAC,CAAwB;IAC7D,IAAI,iBAAiB,IAAI,sBAAsB,CAAC,MAAM,CAAC,CAAiC;IACxF,IAAI,wBAAwB,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAwC;IACvG,IAAI,gBAAgB,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAgC;IACvF,IAAI,WAAW,IAAI,eAAe,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,CAA2B;IAC1F,IAAI,OAAO,IAAI,OAAO,CAAuB;IAE7C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IACxB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC;IACxC,UAAU,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IACpC,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAAC,GAAG,YAAY;IAC5D,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,GAAG,IAAI;IACxC,gBAAgB,CAAC,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI;IAI1D,gBAAgB,CAAC,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI;IAG3D,yBAAyB,CAAC,QAAQ,EAAE,QAAQ,CAAC,gBAAgB,CAAC,GAAG,YAAY;IAQ7E,SAAS,IAAI,IAAI;CAIpB"}
|
package/dist/EngineWorklet.js
CHANGED
@@ -9,6 +9,7 @@ export class EngineWorklet extends AudioWorkletNode {
|
|
9
9
|
#terminator = new Terminator();
|
10
10
|
#project;
|
11
11
|
#playbackTimestamp = new DefaultObservableValue(0.0);
|
12
|
+
#playbackTimestampEnabled = new DefaultObservableValue(true);
|
12
13
|
#position = new DefaultObservableValue(0.0);
|
13
14
|
#isPlaying = new DefaultObservableValue(false);
|
14
15
|
#isRecording = new DefaultObservableValue(false);
|
@@ -22,7 +23,7 @@ export class EngineWorklet extends AudioWorkletNode {
|
|
22
23
|
#playingClips;
|
23
24
|
#commands;
|
24
25
|
#isReady;
|
25
|
-
constructor(context, project, exportConfiguration) {
|
26
|
+
constructor(context, project, exportConfiguration, options) {
|
26
27
|
const numberOfChannels = ExportStemsConfiguration.countStems(Option.wrap(exportConfiguration)) * 2;
|
27
28
|
const reader = SyncStream.reader(EngineStateSchema(), state => {
|
28
29
|
this.#isPlaying.setValue(state.isPlaying);
|
@@ -40,7 +41,8 @@ export class EngineWorklet extends AudioWorkletNode {
|
|
40
41
|
processorOptions: {
|
41
42
|
sab: reader.buffer,
|
42
43
|
project: project.toArrayBuffer(),
|
43
|
-
exportConfiguration
|
44
|
+
exportConfiguration,
|
45
|
+
options
|
44
46
|
}
|
45
47
|
});
|
46
48
|
const { resolve, promise } = Promise.withResolvers();
|
@@ -56,7 +58,12 @@ export class EngineWorklet extends AudioWorkletNode {
|
|
56
58
|
setPosition(position) { dispatcher.dispatchAndForget(this.setPosition, position); }
|
57
59
|
startRecording(countIn) { dispatcher.dispatchAndForget(this.startRecording, countIn); }
|
58
60
|
stopRecording() { dispatcher.dispatchAndForget(this.stopRecording); }
|
59
|
-
setMetronomeEnabled(enabled) {
|
61
|
+
setMetronomeEnabled(enabled) {
|
62
|
+
dispatcher.dispatchAndForget(this.setMetronomeEnabled, enabled);
|
63
|
+
}
|
64
|
+
setPlaybackTimestampEnabled(enabled) {
|
65
|
+
dispatcher.dispatchAndForget(this.setPlaybackTimestampEnabled, enabled);
|
66
|
+
}
|
60
67
|
queryLoadingComplete() {
|
61
68
|
return dispatcher.dispatchAndReturn(this.queryLoadingComplete);
|
62
69
|
}
|
@@ -103,7 +110,7 @@ export class EngineWorklet extends AudioWorkletNode {
|
|
103
110
|
},
|
104
111
|
switchMarkerState: (state) => this.#markerState.setValue(state)
|
105
112
|
});
|
106
|
-
this.#terminator.ownAll(AnimationFrame.add(() => reader.tryRead()), project.liveStreamReceiver.connect(messenger.channel("engine-live-data")), new SyncSource(project.boxGraph, messenger.channel("engine-sync"), false), this.#metronomeEnabled.catchupAndSubscribe(owner => this.#commands.setMetronomeEnabled(owner.getValue())));
|
113
|
+
this.#terminator.ownAll(AnimationFrame.add(() => reader.tryRead()), project.liveStreamReceiver.connect(messenger.channel("engine-live-data")), new SyncSource(project.boxGraph, messenger.channel("engine-sync"), false), this.#metronomeEnabled.catchupAndSubscribe(owner => this.#commands.setMetronomeEnabled(owner.getValue())), this.#playbackTimestampEnabled.catchupAndSubscribe(owner => this.#commands.setPlaybackTimestampEnabled(owner.getValue())));
|
107
114
|
}
|
108
115
|
play() { this.#commands.play(); }
|
109
116
|
stop(reset = false) { this.#commands.stop(reset); }
|
@@ -118,6 +125,7 @@ export class EngineWorklet extends AudioWorkletNode {
|
|
118
125
|
get countInBeatsRemaining() { return this.#countInBeatsRemaining; }
|
119
126
|
get position() { return this.#position; }
|
120
127
|
get playbackTimestamp() { return this.#playbackTimestamp; }
|
128
|
+
get playbackTimestampEnabled() { return this.#playbackTimestampEnabled; }
|
121
129
|
get metronomeEnabled() { return this.#metronomeEnabled; }
|
122
130
|
get markerState() { return this.#markerState; }
|
123
131
|
get project() { return this.#project; }
|
@@ -4,5 +4,6 @@ export declare namespace FilePickerAcceptTypes {
|
|
4
4
|
const ProjectFileType: FilePickerAcceptType;
|
5
5
|
const ProjectBundleFileType: FilePickerAcceptType;
|
6
6
|
const DawprojectFileType: FilePickerAcceptType;
|
7
|
+
const JsonFileType: FilePickerAcceptType;
|
7
8
|
}
|
8
9
|
//# sourceMappingURL=FilePickerAcceptTypes.d.ts.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"FilePickerAcceptTypes.d.ts","sourceRoot":"","sources":["../src/FilePickerAcceptTypes.ts"],"names":[],"mappings":"AAAA,yBAAiB,qBAAqB,CAAC;IAC5B,MAAM,QAAQ,EAAE,iBAKtB,CAAA;IACM,MAAM,cAAc,EAAE,iBAK5B,CAAA;IAEM,MAAM,eAAe,EAAE,oBAG7B,CAAA;IAEM,MAAM,qBAAqB,EAAE,oBAGnC,CAAA;IAEM,MAAM,kBAAkB,EAAE,oBAGhC,CAAA;
|
1
|
+
{"version":3,"file":"FilePickerAcceptTypes.d.ts","sourceRoot":"","sources":["../src/FilePickerAcceptTypes.ts"],"names":[],"mappings":"AAAA,yBAAiB,qBAAqB,CAAC;IAC5B,MAAM,QAAQ,EAAE,iBAKtB,CAAA;IACM,MAAM,cAAc,EAAE,iBAK5B,CAAA;IAEM,MAAM,eAAe,EAAE,oBAG7B,CAAA;IAEM,MAAM,qBAAqB,EAAE,oBAGnC,CAAA;IAEM,MAAM,kBAAkB,EAAE,oBAGhC,CAAA;IACM,MAAM,YAAY,EAAE,oBAG1B,CAAA;CAEJ"}
|
@@ -24,4 +24,8 @@ export var FilePickerAcceptTypes;
|
|
24
24
|
description: "dawproject",
|
25
25
|
accept: { "application/octet-stream": [".dawproject"] }
|
26
26
|
};
|
27
|
+
FilePickerAcceptTypes.JsonFileType = {
|
28
|
+
description: "json",
|
29
|
+
accept: { "application/json": [".json"] }
|
30
|
+
};
|
27
31
|
})(FilePickerAcceptTypes || (FilePickerAcceptTypes = {}));
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"RecordingWorklet.d.ts","sourceRoot":"","sources":["../src/RecordingWorklet.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,GAAG,EAEH,QAAQ,EACR,MAAM,
|
1
|
+
{"version":3,"file":"RecordingWorklet.d.ts","sourceRoot":"","sources":["../src/RecordingWorklet.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,GAAG,EAEH,QAAQ,EACR,MAAM,EAGN,YAAY,EACZ,UAAU,EAEV,IAAI,EACP,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EAAC,KAAK,EAAc,MAAM,qBAAqB,CAAA;AACtD,OAAO,EACH,SAAS,EAET,UAAU,EACV,YAAY,EACZ,iBAAiB,EAEpB,MAAM,0BAA0B,CAAA;AAMjC,qBAAa,gBAAiB,SAAQ,gBAAiB,YAAW,UAAU,EAAE,YAAY;;IAGtF,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAkB;gBAa/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM;IA2BvF,GAAG,CAAC,CAAC,SAAS,UAAU,EAAE,UAAU,EAAE,CAAC,GAAG,CAAC;IAE3C,KAAK,CAAC,KAAK,EAAE,GAAG,GAAG,IAAI;IAEvB,aAAa,CAAC,KAAK,EAAE,GAAG,GAAG,IAAI;IAE/B,IAAI,cAAc,IAAI,GAAG,CAA6C;IACtE,IAAI,IAAI,IAAI,MAAM,CAAC,SAAS,CAAC,CAAoB;IACjD,IAAI,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,CAA6E;IACvG,IAAI,KAAK,IAAI,iBAAiB,CAAqB;IAEnD,UAAU,IAAI,IAAI;IAElB,SAAS,CAAC,QAAQ,EAAE,QAAQ,CAAC,iBAAiB,CAAC,GAAG,YAAY;IAQ9D,SAAS,IAAI,IAAI;IAMjB,QAAQ,IAAI,MAAM;CAyCrB"}
|
package/dist/RecordingWorklet.js
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
import { ByteArrayInput, Notifier, Option, Progress, Terminable, Terminator, UUID } from "@opendaw/lib-std";
|
1
|
+
import { ByteArrayInput, Notifier, Option, panic, Progress, Terminable, Terminator, UUID } from "@opendaw/lib-std";
|
2
2
|
import { BPMTools } from "@opendaw/lib-dsp";
|
3
3
|
import { SamplePeaks } from "@opendaw/lib-fusion";
|
4
4
|
import { mergeChunkPlanes, RingBuffer } from "@opendaw/studio-adapters";
|
5
|
-
import { SampleStorage } from "./samples
|
5
|
+
import { SampleStorage } from "./samples";
|
6
6
|
import { RenderQuantum } from "./RenderQuantum";
|
7
7
|
import { Workers } from "./Workers";
|
8
8
|
import { PeaksWriter } from "./PeaksWriter";
|
@@ -68,7 +68,7 @@ export class RecordingWorklet extends AudioWorkletNode {
|
|
68
68
|
this.#isRecording = false;
|
69
69
|
this.#reader.stop();
|
70
70
|
if (this.#output.length === 0) {
|
71
|
-
return;
|
71
|
+
return panic("No recording data available");
|
72
72
|
}
|
73
73
|
const totalSamples = this.#limitSamples;
|
74
74
|
const sample_rate = this.context.sampleRate;
|
@@ -88,10 +88,17 @@ export class RecordingWorklet extends AudioWorkletNode {
|
|
88
88
|
this.#peaks = Option.wrap(SamplePeaks.from(new ByteArrayInput(peaks)));
|
89
89
|
const bpm = BPMTools.detect(frames[0], sample_rate);
|
90
90
|
const duration = totalSamples / sample_rate;
|
91
|
-
const meta = { name: "Recording", bpm, sample_rate, duration };
|
92
|
-
|
91
|
+
const meta = { name: "Recording", bpm, sample_rate, duration, origin: "recording" };
|
92
|
+
const sample = {
|
93
|
+
uuid: this.uuid,
|
94
|
+
audio: audioData,
|
95
|
+
peaks: peaks,
|
96
|
+
meta
|
97
|
+
};
|
98
|
+
await SampleStorage.saveSample(sample);
|
93
99
|
this.#setState({ type: "loaded" });
|
94
100
|
this.terminate();
|
101
|
+
return sample;
|
95
102
|
}
|
96
103
|
#setState(value) {
|
97
104
|
this.#state = value;
|
@@ -38,28 +38,28 @@ export class CaptureMidi extends Capture {
|
|
38
38
|
notify(signal) { this.#notifier.notify(signal); }
|
39
39
|
subscribeNotes(observer) { return this.#notifier.subscribe(observer); }
|
40
40
|
get label() {
|
41
|
-
return MidiDevices.get().mapOr(
|
41
|
+
return MidiDevices.get().mapOr(() => this.deviceId.getValue().match({
|
42
42
|
none: () => this.armed.getValue() ? this.#filterChannel.match({
|
43
43
|
none: () => `Listening to all devices`,
|
44
44
|
some: channel => `Listening to all devices on channel '${channel}'`
|
45
45
|
}) : "Arm to listen to MIDI device...",
|
46
46
|
some: id => {
|
47
|
-
const device =
|
48
|
-
if (
|
47
|
+
const device = MidiDevices.findInputDeviceById(id);
|
48
|
+
if (device.isEmpty()) {
|
49
49
|
return `⚠️ Could not find device with id '${id}'`;
|
50
50
|
}
|
51
|
-
const deviceName = device.name ?? "Unknown device";
|
51
|
+
const deviceName = device.unwrapOrUndefined()?.name ?? "Unknown device";
|
52
52
|
return this.#filterChannel.match({
|
53
53
|
none: () => `Listening to ${deviceName}`,
|
54
|
-
some: channel => `Listening to ${deviceName} on channel
|
54
|
+
some: channel => `Listening to ${deviceName} on channel #${channel + 1}`
|
55
55
|
});
|
56
56
|
}
|
57
57
|
}), "MIDI not available");
|
58
58
|
}
|
59
59
|
get deviceLabel() {
|
60
60
|
return this.deviceId.getValue()
|
61
|
-
.flatMap(deviceId => MidiDevices.
|
62
|
-
.map(
|
61
|
+
.flatMap(deviceId => MidiDevices.findInputDeviceById(deviceId)
|
62
|
+
.map(device => device.name));
|
63
63
|
}
|
64
64
|
async prepareRecording() {
|
65
65
|
if (MidiDevices.get().isEmpty()) {
|
@@ -70,7 +70,7 @@ export class CaptureMidi extends Capture {
|
|
70
70
|
return Errors.warn("MIDI not available");
|
71
71
|
}
|
72
72
|
}
|
73
|
-
const optInputs = MidiDevices.
|
73
|
+
const optInputs = MidiDevices.inputDevices();
|
74
74
|
if (optInputs.isEmpty()) {
|
75
75
|
return Errors.warn("MIDI not available");
|
76
76
|
}
|
@@ -87,16 +87,16 @@ export class CaptureMidi extends Capture {
|
|
87
87
|
}
|
88
88
|
}
|
89
89
|
startRecording() {
|
90
|
-
const
|
91
|
-
assert(
|
90
|
+
const availableInputDevices = MidiDevices.inputDevices();
|
91
|
+
assert(availableInputDevices.nonEmpty(), "No MIDI input devices found");
|
92
92
|
return RecordMidi.start({ notifier: this.#notifier, project: this.manager.project, capture: this });
|
93
93
|
}
|
94
94
|
async #updateStream() {
|
95
95
|
if (MidiDevices.get().isEmpty()) {
|
96
96
|
await MidiDevices.requestPermission();
|
97
97
|
}
|
98
|
-
const
|
99
|
-
const available =
|
98
|
+
const availableInputDevices = MidiDevices.inputDevices();
|
99
|
+
const available = availableInputDevices.unwrap();
|
100
100
|
const capturing = this.deviceId.getValue().match({
|
101
101
|
none: () => available,
|
102
102
|
some: id => available.filter(device => id === device.id)
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { Terminable } from "@opendaw/lib-std";
|
2
|
-
import {
|
2
|
+
import { SampleLoaderManager } from "@opendaw/studio-adapters";
|
3
3
|
import { Project } from "../project/Project";
|
4
4
|
import { RecordingWorklet } from "../RecordingWorklet";
|
5
5
|
import { Capture } from "./Capture";
|
@@ -7,7 +7,7 @@ export declare namespace RecordAudio {
|
|
7
7
|
type RecordAudioContext = {
|
8
8
|
recordingWorklet: RecordingWorklet;
|
9
9
|
mediaStream: MediaStream;
|
10
|
-
sampleManager:
|
10
|
+
sampleManager: SampleLoaderManager;
|
11
11
|
audioContext: AudioContext;
|
12
12
|
project: Project;
|
13
13
|
capture: Capture;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"RecordAudio.d.ts","sourceRoot":"","sources":["../../src/capture/RecordAudio.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2C,UAAU,EAAmB,MAAM,kBAAkB,CAAA;AAGvG,OAAO,EAAC,
|
1
|
+
{"version":3,"file":"RecordAudio.d.ts","sourceRoot":"","sources":["../../src/capture/RecordAudio.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2C,UAAU,EAAmB,MAAM,kBAAkB,CAAA;AAGvG,OAAO,EAAC,mBAAmB,EAAY,MAAM,0BAA0B,CAAA;AACvE,OAAO,EAAC,OAAO,EAAC,MAAM,oBAAoB,CAAA;AAC1C,OAAO,EAAC,gBAAgB,EAAC,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAC,OAAO,EAAC,MAAM,WAAW,CAAA;AAIjC,yBAAiB,WAAW,CAAC;IACzB,KAAK,kBAAkB,GAAG;QACtB,gBAAgB,EAAE,gBAAgB,CAAA;QAClC,WAAW,EAAE,WAAW,CAAA;QACxB,aAAa,EAAE,mBAAmB,CAAA;QAClC,YAAY,EAAE,YAAY,CAAA;QAC1B,OAAO,EAAE,OAAO,CAAA;QAChB,OAAO,EAAE,OAAO,CAAA;QAChB,MAAM,EAAE,MAAM,CAAA;KACjB,CAAA;IAED,MAAM,CAAC,MAAM,KAAK,GACd,0FAAwF,kBAAkB,KACxG,UAqEL,CAAA;;CACJ"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"CloudAuthManager.d.ts","sourceRoot":"","sources":["../../src/clouds/CloudAuthManager.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAA;AAC3C,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAA;AAI3C,qBAAa,gBAAgB;;IACzB,MAAM,CAAC,MAAM,IAAI,gBAAgB;IAqBjC,QAAQ,CAAC,EAAE,SAAyB;IAIpC,OAAO;IAED,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;
|
1
|
+
{"version":3,"file":"CloudAuthManager.d.ts","sourceRoot":"","sources":["../../src/clouds/CloudAuthManager.ts"],"names":[],"mappings":"AAEA,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAA;AAC3C,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAA;AAI3C,qBAAa,gBAAgB;;IACzB,MAAM,CAAC,MAAM,IAAI,gBAAgB;IAqBjC,QAAQ,CAAC,EAAE,SAAyB;IAIpC,OAAO;IAED,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;CAuLjE"}
|
@@ -71,10 +71,15 @@ export class CloudAuthManager {
|
|
71
71
|
message: "Please wait for authentication...",
|
72
72
|
cancel: () => reject("cancelled")
|
73
73
|
});
|
74
|
+
let handled = false;
|
74
75
|
channel.onmessage = async (event) => {
|
75
76
|
const data = asDefined(event.data, "No data");
|
76
77
|
console.debug("[CloudAuth] Received via BroadcastChannel:", this.id, data);
|
77
78
|
if (data.type === "auth-callback" && isDefined(data.code)) {
|
79
|
+
if (handled) {
|
80
|
+
return;
|
81
|
+
}
|
82
|
+
handled = true;
|
78
83
|
console.debug("[CloudAuth] Processing code from BroadcastChannel...", data.type, data.code);
|
79
84
|
try {
|
80
85
|
const tokenParams = new URLSearchParams({
|
@@ -108,8 +113,11 @@ export class CloudAuthManager {
|
|
108
113
|
}
|
109
114
|
}
|
110
115
|
else if (data.type === "closed") {
|
111
|
-
|
112
|
-
|
116
|
+
// Only reject if we did not already start handling a code
|
117
|
+
if (!handled) {
|
118
|
+
console.debug("[CloudAuth] Callback window closed before code received");
|
119
|
+
reject(null);
|
120
|
+
}
|
113
121
|
}
|
114
122
|
};
|
115
123
|
return promise.finally(() => {
|
@@ -3,6 +3,6 @@ import { CloudAuthManager } from "./CloudAuthManager";
|
|
3
3
|
import { CloudService } from "./CloudService";
|
4
4
|
export declare namespace CloudBackup {
|
5
5
|
const backup: (cloudAuthManager: CloudAuthManager, service: CloudService) => Promise<void>;
|
6
|
-
const backupWithHandler: (cloudHandler: CloudHandler, service: CloudService) => Promise<
|
6
|
+
const backupWithHandler: (cloudHandler: CloudHandler, service: CloudService) => Promise<undefined>;
|
7
7
|
}
|
8
8
|
//# sourceMappingURL=CloudBackup.d.ts.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"CloudBackup.d.ts","sourceRoot":"","sources":["../../src/clouds/CloudBackup.ts"],"names":[],"mappings":"
|
1
|
+
{"version":3,"file":"CloudBackup.d.ts","sourceRoot":"","sources":["../../src/clouds/CloudBackup.ts"],"names":[],"mappings":"AAUA,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAA;AAG3C,OAAO,EAAC,gBAAgB,EAAC,MAAM,oBAAoB,CAAA;AACnD,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAA;AAK3C,yBAAiB,WAAW,CAAC;IAClB,MAAM,MAAM,GAAU,kBAAkB,gBAAgB,EAAE,SAAS,YAAY,kBA+BrF,CAAA;IAEM,MAAM,iBAAiB,GAAU,cAAc,YAAY,EAAE,SAAS,YAAY,uBA+CxF,CAAA;CACJ"}
|
@@ -1,7 +1,9 @@
|
|
1
|
-
import { DefaultObservableValue, Progress, RuntimeNotifier, RuntimeSignal } from "@opendaw/lib-std";
|
1
|
+
import { DefaultObservableValue, Errors, isInstanceOf, Progress, RuntimeNotifier, RuntimeSignal, TimeSpan } from "@opendaw/lib-std";
|
2
2
|
import { CloudBackupSamples } from "./CloudBackupSamples";
|
3
3
|
import { CloudBackupProjects } from "./CloudBackupProjects";
|
4
4
|
import { ProjectSignals } from "../project/ProjectSignals";
|
5
|
+
import { Promises } from "@opendaw/lib-runtime";
|
6
|
+
import { Browser } from "@opendaw/lib-dom";
|
5
7
|
export var CloudBackup;
|
6
8
|
(function (CloudBackup) {
|
7
9
|
CloudBackup.backup = async (cloudAuthManager, service) => {
|
@@ -28,6 +30,9 @@ export var CloudBackup;
|
|
28
30
|
});
|
29
31
|
}
|
30
32
|
catch (reason) {
|
33
|
+
if (Errors.isAbort(reason)) {
|
34
|
+
return;
|
35
|
+
}
|
31
36
|
console.warn(reason);
|
32
37
|
await RuntimeNotifier.info({
|
33
38
|
headline: `Could not sync`,
|
@@ -43,11 +48,46 @@ export var CloudBackup;
|
|
43
48
|
const notification = RuntimeNotifier.progress({ headline: `Backup with ${service}`, progress: progressValue });
|
44
49
|
const log = (text) => notification.message = text;
|
45
50
|
const [progressSamples, progressProjects] = Progress.split(progress => progressValue.setValue(progress), 2);
|
51
|
+
const lockPath = "lock.json";
|
52
|
+
let canReleaseLock = false;
|
46
53
|
try {
|
54
|
+
const { status, error, value } = await Promises.tryCatch(cloudHandler.download(lockPath));
|
55
|
+
console.debug("LOCK", status);
|
56
|
+
if (status === "resolved") {
|
57
|
+
const lock = JSON.parse(new TextDecoder().decode(value));
|
58
|
+
if (lock.id !== Browser.id()) {
|
59
|
+
// another browser is currently doing a backup
|
60
|
+
const lockCreated = new Date(lock.created);
|
61
|
+
const timeString = TimeSpan.millis(lockCreated.getTime() - new Date().getTime()).toString();
|
62
|
+
const approved = await RuntimeNotifier.approve({
|
63
|
+
headline: "Cloud Locked!",
|
64
|
+
message: `There is a lock on the backup folder since ${timeString}.
|
65
|
+
This means the account is currently busy with a backup or a previous backup did not finish properly. If you share this account, please coordinate with the other person or simply wait a few minutes and try again. Ignoring the lock while another backup is still running can cause the cloud data to become inconsistent.`,
|
66
|
+
approveText: "Wait",
|
67
|
+
cancelText: "Ignore"
|
68
|
+
});
|
69
|
+
if (approved) {
|
70
|
+
return Promise.reject(Errors.AbortError);
|
71
|
+
}
|
72
|
+
}
|
73
|
+
}
|
74
|
+
else if (!isInstanceOf(error, Errors.FileNotFound)) {
|
75
|
+
await RuntimeNotifier.info({
|
76
|
+
headline: "Error reading lock file",
|
77
|
+
message: "Abort backup."
|
78
|
+
});
|
79
|
+
throw error;
|
80
|
+
}
|
81
|
+
canReleaseLock = true;
|
82
|
+
const json = { id: Browser.id(), created: new Date().toISOString() };
|
83
|
+
await cloudHandler.upload(lockPath, new TextEncoder().encode(JSON.stringify(json)).buffer);
|
47
84
|
await CloudBackupSamples.start(cloudHandler, progressSamples, log);
|
48
85
|
await CloudBackupProjects.start(cloudHandler, progressProjects, log);
|
49
86
|
}
|
50
87
|
finally {
|
88
|
+
if (canReleaseLock) {
|
89
|
+
await cloudHandler.delete(lockPath);
|
90
|
+
}
|
51
91
|
progressValue.terminate();
|
52
92
|
notification.terminate();
|
53
93
|
}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"CloudBackupSamples.d.ts","sourceRoot":"","sources":["../../src/clouds/CloudBackupSamples.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,SAAS,EAAE,QAAQ,EAAmB,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAGlG,OAAO,EAAY,MAAM,EAAC,MAAM,0BAA0B,CAAA;AAG1D,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAA;AAM3C,qBAAa,kBAAkB;;IAC3B,MAAM,CAAC,QAAQ,CAAC,UAAU,aAAY;IACtC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,SAAkC;IACnE,MAAM,CAAC,QAAQ,CAAC,eAAe,GAAI,aAAW,MAAM,EAAE,aAAW,MAAM,aAAY;IAEnF,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,GAAG,MAAM;WAE5B,KAAK,CAAC,YAAY,EAAE,YAAY,EAC1B,QAAQ,EAAE,QAAQ,CAAC,OAAO,EAC1B,GAAG,EAAE,SAAS,CAAC,MAAM,CAAC;IAgBzC,OAAO;
|
1
|
+
{"version":3,"file":"CloudBackupSamples.d.ts","sourceRoot":"","sources":["../../src/clouds/CloudBackupSamples.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,SAAS,EAAE,QAAQ,EAAmB,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAGlG,OAAO,EAAY,MAAM,EAAC,MAAM,0BAA0B,CAAA;AAG1D,OAAO,EAAC,YAAY,EAAC,MAAM,gBAAgB,CAAA;AAM3C,qBAAa,kBAAkB;;IAC3B,MAAM,CAAC,QAAQ,CAAC,UAAU,aAAY;IACtC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,SAAkC;IACnE,MAAM,CAAC,QAAQ,CAAC,eAAe,GAAI,aAAW,MAAM,EAAE,aAAW,MAAM,aAAY;IAEnF,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,GAAG,MAAM;WAE5B,KAAK,CAAC,YAAY,EAAE,YAAY,EAC1B,QAAQ,EAAE,QAAQ,CAAC,OAAO,EAC1B,GAAG,EAAE,SAAS,CAAC,MAAM,CAAC;IAgBzC,OAAO;CA2HV"}
|
@@ -114,7 +114,12 @@ export class CloudBackupSamples {
|
|
114
114
|
};
|
115
115
|
const shifts = SamplePeaks.findBestFit(audioData.numberOfFrames);
|
116
116
|
const peaks = await Workers.Peak.generateAsync(Progress.Empty, shifts, audioData.frames, audioData.numberOfFrames, audioData.numberOfChannels);
|
117
|
-
await SampleStorage.saveSample(
|
117
|
+
await SampleStorage.saveSample({
|
118
|
+
uuid: UUID.parse(sample.uuid),
|
119
|
+
audio: audioData,
|
120
|
+
peaks: peaks,
|
121
|
+
meta: sample
|
122
|
+
});
|
118
123
|
return sample;
|
119
124
|
}));
|
120
125
|
this.#log("Download samples complete.");
|
package/dist/index.d.ts
CHANGED
@@ -18,19 +18,14 @@ export * from "./project/ProjectPaths";
|
|
18
18
|
export * from "./project/ProjectProfile";
|
19
19
|
export * from "./project/ProjectSignals";
|
20
20
|
export * from "./project/ProjectStorage";
|
21
|
-
export * from "./samples/
|
22
|
-
export * from "./samples/MainThreadSampleLoader";
|
23
|
-
export * from "./samples/MainThreadSampleManager";
|
24
|
-
export * from "./samples/OpenSampleAPI";
|
25
|
-
export * from "./samples/SampleAPI";
|
26
|
-
export * from "./samples/SampleImporter";
|
27
|
-
export * from "./samples/SampleProvider";
|
21
|
+
export * from "./samples/index";
|
28
22
|
export * from "./sync-log/Commit";
|
29
23
|
export * from "./sync-log/SyncLogReader";
|
30
24
|
export * from "./sync-log/SyncLogWriter";
|
31
25
|
export * from "./clouds/CloudAuthManager";
|
32
26
|
export * from "./clouds/CloudHandler";
|
33
27
|
export * from "./clouds/CloudBackup";
|
28
|
+
export * from "./ui/TimelineRange";
|
34
29
|
export * from "./AudioDevices";
|
35
30
|
export * from "./AudioOfflineRenderer";
|
36
31
|
export * from "./AudioUnitOrdering";
|
package/dist/index.d.ts.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA;AACjC,cAAc,wBAAwB,CAAA;AACtC,cAAc,uBAAuB,CAAA;AACrC,cAAc,0BAA0B,CAAA;AACxC,cAAc,qBAAqB,CAAA;AAEnC,cAAc,yBAAyB,CAAA;AACvC,cAAc,iCAAiC,CAAA;AAC/C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,+BAA+B,CAAA;AAE7C,cAAc,oBAAoB,CAAA;AAClC,cAAc,qBAAqB,CAAA;AAEnC,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA;AACpC,cAAc,yBAAyB,CAAA;AACvC,cAAc,sBAAsB,CAAA;AACpC,cAAc,uBAAuB,CAAA;AACrC,cAAc,wBAAwB,CAAA;AACtC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AAExC,cAAc,
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA;AACjC,cAAc,wBAAwB,CAAA;AACtC,cAAc,uBAAuB,CAAA;AACrC,cAAc,0BAA0B,CAAA;AACxC,cAAc,qBAAqB,CAAA;AAEnC,cAAc,yBAAyB,CAAA;AACvC,cAAc,iCAAiC,CAAA;AAC/C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,+BAA+B,CAAA;AAE7C,cAAc,oBAAoB,CAAA;AAClC,cAAc,qBAAqB,CAAA;AAEnC,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA;AACpC,cAAc,yBAAyB,CAAA;AACvC,cAAc,sBAAsB,CAAA;AACpC,cAAc,uBAAuB,CAAA;AACrC,cAAc,wBAAwB,CAAA;AACtC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AAExC,cAAc,iBAAiB,CAAA;AAE/B,cAAc,mBAAmB,CAAA;AACjC,cAAc,0BAA0B,CAAA;AACxC,cAAc,0BAA0B,CAAA;AAExC,cAAc,2BAA2B,CAAA;AACzC,cAAc,uBAAuB,CAAA;AACrC,cAAc,sBAAsB,CAAA;AAEpC,cAAc,oBAAoB,CAAA;AAElC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,wBAAwB,CAAA;AACtC,cAAc,qBAAqB,CAAA;AACnC,cAAc,cAAc,CAAA;AAC5B,cAAc,UAAU,CAAA;AACxB,cAAc,aAAa,CAAA;AAC3B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,mBAAmB,CAAA;AACjC,cAAc,UAAU,CAAA;AACxB,cAAc,gBAAgB,CAAA;AAC9B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,yBAAyB,CAAA;AACvC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,uBAAuB,CAAA;AACrC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,SAAS,CAAA;AACvB,cAAc,eAAe,CAAA;AAC7B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,WAAW,CAAA;AACzB,cAAc,WAAW,CAAA;AACzB,cAAc,iBAAiB,CAAA"}
|
package/dist/index.js
CHANGED
@@ -18,19 +18,14 @@ export * from "./project/ProjectPaths";
|
|
18
18
|
export * from "./project/ProjectProfile";
|
19
19
|
export * from "./project/ProjectSignals";
|
20
20
|
export * from "./project/ProjectStorage";
|
21
|
-
export * from "./samples/
|
22
|
-
export * from "./samples/MainThreadSampleLoader";
|
23
|
-
export * from "./samples/MainThreadSampleManager";
|
24
|
-
export * from "./samples/OpenSampleAPI";
|
25
|
-
export * from "./samples/SampleAPI";
|
26
|
-
export * from "./samples/SampleImporter";
|
27
|
-
export * from "./samples/SampleProvider";
|
21
|
+
export * from "./samples/index";
|
28
22
|
export * from "./sync-log/Commit";
|
29
23
|
export * from "./sync-log/SyncLogReader";
|
30
24
|
export * from "./sync-log/SyncLogWriter";
|
31
25
|
export * from "./clouds/CloudAuthManager";
|
32
26
|
export * from "./clouds/CloudHandler";
|
33
27
|
export * from "./clouds/CloudBackup";
|
28
|
+
export * from "./ui/TimelineRange";
|
34
29
|
export * from "./AudioDevices";
|
35
30
|
export * from "./AudioOfflineRenderer";
|
36
31
|
export * from "./AudioUnitOrdering";
|