@opendaw/studio-core 0.0.99 → 0.0.101

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.
Files changed (91) hide show
  1. package/dist/EffectFactories.d.ts.map +1 -1
  2. package/dist/EffectFactories.js +39 -24
  3. package/dist/Engine.d.ts +2 -0
  4. package/dist/Engine.d.ts.map +1 -1
  5. package/dist/EngineFacade.d.ts +2 -0
  6. package/dist/EngineFacade.d.ts.map +1 -1
  7. package/dist/EngineFacade.js +3 -0
  8. package/dist/EngineWorklet.d.ts +2 -0
  9. package/dist/EngineWorklet.d.ts.map +1 -1
  10. package/dist/EngineWorklet.js +10 -2
  11. package/dist/HRClockWorker.d.ts +7 -0
  12. package/dist/HRClockWorker.d.ts.map +1 -0
  13. package/dist/HRClockWorker.js +54 -0
  14. package/dist/OfflineEngineRenderer.d.ts.map +1 -1
  15. package/dist/OfflineEngineRenderer.js +5 -2
  16. package/dist/RecordingWorklet.d.ts +2 -1
  17. package/dist/RecordingWorklet.d.ts.map +1 -1
  18. package/dist/RecordingWorklet.js +9 -1
  19. package/dist/Storage.d.ts.map +1 -1
  20. package/dist/Storage.js +1 -0
  21. package/dist/StudioPreferences.d.ts +8 -0
  22. package/dist/StudioPreferences.d.ts.map +1 -1
  23. package/dist/StudioSettings.d.ts +13 -0
  24. package/dist/StudioSettings.d.ts.map +1 -1
  25. package/dist/StudioSettings.js +15 -0
  26. package/dist/capture/CaptureAudio.d.ts.map +1 -1
  27. package/dist/capture/CaptureAudio.js +8 -11
  28. package/dist/capture/RecordAudio.d.ts.map +1 -1
  29. package/dist/capture/RecordAudio.js +1 -0
  30. package/dist/processors.js +24 -24
  31. package/dist/processors.js.map +4 -4
  32. package/dist/project/Project.d.ts +6 -1
  33. package/dist/project/Project.d.ts.map +1 -1
  34. package/dist/project/Project.js +34 -2
  35. package/dist/project/ProjectApi.d.ts.map +1 -1
  36. package/dist/project/ProjectApi.js +14 -3
  37. package/dist/project/audio/AudioContentFactory.d.ts +5 -0
  38. package/dist/project/audio/AudioContentFactory.d.ts.map +1 -1
  39. package/dist/project/audio/AudioContentFactory.js +13 -0
  40. package/dist/ui/{generic → clipboard}/ClipboardManager.d.ts +3 -3
  41. package/dist/ui/clipboard/ClipboardManager.d.ts.map +1 -0
  42. package/dist/ui/{generic → clipboard}/ClipboardManager.js +70 -14
  43. package/dist/ui/clipboard/ClipboardUtils.d.ts +12 -0
  44. package/dist/ui/clipboard/ClipboardUtils.d.ts.map +1 -0
  45. package/dist/ui/clipboard/ClipboardUtils.js +94 -0
  46. package/dist/ui/{generic → clipboard}/ContextMenu.d.ts +1 -1
  47. package/dist/ui/clipboard/ContextMenu.d.ts.map +1 -0
  48. package/dist/ui/{generic → clipboard}/ContextMenu.js +1 -1
  49. package/dist/ui/clipboard/types/AudioUnitsClipboardHandler.d.ts +18 -0
  50. package/dist/ui/clipboard/types/AudioUnitsClipboardHandler.d.ts.map +1 -0
  51. package/dist/ui/clipboard/types/AudioUnitsClipboardHandler.js +215 -0
  52. package/dist/ui/clipboard/types/DevicesClipboardHandler.d.ts +18 -0
  53. package/dist/ui/clipboard/types/DevicesClipboardHandler.d.ts.map +1 -0
  54. package/dist/ui/clipboard/types/DevicesClipboardHandler.js +188 -0
  55. package/dist/ui/clipboard/types/NotesClipboardHandler.d.ts +21 -0
  56. package/dist/ui/clipboard/types/NotesClipboardHandler.d.ts.map +1 -0
  57. package/dist/ui/clipboard/types/NotesClipboardHandler.js +72 -0
  58. package/dist/ui/clipboard/types/RegionsClipboardHandler.d.ts +24 -0
  59. package/dist/ui/clipboard/types/RegionsClipboardHandler.d.ts.map +1 -0
  60. package/dist/ui/clipboard/types/RegionsClipboardHandler.js +137 -0
  61. package/dist/ui/clipboard/types/ValuesClipboardHandler.d.ts +22 -0
  62. package/dist/ui/clipboard/types/ValuesClipboardHandler.d.ts.map +1 -0
  63. package/dist/ui/clipboard/types/ValuesClipboardHandler.js +135 -0
  64. package/dist/ui/index.d.ts +14 -3
  65. package/dist/ui/index.d.ts.map +1 -1
  66. package/dist/ui/index.js +14 -3
  67. package/dist/ui/menu/MenuItems.d.ts.map +1 -0
  68. package/dist/ui/timeline/RegionClipResolver.d.ts +5 -1
  69. package/dist/ui/timeline/RegionClipResolver.d.ts.map +1 -1
  70. package/dist/ui/timeline/RegionClipResolver.js +5 -1
  71. package/dist/ui/timeline/RegionKeepExistingResolver.d.ts +34 -0
  72. package/dist/ui/timeline/RegionKeepExistingResolver.d.ts.map +1 -0
  73. package/dist/ui/timeline/RegionKeepExistingResolver.js +171 -0
  74. package/dist/ui/timeline/RegionOverlapResolver.d.ts +33 -0
  75. package/dist/ui/timeline/RegionOverlapResolver.d.ts.map +1 -0
  76. package/dist/ui/timeline/RegionOverlapResolver.js +79 -0
  77. package/dist/ui/timeline/RegionPushExistingResolver.d.ts +31 -0
  78. package/dist/ui/timeline/RegionPushExistingResolver.d.ts.map +1 -0
  79. package/dist/ui/timeline/RegionPushExistingResolver.js +159 -0
  80. package/dist/ui/timeline/TimelineFocus.d.ts +14 -0
  81. package/dist/ui/timeline/TimelineFocus.d.ts.map +1 -0
  82. package/dist/ui/timeline/TimelineFocus.js +45 -0
  83. package/dist/ui/timeline/TrackResolver.d.ts +11 -0
  84. package/dist/ui/timeline/TrackResolver.d.ts.map +1 -0
  85. package/dist/ui/timeline/TrackResolver.js +5 -0
  86. package/package.json +62 -61
  87. package/dist/ui/generic/ClipboardManager.d.ts.map +0 -1
  88. package/dist/ui/generic/ContextMenu.d.ts.map +0 -1
  89. package/dist/ui/generic/MenuItems.d.ts.map +0 -1
  90. /package/dist/ui/{generic → menu}/MenuItems.d.ts +0 -0
  91. /package/dist/ui/{generic → menu}/MenuItems.js +0 -0
