@opendaw/studio-core 0.0.44 → 0.0.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/AudioOfflineRenderer.d.ts +1 -2
- package/dist/AudioOfflineRenderer.d.ts.map +1 -1
- package/dist/AudioOfflineRenderer.js +10 -3
- package/dist/EffectBox.d.ts +2 -2
- package/dist/EffectBox.d.ts.map +1 -1
- package/dist/EffectFactories.d.ts +6 -0
- package/dist/EffectFactories.d.ts.map +1 -1
- package/dist/EffectFactories.js +29 -24
- package/dist/EffectFactory.d.ts +1 -1
- package/dist/EffectFactory.d.ts.map +1 -1
- package/dist/EffectParameterDefaults.d.ts +5 -0
- package/dist/EffectParameterDefaults.d.ts.map +1 -0
- package/dist/EffectParameterDefaults.js +27 -0
- package/dist/Engine.d.ts +1 -1
- package/dist/Engine.d.ts.map +1 -1
- package/dist/EngineFacade.d.ts +1 -1
- package/dist/EngineFacade.d.ts.map +1 -1
- package/dist/EngineFacade.js +1 -1
- package/dist/EngineWorklet.d.ts +1 -1
- package/dist/EngineWorklet.d.ts.map +1 -1
- package/dist/EngineWorklet.js +3 -2
- package/dist/Preferences.d.ts +20 -0
- package/dist/Preferences.d.ts.map +1 -0
- package/dist/Preferences.js +46 -0
- package/dist/capture/CaptureDevices.js +2 -2
- package/dist/capture/RecordTrack.d.ts +2 -2
- package/dist/capture/RecordTrack.d.ts.map +1 -1
- package/dist/capture/Recording.d.ts +1 -1
- package/dist/capture/Recording.d.ts.map +1 -1
- package/dist/capture/Recording.js +1 -1
- package/dist/dawproject/BuiltinDevices.d.ts.map +1 -1
- package/dist/dawproject/BuiltinDevices.js +3 -2
- package/dist/dawproject/{DawProjectImport.d.ts → DawProjectImporter.d.ts} +1 -1
- package/dist/dawproject/DawProjectImporter.d.ts.map +1 -0
- package/dist/dawproject/{DawProjectImport.js → DawProjectImporter.js} +17 -5
- package/dist/dawproject/DawProjectImporter.test.d.ts +2 -0
- package/dist/dawproject/DawProjectImporter.test.d.ts.map +1 -0
- package/dist/dawproject/{DawProjectImport.test.js → DawProjectImporter.test.js} +1 -1
- package/dist/dawproject/DawProjectService.js +1 -1
- package/dist/dawproject/index.d.ts +1 -1
- package/dist/dawproject/index.d.ts.map +1 -1
- package/dist/dawproject/index.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/midi/MIDILearning.d.ts +1 -1
- package/dist/midi/MIDILearning.d.ts.map +1 -1
- package/dist/midi/MIDILearning.js +22 -3
- package/dist/processors.js +12 -12
- package/dist/processors.js.map +4 -4
- package/dist/project/Project.d.ts +10 -6
- package/dist/project/Project.d.ts.map +1 -1
- package/dist/project/Project.js +43 -30
- package/dist/project/ProjectMigration.d.ts.map +1 -1
- package/dist/project/ProjectMigration.js +10 -1
- package/dist/project/Recovery.d.ts +9 -0
- package/dist/project/Recovery.d.ts.map +1 -0
- package/dist/project/Recovery.js +49 -0
- package/dist/project/index.d.ts +1 -0
- package/dist/project/index.d.ts.map +1 -1
- package/dist/project/index.js +1 -0
- package/dist/workers-main.js +2 -2
- package/dist/workers-main.js.map +4 -4
- package/package.json +49 -49
- package/dist/dawproject/DawProjectImport.d.ts.map +0 -1
- package/dist/dawproject/DawProjectImport.test.d.ts +0 -2
- package/dist/dawproject/DawProjectImport.test.d.ts.map +0 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Procedure, Terminable, TerminableOwner, Terminator } from "@opendaw/lib-std";
|
|
2
|
-
import {
|
|
1
|
+
import { Func, Procedure, Terminable, TerminableOwner, Terminator } from "@opendaw/lib-std";
|
|
2
|
+
import { BoxEditing, BoxGraph } from "@opendaw/lib-box";
|
|
3
3
|
import { AudioBusBox, AudioUnitBox, BoxIO, RootBox, TimelineBox, UserInterfaceBox } from "@opendaw/studio-boxes";
|
|
4
4
|
import { BoxAdapters, BoxAdaptersContext, ClipSequencing, ParameterFieldAdapters, ProcessorOptions, ProjectSkeleton, RootBoxAdapter, SampleLoaderManager, SoundfontLoaderManager, TimelineBoxAdapter, UserEditingManager, VertexSelection } from "@opendaw/studio-adapters";
|
|
5
5
|
import { LiveStreamBroadcaster, LiveStreamReceiver } from "@opendaw/lib-fusion";
|
|
@@ -11,23 +11,26 @@ import { EngineFacade } from "../EngineFacade";
|
|
|
11
11
|
import { EngineWorklet } from "../EngineWorklet";
|
|
12
12
|
import { MIDILearning } from "../midi";
|
|
13
13
|
export type RestartWorklet = {
|
|
14
|
-
unload:
|
|
14
|
+
unload: Func<unknown, Promise<unknown>>;
|
|
15
15
|
load: Procedure<EngineWorklet>;
|
|
16
16
|
};
|
|
17
|
+
export type ProjectCreateOptions = {
|
|
18
|
+
noDefaultUser?: boolean;
|
|
19
|
+
};
|
|
17
20
|
export declare class Project implements BoxAdaptersContext, Terminable, TerminableOwner {
|
|
18
21
|
#private;
|
|
19
|
-
static new(env: ProjectEnv): Project;
|
|
22
|
+
static new(env: ProjectEnv, options?: ProjectCreateOptions): Project;
|
|
20
23
|
static load(env: ProjectEnv, arrayBuffer: ArrayBuffer): Project;
|
|
21
24
|
static skeleton(env: ProjectEnv, skeleton: ProjectSkeleton): Project;
|
|
22
25
|
readonly boxGraph: BoxGraph<BoxIO.TypeMap>;
|
|
23
26
|
readonly rootBox: RootBox;
|
|
24
|
-
readonly
|
|
27
|
+
readonly userInterfaceBoxes: ReadonlyArray<UserInterfaceBox>;
|
|
25
28
|
readonly masterBusBox: AudioBusBox;
|
|
26
29
|
readonly masterAudioUnit: AudioUnitBox;
|
|
27
30
|
readonly timelineBox: TimelineBox;
|
|
28
31
|
readonly api: ProjectApi;
|
|
29
32
|
readonly captureDevices: CaptureDevices;
|
|
30
|
-
readonly editing:
|
|
33
|
+
readonly editing: BoxEditing;
|
|
31
34
|
readonly selection: VertexSelection;
|
|
32
35
|
readonly boxAdapters: BoxAdapters;
|
|
33
36
|
readonly userEditingManager: UserEditingManager;
|
|
@@ -39,6 +42,7 @@ export declare class Project implements BoxAdaptersContext, Terminable, Terminab
|
|
|
39
42
|
private constructor();
|
|
40
43
|
startAudioWorklet(restart?: RestartWorklet, options?: ProcessorOptions): EngineWorklet;
|
|
41
44
|
startRecording(countIn?: boolean): void;
|
|
45
|
+
follow(box: UserInterfaceBox): void;
|
|
42
46
|
own<T extends Terminable>(terminable: T): T;
|
|
43
47
|
ownAll<T extends Terminable>(...terminables: Array<T>): void;
|
|
44
48
|
spawn(): Terminator;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Project.d.ts","sourceRoot":"","sources":["../../src/project/Project.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"Project.d.ts","sourceRoot":"","sources":["../../src/project/Project.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,IAAI,EAGJ,SAAS,EAET,UAAU,EACV,eAAe,EACf,UAAU,EAEb,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAC,UAAU,EAAE,QAAQ,EAAC,MAAM,kBAAkB,CAAA;AACrD,OAAO,EACH,WAAW,EACX,YAAY,EACZ,KAAK,EAIL,OAAO,EACP,WAAW,EAEX,gBAAgB,EACnB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACH,WAAW,EACX,kBAAkB,EAClB,cAAc,EAEd,sBAAsB,EACtB,gBAAgB,EAGhB,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,sBAAsB,EACtB,kBAAkB,EAElB,kBAAkB,EAClB,eAAe,EAClB,MAAM,0BAA0B,CAAA;AACjC,OAAO,EAAC,qBAAqB,EAAE,kBAAkB,EAAC,MAAM,qBAAqB,CAAA;AAE7E,OAAO,EAAC,UAAU,EAAC,MAAM,cAAc,CAAA;AACvC,OAAO,EAAC,KAAK,EAAC,MAAM,UAAU,CAAA;AAC9B,OAAO,EAAC,UAAU,EAAC,MAAM,cAAc,CAAA;AAEvC,OAAO,EAAC,cAAc,EAAY,MAAM,YAAY,CAAA;AACpD,OAAO,EAAC,YAAY,EAAC,MAAM,iBAAiB,CAAA;AAC5C,OAAO,EAAC,aAAa,EAAC,MAAM,kBAAkB,CAAA;AAC9C,OAAO,EAAC,YAAY,EAAC,MAAM,SAAS,CAAA;AAIpC,MAAM,MAAM,cAAc,GAAG;IAAE,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IAAC,IAAI,EAAE,SAAS,CAAC,aAAa,CAAC,CAAA;CAAE,CAAA;AAExG,MAAM,MAAM,oBAAoB,GAAG;IAC/B,aAAa,CAAC,EAAE,OAAO,CAAA;CAC1B,CAAA;AAGD,qBAAa,OAAQ,YAAW,kBAAkB,EAAE,UAAU,EAAE,eAAe;;IAC3E,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO;IAoDpE,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,GAAG,OAAO;IAI/D,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,UAAU,EAAE,QAAQ,EAAE,eAAe,GAAG,OAAO;IASpE,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IAE1C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,kBAAkB,EAAE,aAAa,CAAC,gBAAgB,CAAC,CAAA;IAC5D,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAA;IAClC,QAAQ,CAAC,eAAe,EAAE,YAAY,CAAA;IACtC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAA;IAEjC,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAA;IACxB,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAA;IACvC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAA;IAC5B,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAA;IACnC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAA;IACjC,QAAQ,CAAC,kBAAkB,EAAE,kBAAkB,CAAA;IAC/C,QAAQ,CAAC,sBAAsB,EAAE,sBAAsB,CAAA;IACvD,QAAQ,CAAC,kBAAkB,EAAE,kBAAkB,CAAA;IAC/C,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAA;IACnC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;IACrB,QAAQ,CAAC,MAAM,eAAqB;IAEpC,OAAO;IAkCP,iBAAiB,CAAC,OAAO,CAAC,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,aAAa;IAoBtF,cAAc,CAAC,OAAO,GAAE,OAAc;IAMtC,MAAM,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI;IAKnC,GAAG,CAAC,CAAC,SAAS,UAAU,EAAE,UAAU,EAAE,CAAC,GAAG,CAAC;IAC3C,MAAM,CAAC,CAAC,SAAS,UAAU,EAAE,GAAG,WAAW,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI;IAC5D,KAAK,IAAI,UAAU;IAEnB,IAAI,GAAG,IAAI,UAAU,CAAmB;IACxC,IAAI,GAAG,IAAI,MAAM,CAAyC;IAC1D,IAAI,cAAc,IAAI,cAAc,CAAmE;IACvG,IAAI,kBAAkB,IAAI,kBAAkB,CAA2E;IACvH,IAAI,aAAa,IAAI,mBAAmB,CAAiC;IACzE,IAAI,gBAAgB,IAAI,sBAAsB,CAAoC;IAClF,IAAI,cAAc,IAAI,cAAc,CAAkD;IACtF,IAAI,cAAc,IAAI,OAAO,CAAe;IAC5C,IAAI,YAAY,IAAI,OAAO,CAAc;IACzC,IAAI,qBAAqB,IAAI,qBAAqB,CAAkD;IAEpG,IAAI,QAAQ,IAAI,eAAe,CAW9B;IAED,aAAa,IAAI,eAAe;IAUhC,IAAI,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,OAAO;IAIxC,OAAO,IAAI,OAAO;IAgBlB,SAAS,IAAI,IAAI;CAIpB"}
|
package/dist/project/Project.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Arrays, ByteArrayOutput, Option, panic, safeExecute, Terminator, UUID } from "@opendaw/lib-std";
|
|
2
|
-
import {
|
|
3
|
-
import { AudioBusBox, AudioUnitBox, BoxIO, GrooveShuffleBox, RootBox, TimelineBox, UserInterfaceBox } from "@opendaw/studio-boxes";
|
|
2
|
+
import { BoxEditing, BoxGraph } from "@opendaw/lib-box";
|
|
3
|
+
import { AudioBusBox, AudioUnitBox, BoxIO, CompressorDeviceBox, GrooveShuffleBox, RootBox, TimelineBox, UserInterfaceBox } from "@opendaw/studio-boxes";
|
|
4
4
|
import { BoxAdapters, IconSymbol, ParameterFieldAdapters, ProjectDecoder, RootBoxAdapter, TimelineBoxAdapter, UnionBoxTypes, UserEditingManager, VertexSelection } from "@opendaw/studio-adapters";
|
|
5
5
|
import { LiveStreamReceiver } from "@opendaw/lib-fusion";
|
|
6
6
|
import { AudioUnitType } from "@opendaw/studio-enums";
|
|
@@ -11,9 +11,10 @@ import { CaptureDevices, Recording } from "../capture";
|
|
|
11
11
|
import { EngineFacade } from "../EngineFacade";
|
|
12
12
|
import { MIDILearning } from "../midi";
|
|
13
13
|
import { ProjectValidation } from "./ProjectValidation";
|
|
14
|
+
import { Preferences } from "../Preferences";
|
|
14
15
|
// Main Entry Point for a Project
|
|
15
16
|
export class Project {
|
|
16
|
-
static new(env) {
|
|
17
|
+
static new(env, options) {
|
|
17
18
|
const boxGraph = new BoxGraph(Option.wrap(BoxIO.create));
|
|
18
19
|
const isoString = new Date().toISOString();
|
|
19
20
|
console.debug(`New Project created on ${isoString}`);
|
|
@@ -25,29 +26,42 @@ export class Project {
|
|
|
25
26
|
box.groove.refer(grooveShuffleBox);
|
|
26
27
|
box.created.setValue(isoString);
|
|
27
28
|
});
|
|
28
|
-
const
|
|
29
|
-
const masterBusBox = AudioBusBox.create(boxGraph, UUID.generate(), box => {
|
|
29
|
+
const primaryAudioBus = AudioBusBox.create(boxGraph, UUID.generate(), box => {
|
|
30
30
|
box.collection.refer(rootBox.audioBusses);
|
|
31
31
|
box.label.setValue("Output");
|
|
32
32
|
box.icon.setValue(IconSymbol.toName(IconSymbol.SpeakerHeadphone));
|
|
33
33
|
box.color.setValue(/*Colors.blue*/ "hsl(189, 100%, 65%)"); // TODO
|
|
34
34
|
});
|
|
35
|
-
const
|
|
35
|
+
const primaryAudioOutputUnit = AudioUnitBox.create(boxGraph, UUID.generate(), box => {
|
|
36
36
|
box.type.setValue(AudioUnitType.Output);
|
|
37
37
|
box.collection.refer(rootBox.audioUnits);
|
|
38
38
|
box.output.refer(rootBox.outputDevice);
|
|
39
39
|
box.index.setValue(0);
|
|
40
40
|
});
|
|
41
|
+
if (Preferences.values["auto-create-output-compressor"]) {
|
|
42
|
+
CompressorDeviceBox.create(boxGraph, UUID.generate(), box => {
|
|
43
|
+
box.label.setValue("Compressor");
|
|
44
|
+
box.index.setValue(0);
|
|
45
|
+
box.host.refer(primaryAudioOutputUnit.audioEffects);
|
|
46
|
+
box.threshold.setValue(0);
|
|
47
|
+
box.ratio.setValue(24);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
41
50
|
const timelineBox = TimelineBox.create(boxGraph, UUID.generate());
|
|
42
51
|
rootBox.timeline.refer(timelineBox.root);
|
|
43
|
-
|
|
44
|
-
|
|
52
|
+
primaryAudioBus.output.refer(primaryAudioOutputUnit.input);
|
|
53
|
+
const userInterfaceBoxes = [];
|
|
54
|
+
if (options?.noDefaultUser !== true) {
|
|
55
|
+
const userInterfaceBox = UserInterfaceBox.create(boxGraph, UUID.generate());
|
|
56
|
+
userInterfaceBox.root.refer(rootBox.users);
|
|
57
|
+
userInterfaceBoxes.push(userInterfaceBox);
|
|
58
|
+
}
|
|
45
59
|
boxGraph.endTransaction();
|
|
46
60
|
return new Project(env, boxGraph, {
|
|
47
61
|
rootBox,
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
62
|
+
primaryAudioBus,
|
|
63
|
+
primaryAudioOutputUnit,
|
|
64
|
+
userInterfaceBoxes,
|
|
51
65
|
timelineBox
|
|
52
66
|
});
|
|
53
67
|
}
|
|
@@ -63,7 +77,7 @@ export class Project {
|
|
|
63
77
|
#env;
|
|
64
78
|
boxGraph;
|
|
65
79
|
rootBox;
|
|
66
|
-
|
|
80
|
+
userInterfaceBoxes;
|
|
67
81
|
masterBusBox;
|
|
68
82
|
masterAudioUnit;
|
|
69
83
|
timelineBox;
|
|
@@ -78,26 +92,28 @@ export class Project {
|
|
|
78
92
|
midiLearning;
|
|
79
93
|
mixer;
|
|
80
94
|
engine = new EngineFacade();
|
|
81
|
-
constructor(env, boxGraph, { rootBox,
|
|
95
|
+
constructor(env, boxGraph, { rootBox, userInterfaceBoxes, primaryAudioBus, primaryAudioOutputUnit, timelineBox }) {
|
|
82
96
|
this.#env = env;
|
|
83
97
|
this.boxGraph = boxGraph;
|
|
84
98
|
this.rootBox = rootBox;
|
|
85
|
-
this.
|
|
86
|
-
this.masterBusBox =
|
|
87
|
-
this.masterAudioUnit =
|
|
99
|
+
this.userInterfaceBoxes = userInterfaceBoxes;
|
|
100
|
+
this.masterBusBox = primaryAudioBus;
|
|
101
|
+
this.masterAudioUnit = primaryAudioOutputUnit;
|
|
88
102
|
this.timelineBox = timelineBox;
|
|
89
103
|
this.api = new ProjectApi(this);
|
|
90
|
-
this.editing = new
|
|
104
|
+
this.editing = new BoxEditing(this.boxGraph);
|
|
91
105
|
this.selection = new VertexSelection(this.editing, this.boxGraph);
|
|
92
106
|
this.parameterFieldAdapters = new ParameterFieldAdapters();
|
|
93
107
|
this.boxAdapters = this.#terminator.own(new BoxAdapters(this));
|
|
94
108
|
this.userEditingManager = new UserEditingManager(this.editing);
|
|
95
|
-
this.userEditingManager.follow(this.userInterfaceBox);
|
|
96
|
-
this.selection.switch(this.userInterfaceBox.selection);
|
|
97
109
|
this.liveStreamReceiver = this.#terminator.own(new LiveStreamReceiver());
|
|
98
110
|
this.midiLearning = this.#terminator.own(new MIDILearning(this));
|
|
99
111
|
this.captureDevices = this.#terminator.own(new CaptureDevices(this));
|
|
100
112
|
this.mixer = new Mixer(this.rootBoxAdapter.audioUnits);
|
|
113
|
+
// TODO We are probably doing that from the outside
|
|
114
|
+
if (this.userInterfaceBoxes.length > 0) {
|
|
115
|
+
this.follow(this.userInterfaceBoxes[0]);
|
|
116
|
+
}
|
|
101
117
|
console.debug(`Project was created on ${this.rootBoxAdapter.created.toString()}`);
|
|
102
118
|
}
|
|
103
119
|
startAudioWorklet(restart, options) {
|
|
@@ -109,8 +125,8 @@ export class Project {
|
|
|
109
125
|
// we will only accept the first error
|
|
110
126
|
engine.removeEventListener("error", handler);
|
|
111
127
|
engine.removeEventListener("processorerror", handler);
|
|
112
|
-
safeExecute(restart?.unload, event);
|
|
113
128
|
lifecycle.terminate();
|
|
129
|
+
await safeExecute(restart?.unload, event);
|
|
114
130
|
safeExecute(restart?.load, this.startAudioWorklet(restart));
|
|
115
131
|
};
|
|
116
132
|
engine.addEventListener("error", handler);
|
|
@@ -126,6 +142,10 @@ export class Project {
|
|
|
126
142
|
}
|
|
127
143
|
Recording.start(this, countIn).finally();
|
|
128
144
|
}
|
|
145
|
+
follow(box) {
|
|
146
|
+
this.userEditingManager.follow(box);
|
|
147
|
+
this.selection.switch(box.selection);
|
|
148
|
+
}
|
|
129
149
|
own(terminable) { return this.#terminator.own(terminable); }
|
|
130
150
|
ownAll(...terminables) { return this.#terminator.ownAll(...terminables); }
|
|
131
151
|
spawn() { return this.#terminator.spawn(); }
|
|
@@ -145,9 +165,9 @@ export class Project {
|
|
|
145
165
|
mandatoryBoxes: {
|
|
146
166
|
rootBox: this.rootBox,
|
|
147
167
|
timelineBox: this.timelineBox,
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
168
|
+
primaryAudioBus: this.masterBusBox,
|
|
169
|
+
primaryAudioOutputUnit: this.masterAudioUnit,
|
|
170
|
+
userInterfaceBoxes: this.userInterfaceBoxes
|
|
151
171
|
}
|
|
152
172
|
};
|
|
153
173
|
}
|
|
@@ -155,16 +175,9 @@ export class Project {
|
|
|
155
175
|
const output = ByteArrayOutput.create();
|
|
156
176
|
output.writeInt(ProjectDecoder.MAGIC_HEADER_OPEN);
|
|
157
177
|
output.writeInt(ProjectDecoder.FORMAT_VERSION);
|
|
158
|
-
// store all boxes
|
|
159
178
|
const boxGraphChunk = this.boxGraph.toArrayBuffer();
|
|
160
179
|
output.writeInt(boxGraphChunk.byteLength);
|
|
161
180
|
output.writeBytes(new Int8Array(boxGraphChunk));
|
|
162
|
-
// store mandatory boxes' addresses
|
|
163
|
-
UUID.toDataOutput(output, this.rootBox.address.uuid);
|
|
164
|
-
UUID.toDataOutput(output, this.userInterfaceBox.address.uuid);
|
|
165
|
-
UUID.toDataOutput(output, this.masterBusBox.address.uuid);
|
|
166
|
-
UUID.toDataOutput(output, this.masterAudioUnit.address.uuid);
|
|
167
|
-
UUID.toDataOutput(output, this.timelineBox.address.uuid);
|
|
168
181
|
return output.toArrayBuffer();
|
|
169
182
|
}
|
|
170
183
|
copy(env) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProjectMigration.d.ts","sourceRoot":"","sources":["../../src/project/ProjectMigration.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ProjectMigration.d.ts","sourceRoot":"","sources":["../../src/project/ProjectMigration.ts"],"names":[],"mappings":"AAaA,OAAO,EAAC,eAAe,EAAC,MAAM,0BAA0B,CAAA;AAExD,qBAAa,gBAAgB;IACzB,MAAM,CAAC,OAAO,CAAC,EAAC,QAAQ,EAAE,cAAc,EAAC,EAAE,eAAe,GAAG,IAAI;CA4EpE"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CaptureAudioBox, CaptureMidiBox, GrooveShuffleBox, ValueEventCurveBox } from "@opendaw/studio-boxes";
|
|
2
|
-
import { asDefined, asInstanceOf, UUID } from "@opendaw/lib-std";
|
|
2
|
+
import { asDefined, asInstanceOf, clamp, UUID } from "@opendaw/lib-std";
|
|
3
3
|
import { AudioUnitType } from "@opendaw/studio-enums";
|
|
4
4
|
export class ProjectMigration {
|
|
5
5
|
static migrate({ boxGraph, mandatoryBoxes }) {
|
|
@@ -70,6 +70,15 @@ export class ProjectMigration {
|
|
|
70
70
|
}));
|
|
71
71
|
box.capture.refer(captureBox);
|
|
72
72
|
boxGraph.endTransaction();
|
|
73
|
+
},
|
|
74
|
+
visitRevampDeviceBox: (box) => {
|
|
75
|
+
// Clamp order in RevampDeviceBox to 0-3
|
|
76
|
+
// The older version stored the actual order,
|
|
77
|
+
// but the new version only stores indices, so 4 is not valid anymore
|
|
78
|
+
boxGraph.beginTransaction();
|
|
79
|
+
box.lowPass.order.setValue(clamp(box.lowPass.order.getValue(), 0, 3));
|
|
80
|
+
box.highPass.order.setValue(clamp(box.highPass.order.getValue(), 0, 3));
|
|
81
|
+
boxGraph.endTransaction();
|
|
73
82
|
}
|
|
74
83
|
}));
|
|
75
84
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Option, Provider } from "@opendaw/lib-std";
|
|
2
|
+
import { ProjectEnv, ProjectProfile } from "../";
|
|
3
|
+
export declare class Recovery {
|
|
4
|
+
#private;
|
|
5
|
+
constructor(projectProfileService: Provider<Option<ProjectProfile>>, env: ProjectEnv);
|
|
6
|
+
restoreProfile(): Promise<Option<ProjectProfile>>;
|
|
7
|
+
createBackupCommand(): Option<Provider<Promise<void>>>;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=Recovery.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Recovery.d.ts","sourceRoot":"","sources":["../../src/project/Recovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAE,QAAQ,EAAO,MAAM,kBAAkB,CAAA;AAEvD,OAAO,EAAU,UAAU,EAAe,cAAc,EAAU,MAAM,KAAK,CAAA;AAE7E,qBAAa,QAAQ;;gBAML,qBAAqB,EAAE,QAAQ,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,EAAE,GAAG,EAAE,UAAU;IAK9E,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;IAsBvD,mBAAmB,IAAI,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;CAgBzD"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Option, UUID } from "@opendaw/lib-std";
|
|
2
|
+
import { Promises } from "@opendaw/lib-runtime";
|
|
3
|
+
import { Project, ProjectProfile, Workers } from "../";
|
|
4
|
+
export class Recovery {
|
|
5
|
+
static #RESTORE_FILE_PATH = ".backup";
|
|
6
|
+
#projectProfileProvider;
|
|
7
|
+
#env;
|
|
8
|
+
constructor(projectProfileService, env) {
|
|
9
|
+
this.#projectProfileProvider = projectProfileService;
|
|
10
|
+
this.#env = env;
|
|
11
|
+
}
|
|
12
|
+
async restoreProfile() {
|
|
13
|
+
const backupResult = await Promises.tryCatch(Workers.Opfs.list(Recovery.#RESTORE_FILE_PATH));
|
|
14
|
+
if (backupResult.status === "rejected" || backupResult.value.length === 0) {
|
|
15
|
+
return Option.None;
|
|
16
|
+
}
|
|
17
|
+
const readResult = await Promises.tryCatch(Promise.all([
|
|
18
|
+
Workers.Opfs.read(`${Recovery.#RESTORE_FILE_PATH}/uuid`)
|
|
19
|
+
.then(x => UUID.validateBytes(x)),
|
|
20
|
+
Workers.Opfs.read(`${Recovery.#RESTORE_FILE_PATH}/project.od`)
|
|
21
|
+
.then(x => Project.load(this.#env, x.buffer)),
|
|
22
|
+
Workers.Opfs.read(`${Recovery.#RESTORE_FILE_PATH}/meta.json`)
|
|
23
|
+
.then(x => JSON.parse(new TextDecoder().decode(x.buffer))),
|
|
24
|
+
Workers.Opfs.read(`${Recovery.#RESTORE_FILE_PATH}/saved`)
|
|
25
|
+
.then(x => x.at(0) === 1)
|
|
26
|
+
]));
|
|
27
|
+
const deleteResult = await Promises.tryCatch(Workers.Opfs.delete(Recovery.#RESTORE_FILE_PATH));
|
|
28
|
+
console.debug(`delete backup: "${deleteResult.status}"`);
|
|
29
|
+
if (readResult.status === "rejected") {
|
|
30
|
+
return Option.None;
|
|
31
|
+
}
|
|
32
|
+
const [uuid, project, meta, saved] = readResult.value;
|
|
33
|
+
const profile = new ProjectProfile(uuid, project, meta, Option.None, saved);
|
|
34
|
+
console.debug(`restore ${profile}, saved: ${saved}`);
|
|
35
|
+
return Option.wrap(profile);
|
|
36
|
+
}
|
|
37
|
+
createBackupCommand() {
|
|
38
|
+
return this.#projectProfileProvider().map((profile) => async () => {
|
|
39
|
+
console.debug("backup project");
|
|
40
|
+
const { project, meta, uuid } = profile;
|
|
41
|
+
return Promises.tryCatch(Promise.all([
|
|
42
|
+
Workers.Opfs.write(`${Recovery.#RESTORE_FILE_PATH}/uuid`, uuid),
|
|
43
|
+
Workers.Opfs.write(`${Recovery.#RESTORE_FILE_PATH}/project.od`, new Uint8Array(project.toArrayBuffer())),
|
|
44
|
+
Workers.Opfs.write(`${Recovery.#RESTORE_FILE_PATH}/meta.json`, new TextEncoder().encode(JSON.stringify(meta))),
|
|
45
|
+
Workers.Opfs.write(`${Recovery.#RESTORE_FILE_PATH}/saved`, new Uint8Array([profile.saved() ? 1 : 0]))
|
|
46
|
+
])).then(result => console.debug(`backup result: ${result.status}`));
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
}
|
package/dist/project/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/project/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAC5B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA;AAC5B,cAAc,eAAe,CAAA;AAC7B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/project/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAC5B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,cAAc,CAAA;AAC5B,cAAc,eAAe,CAAA;AAC7B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,YAAY,CAAA"}
|
package/dist/project/index.js
CHANGED