@opendaw/studio-core 0.0.39 → 0.0.41
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/InstrumentFactories.d.ts.map +1 -1
- package/dist/InstrumentFactories.js +15 -12
- package/dist/capture/CaptureMidi.d.ts.map +1 -1
- package/dist/capture/CaptureMidi.js +8 -15
- package/dist/capture/RecordAudio.d.ts.map +1 -1
- package/dist/capture/RecordAudio.js +2 -1
- package/dist/capture/Recording.d.ts.map +1 -1
- package/dist/capture/Recording.js +1 -2
- package/dist/clouds/CloudAuthManager.js +2 -2
- package/dist/dawproject/DawProjectImport.d.ts +2 -2
- package/dist/dawproject/DawProjectImport.d.ts.map +1 -1
- package/dist/dawproject/DawProjectImport.js +4 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/midi/MidiDevices.d.ts +1 -1
- package/dist/midi/MidiDevices.d.ts.map +1 -1
- package/dist/midi/MidiDevices.js +3 -3
- package/dist/midi/SoftwareMIDIInput.d.ts.map +1 -1
- package/dist/midi/SoftwareMIDIInput.js +5 -1
- package/dist/processors.js +3 -3
- package/dist/processors.js.map +4 -4
- package/dist/project/Project.d.ts +3 -3
- package/dist/project/Project.d.ts.map +1 -1
- package/dist/project/Project.js +5 -4
- package/dist/project/ProjectMigration.d.ts +2 -2
- package/dist/project/ProjectMigration.d.ts.map +1 -1
- package/dist/project/ProjectMigration.js +0 -1
- package/dist/project/ProjectValidation.d.ts +5 -0
- package/dist/project/ProjectValidation.d.ts.map +1 -0
- package/dist/project/ProjectValidation.js +50 -0
- package/dist/samples/index.d.ts +0 -1
- package/dist/samples/index.d.ts.map +1 -1
- package/dist/samples/index.js +0 -1
- package/dist/ui/TimelineRange.d.ts +3 -1
- package/dist/ui/TimelineRange.d.ts.map +1 -1
- package/dist/ui/TimelineRange.js +7 -5
- package/dist/utils/AutofitUtils.d.ts +7 -0
- package/dist/utils/AutofitUtils.d.ts.map +1 -0
- package/dist/utils/AutofitUtils.js +78 -0
- package/dist/workers-main.js +2 -2
- package/dist/workers-main.js.map +3 -3
- package/dist/yjs/YMapper.d.ts +9 -0
- package/dist/yjs/YMapper.d.ts.map +1 -0
- package/dist/yjs/YMapper.js +45 -0
- package/dist/yjs/YService.d.ts +7 -0
- package/dist/yjs/YService.d.ts.map +1 -0
- package/dist/yjs/YService.js +69 -0
- package/dist/yjs/YSync.d.ts +17 -0
- package/dist/yjs/YSync.d.ts.map +1 -0
- package/dist/yjs/YSync.js +195 -0
- package/package.json +16 -16
- package/dist/samples/P2PSampleProvider.d.ts +0 -13
- package/dist/samples/P2PSampleProvider.d.ts.map +0 -1
- package/dist/samples/P2PSampleProvider.js +0 -350
@@ -0,0 +1,9 @@
|
|
1
|
+
import { Address, Box } from "@opendaw/lib-box";
|
2
|
+
import * as Y from "yjs";
|
3
|
+
export declare namespace YMapper {
|
4
|
+
const createBoxMap: (box: Box) => Y.Map<unknown>;
|
5
|
+
const applyFromBoxMap: (box: Box, source: Y.Map<unknown>) => void;
|
6
|
+
const pathToAddress: ([uuidAsString, _, ...fieldKeysFromPath]: ReadonlyArray<string | number>, leafKey: string) => Address;
|
7
|
+
const findMap: (map: Y.Map<unknown>, fieldKeys: ReadonlyArray<string | number>) => Y.Map<unknown>;
|
8
|
+
}
|
9
|
+
//# sourceMappingURL=YMapper.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"YMapper.d.ts","sourceRoot":"","sources":["../../src/yjs/YMapper.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,OAAO,EAEP,GAAG,EAON,MAAM,kBAAkB,CAAA;AACzB,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AAGxB,yBAAiB,OAAO,CAAC;IACd,MAAM,YAAY,GAAI,KAAK,GAAG,KAAG,CAAC,CAAC,GAAG,CAAC,OAAO,CAKpD,CAAA;IAEM,MAAM,eAAe,GAAI,KAAK,GAAG,EAAE,QAAQ,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,KAAG,IAgBlE,CAAA;IAEM,MAAM,aAAa,GAAI,yCAAyC,aAAa,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,SAAS,MAAM,KAAG,OAMxH,CAAA;IAEM,MAAM,OAAO,GAAI,KAAK,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,WAAW,aAAa,CAAC,MAAM,GAAG,MAAM,CAAC,KAAG,CAAC,CAAC,GAAG,CAAC,OAAO,CACS,CAAA;CAYlH"}
|
@@ -0,0 +1,45 @@
|
|
1
|
+
import { Address } from "@opendaw/lib-box";
|
2
|
+
import * as Y from "yjs";
|
3
|
+
import { asDefined, asInstanceOf, assert, isDefined, UUID } from "@opendaw/lib-std";
|
4
|
+
export var YMapper;
|
5
|
+
(function (YMapper) {
|
6
|
+
YMapper.createBoxMap = (box) => {
|
7
|
+
const map = new Y.Map();
|
8
|
+
map.set("name", box.name);
|
9
|
+
map.set("fields", createDeepMap(box.record()));
|
10
|
+
return map;
|
11
|
+
};
|
12
|
+
YMapper.applyFromBoxMap = (box, source) => {
|
13
|
+
const writeBranch = (vertex, map) => {
|
14
|
+
vertex.fields().forEach(field => {
|
15
|
+
const value = map.get(String(field.fieldKey));
|
16
|
+
field.accept({
|
17
|
+
visitArrayField: (field) => writeBranch(field, asInstanceOf(value, Y.Map)),
|
18
|
+
visitObjectField: (field) => writeBranch(field, asInstanceOf(value, Y.Map)),
|
19
|
+
// those will panic if the type is a mismatch
|
20
|
+
visitPointerField: (field) => field.fromJSON(value),
|
21
|
+
visitPrimitiveField: (field) => field.fromJSON(value)
|
22
|
+
});
|
23
|
+
});
|
24
|
+
};
|
25
|
+
writeBranch(box, source);
|
26
|
+
};
|
27
|
+
YMapper.pathToAddress = ([uuidAsString, _, ...fieldKeysFromPath], leafKey) => {
|
28
|
+
assert(isDefined(uuidAsString), "Invalid path");
|
29
|
+
const fieldKeys = new Int16Array(fieldKeysFromPath.length + 1);
|
30
|
+
fieldKeysFromPath.forEach((key, index) => fieldKeys[index] = Number(key));
|
31
|
+
fieldKeys[fieldKeysFromPath.length] = Number(leafKey);
|
32
|
+
return new Address(UUID.parse(String(uuidAsString)), fieldKeys);
|
33
|
+
};
|
34
|
+
YMapper.findMap = (map, fieldKeys) => fieldKeys.reduce((map, key) => asDefined(map.get(String(key)), "Could not findMap"), map);
|
35
|
+
const createDeepMap = (struct) => Object.entries(struct)
|
36
|
+
.reduce((map, [key, field]) => {
|
37
|
+
field.accept({
|
38
|
+
visitPrimitiveField: (field) => map.set(key, field.toJSON() ?? null),
|
39
|
+
visitPointerField: (field) => map.set(key, field.toJSON() ?? null),
|
40
|
+
visitArrayField: (field) => map.set(key, createDeepMap(field.record())),
|
41
|
+
visitObjectField: (field) => map.set(key, createDeepMap(field.record()))
|
42
|
+
});
|
43
|
+
return map;
|
44
|
+
}, new Y.Map());
|
45
|
+
})(YMapper || (YMapper = {}));
|
@@ -0,0 +1,7 @@
|
|
1
|
+
import { Option } from "@opendaw/lib-std";
|
2
|
+
import { ProjectEnv } from "../project/ProjectEnv";
|
3
|
+
import { Project } from "../project/Project";
|
4
|
+
export declare namespace YService {
|
5
|
+
const getOrCreateRoom: (optProject: Option<Project>, env: ProjectEnv, roomName: string) => Promise<Project>;
|
6
|
+
}
|
7
|
+
//# sourceMappingURL=YService.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"YService.d.ts","sourceRoot":"","sources":["../../src/yjs/YService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,MAAM,EAAmC,MAAM,kBAAkB,CAAA;AAQjF,OAAO,EAAC,UAAU,EAAC,MAAM,uBAAuB,CAAA;AAChD,OAAO,EAAC,OAAO,EAAC,MAAM,oBAAoB,CAAA;AAI1C,yBAAiB,QAAQ,CAAC;IAKf,MAAM,eAAe,GAAU,YAAY,MAAM,CAAC,OAAO,CAAC,EAC3B,KAAK,UAAU,EACf,UAAU,MAAM,KAAG,OAAO,CAAC,OAAO,CAiDvE,CAAA;CACJ"}
|
@@ -0,0 +1,69 @@
|
|
1
|
+
import { Errors, Option, panic, RuntimeNotifier, TimeSpan } from "@opendaw/lib-std";
|
2
|
+
import { BoxGraph } from "@opendaw/lib-box";
|
3
|
+
import { Promises } from "@opendaw/lib-runtime";
|
4
|
+
import { BoxIO } from "@opendaw/studio-boxes";
|
5
|
+
import { ProjectDecoder } from "@opendaw/studio-adapters";
|
6
|
+
import { YSync } from "./YSync";
|
7
|
+
import * as Y from "yjs";
|
8
|
+
import { WebsocketProvider } from "y-websocket";
|
9
|
+
import { Project } from "../project/Project";
|
10
|
+
// https://inspector.yjs.dev/
|
11
|
+
export var YService;
|
12
|
+
(function (YService) {
|
13
|
+
const { VITE_VJS_USE_LOCAL_SERVER, VITE_VJS_LOCAL_SERVER_URL, VITE_VJS_ONLINE_SERVER_URL } = import.meta.env;
|
14
|
+
const isDev = VITE_VJS_USE_LOCAL_SERVER === "true";
|
15
|
+
const serverUrl = isDev ? VITE_VJS_LOCAL_SERVER_URL : VITE_VJS_ONLINE_SERVER_URL;
|
16
|
+
YService.getOrCreateRoom = async (optProject, env, roomName) => {
|
17
|
+
if (roomName === "signaling") {
|
18
|
+
return panic("Invalid room name: signaling");
|
19
|
+
}
|
20
|
+
const doc = new Y.Doc();
|
21
|
+
const provider = new WebsocketProvider(serverUrl, roomName, doc);
|
22
|
+
console.debug("clientID:", doc.clientID);
|
23
|
+
console.debug("Provider url:", provider.url);
|
24
|
+
if (!provider.synced) {
|
25
|
+
const { resolve, promise } = Promise.withResolvers();
|
26
|
+
const onSync = (isSynced) => {
|
27
|
+
if (isSynced) {
|
28
|
+
provider.off("sync", onSync);
|
29
|
+
resolve();
|
30
|
+
}
|
31
|
+
};
|
32
|
+
provider.on("sync", onSync);
|
33
|
+
await Promises.timeout(promise, TimeSpan.seconds(10), "Timeout 'synced'");
|
34
|
+
}
|
35
|
+
const boxesMap = doc.getMap("boxes");
|
36
|
+
if (boxesMap.size === 0) {
|
37
|
+
const project = optProject.match({
|
38
|
+
none: () => Project.new(env),
|
39
|
+
some: project => project.copy()
|
40
|
+
});
|
41
|
+
const sync = await YSync.populate({ boxGraph: project.boxGraph, doc, conflict: () => project.invalid() });
|
42
|
+
project.own(sync);
|
43
|
+
project.editing.disable();
|
44
|
+
return project;
|
45
|
+
}
|
46
|
+
else {
|
47
|
+
if (optProject.nonEmpty()) {
|
48
|
+
const approved = await RuntimeNotifier.approve({
|
49
|
+
headline: "Room Already Exists",
|
50
|
+
message: "Do you want to join it?",
|
51
|
+
approveText: "Join",
|
52
|
+
cancelText: "Cancel"
|
53
|
+
});
|
54
|
+
if (!approved) {
|
55
|
+
return Promise.reject(Errors.AbortError);
|
56
|
+
}
|
57
|
+
}
|
58
|
+
const boxGraph = new BoxGraph(Option.wrap(BoxIO.create));
|
59
|
+
const sync = await YSync.join({ boxGraph, doc, conflict: () => project.invalid() });
|
60
|
+
const project = Project.skeleton(env, {
|
61
|
+
boxGraph,
|
62
|
+
mandatoryBoxes: ProjectDecoder.findMandatoryBoxes(boxGraph)
|
63
|
+
});
|
64
|
+
project.own(sync);
|
65
|
+
project.editing.disable();
|
66
|
+
return project;
|
67
|
+
}
|
68
|
+
};
|
69
|
+
})(YService || (YService = {}));
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import { Provider, Terminable } from "@opendaw/lib-std";
|
2
|
+
import { BoxGraph } from "@opendaw/lib-box";
|
3
|
+
import * as Y from "yjs";
|
4
|
+
export type Construct<T> = {
|
5
|
+
boxGraph: BoxGraph<T>;
|
6
|
+
doc: Y.Doc;
|
7
|
+
conflict?: Provider<boolean>;
|
8
|
+
};
|
9
|
+
export declare class YSync<T> implements Terminable {
|
10
|
+
#private;
|
11
|
+
static isEmpty(doc: Y.Doc): boolean;
|
12
|
+
static populate<T>({ boxGraph, doc }: Construct<T>): Promise<YSync<T>>;
|
13
|
+
static join<T>({ boxGraph, doc }: Construct<T>): Promise<YSync<T>>;
|
14
|
+
constructor({ boxGraph, doc, conflict }: Construct<T>);
|
15
|
+
terminate(): void;
|
16
|
+
}
|
17
|
+
//# sourceMappingURL=YSync.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"YSync.d.ts","sourceRoot":"","sources":["../../src/yjs/YSync.ts"],"names":[],"mappings":"AAAA,OAAO,EASH,QAAQ,EAER,UAAU,EAGb,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAa,QAAQ,EAA2D,MAAM,kBAAkB,CAAA;AAE/G,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AAIxB,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI;IACvB,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;IACtB,GAAG,EAAE,CAAC,CAAC,GAAG,CAAA;IACV,QAAQ,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;CAC/B,CAAA;AAED,qBAAa,KAAK,CAAC,CAAC,CAAE,YAAW,UAAU;;IACvC,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,GAAG,OAAO;WAItB,QAAQ,CAAC,CAAC,EAAE,EAAC,QAAQ,EAAE,GAAG,EAAC,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;WAa7D,IAAI,CAAC,CAAC,EAAE,EAAC,QAAQ,EAAE,GAAG,EAAC,EAAE,SAAS,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;gBA4B1D,EAAC,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAC,EAAE,SAAS,CAAC,CAAC,CAAC;IASnD,SAAS,IAAI,IAAI;CAkJpB"}
|
@@ -0,0 +1,195 @@
|
|
1
|
+
import { asDefined, assert, EmptyExec, isInstanceOf, isUndefined, Option, panic, Terminable, Terminator, UUID } from "@opendaw/lib-std";
|
2
|
+
import { YMapper } from "./YMapper";
|
3
|
+
import * as Y from "yjs";
|
4
|
+
export class YSync {
|
5
|
+
static isEmpty(doc) {
|
6
|
+
return doc.getMap("boxes").size === 0;
|
7
|
+
}
|
8
|
+
static async populate({ boxGraph, doc }) {
|
9
|
+
console.debug("populate");
|
10
|
+
const boxesMap = doc.getMap("boxes");
|
11
|
+
assert(boxesMap.size === 0, "BoxesMap must be empty");
|
12
|
+
const sync = new YSync({ boxGraph, doc });
|
13
|
+
doc.transact(() => boxGraph.boxes().forEach(box => {
|
14
|
+
const key = UUID.toString(box.address.uuid);
|
15
|
+
const map = YMapper.createBoxMap(box);
|
16
|
+
boxesMap.set(key, map);
|
17
|
+
}), "populate");
|
18
|
+
return sync;
|
19
|
+
}
|
20
|
+
static async join({ boxGraph, doc }) {
|
21
|
+
console.debug("join");
|
22
|
+
assert(boxGraph.boxes().length === 0, "BoxGraph must be empty");
|
23
|
+
const sync = new YSync({ boxGraph, doc });
|
24
|
+
boxGraph.beginTransaction();
|
25
|
+
const boxesMap = doc.getMap("boxes");
|
26
|
+
boxesMap.forEach((value, key) => {
|
27
|
+
const boxMap = value;
|
28
|
+
const uuid = UUID.parse(key);
|
29
|
+
const name = boxMap.get("name");
|
30
|
+
const fields = boxMap.get("fields");
|
31
|
+
boxGraph.createBox(name, uuid, box => YMapper.applyFromBoxMap(box, fields));
|
32
|
+
});
|
33
|
+
boxGraph.endTransaction();
|
34
|
+
boxGraph.verifyPointers();
|
35
|
+
return sync;
|
36
|
+
}
|
37
|
+
#terminator = new Terminator();
|
38
|
+
#boxGraph;
|
39
|
+
#doc;
|
40
|
+
#conflict;
|
41
|
+
#boxesMap;
|
42
|
+
#updates;
|
43
|
+
#ignoreUpdates = false;
|
44
|
+
constructor({ boxGraph, doc, conflict }) {
|
45
|
+
this.#boxGraph = boxGraph;
|
46
|
+
this.#doc = doc;
|
47
|
+
this.#conflict = Option.wrap(conflict);
|
48
|
+
this.#boxesMap = doc.getMap("boxes");
|
49
|
+
this.#updates = [];
|
50
|
+
this.#terminator.ownAll(this.#setupYjs(), this.#setupOpenDAW());
|
51
|
+
}
|
52
|
+
terminate() { this.#terminator.terminate(); }
|
53
|
+
#setupYjs() {
|
54
|
+
const eventHandler = (events, transaction) => {
|
55
|
+
console.debug("got updates", transaction.origin);
|
56
|
+
if (transaction.local) {
|
57
|
+
console.debug("Skip local update");
|
58
|
+
return;
|
59
|
+
}
|
60
|
+
this.#boxGraph.beginTransaction();
|
61
|
+
events.forEach(event => {
|
62
|
+
const path = event.path;
|
63
|
+
const keys = event.changes.keys;
|
64
|
+
keys.entries().forEach(([key, change]) => {
|
65
|
+
if (change.action === "add") {
|
66
|
+
assert(path.length === 0, "'Add' cannot have a path");
|
67
|
+
const map = this.#boxesMap.get(key);
|
68
|
+
const name = map.get("name");
|
69
|
+
const fields = map.get("fields");
|
70
|
+
const uuid = UUID.parse(key);
|
71
|
+
this.#boxGraph.createBox(name, uuid, box => YMapper.applyFromBoxMap(box, fields));
|
72
|
+
}
|
73
|
+
else if (change.action === "update") {
|
74
|
+
if (path.length === 0) {
|
75
|
+
return;
|
76
|
+
}
|
77
|
+
assert(path.length >= 2, "Invalid path: must have at least 2 elements (uuid, 'fields').");
|
78
|
+
this.#updateValue(path, key);
|
79
|
+
}
|
80
|
+
else if (change.action === "delete") {
|
81
|
+
assert(path.length === 0, "'Delete' cannot have a path");
|
82
|
+
const box = this.#boxGraph.findBox(UUID.parse(key))
|
83
|
+
.unwrap("Could not find box to delete");
|
84
|
+
// It is possible that Yjs have swallowed the pointer updates since were are 'inside' the box.
|
85
|
+
box.outgoingEdges().forEach(([pointer]) => pointer.defer());
|
86
|
+
box.incomingEdges().forEach(pointer => pointer.defer());
|
87
|
+
this.#boxGraph.unstageBox(box);
|
88
|
+
}
|
89
|
+
});
|
90
|
+
});
|
91
|
+
this.#ignoreUpdates = true;
|
92
|
+
this.#boxGraph.endTransaction();
|
93
|
+
this.#boxGraph.verifyPointers();
|
94
|
+
this.#ignoreUpdates = false;
|
95
|
+
const highLevelConflict = this.#conflict.mapOr(check => check(), false);
|
96
|
+
if (highLevelConflict) {
|
97
|
+
this.#rollbackTransaction(events);
|
98
|
+
}
|
99
|
+
};
|
100
|
+
this.#boxesMap.observeDeep(eventHandler);
|
101
|
+
return { terminate: () => { this.#boxesMap.unobserveDeep(eventHandler); } };
|
102
|
+
}
|
103
|
+
#updateValue(path, key) {
|
104
|
+
const [uuidAsString, fieldsKey, ...fieldKeys] = path;
|
105
|
+
const targetMap = YMapper.findMap(this.#boxesMap
|
106
|
+
.get(String(uuidAsString))
|
107
|
+
.get(String(fieldsKey)), fieldKeys);
|
108
|
+
const vertexOption = this.#boxGraph.findVertex(YMapper.pathToAddress(path, key));
|
109
|
+
const vertex = vertexOption.unwrap("Could not find field");
|
110
|
+
assert(vertex.isField(), "Vertex must be either Primitive or Pointer");
|
111
|
+
vertex.accept({
|
112
|
+
visitField: (_) => panic("Vertex must be either Primitive or Pointer"),
|
113
|
+
visitArrayField: (_) => panic("Vertex must be either Primitive or Pointer"),
|
114
|
+
visitObjectField: (_) => panic("Vertex must be either Primitive or Pointer"),
|
115
|
+
visitPointerField: (field) => field.fromJSON(targetMap.get(key)),
|
116
|
+
visitPrimitiveField: (field) => field.fromJSON(targetMap.get(key))
|
117
|
+
});
|
118
|
+
}
|
119
|
+
#rollbackTransaction(events) {
|
120
|
+
console.debug("rollbackTransaction", events.length);
|
121
|
+
for (let i = events.length - 1; i >= 0; i--) {
|
122
|
+
const event = events[i];
|
123
|
+
const target = event.target;
|
124
|
+
if (!isInstanceOf(target, Y.Map)) {
|
125
|
+
return panic("Only Y.Map events are supported");
|
126
|
+
}
|
127
|
+
Array.from(event.changes.keys.entries())
|
128
|
+
.reverse()
|
129
|
+
.forEach(([key, change]) => {
|
130
|
+
if (change.action === "add") {
|
131
|
+
target.delete(key);
|
132
|
+
}
|
133
|
+
else if (change.action === "update") {
|
134
|
+
if (isUndefined(change.oldValue)) {
|
135
|
+
target.delete(key);
|
136
|
+
}
|
137
|
+
else {
|
138
|
+
target.set(key, change.oldValue);
|
139
|
+
}
|
140
|
+
}
|
141
|
+
else if (change.action === "delete") {
|
142
|
+
target.set(key, change.oldValue);
|
143
|
+
}
|
144
|
+
});
|
145
|
+
}
|
146
|
+
}
|
147
|
+
#setupOpenDAW() {
|
148
|
+
return Terminable.many(this.#boxGraph.subscribeTransaction({
|
149
|
+
onBeginTransaction: EmptyExec,
|
150
|
+
onEndTransaction: () => {
|
151
|
+
if (this.#ignoreUpdates) {
|
152
|
+
this.#updates.length = 0;
|
153
|
+
return;
|
154
|
+
}
|
155
|
+
this.#doc.transact(() => this.#updates.forEach(update => {
|
156
|
+
/**
|
157
|
+
* TRANSFER CHANGES FROM OPENDAW TO LIVEBLOCKS
|
158
|
+
*/
|
159
|
+
if (update.type === "new") {
|
160
|
+
const uuid = update.uuid;
|
161
|
+
const key = UUID.toString(uuid);
|
162
|
+
const box = this.#boxGraph.findBox(uuid).unwrap();
|
163
|
+
this.#boxesMap.set(key, YMapper.createBoxMap(box));
|
164
|
+
}
|
165
|
+
else if (update.type === "primitive") {
|
166
|
+
const key = UUID.toString(update.address.uuid);
|
167
|
+
const boxObject = asDefined(this.#boxesMap.get(key), "Could not find box");
|
168
|
+
const { address: { fieldKeys }, newValue } = update;
|
169
|
+
let field = boxObject.get("fields");
|
170
|
+
for (let i = 0; i < fieldKeys.length - 1; i++) {
|
171
|
+
field = asDefined(field.get(String(fieldKeys[i])), `No field at '${fieldKeys[i]}'`);
|
172
|
+
}
|
173
|
+
field.set(String(fieldKeys[fieldKeys.length - 1]), newValue);
|
174
|
+
}
|
175
|
+
else if (update.type === "pointer") {
|
176
|
+
const key = UUID.toString(update.address.uuid);
|
177
|
+
const boxObject = asDefined(this.#boxesMap.get(key), "Could not find box");
|
178
|
+
const { address: { fieldKeys }, newAddress } = update;
|
179
|
+
let field = boxObject.get("fields");
|
180
|
+
for (let i = 0; i < fieldKeys.length - 1; i++) {
|
181
|
+
field = asDefined(field.get(String(fieldKeys[i])), `No field at '${fieldKeys[i]}'`);
|
182
|
+
}
|
183
|
+
field.set(String(fieldKeys[fieldKeys.length - 1]), newAddress.mapOr(address => address.toString(), null));
|
184
|
+
}
|
185
|
+
else if (update.type === "delete") {
|
186
|
+
this.#boxesMap.delete(UUID.toString(update.uuid));
|
187
|
+
}
|
188
|
+
}), "openDAW");
|
189
|
+
this.#updates.length = 0;
|
190
|
+
}
|
191
|
+
}), this.#boxGraph.subscribeToAllUpdatesImmediate({
|
192
|
+
onUpdate: (update) => this.#updates.push(update)
|
193
|
+
}));
|
194
|
+
}
|
195
|
+
}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@opendaw/studio-core",
|
3
|
-
"version": "0.0.
|
3
|
+
"version": "0.0.41",
|
4
4
|
"license": "LGPL-3.0-or-later",
|
5
5
|
"publishConfig": {
|
6
6
|
"access": "public"
|
@@ -28,26 +28,26 @@
|
|
28
28
|
"dependencies": {
|
29
29
|
"@liveblocks/client": "^3.7.1",
|
30
30
|
"@liveblocks/yjs": "^3.7.1",
|
31
|
-
"@opendaw/lib-box": "^0.0.
|
32
|
-
"@opendaw/lib-dawproject": "^0.0.
|
33
|
-
"@opendaw/lib-dom": "^0.0.
|
34
|
-
"@opendaw/lib-dsp": "^0.0.
|
35
|
-
"@opendaw/lib-fusion": "^0.0.
|
36
|
-
"@opendaw/lib-runtime": "^0.0.
|
37
|
-
"@opendaw/lib-std": "^0.0.
|
38
|
-
"@opendaw/studio-adapters": "^0.0.
|
39
|
-
"@opendaw/studio-boxes": "^0.0.
|
40
|
-
"@opendaw/studio-enums": "^0.0.
|
31
|
+
"@opendaw/lib-box": "^0.0.32",
|
32
|
+
"@opendaw/lib-dawproject": "^0.0.18",
|
33
|
+
"@opendaw/lib-dom": "^0.0.32",
|
34
|
+
"@opendaw/lib-dsp": "^0.0.32",
|
35
|
+
"@opendaw/lib-fusion": "^0.0.32",
|
36
|
+
"@opendaw/lib-runtime": "^0.0.32",
|
37
|
+
"@opendaw/lib-std": "^0.0.32",
|
38
|
+
"@opendaw/studio-adapters": "^0.0.33",
|
39
|
+
"@opendaw/studio-boxes": "^0.0.32",
|
40
|
+
"@opendaw/studio-enums": "^0.0.23",
|
41
41
|
"dropbox": "^10.34.0",
|
42
|
-
"y-
|
42
|
+
"y-websocket": "^1.4.5",
|
43
43
|
"yjs": "^13.6.27"
|
44
44
|
},
|
45
45
|
"devDependencies": {
|
46
46
|
"@opendaw/eslint-config": "^0.0.19",
|
47
|
-
"@opendaw/studio-core-processors": "^0.0.
|
48
|
-
"@opendaw/studio-core-workers": "^0.0.
|
49
|
-
"@opendaw/studio-forge-boxes": "^0.0.
|
47
|
+
"@opendaw/studio-core-processors": "^0.0.33",
|
48
|
+
"@opendaw/studio-core-workers": "^0.0.28",
|
49
|
+
"@opendaw/studio-forge-boxes": "^0.0.32",
|
50
50
|
"@opendaw/typescript-config": "^0.0.20"
|
51
51
|
},
|
52
|
-
"gitHead": "
|
52
|
+
"gitHead": "705da8c69733c18fbae25c63f87cba8a367b8b38"
|
53
53
|
}
|
@@ -1,13 +0,0 @@
|
|
1
|
-
import { Progress, UUID } from "@opendaw/lib-std";
|
2
|
-
import { AudioData, SampleMetaData } from "@opendaw/studio-adapters";
|
3
|
-
import * as Y from "yjs";
|
4
|
-
import { WebrtcProvider } from "y-webrtc";
|
5
|
-
import { SampleProvider } from "./SampleProvider";
|
6
|
-
export declare class P2PSampleProvider implements SampleProvider {
|
7
|
-
#private;
|
8
|
-
static create(doc: Y.Doc, provider: WebrtcProvider): P2PSampleProvider;
|
9
|
-
constructor(doc: Y.Doc, provider: WebrtcProvider);
|
10
|
-
fetch(uuid: UUID.Bytes, progress: Progress.Handler): Promise<[AudioData, SampleMetaData]>;
|
11
|
-
share(uuidAsString: string, audioData: AudioData, peaks: ArrayBuffer, metadata: SampleMetaData): Promise<void>;
|
12
|
-
}
|
13
|
-
//# sourceMappingURL=P2PSampleProvider.d.ts.map
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"P2PSampleProvider.d.ts","sourceRoot":"","sources":["../../src/samples/P2PSampleProvider.ts"],"names":[],"mappings":"AAAA,OAAO,EAA8C,QAAQ,EAAE,IAAI,EAAC,MAAM,kBAAkB,CAAA;AAC5F,OAAO,EAAC,SAAS,EAAE,cAAc,EAAC,MAAM,0BAA0B,CAAA;AAClE,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AACxB,OAAO,EAAC,cAAc,EAAC,MAAM,UAAU,CAAA;AACvC,OAAO,EAAC,cAAc,EAAC,MAAM,kBAAkB,CAAA;AAkC/C,qBAAa,iBAAkB,YAAW,cAAc;;IACpD,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,QAAQ,EAAE,cAAc,GAAG,iBAAiB;gBAc1D,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,QAAQ,EAAE,cAAc;IAY1C,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,CAAC,OAAO,GAAG,OAAO,CAAC,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;IAmDzF,KAAK,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;CAkSvH"}
|