@@ -0,0 +1,33 @@
1
+ import { Exec, int } from "@opendaw/lib-std";
2
+ import { ppqn } from "@opendaw/lib-dsp";
3
+ import { BoxEditing } from "@opendaw/lib-box";
4
+ import { AnyRegionBoxAdapter, BoxAdapters, TrackBoxAdapter } from "@opendaw/studio-adapters";
5
+ import { RegionModifyStrategies } from "./RegionModifyStrategies";
6
+ import { ProjectApi } from "../../project";
7
+ import { TrackResolver } from "./TrackResolver";
8
+ export declare class RegionOverlapResolver {
9
+ #private;
10
+ constructor(editing: BoxEditing, projectApi: ProjectApi, boxAdapters: BoxAdapters);
11
+ /**
12
+ * For selection-based operations (move, resize, copy).
13
+ * @param tracks - The tracks involved in the operation
14
+ * @param adapters - The region adapters being modified
15
+ * @param strategy - The modify strategy (determines if it's a copy, etc.)
16
+ * @param deltaIndex - Track index delta (for cross-track moves)
17
+ * @param changes - Callback that performs the actual changes. Receives a TrackResolver
18
+ * that should be used to determine target tracks for copies.
19
+ */
20
+ apply(tracks: ReadonlyArray<TrackBoxAdapter>, adapters: ReadonlyArray<AnyRegionBoxAdapter>, strategy: RegionModifyStrategies, deltaIndex: int, changes: (trackResolver: TrackResolver) => void): void;
21
+ /**
22
+ * For range-based operations (drop, duplicate).
23
+ * Returns the target track to use (may differ from input track for keep-existing mode).
24
+ */
25
+ resolveTargetTrack(track: TrackBoxAdapter, position: ppqn, complete: ppqn): TrackBoxAdapter;
26
+ /**
27
+ * Creates a resolver function for range-based operations (to be called inside an existing transaction).
28
+ * Call this BEFORE creating the region to capture the "before" state.
29
+ * Then call the returned function AFTER creating the region.
30
+ */
31
+ fromRange(track: TrackBoxAdapter, position: ppqn, complete: ppqn): Exec;
32
+ }
33
+ //# sourceMappingURL=RegionOverlapResolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RegionOverlapResolver.d.ts","sourceRoot":"","sources":["../../../src/ui/timeline/RegionOverlapResolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,IAAI,EAAE,GAAG,EAAC,MAAM,kBAAkB,CAAA;AAC1C,OAAO,EAAC,IAAI,EAAC,MAAM,kBAAkB,CAAA;AACrC,OAAO,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAA;AAC3C,OAAO,EAAC,mBAAmB,EAAE,WAAW,EAAE,eAAe,EAAC,MAAM,0BAA0B,CAAA;AAC1F,OAAO,EAAC,sBAAsB,EAAC,MAAM,0BAA0B,CAAA;AAK/D,OAAO,EAAC,UAAU,EAAC,MAAM,eAAe,CAAA;AACxC,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAA;AAE7C,qBAAa,qBAAqB;;gBAKlB,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW;IAMjF;;;;;;;;OAQG;IACH,KAAK,CAAC,MAAM,EAAE,aAAa,CAAC,eAAe,CAAC,EACtC,QAAQ,EAAE,aAAa,CAAC,mBAAmB,CAAC,EAC5C,QAAQ,EAAE,sBAAsB,EAChC,UAAU,EAAE,GAAG,EACf,OAAO,EAAE,CAAC,aAAa,EAAE,aAAa,KAAK,IAAI,GAAG,IAAI;IA2B5D;;;OAGG;IACH,kBAAkB,CAAC,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,GAAG,eAAe;IAS3F;;;;OAIG;IACH,SAAS,CAAC,KAAK,EAAE,eAAe,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,GAAG,IAAI;CAW1E"}
@@ -0,0 +1,79 @@
1
+ import { RegionClipResolver } from "./RegionClipResolver";
2
+ import { RegionKeepExistingResolver } from "./RegionKeepExistingResolver";
3
+ import { RegionPushExistingResolver } from "./RegionPushExistingResolver";
4
+ import { StudioPreferences } from "../../StudioPreferences";
5
+ export class RegionOverlapResolver {
6
+ #editing;
7
+ #projectApi;
8
+ #boxAdapters;
9
+ constructor(editing, projectApi, boxAdapters) {
10
+ this.#editing = editing;
11
+ this.#projectApi = projectApi;
12
+ this.#boxAdapters = boxAdapters;
13
+ }
14
+ /**
15
+ * For selection-based operations (move, resize, copy).
16
+ * @param tracks - The tracks involved in the operation
17
+ * @param adapters - The region adapters being modified
18
+ * @param strategy - The modify strategy (determines if it's a copy, etc.)
19
+ * @param deltaIndex - Track index delta (for cross-track moves)
20
+ * @param changes - Callback that performs the actual changes. Receives a TrackResolver
21
+ * that should be used to determine target tracks for copies.
22
+ */
23
+ apply(tracks, adapters, strategy, deltaIndex, changes) {
24
+ const behaviour = StudioPreferences.settings.editing["overlapping-regions-behaviour"];
25
+ if (behaviour === "clip") {
26
+ const { postProcess, trackResolver } = RegionClipResolver.fromSelection(tracks, adapters, strategy, deltaIndex);
27
+ this.#editing.modify(() => {
28
+ changes(trackResolver);
29
+ postProcess();
30
+ });
31
+ RegionClipResolver.validateTracks(tracks);
32
+ }
33
+ else if (behaviour === "push-existing") {
34
+ const { postProcess, trackResolver } = RegionPushExistingResolver.fromSelection(tracks, adapters, strategy, deltaIndex, this.#projectApi, this.#boxAdapters);
35
+ this.#editing.modify(() => {
36
+ changes(trackResolver);
37
+ postProcess();
38
+ });
39
+ }
40
+ else {
41
+ // keep-existing
42
+ const { postProcess, trackResolver } = RegionKeepExistingResolver.fromSelection(tracks, adapters, strategy, deltaIndex, this.#projectApi, this.#boxAdapters);
43
+ this.#editing.modify(() => {
44
+ changes(trackResolver);
45
+ postProcess();
46
+ });
47
+ }
48
+ }
49
+ /**
50
+ * For range-based operations (drop, duplicate).
51
+ * Returns the target track to use (may differ from input track for keep-existing mode).
52
+ */
53
+ resolveTargetTrack(track, position, complete) {
54
+ const behaviour = StudioPreferences.settings.editing["overlapping-regions-behaviour"];
55
+ if (behaviour === "keep-existing") {
56
+ return RegionKeepExistingResolver
57
+ .resolveTargetTrack(track, position, complete, this.#projectApi, this.#boxAdapters);
58
+ }
59
+ return track;
60
+ }
61
+ /**
62
+ * Creates a resolver function for range-based operations (to be called inside an existing transaction).
63
+ * Call this BEFORE creating the region to capture the "before" state.
64
+ * Then call the returned function AFTER creating the region.
65
+ */
66
+ fromRange(track, position, complete) {
67
+ const behaviour = StudioPreferences.settings.editing["overlapping-regions-behaviour"];
68
+ if (behaviour === "clip") {
69
+ return RegionClipResolver.fromRange(track, position, complete);
70
+ }
71
+ else if (behaviour === "push-existing") {
72
+ return RegionPushExistingResolver.fromRange(track, position, complete, this.#projectApi, this.#boxAdapters);
73
+ }
74
+ else {
75
+ // keep-existing: nothing to do after creation - caller should use resolveTargetTrack before creating
76
+ return () => { };
77
+ }
78
+ }
79
+ }
@@ -0,0 +1,31 @@
1
+ import { Exec, int } from "@opendaw/lib-std";
2
+ import { ppqn } from "@opendaw/lib-dsp";
3
+ import { AnyRegionBoxAdapter, BoxAdapters, TrackBoxAdapter } from "@opendaw/studio-adapters";
4
+ import { RegionModifyStrategies } from "./RegionModifyStrategies";
5
+ import { ProjectApi } from "../../project";
6
+ import { TrackResolver } from "./TrackResolver";
7
+ /**
8
+ * Resolver for "push-existing" overlap behavior.
9
+ * When overlap is detected, the EXISTING (overlapped) regions move to a track below.
10
+ * Incoming regions stay where they were placed.
11
+ */
12
+ export declare class RegionPushExistingResolver {
13
+ #private;
14
+ /**
15
+ * For selection-based operations (move, resize).
16
+ * Returns:
17
+ * - postProcess: function to call AFTER changes are applied
18
+ * - trackResolver: Identity (incoming regions stay where placed)
19
+ */
20
+ static fromSelection(tracks: ReadonlyArray<TrackBoxAdapter>, adapters: ReadonlyArray<AnyRegionBoxAdapter>, strategy: RegionModifyStrategies, deltaIndex: int, projectApi: ProjectApi, boxAdapters: BoxAdapters): {
21
+ postProcess: Exec;
22
+ trackResolver: TrackResolver;
23
+ };
24
+ /**
25
+ * For range-based operations (drop, duplicate).
26
+ * Returns a function that should be called AFTER the region is created.
27
+ */
28
+ static fromRange(track: TrackBoxAdapter, position: ppqn, complete: ppqn, projectApi: ProjectApi, boxAdapters: BoxAdapters): Exec;
29
+ private constructor();
30
+ }
31
+ //# sourceMappingURL=RegionPushExistingResolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RegionPushExistingResolver.d.ts","sourceRoot":"","sources":["../../../src/ui/timeline/RegionPushExistingResolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,IAAI,EAAE,GAAG,EAAsB,MAAM,kBAAkB,CAAA;AAC1E,OAAO,EAAC,IAAI,EAAC,MAAM,kBAAkB,CAAA;AACrC,OAAO,EAAC,mBAAmB,EAAE,WAAW,EAAE,eAAe,EAAY,MAAM,0BAA0B,CAAA;AAErG,OAAO,EAAC,sBAAsB,EAAC,MAAM,0BAA0B,CAAA;AAC/D,OAAO,EAAC,UAAU,EAAC,MAAM,eAAe,CAAA;AACxC,OAAO,EAAC,aAAa,EAAC,MAAM,iBAAiB,CAAA;AAE7C;;;;GAIG;AACH,qBAAa,0BAA0B;;IACnC;;;;;OAKG;IACH,MAAM,CAAC,aAAa,CAAC,MAAM,EAAE,aAAa,CAAC,eAAe,CAAC,EACtC,QAAQ,EAAE,aAAa,CAAC,mBAAmB,CAAC,EAC5C,QAAQ,EAAE,sBAAsB,EAChC,UAAU,EAAE,GAAG,EACf,UAAU,EAAE,UAAU,EACtB,WAAW,EAAE,WAAW,GAAG;QAAE,WAAW,EAAE,IAAI,CAAC;QAAC,aAAa,EAAE,aAAa,CAAA;KAAE;IA6BnG;;;OAGG;IACH,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,eAAe,EACtB,QAAQ,EAAE,IAAI,EACd,QAAQ,EAAE,IAAI,EACd,UAAU,EAAE,UAAU,EACtB,WAAW,EAAE,WAAW,GAAG,IAAI;IAqEhD,OAAO;CAsBV"}
@@ -0,0 +1,159 @@
1
+ import { EmptyExec, isDefined } from "@opendaw/lib-std";
2
+ import { TrackBoxAdapter, TrackType } from "@opendaw/studio-adapters";
3
+ import { TrackResolver } from "./TrackResolver";
4
+ /**
5
+ * Resolver for "push-existing" overlap behavior.
6
+ * When overlap is detected, the EXISTING (overlapped) regions move to a track below.
7
+ * Incoming regions stay where they were placed.
8
+ */
9
+ export class RegionPushExistingResolver {
10
+ /**
11
+ * For selection-based operations (move, resize).
12
+ * Returns:
13
+ * - postProcess: function to call AFTER changes are applied
14
+ * - trackResolver: Identity (incoming regions stay where placed)
15
+ */
16
+ static fromSelection(tracks, adapters, strategy, deltaIndex, projectApi, boxAdapters) {
17
+ const resolver = new RegionPushExistingResolver(projectApi, boxAdapters);
18
+ // Capture overlapped regions BEFORE changes
19
+ for (const track of tracks) {
20
+ const selectedStrategy = strategy.selectedModifyStrategy();
21
+ const overlapped = [];
22
+ for (const adapter of adapters) {
23
+ const adapterTrackIndex = adapter.trackBoxAdapter.unwrap().listIndex + deltaIndex;
24
+ if (adapterTrackIndex !== track.listIndex) {
25
+ continue;
26
+ }
27
+ const position = selectedStrategy.readPosition(adapter);
28
+ const complete = selectedStrategy.readComplete(adapter);
29
+ for (const region of track.regions.collection.iterateRange(0, complete)) {
30
+ if (region.complete <= position) {
31
+ continue;
32
+ }
33
+ if (region.position >= complete) {
34
+ break;
35
+ }
36
+ if (region.isSelected && !strategy.showOrigin()) {
37
+ continue;
38
+ }
39
+ if (!overlapped.includes(region)) {
40
+ overlapped.push(region);
41
+ }
42
+ }
43
+ }
44
+ if (overlapped.length > 0) {
45
+ resolver.#overlappedByTrack.set(track, overlapped);
46
+ }
47
+ }
48
+ return {
49
+ postProcess: () => resolver.#solve(),
50
+ trackResolver: TrackResolver.Identity
51
+ };
52
+ }
53
+ /**
54
+ * For range-based operations (drop, duplicate).
55
+ * Returns a function that should be called AFTER the region is created.
56
+ */
57
+ static fromRange(track, position, complete, projectApi, boxAdapters) {
58
+ if (track.type === TrackType.Value) {
59
+ return () => { };
60
+ }
61
+ // Find overlapped regions BEFORE changes
62
+ const overlapped = [];
63
+ for (const region of track.regions.collection.iterateRange(0, complete)) {
64
+ if (region.complete <= position) {
65
+ continue;
66
+ }
67
+ if (region.position >= complete) {
68
+ break;
69
+ }
70
+ overlapped.push(region);
71
+ }
72
+ if (overlapped.length === 0) {
73
+ return EmptyExec;
74
+ }
75
+ return () => {
76
+ const targetTrack = RegionPushExistingResolver.#findOrCreateTrackBelow(track, overlapped, projectApi, boxAdapters);
77
+ if (isDefined(targetTrack)) {
78
+ for (const region of overlapped) {
79
+ region.box.regions.refer(targetTrack.box.regions);
80
+ }
81
+ track.regions.dispatchChange();
82
+ targetTrack.regions.dispatchChange();
83
+ }
84
+ };
85
+ }
86
+ static #findOrCreateTrackBelow(sourceTrack, regionsToPlace, projectApi, boxAdapters) {
87
+ const trackType = sourceTrack.type;
88
+ if (trackType === TrackType.Value) {
89
+ return undefined;
90
+ }
91
+ const minPosition = Math.min(...regionsToPlace.map(region => region.position));
92
+ const maxComplete = Math.max(...regionsToPlace.map(region => region.complete));
93
+ const audioUnit = sourceTrack.audioUnit;
94
+ // Get all tracks of same type in this audio unit, sorted by index
95
+ const siblingTracks = audioUnit.tracks.pointerHub.incoming()
96
+ .map(vertex => vertex.box)
97
+ .filter(trackBox => trackBox.type.getValue() === trackType)
98
+ .sort((boxA, boxB) => boxA.index.getValue() - boxB.index.getValue());
99
+ const sourceIndex = sourceTrack.indexField.getValue();
100
+ // Look for existing track below with space
101
+ for (const trackBox of siblingTracks) {
102
+ if (trackBox.index.getValue() <= sourceIndex) {
103
+ continue;
104
+ }
105
+ if (RegionPushExistingResolver.#hasSpace(trackBox, minPosition, maxComplete)) {
106
+ return boxAdapters.adapterFor(trackBox, TrackBoxAdapter);
107
+ }
108
+ }
109
+ // No suitable existing track found, create new track below source
110
+ const insertIndex = sourceIndex + 1;
111
+ const newTrackBox = trackType === TrackType.Audio
112
+ ? projectApi.createAudioTrack(audioUnit, insertIndex)
113
+ : projectApi.createNoteTrack(audioUnit, insertIndex);
114
+ return boxAdapters.adapterFor(newTrackBox, TrackBoxAdapter);
115
+ }
116
+ static #hasSpace(trackBox, position, complete) {
117
+ for (const vertex of trackBox.regions.pointerHub.incoming()) {
118
+ const regionPosition = vertex.box.position.getValue();
119
+ const regionDuration = vertex.box.duration.getValue();
120
+ const regionComplete = regionPosition + regionDuration;
121
+ if (regionComplete <= position) {
122
+ continue;
123
+ }
124
+ if (regionPosition >= complete) {
125
+ continue;
126
+ }
127
+ return false;
128
+ }
129
+ return true;
130
+ }
131
+ #projectApi;
132
+ #boxAdapters;
133
+ #overlappedByTrack;
134
+ constructor(projectApi, boxAdapters) {
135
+ this.#projectApi = projectApi;
136
+ this.#boxAdapters = boxAdapters;
137
+ this.#overlappedByTrack = new Map();
138
+ }
139
+ #solve() {
140
+ const affectedTracks = [];
141
+ for (const [track, overlapped] of this.#overlappedByTrack) {
142
+ const targetTrack = RegionPushExistingResolver.#findOrCreateTrackBelow(track, overlapped, this.#projectApi, this.#boxAdapters);
143
+ if (!isDefined(targetTrack)) {
144
+ continue;
145
+ }
146
+ if (!affectedTracks.includes(targetTrack)) {
147
+ affectedTracks.push(targetTrack);
148
+ }
149
+ if (!affectedTracks.includes(track)) {
150
+ affectedTracks.push(track);
151
+ }
152
+ for (const region of overlapped) {
153
+ region.box.regions.refer(targetTrack.box.regions);
154
+ }
155
+ }
156
+ // Dispatch change on all affected tracks to ensure UI updates
157
+ affectedTracks.forEach(track => track.regions.dispatchChange());
158
+ }
159
+ }
@@ -0,0 +1,14 @@
1
+ import { MutableObservableOption, Terminable } from "@opendaw/lib-std";
2
+ import { AnyRegionBoxAdapter, TrackBoxAdapter } from "@opendaw/studio-adapters";
3
+ export declare class TimelineFocus implements Terminable {
4
+ #private;
5
+ constructor();
6
+ get track(): MutableObservableOption<TrackBoxAdapter>;
7
+ get region(): MutableObservableOption<AnyRegionBoxAdapter>;
8
+ focusTrack(track: TrackBoxAdapter): void;
9
+ focusRegion(region: AnyRegionBoxAdapter): void;
10
+ clearRegionFocus(): void;
11
+ clear(): void;
12
+ terminate(): void;
13
+ }
14
+ //# sourceMappingURL=TimelineFocus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TimelineFocus.d.ts","sourceRoot":"","sources":["../../../src/ui/timeline/TimelineFocus.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,uBAAuB,EAAE,UAAU,EAAa,MAAM,kBAAkB,CAAA;AAChF,OAAO,EAAC,mBAAmB,EAAE,eAAe,EAAC,MAAM,0BAA0B,CAAA;AAE7E,qBAAa,aAAc,YAAW,UAAU;;;IAY5C,IAAI,KAAK,IAAI,uBAAuB,CAAC,eAAe,CAAC,CAAqB;IAC1E,IAAI,MAAM,IAAI,uBAAuB,CAAC,mBAAmB,CAAC,CAAsB;IAEhF,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI;IAWxC,WAAW,CAAC,MAAM,EAAE,mBAAmB,GAAG,IAAI;IAW9C,gBAAgB,IAAI,IAAI;IAKxB,KAAK,IAAI,IAAI;IAOb,SAAS,IAAI,IAAI;CACpB"}
@@ -0,0 +1,45 @@
1
+ import { MutableObservableOption, Terminator } from "@opendaw/lib-std";
2
+ export class TimelineFocus {
3
+ #terminator = new Terminator();
4
+ #trackSubscription = this.#terminator.own(new Terminator());
5
+ #regionSubscription = this.#terminator.own(new Terminator());
6
+ #track;
7
+ #region;
8
+ constructor() {
9
+ this.#track = this.#terminator.own(new MutableObservableOption());
10
+ this.#region = this.#terminator.own(new MutableObservableOption());
11
+ }
12
+ get track() { return this.#track; }
13
+ get region() { return this.#region; }
14
+ focusTrack(track) {
15
+ this.#trackSubscription.terminate();
16
+ this.#trackSubscription.own(track.box.subscribeDeletion(() => {
17
+ console.debug("TimelineFocus: track deleted");
18
+ this.#trackSubscription.terminate();
19
+ this.#track.clear();
20
+ }));
21
+ this.#track.wrap(track);
22
+ this.clearRegionFocus();
23
+ }
24
+ focusRegion(region) {
25
+ region.trackBoxAdapter.ifSome(track => this.focusTrack(track));
26
+ this.#regionSubscription.terminate();
27
+ this.#regionSubscription.own(region.box.subscribeDeletion(() => {
28
+ console.debug("TimelineFocus: region deleted");
29
+ this.#regionSubscription.terminate();
30
+ this.#region.clear();
31
+ }));
32
+ this.#region.wrap(region);
33
+ }
34
+ clearRegionFocus() {
35
+ this.#regionSubscription.terminate();
36
+ this.#region.clear();
37
+ }
38
+ clear() {
39
+ this.#trackSubscription.terminate();
40
+ this.#regionSubscription.terminate();
41
+ this.#track.clear();
42
+ this.#region.clear();
43
+ }
44
+ terminate() { this.#terminator.terminate(); }
45
+ }
@@ -0,0 +1,11 @@
1
+ import { AnyRegionBoxAdapter, TrackBoxAdapter } from "@opendaw/studio-adapters";
2
+ /**
3
+ * Function to resolve the target track for a region.
4
+ * Used by overlap resolvers to provide track overrides for copy operations.
5
+ */
6
+ export type TrackResolver = (adapter: AnyRegionBoxAdapter, defaultTrack: TrackBoxAdapter) => TrackBoxAdapter;
7
+ export declare namespace TrackResolver {
8
+ /** Identity resolver - always returns the default track */
9
+ const Identity: TrackResolver;
10
+ }
11
+ //# sourceMappingURL=TrackResolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TrackResolver.d.ts","sourceRoot":"","sources":["../../../src/ui/timeline/TrackResolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,mBAAmB,EAAE,eAAe,EAAC,MAAM,0BAA0B,CAAA;AAE7E;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,eAAe,KAAK,eAAe,CAAA;AAE5G,yBAAiB,aAAa,CAAC;IAC3B,2DAA2D;IACpD,MAAM,QAAQ,EAAE,aAAwD,CAAA;CAClF"}
@@ -0,0 +1,5 @@
1
+ export var TrackResolver;
2
+ (function (TrackResolver) {
3
+ /** Identity resolver - always returns the default track */
4
+ TrackResolver.Identity = (_adapter, defaultTrack) => defaultTrack;
5
+ })(TrackResolver || (TrackResolver = {}));
package/package.json CHANGED
@@ -1,65 +1,66 @@
1
1
  {
2
- "name": "@opendaw/studio-core",
3
- "version": "0.0.99",
4
- "license": "LGPL-3.0-or-later",
5
- "publishConfig": {
6
- "access": "public"
2
+ "name": "@opendaw/studio-core",
3
+ "version": "0.0.101",
4
+ "license": "LGPL-3.0-or-later",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "main": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
7
14
  },
8
- "main": "./dist/index.js",
9
- "types": "./dist/index.d.ts",
10
- "exports": {
11
- ".": {
12
- "types": "./dist/index.d.ts",
13
- "default": "./dist/index.js"
14
- },
15
- "./FFmpegWorker": {
16
- "types": "./dist/ffmpeg/FFmpegWorker.d.ts",
17
- "default": "./dist/ffmpeg/FFmpegWorker.js"
18
- },
19
- "./workers-main.js": "./dist/workers-main.js",
20
- "./processors.js": "./dist/processors.js",
21
- "./offline-engine.js": "./dist/offline-engine.js"
15
+ "./FFmpegWorker": {
16
+ "types": "./dist/ffmpeg/FFmpegWorker.d.ts",
17
+ "default": "./dist/ffmpeg/FFmpegWorker.js"
22
18
  },
23
- "files": [
24
- "dist/**",
25
- "dist/workers-main.js",
26
- "dist/processors.js",
27
- "dist/offline-engine.js",
28
- "dist/ffmpeg/FFmpegWorker.js"
29
- ],
30
- "scripts": {
31
- "build": "tsc",
32
- "lint": "eslint \"**/*.ts\"",
33
- "test": "vitest run --config vitest.config.ts"
34
- },
35
- "dependencies": {
36
- "@opendaw/lib-box": "^0.0.69",
37
- "@opendaw/lib-dawproject": "^0.0.54",
38
- "@opendaw/lib-dom": "^0.0.70",
39
- "@opendaw/lib-dsp": "^0.0.68",
40
- "@opendaw/lib-fusion": "^0.0.74",
41
- "@opendaw/lib-runtime": "^0.0.66",
42
- "@opendaw/lib-std": "^0.0.65",
43
- "@opendaw/studio-adapters": "^0.0.79",
44
- "@opendaw/studio-boxes": "^0.0.71",
45
- "@opendaw/studio-enums": "^0.0.60",
46
- "dropbox": "^10.34.0",
47
- "y-websocket": "^1.4.5",
48
- "yjs": "^13.6.27",
49
- "zod": "^4.1.12"
50
- },
51
- "peerDependencies": {
52
- "@ffmpeg/ffmpeg": "^0.12.15",
53
- "@ffmpeg/util": "^0.12.2"
54
- },
55
- "devDependencies": {
56
- "@ffmpeg/ffmpeg": "^0.12.15",
57
- "@ffmpeg/util": "^0.12.2",
58
- "@opendaw/eslint-config": "^0.0.27",
59
- "@opendaw/studio-core-processors": "^0.0.82",
60
- "@opendaw/studio-core-workers": "^0.0.74",
61
- "@opendaw/studio-forge-boxes": "^0.0.71",
62
- "@opendaw/typescript-config": "^0.0.28"
63
- },
64
- "gitHead": "182679bcfec5f187c52b2cb1e867098cf6d0f766"
19
+ "./workers-main.js": "./dist/workers-main.js",
20
+ "./processors.js": "./dist/processors.js",
21
+ "./offline-engine.js": "./dist/offline-engine.js"
22
+ },
23
+ "files": [
24
+ "dist/**",
25
+ "dist/workers-main.js",
26
+ "dist/processors.js",
27
+ "dist/offline-engine.js",
28
+ "dist/ffmpeg/FFmpegWorker.js"
29
+ ],
30
+ "scripts": {
31
+ "build": "tsc",
32
+ "lint": "eslint \"**/*.ts\"",
33
+ "test": "vitest run --config vitest.config.ts"
34
+ },
35
+ "dependencies": {
36
+ "@opendaw/lib-box": "^0.0.70",
37
+ "@opendaw/lib-dawproject": "^0.0.55",
38
+ "@opendaw/lib-dom": "^0.0.71",
39
+ "@opendaw/lib-dsp": "^0.0.69",
40
+ "@opendaw/lib-fusion": "^0.0.75",
41
+ "@opendaw/lib-runtime": "^0.0.67",
42
+ "@opendaw/lib-std": "^0.0.66",
43
+ "@opendaw/nam-wasm": "^1.0.3",
44
+ "@opendaw/studio-adapters": "^0.0.80",
45
+ "@opendaw/studio-boxes": "^0.0.72",
46
+ "@opendaw/studio-enums": "^0.0.61",
47
+ "dropbox": "^10.34.0",
48
+ "y-websocket": "^1.4.5",
49
+ "yjs": "^13.6.27",
50
+ "zod": "^4.1.12"
51
+ },
52
+ "peerDependencies": {
53
+ "@ffmpeg/ffmpeg": "^0.12.15",
54
+ "@ffmpeg/util": "^0.12.2"
55
+ },
56
+ "devDependencies": {
57
+ "@ffmpeg/ffmpeg": "^0.12.15",
58
+ "@ffmpeg/util": "^0.12.2",
59
+ "@opendaw/eslint-config": "^0.0.27",
60
+ "@opendaw/studio-core-processors": "^0.0.83",
61
+ "@opendaw/studio-core-workers": "^0.0.75",
62
+ "@opendaw/studio-forge-boxes": "^0.0.72",
63
+ "@opendaw/typescript-config": "^0.0.28"
64
+ },
65
+ "gitHead": "a23a423a60a8b0cebfb973224ffb6eddd6fb6943"
65
66
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"ClipboardManager.d.ts","sourceRoot":"","sources":["../../../src/ui/generic/ClipboardManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAa,MAAM,kBAAkB,CAAA;AAOpF,MAAM,MAAM,cAAc,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,CAAC,SAAS,SAAS,GAAG,SAAS,IAAI;IACrF,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAA;IAChB,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAA;CACnB,CAAA;AAED,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,cAAc;IACtD,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAA;IAChC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAA;IAC/B,QAAQ,CAAC,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAA;IACxD,IAAI,IAAI,MAAM,CAAC,CAAC,CAAC,CAAA;IACjB,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,CAAA;IAChB,KAAK,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAAA;CACrC;AAED,yBAAiB,gBAAgB,CAAC;IAC9B,KAAK,QAAQ,GAAG,cAAc,CAAA;IAS9B,MAAM,CAAC,MAAM,OAAO,GAAI,CAAC,SAAS,QAAQ,EAAE,SAAS,WAAW,EAAE,SAAS,gBAAgB,CAAC,CAAC,CAAC,KAAG,YAqEhG,CAAA;;CACJ"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ContextMenu.d.ts","sourceRoot":"","sources":["../../../src/ui/generic/ContextMenu.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,MAAM,EAAU,YAAY,EAAC,MAAM,kBAAkB,CAAA;AAE7D,OAAO,EAAC,QAAQ,EAAe,MAAM,aAAa,CAAA;AAElD,yBAAiB,WAAW,CAAC;IAClB,MAAM,uBAAuB,EAAG,gBAAyB,CAAA;IAEhE,KAAY,WAAW,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAA;IAEtE,UAAiB,SAAS;QACtB,QAAQ,CAAC,GAAG,KAAK,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAA;QAEpC,IAAI,MAAM,IAAI,MAAM,CAAA;KACvB;IAqCM,MAAM,OAAO,GAAI,OAAO,WAAW,EAAE,aAAa,WAAW,KAAG,YAkBhD,CAAA;IAEhB,MAAM,SAAS,GAAI,QAAQ,WAAW,EAAE,SAAS,CAAC,SAAS,EAAE,SAAS,KAAK,OAAO,KAAG,YAI/D,CAAA;CAChC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"MenuItems.d.ts","sourceRoot":"","sources":["../../../src/ui/generic/MenuItems.ts"],"names":[],"mappings":"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"}
File without changes
File without changes