@waveform-playlist/browser 11.0.1 → 11.2.0
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/index.d.mts +15 -20
- package/dist/index.d.ts +15 -20
- package/dist/index.js +487 -405
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +366 -283
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -10
package/dist/index.js
CHANGED
|
@@ -122,7 +122,7 @@ __export(index_exports, {
|
|
|
122
122
|
effectDefinitions: () => effectDefinitions,
|
|
123
123
|
getEffectDefinition: () => getEffectDefinition,
|
|
124
124
|
getEffectsByCategory: () => getEffectsByCategory,
|
|
125
|
-
getShortcutLabel: () => getShortcutLabel,
|
|
125
|
+
getShortcutLabel: () => import_core3.getShortcutLabel,
|
|
126
126
|
getWaveformDataMetadata: () => getWaveformDataMetadata,
|
|
127
127
|
loadPeaksFromWaveformData: () => loadPeaksFromWaveformData,
|
|
128
128
|
loadWaveformData: () => loadWaveformData,
|
|
@@ -161,7 +161,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
161
161
|
var Tone2 = __toESM(require("tone"));
|
|
162
162
|
|
|
163
163
|
// src/WaveformPlaylistContext.tsx
|
|
164
|
-
var
|
|
164
|
+
var import_react24 = require("react");
|
|
165
165
|
var import_styled_components = require("styled-components");
|
|
166
166
|
var import_playout5 = require("@waveform-playlist/playout");
|
|
167
167
|
var import_engine3 = require("@waveform-playlist/engine");
|
|
@@ -172,11 +172,13 @@ var import_tone4 = require("tone");
|
|
|
172
172
|
var import_waveform_data = __toESM(require("waveform-data"));
|
|
173
173
|
function loadWaveformData(src) {
|
|
174
174
|
return __async(this, null, function* () {
|
|
175
|
+
var _a, _b;
|
|
175
176
|
const response = yield fetch(src);
|
|
176
177
|
if (!response.ok) {
|
|
177
178
|
throw new Error(`Failed to fetch waveform data: ${response.statusText}`);
|
|
178
179
|
}
|
|
179
|
-
const
|
|
180
|
+
const { pathname } = new URL(src, (_b = (_a = globalThis.location) == null ? void 0 : _a.href) != null ? _b : "http://localhost");
|
|
181
|
+
const isBinary = pathname.toLowerCase().endsWith(".dat");
|
|
180
182
|
if (isBinary) {
|
|
181
183
|
const arrayBuffer = yield response.arrayBuffer();
|
|
182
184
|
return import_waveform_data.default.create(arrayBuffer);
|
|
@@ -542,12 +544,52 @@ function useSelectedTrack({ engineRef }) {
|
|
|
542
544
|
};
|
|
543
545
|
}
|
|
544
546
|
|
|
545
|
-
// src/hooks/
|
|
547
|
+
// src/hooks/useUndoState.ts
|
|
546
548
|
var import_react7 = require("react");
|
|
549
|
+
function useUndoState({ engineRef }) {
|
|
550
|
+
const [canUndo, setCanUndo] = (0, import_react7.useState)(false);
|
|
551
|
+
const [canRedo, setCanRedo] = (0, import_react7.useState)(false);
|
|
552
|
+
const canUndoRef = (0, import_react7.useRef)(false);
|
|
553
|
+
const canRedoRef = (0, import_react7.useRef)(false);
|
|
554
|
+
const undo = (0, import_react7.useCallback)(() => {
|
|
555
|
+
if (!engineRef.current) {
|
|
556
|
+
console.warn("[waveform-playlist] undo: engine not ready, call ignored");
|
|
557
|
+
return;
|
|
558
|
+
}
|
|
559
|
+
engineRef.current.undo();
|
|
560
|
+
}, [engineRef]);
|
|
561
|
+
const redo = (0, import_react7.useCallback)(() => {
|
|
562
|
+
if (!engineRef.current) {
|
|
563
|
+
console.warn("[waveform-playlist] redo: engine not ready, call ignored");
|
|
564
|
+
return;
|
|
565
|
+
}
|
|
566
|
+
engineRef.current.redo();
|
|
567
|
+
}, [engineRef]);
|
|
568
|
+
const onEngineState = (0, import_react7.useCallback)((state) => {
|
|
569
|
+
if (state.canUndo !== canUndoRef.current) {
|
|
570
|
+
canUndoRef.current = state.canUndo;
|
|
571
|
+
setCanUndo(state.canUndo);
|
|
572
|
+
}
|
|
573
|
+
if (state.canRedo !== canRedoRef.current) {
|
|
574
|
+
canRedoRef.current = state.canRedo;
|
|
575
|
+
setCanRedo(state.canRedo);
|
|
576
|
+
}
|
|
577
|
+
}, []);
|
|
578
|
+
return {
|
|
579
|
+
canUndo,
|
|
580
|
+
canRedo,
|
|
581
|
+
undo,
|
|
582
|
+
redo,
|
|
583
|
+
onEngineState
|
|
584
|
+
};
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
// src/hooks/useAudioEffects.ts
|
|
588
|
+
var import_react8 = require("react");
|
|
547
589
|
var import_tone = require("tone");
|
|
548
590
|
var useMasterAnalyser = (fftSize = 256) => {
|
|
549
|
-
const analyserRef = (0,
|
|
550
|
-
const masterEffects = (0,
|
|
591
|
+
const analyserRef = (0, import_react8.useRef)(null);
|
|
592
|
+
const masterEffects = (0, import_react8.useCallback)(
|
|
551
593
|
(masterGainNode, destination, _isOffline) => {
|
|
552
594
|
const analyserNode = new import_tone.Analyser("fft", fftSize);
|
|
553
595
|
masterGainNode.connect(analyserNode);
|
|
@@ -564,7 +606,7 @@ var useMasterAnalyser = (fftSize = 256) => {
|
|
|
564
606
|
};
|
|
565
607
|
|
|
566
608
|
// src/hooks/useAudioTracks.ts
|
|
567
|
-
var
|
|
609
|
+
var import_react9 = require("react");
|
|
568
610
|
var import_core = require("@waveform-playlist/core");
|
|
569
611
|
var Tone = __toESM(require("tone"));
|
|
570
612
|
function buildTrackFromConfig(config, index, audioBuffer, stableIds, contextSampleRate = 48e3) {
|
|
@@ -622,14 +664,14 @@ function buildTrackFromConfig(config, index, audioBuffer, stableIds, contextSamp
|
|
|
622
664
|
function useAudioTracks(configs, options = {}) {
|
|
623
665
|
const { immediate = false, progressive = false } = options;
|
|
624
666
|
const isImmediate = immediate || progressive;
|
|
625
|
-
const [loading, setLoading] = (0,
|
|
626
|
-
const [error, setError] = (0,
|
|
627
|
-
const [loadedCount, setLoadedCount] = (0,
|
|
667
|
+
const [loading, setLoading] = (0, import_react9.useState)(true);
|
|
668
|
+
const [error, setError] = (0, import_react9.useState)(null);
|
|
669
|
+
const [loadedCount, setLoadedCount] = (0, import_react9.useState)(0);
|
|
628
670
|
const totalCount = configs.length;
|
|
629
|
-
const [loadedBuffers, setLoadedBuffers] = (0,
|
|
630
|
-
const stableIdsRef = (0,
|
|
631
|
-
const contextSampleRateRef = (0,
|
|
632
|
-
const derivedTracks = (0,
|
|
671
|
+
const [loadedBuffers, setLoadedBuffers] = (0, import_react9.useState)(/* @__PURE__ */ new Map());
|
|
672
|
+
const stableIdsRef = (0, import_react9.useRef)(/* @__PURE__ */ new Map());
|
|
673
|
+
const contextSampleRateRef = (0, import_react9.useRef)(48e3);
|
|
674
|
+
const derivedTracks = (0, import_react9.useMemo)(() => {
|
|
633
675
|
if (!isImmediate) return null;
|
|
634
676
|
const result = [];
|
|
635
677
|
for (let i = 0; i < configs.length; i++) {
|
|
@@ -644,13 +686,13 @@ function useAudioTracks(configs, options = {}) {
|
|
|
644
686
|
}
|
|
645
687
|
return result;
|
|
646
688
|
}, [isImmediate, configs, loadedBuffers]);
|
|
647
|
-
const [tracks, setTracks] = (0,
|
|
648
|
-
const prevDerivedRef = (0,
|
|
689
|
+
const [tracks, setTracks] = (0, import_react9.useState)(derivedTracks != null ? derivedTracks : []);
|
|
690
|
+
const prevDerivedRef = (0, import_react9.useRef)(derivedTracks);
|
|
649
691
|
if (derivedTracks !== prevDerivedRef.current) {
|
|
650
692
|
prevDerivedRef.current = derivedTracks;
|
|
651
693
|
if (derivedTracks) setTracks(derivedTracks);
|
|
652
694
|
}
|
|
653
|
-
(0,
|
|
695
|
+
(0, import_react9.useEffect)(() => {
|
|
654
696
|
if (configs.length === 0) {
|
|
655
697
|
setTracks([]);
|
|
656
698
|
setLoading(false);
|
|
@@ -758,7 +800,7 @@ function useAudioTracks(configs, options = {}) {
|
|
|
758
800
|
}
|
|
759
801
|
|
|
760
802
|
// src/hooks/useClipDragHandlers.ts
|
|
761
|
-
var
|
|
803
|
+
var import_react10 = __toESM(require("react"));
|
|
762
804
|
|
|
763
805
|
// src/utils/boundaryTrim.ts
|
|
764
806
|
var import_engine = require("@waveform-playlist/engine");
|
|
@@ -812,17 +854,24 @@ function useClipDragHandlers({
|
|
|
812
854
|
snapSamplePosition
|
|
813
855
|
}) {
|
|
814
856
|
const { sampleRate } = usePlaylistData();
|
|
815
|
-
const snapSamplePositionRef =
|
|
857
|
+
const snapSamplePositionRef = import_react10.default.useRef(snapSamplePosition);
|
|
816
858
|
snapSamplePositionRef.current = snapSamplePosition;
|
|
817
|
-
const originalClipStateRef =
|
|
818
|
-
const lastBoundaryDeltaRef =
|
|
819
|
-
const onDragStart =
|
|
859
|
+
const originalClipStateRef = import_react10.default.useRef(null);
|
|
860
|
+
const lastBoundaryDeltaRef = import_react10.default.useRef(0);
|
|
861
|
+
const onDragStart = import_react10.default.useCallback(
|
|
820
862
|
(event) => {
|
|
821
863
|
var _a;
|
|
822
864
|
const data = (_a = event.operation.source) == null ? void 0 : _a.data;
|
|
823
865
|
if (!data) return;
|
|
824
866
|
if (!data.boundary) {
|
|
825
867
|
originalClipStateRef.current = null;
|
|
868
|
+
if (engineRef.current) {
|
|
869
|
+
engineRef.current.beginTransaction();
|
|
870
|
+
} else {
|
|
871
|
+
console.warn(
|
|
872
|
+
"[waveform-playlist] onDragStart: engine not ready, move will not be grouped for undo"
|
|
873
|
+
);
|
|
874
|
+
}
|
|
826
875
|
return;
|
|
827
876
|
}
|
|
828
877
|
const track = tracks[data.trackIndex];
|
|
@@ -834,11 +883,18 @@ function useClipDragHandlers({
|
|
|
834
883
|
startSample: clip.startSample
|
|
835
884
|
};
|
|
836
885
|
isDraggingRef.current = true;
|
|
886
|
+
if (engineRef.current) {
|
|
887
|
+
engineRef.current.beginTransaction();
|
|
888
|
+
} else {
|
|
889
|
+
console.warn(
|
|
890
|
+
"[waveform-playlist] onDragStart: engine not ready, trim will not be grouped for undo"
|
|
891
|
+
);
|
|
892
|
+
}
|
|
837
893
|
}
|
|
838
894
|
},
|
|
839
|
-
[tracks, isDraggingRef]
|
|
895
|
+
[tracks, isDraggingRef, engineRef]
|
|
840
896
|
);
|
|
841
|
-
const onDragMove =
|
|
897
|
+
const onDragMove = import_react10.default.useCallback(
|
|
842
898
|
(event) => {
|
|
843
899
|
var _a, _b, _c;
|
|
844
900
|
const data = (_a = event.operation.source) == null ? void 0 : _a.data;
|
|
@@ -900,9 +956,9 @@ function useClipDragHandlers({
|
|
|
900
956
|
},
|
|
901
957
|
[tracks, onTracksChange, samplesPerPixel, sampleRate]
|
|
902
958
|
);
|
|
903
|
-
const onDragEnd =
|
|
959
|
+
const onDragEnd = import_react10.default.useCallback(
|
|
904
960
|
(event) => {
|
|
905
|
-
var _a, _b, _c;
|
|
961
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
906
962
|
if (event.canceled) {
|
|
907
963
|
if (originalClipStateRef.current) {
|
|
908
964
|
const cancelData = (_a = event.operation.source) == null ? void 0 : _a.data;
|
|
@@ -927,23 +983,30 @@ function useClipDragHandlers({
|
|
|
927
983
|
isDraggingRef.current = false;
|
|
928
984
|
originalClipStateRef.current = null;
|
|
929
985
|
lastBoundaryDeltaRef.current = 0;
|
|
986
|
+
(_b = engineRef.current) == null ? void 0 : _b.abortTransaction();
|
|
987
|
+
return;
|
|
988
|
+
}
|
|
989
|
+
const data = (_c = event.operation.source) == null ? void 0 : _c.data;
|
|
990
|
+
if (!data) {
|
|
991
|
+
isDraggingRef.current = false;
|
|
992
|
+
(_d = engineRef.current) == null ? void 0 : _d.abortTransaction();
|
|
930
993
|
return;
|
|
931
994
|
}
|
|
932
|
-
const data = (_b = event.operation.source) == null ? void 0 : _b.data;
|
|
933
|
-
if (!data) return;
|
|
934
995
|
const { trackIndex, clipId, boundary } = data;
|
|
935
996
|
const sampleDelta = boundary ? lastBoundaryDeltaRef.current : event.operation.transform.x * samplesPerPixel;
|
|
936
|
-
const trackId = (
|
|
997
|
+
const trackId = (_e = tracks[trackIndex]) == null ? void 0 : _e.id;
|
|
937
998
|
if (boundary) {
|
|
938
999
|
isDraggingRef.current = false;
|
|
939
1000
|
if (!trackId) {
|
|
940
1001
|
console.warn(
|
|
941
1002
|
`[waveform-playlist] onDragEnd: track at index ${trackIndex} not found \u2014 trim not synced to adapter`
|
|
942
1003
|
);
|
|
1004
|
+
(_f = engineRef.current) == null ? void 0 : _f.abortTransaction();
|
|
943
1005
|
} else if (!engineRef.current) {
|
|
944
1006
|
console.warn("[waveform-playlist] engineRef is null \u2014 trim not synced to adapter");
|
|
945
1007
|
} else {
|
|
946
1008
|
engineRef.current.trimClip(trackId, clipId, boundary, Math.floor(sampleDelta));
|
|
1009
|
+
engineRef.current.commitTransaction();
|
|
947
1010
|
}
|
|
948
1011
|
originalClipStateRef.current = null;
|
|
949
1012
|
lastBoundaryDeltaRef.current = 0;
|
|
@@ -953,10 +1016,12 @@ function useClipDragHandlers({
|
|
|
953
1016
|
console.warn(
|
|
954
1017
|
`[waveform-playlist] onDragEnd: track at index ${trackIndex} not found \u2014 move not synced to adapter`
|
|
955
1018
|
);
|
|
1019
|
+
(_g = engineRef.current) == null ? void 0 : _g.abortTransaction();
|
|
956
1020
|
} else if (!engineRef.current) {
|
|
957
1021
|
console.warn("[waveform-playlist] engineRef is null \u2014 move not synced to adapter");
|
|
958
1022
|
} else {
|
|
959
1023
|
engineRef.current.moveClip(trackId, clipId, Math.floor(sampleDelta));
|
|
1024
|
+
engineRef.current.commitTransaction();
|
|
960
1025
|
}
|
|
961
1026
|
},
|
|
962
1027
|
[tracks, onTracksChange, samplesPerPixel, engineRef, isDraggingRef]
|
|
@@ -969,7 +1034,7 @@ function useClipDragHandlers({
|
|
|
969
1034
|
}
|
|
970
1035
|
|
|
971
1036
|
// src/hooks/useAnnotationDragHandlers.ts
|
|
972
|
-
var
|
|
1037
|
+
var import_react11 = __toESM(require("react"));
|
|
973
1038
|
var import_playout = require("@waveform-playlist/playout");
|
|
974
1039
|
var LINK_THRESHOLD = 0.01;
|
|
975
1040
|
function useAnnotationDragHandlers({
|
|
@@ -980,8 +1045,8 @@ function useAnnotationDragHandlers({
|
|
|
980
1045
|
duration,
|
|
981
1046
|
linkEndpoints
|
|
982
1047
|
}) {
|
|
983
|
-
const originalAnnotationStateRef =
|
|
984
|
-
const onDragStart =
|
|
1048
|
+
const originalAnnotationStateRef = import_react11.default.useRef(null);
|
|
1049
|
+
const onDragStart = import_react11.default.useCallback(
|
|
985
1050
|
(event) => {
|
|
986
1051
|
var _a;
|
|
987
1052
|
const data = (_a = event.operation.source) == null ? void 0 : _a.data;
|
|
@@ -1000,7 +1065,7 @@ function useAnnotationDragHandlers({
|
|
|
1000
1065
|
},
|
|
1001
1066
|
[annotations]
|
|
1002
1067
|
);
|
|
1003
|
-
const onDragMove =
|
|
1068
|
+
const onDragMove = import_react11.default.useCallback(
|
|
1004
1069
|
(event) => {
|
|
1005
1070
|
var _a, _b, _c;
|
|
1006
1071
|
if (!originalAnnotationStateRef.current) {
|
|
@@ -1026,7 +1091,7 @@ function useAnnotationDragHandlers({
|
|
|
1026
1091
|
},
|
|
1027
1092
|
[annotations, onAnnotationsChange, samplesPerPixel, sampleRate, duration, linkEndpoints]
|
|
1028
1093
|
);
|
|
1029
|
-
const onDragEnd =
|
|
1094
|
+
const onDragEnd = import_react11.default.useCallback(
|
|
1030
1095
|
(event) => {
|
|
1031
1096
|
if (event.canceled && originalAnnotationStateRef.current) {
|
|
1032
1097
|
const { annotationIndex, start, end } = originalAnnotationStateRef.current;
|
|
@@ -1134,7 +1199,7 @@ function updateAnnotationBoundaries({
|
|
|
1134
1199
|
}
|
|
1135
1200
|
|
|
1136
1201
|
// src/hooks/useDragSensors.ts
|
|
1137
|
-
var
|
|
1202
|
+
var import_react12 = require("react");
|
|
1138
1203
|
var import_dom = require("@dnd-kit/dom");
|
|
1139
1204
|
function useDragSensors(options = {}) {
|
|
1140
1205
|
const {
|
|
@@ -1143,7 +1208,7 @@ function useDragSensors(options = {}) {
|
|
|
1143
1208
|
touchTolerance = 5,
|
|
1144
1209
|
mouseDistance = 1
|
|
1145
1210
|
} = options;
|
|
1146
|
-
return (0,
|
|
1211
|
+
return (0, import_react12.useMemo)(() => {
|
|
1147
1212
|
if (touchOptimized) {
|
|
1148
1213
|
return [
|
|
1149
1214
|
import_dom.PointerSensor.configure({
|
|
@@ -1172,14 +1237,14 @@ function useDragSensors(options = {}) {
|
|
|
1172
1237
|
}
|
|
1173
1238
|
|
|
1174
1239
|
// src/hooks/useClipSplitting.ts
|
|
1175
|
-
var
|
|
1240
|
+
var import_react13 = require("react");
|
|
1176
1241
|
var import_engine2 = require("@waveform-playlist/engine");
|
|
1177
1242
|
var useClipSplitting = (options) => {
|
|
1178
1243
|
const { tracks, engineRef } = options;
|
|
1179
1244
|
const { sampleRate } = usePlaylistData();
|
|
1180
1245
|
const { currentTimeRef } = usePlaybackAnimation();
|
|
1181
1246
|
const { selectedTrackId } = usePlaylistState();
|
|
1182
|
-
const splitClipAt = (0,
|
|
1247
|
+
const splitClipAt = (0, import_react13.useCallback)(
|
|
1183
1248
|
(trackIndex, clipIndex, splitTime) => {
|
|
1184
1249
|
const { samplesPerPixel } = options;
|
|
1185
1250
|
const track = tracks[trackIndex];
|
|
@@ -1203,7 +1268,7 @@ var useClipSplitting = (options) => {
|
|
|
1203
1268
|
},
|
|
1204
1269
|
[tracks, options, engineRef, sampleRate]
|
|
1205
1270
|
);
|
|
1206
|
-
const splitClipAtPlayhead = (0,
|
|
1271
|
+
const splitClipAtPlayhead = (0, import_react13.useCallback)(() => {
|
|
1207
1272
|
var _a;
|
|
1208
1273
|
if (!selectedTrackId) {
|
|
1209
1274
|
console.warn("[waveform-playlist] No track selected \u2014 click a clip to select a track first");
|
|
@@ -1234,36 +1299,16 @@ var useClipSplitting = (options) => {
|
|
|
1234
1299
|
};
|
|
1235
1300
|
|
|
1236
1301
|
// src/hooks/useKeyboardShortcuts.ts
|
|
1237
|
-
var
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
if (event.repeat) return;
|
|
1241
|
-
const target = event.target;
|
|
1242
|
-
if (target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.isContentEditable) {
|
|
1243
|
-
return;
|
|
1244
|
-
}
|
|
1245
|
-
const matchingShortcut = shortcuts.find((shortcut) => {
|
|
1246
|
-
const keyMatch = event.key.toLowerCase() === shortcut.key.toLowerCase() || event.key === shortcut.key;
|
|
1247
|
-
const ctrlMatch = shortcut.ctrlKey === void 0 || event.ctrlKey === shortcut.ctrlKey;
|
|
1248
|
-
const shiftMatch = shortcut.shiftKey === void 0 || event.shiftKey === shortcut.shiftKey;
|
|
1249
|
-
const metaMatch = shortcut.metaKey === void 0 || event.metaKey === shortcut.metaKey;
|
|
1250
|
-
const altMatch = shortcut.altKey === void 0 || event.altKey === shortcut.altKey;
|
|
1251
|
-
return keyMatch && ctrlMatch && shiftMatch && metaMatch && altMatch;
|
|
1252
|
-
});
|
|
1253
|
-
if (matchingShortcut) {
|
|
1254
|
-
if (matchingShortcut.preventDefault !== false) {
|
|
1255
|
-
event.preventDefault();
|
|
1256
|
-
}
|
|
1257
|
-
matchingShortcut.action();
|
|
1258
|
-
}
|
|
1259
|
-
}
|
|
1302
|
+
var import_react14 = require("react");
|
|
1303
|
+
var import_core2 = require("@waveform-playlist/core");
|
|
1304
|
+
var import_core3 = require("@waveform-playlist/core");
|
|
1260
1305
|
var useKeyboardShortcuts = (options) => {
|
|
1261
1306
|
const { shortcuts, enabled = true } = options;
|
|
1262
|
-
const handleKeyDown = (0,
|
|
1263
|
-
(event) => handleKeyboardEvent(event, shortcuts, enabled),
|
|
1307
|
+
const handleKeyDown = (0, import_react14.useCallback)(
|
|
1308
|
+
(event) => (0, import_core2.handleKeyboardEvent)(event, shortcuts, enabled),
|
|
1264
1309
|
[shortcuts, enabled]
|
|
1265
1310
|
);
|
|
1266
|
-
(0,
|
|
1311
|
+
(0, import_react14.useEffect)(() => {
|
|
1267
1312
|
if (!enabled) return;
|
|
1268
1313
|
window.addEventListener("keydown", handleKeyDown);
|
|
1269
1314
|
return () => {
|
|
@@ -1271,42 +1316,24 @@ var useKeyboardShortcuts = (options) => {
|
|
|
1271
1316
|
};
|
|
1272
1317
|
}, [handleKeyDown, enabled]);
|
|
1273
1318
|
};
|
|
1274
|
-
var getShortcutLabel = (shortcut) => {
|
|
1275
|
-
const parts = [];
|
|
1276
|
-
const isMac = typeof navigator !== "undefined" && navigator.platform.includes("Mac");
|
|
1277
|
-
if (shortcut.metaKey) {
|
|
1278
|
-
parts.push(isMac ? "Cmd" : "Ctrl");
|
|
1279
|
-
}
|
|
1280
|
-
if (shortcut.ctrlKey && !shortcut.metaKey) {
|
|
1281
|
-
parts.push("Ctrl");
|
|
1282
|
-
}
|
|
1283
|
-
if (shortcut.altKey) {
|
|
1284
|
-
parts.push(isMac ? "Option" : "Alt");
|
|
1285
|
-
}
|
|
1286
|
-
if (shortcut.shiftKey) {
|
|
1287
|
-
parts.push("Shift");
|
|
1288
|
-
}
|
|
1289
|
-
parts.push(shortcut.key.toUpperCase());
|
|
1290
|
-
return parts.join("+");
|
|
1291
|
-
};
|
|
1292
1319
|
|
|
1293
1320
|
// src/hooks/usePlaybackShortcuts.ts
|
|
1294
|
-
var
|
|
1321
|
+
var import_react15 = require("react");
|
|
1295
1322
|
var usePlaybackShortcuts = (options = {}) => {
|
|
1296
1323
|
const { enabled = true, additionalShortcuts = [], shortcuts: overrideShortcuts } = options;
|
|
1297
1324
|
const { isPlaying } = usePlaybackAnimation();
|
|
1298
1325
|
const { setCurrentTime, play, pause, stop } = usePlaylistControls();
|
|
1299
|
-
const togglePlayPause = (0,
|
|
1326
|
+
const togglePlayPause = (0, import_react15.useCallback)(() => {
|
|
1300
1327
|
if (isPlaying) {
|
|
1301
1328
|
pause();
|
|
1302
1329
|
} else {
|
|
1303
1330
|
play();
|
|
1304
1331
|
}
|
|
1305
1332
|
}, [isPlaying, play, pause]);
|
|
1306
|
-
const stopPlayback = (0,
|
|
1333
|
+
const stopPlayback = (0, import_react15.useCallback)(() => {
|
|
1307
1334
|
stop();
|
|
1308
1335
|
}, [stop]);
|
|
1309
|
-
const rewindToStart = (0,
|
|
1336
|
+
const rewindToStart = (0, import_react15.useCallback)(() => {
|
|
1310
1337
|
setCurrentTime(0);
|
|
1311
1338
|
if (isPlaying) {
|
|
1312
1339
|
play(0);
|
|
@@ -1346,7 +1373,7 @@ var usePlaybackShortcuts = (options = {}) => {
|
|
|
1346
1373
|
};
|
|
1347
1374
|
|
|
1348
1375
|
// src/hooks/useAnnotationKeyboardControls.ts
|
|
1349
|
-
var
|
|
1376
|
+
var import_react16 = require("react");
|
|
1350
1377
|
var LINK_THRESHOLD2 = 0.01;
|
|
1351
1378
|
var TIME_DELTA = 0.01;
|
|
1352
1379
|
function useAnnotationKeyboardControls({
|
|
@@ -1362,11 +1389,11 @@ function useAnnotationKeyboardControls({
|
|
|
1362
1389
|
onPlay
|
|
1363
1390
|
}) {
|
|
1364
1391
|
const { samplesPerPixel, sampleRate } = usePlaylistData();
|
|
1365
|
-
const activeIndex = (0,
|
|
1392
|
+
const activeIndex = (0, import_react16.useMemo)(() => {
|
|
1366
1393
|
if (!activeAnnotationId) return -1;
|
|
1367
1394
|
return annotations.findIndex((a) => a.id === activeAnnotationId);
|
|
1368
1395
|
}, [annotations, activeAnnotationId]);
|
|
1369
|
-
const scrollToAnnotation = (0,
|
|
1396
|
+
const scrollToAnnotation = (0, import_react16.useCallback)(
|
|
1370
1397
|
(annotationId) => {
|
|
1371
1398
|
if (!(scrollContainerRef == null ? void 0 : scrollContainerRef.current) || !samplesPerPixel || !sampleRate) return;
|
|
1372
1399
|
const annotation = annotations.find((a) => a.id === annotationId);
|
|
@@ -1389,12 +1416,12 @@ function useAnnotationKeyboardControls({
|
|
|
1389
1416
|
},
|
|
1390
1417
|
[annotations, scrollContainerRef, samplesPerPixel, sampleRate]
|
|
1391
1418
|
);
|
|
1392
|
-
(0,
|
|
1419
|
+
(0, import_react16.useEffect)(() => {
|
|
1393
1420
|
if (activeAnnotationId && (scrollContainerRef == null ? void 0 : scrollContainerRef.current) && samplesPerPixel && sampleRate) {
|
|
1394
1421
|
scrollToAnnotation(activeAnnotationId);
|
|
1395
1422
|
}
|
|
1396
1423
|
}, [activeAnnotationId, scrollToAnnotation, scrollContainerRef, samplesPerPixel, sampleRate]);
|
|
1397
|
-
const moveStartBoundary = (0,
|
|
1424
|
+
const moveStartBoundary = (0, import_react16.useCallback)(
|
|
1398
1425
|
(delta) => {
|
|
1399
1426
|
if (activeIndex < 0) return;
|
|
1400
1427
|
const annotation = annotations[activeIndex];
|
|
@@ -1423,7 +1450,7 @@ function useAnnotationKeyboardControls({
|
|
|
1423
1450
|
},
|
|
1424
1451
|
[annotations, activeIndex, linkEndpoints, onAnnotationsChange]
|
|
1425
1452
|
);
|
|
1426
|
-
const moveEndBoundary = (0,
|
|
1453
|
+
const moveEndBoundary = (0, import_react16.useCallback)(
|
|
1427
1454
|
(delta) => {
|
|
1428
1455
|
if (activeIndex < 0) return;
|
|
1429
1456
|
const annotation = annotations[activeIndex];
|
|
@@ -1483,7 +1510,7 @@ function useAnnotationKeyboardControls({
|
|
|
1483
1510
|
},
|
|
1484
1511
|
[annotations, activeIndex, duration, linkEndpoints, onAnnotationsChange]
|
|
1485
1512
|
);
|
|
1486
|
-
const selectPrevious = (0,
|
|
1513
|
+
const selectPrevious = (0, import_react16.useCallback)(() => {
|
|
1487
1514
|
if (!onActiveAnnotationChange || annotations.length === 0) return;
|
|
1488
1515
|
if (activeIndex <= 0) {
|
|
1489
1516
|
onActiveAnnotationChange(annotations[annotations.length - 1].id);
|
|
@@ -1491,7 +1518,7 @@ function useAnnotationKeyboardControls({
|
|
|
1491
1518
|
onActiveAnnotationChange(annotations[activeIndex - 1].id);
|
|
1492
1519
|
}
|
|
1493
1520
|
}, [annotations, activeIndex, onActiveAnnotationChange]);
|
|
1494
|
-
const selectNext = (0,
|
|
1521
|
+
const selectNext = (0, import_react16.useCallback)(() => {
|
|
1495
1522
|
if (!onActiveAnnotationChange || annotations.length === 0) return;
|
|
1496
1523
|
if (activeIndex < 0 || activeIndex >= annotations.length - 1) {
|
|
1497
1524
|
onActiveAnnotationChange(annotations[0].id);
|
|
@@ -1499,25 +1526,25 @@ function useAnnotationKeyboardControls({
|
|
|
1499
1526
|
onActiveAnnotationChange(annotations[activeIndex + 1].id);
|
|
1500
1527
|
}
|
|
1501
1528
|
}, [annotations, activeIndex, onActiveAnnotationChange]);
|
|
1502
|
-
const selectFirst = (0,
|
|
1529
|
+
const selectFirst = (0, import_react16.useCallback)(() => {
|
|
1503
1530
|
if (!onActiveAnnotationChange || annotations.length === 0) return;
|
|
1504
1531
|
onActiveAnnotationChange(annotations[0].id);
|
|
1505
1532
|
}, [annotations, onActiveAnnotationChange]);
|
|
1506
|
-
const selectLast = (0,
|
|
1533
|
+
const selectLast = (0, import_react16.useCallback)(() => {
|
|
1507
1534
|
if (!onActiveAnnotationChange || annotations.length === 0) return;
|
|
1508
1535
|
onActiveAnnotationChange(annotations[annotations.length - 1].id);
|
|
1509
1536
|
}, [annotations, onActiveAnnotationChange]);
|
|
1510
|
-
const clearSelection = (0,
|
|
1537
|
+
const clearSelection = (0, import_react16.useCallback)(() => {
|
|
1511
1538
|
if (!onActiveAnnotationChange) return;
|
|
1512
1539
|
onActiveAnnotationChange(null);
|
|
1513
1540
|
}, [onActiveAnnotationChange]);
|
|
1514
|
-
const playActiveAnnotation = (0,
|
|
1541
|
+
const playActiveAnnotation = (0, import_react16.useCallback)(() => {
|
|
1515
1542
|
if (activeIndex < 0 || !onPlay) return;
|
|
1516
1543
|
const annotation = annotations[activeIndex];
|
|
1517
1544
|
const playDuration = !continuousPlay ? annotation.end - annotation.start : void 0;
|
|
1518
1545
|
onPlay(annotation.start, playDuration);
|
|
1519
1546
|
}, [annotations, activeIndex, continuousPlay, onPlay]);
|
|
1520
|
-
const activeAnnotationShortcuts = (0,
|
|
1547
|
+
const activeAnnotationShortcuts = (0, import_react16.useMemo)(
|
|
1521
1548
|
() => [
|
|
1522
1549
|
{
|
|
1523
1550
|
key: "[",
|
|
@@ -1554,7 +1581,7 @@ function useAnnotationKeyboardControls({
|
|
|
1554
1581
|
],
|
|
1555
1582
|
[moveStartBoundary, moveEndBoundary, playActiveAnnotation]
|
|
1556
1583
|
);
|
|
1557
|
-
const navigationShortcuts = (0,
|
|
1584
|
+
const navigationShortcuts = (0, import_react16.useMemo)(
|
|
1558
1585
|
() => [
|
|
1559
1586
|
{
|
|
1560
1587
|
key: "ArrowUp",
|
|
@@ -1623,7 +1650,7 @@ function useAnnotationKeyboardControls({
|
|
|
1623
1650
|
}
|
|
1624
1651
|
|
|
1625
1652
|
// src/hooks/useDynamicEffects.ts
|
|
1626
|
-
var
|
|
1653
|
+
var import_react17 = require("react");
|
|
1627
1654
|
|
|
1628
1655
|
// src/effects/effectDefinitions.ts
|
|
1629
1656
|
var effectDefinitions = [
|
|
@@ -2298,13 +2325,13 @@ function createEffectChain(effects) {
|
|
|
2298
2325
|
// src/hooks/useDynamicEffects.ts
|
|
2299
2326
|
var import_tone3 = require("tone");
|
|
2300
2327
|
function useDynamicEffects(fftSize = 256) {
|
|
2301
|
-
const [activeEffects, setActiveEffects] = (0,
|
|
2302
|
-
const activeEffectsRef = (0,
|
|
2328
|
+
const [activeEffects, setActiveEffects] = (0, import_react17.useState)([]);
|
|
2329
|
+
const activeEffectsRef = (0, import_react17.useRef)(activeEffects);
|
|
2303
2330
|
activeEffectsRef.current = activeEffects;
|
|
2304
|
-
const effectInstancesRef = (0,
|
|
2305
|
-
const analyserRef = (0,
|
|
2306
|
-
const graphNodesRef = (0,
|
|
2307
|
-
const rebuildChain = (0,
|
|
2331
|
+
const effectInstancesRef = (0, import_react17.useRef)(/* @__PURE__ */ new Map());
|
|
2332
|
+
const analyserRef = (0, import_react17.useRef)(null);
|
|
2333
|
+
const graphNodesRef = (0, import_react17.useRef)(null);
|
|
2334
|
+
const rebuildChain = (0, import_react17.useCallback)((effects) => {
|
|
2308
2335
|
const nodes = graphNodesRef.current;
|
|
2309
2336
|
if (!nodes) return;
|
|
2310
2337
|
const { masterGainNode, destination, analyserNode } = nodes;
|
|
@@ -2332,7 +2359,7 @@ function useDynamicEffects(fftSize = 256) {
|
|
|
2332
2359
|
analyserNode.connect(destination);
|
|
2333
2360
|
}
|
|
2334
2361
|
}, []);
|
|
2335
|
-
const addEffect = (0,
|
|
2362
|
+
const addEffect = (0, import_react17.useCallback)((effectId) => {
|
|
2336
2363
|
const definition = getEffectDefinition(effectId);
|
|
2337
2364
|
if (!definition) {
|
|
2338
2365
|
console.error(`Unknown effect: ${effectId}`);
|
|
@@ -2353,7 +2380,7 @@ function useDynamicEffects(fftSize = 256) {
|
|
|
2353
2380
|
};
|
|
2354
2381
|
setActiveEffects((prev) => [...prev, newActiveEffect]);
|
|
2355
2382
|
}, []);
|
|
2356
|
-
const removeEffect = (0,
|
|
2383
|
+
const removeEffect = (0, import_react17.useCallback)((instanceId) => {
|
|
2357
2384
|
const instance = effectInstancesRef.current.get(instanceId);
|
|
2358
2385
|
if (instance) {
|
|
2359
2386
|
instance.dispose();
|
|
@@ -2361,7 +2388,7 @@ function useDynamicEffects(fftSize = 256) {
|
|
|
2361
2388
|
}
|
|
2362
2389
|
setActiveEffects((prev) => prev.filter((e) => e.instanceId !== instanceId));
|
|
2363
2390
|
}, []);
|
|
2364
|
-
const updateParameter = (0,
|
|
2391
|
+
const updateParameter = (0, import_react17.useCallback)(
|
|
2365
2392
|
(instanceId, paramName, value) => {
|
|
2366
2393
|
const instance = effectInstancesRef.current.get(instanceId);
|
|
2367
2394
|
if (instance) {
|
|
@@ -2375,7 +2402,7 @@ function useDynamicEffects(fftSize = 256) {
|
|
|
2375
2402
|
},
|
|
2376
2403
|
[]
|
|
2377
2404
|
);
|
|
2378
|
-
const toggleBypass = (0,
|
|
2405
|
+
const toggleBypass = (0, import_react17.useCallback)((instanceId) => {
|
|
2379
2406
|
var _a;
|
|
2380
2407
|
const effect = activeEffectsRef.current.find((e) => e.instanceId === instanceId);
|
|
2381
2408
|
if (!effect) return;
|
|
@@ -2389,7 +2416,7 @@ function useDynamicEffects(fftSize = 256) {
|
|
|
2389
2416
|
(prev) => prev.map((e) => e.instanceId === instanceId ? __spreadProps(__spreadValues({}, e), { bypassed: newBypassed }) : e)
|
|
2390
2417
|
);
|
|
2391
2418
|
}, []);
|
|
2392
|
-
const reorderEffects = (0,
|
|
2419
|
+
const reorderEffects = (0, import_react17.useCallback)((fromIndex, toIndex) => {
|
|
2393
2420
|
setActiveEffects((prev) => {
|
|
2394
2421
|
const newEffects = [...prev];
|
|
2395
2422
|
const [removed] = newEffects.splice(fromIndex, 1);
|
|
@@ -2397,15 +2424,15 @@ function useDynamicEffects(fftSize = 256) {
|
|
|
2397
2424
|
return newEffects;
|
|
2398
2425
|
});
|
|
2399
2426
|
}, []);
|
|
2400
|
-
const clearAllEffects = (0,
|
|
2427
|
+
const clearAllEffects = (0, import_react17.useCallback)(() => {
|
|
2401
2428
|
effectInstancesRef.current.forEach((inst) => inst.dispose());
|
|
2402
2429
|
effectInstancesRef.current.clear();
|
|
2403
2430
|
setActiveEffects([]);
|
|
2404
2431
|
}, []);
|
|
2405
|
-
(0,
|
|
2432
|
+
(0, import_react17.useEffect)(() => {
|
|
2406
2433
|
rebuildChain(activeEffects);
|
|
2407
2434
|
}, [activeEffects, rebuildChain]);
|
|
2408
|
-
const masterEffects = (0,
|
|
2435
|
+
const masterEffects = (0, import_react17.useCallback)(
|
|
2409
2436
|
(masterGainNode, destination, _isOffline) => {
|
|
2410
2437
|
const analyserNode = new import_tone3.Analyser("fft", fftSize);
|
|
2411
2438
|
analyserRef.current = analyserNode;
|
|
@@ -2437,14 +2464,14 @@ function useDynamicEffects(fftSize = 256) {
|
|
|
2437
2464
|
[fftSize]
|
|
2438
2465
|
// Only fftSize - reads effects from ref
|
|
2439
2466
|
);
|
|
2440
|
-
(0,
|
|
2467
|
+
(0, import_react17.useEffect)(() => {
|
|
2441
2468
|
const effectInstances = effectInstancesRef.current;
|
|
2442
2469
|
return () => {
|
|
2443
2470
|
effectInstances.forEach((inst) => inst.dispose());
|
|
2444
2471
|
effectInstances.clear();
|
|
2445
2472
|
};
|
|
2446
2473
|
}, []);
|
|
2447
|
-
const createOfflineEffectsFunction = (0,
|
|
2474
|
+
const createOfflineEffectsFunction = (0, import_react17.useCallback)(() => {
|
|
2448
2475
|
const nonBypassedEffects = activeEffects.filter((e) => !e.bypassed);
|
|
2449
2476
|
if (nonBypassedEffects.length === 0) {
|
|
2450
2477
|
return void 0;
|
|
@@ -2486,14 +2513,14 @@ function useDynamicEffects(fftSize = 256) {
|
|
|
2486
2513
|
}
|
|
2487
2514
|
|
|
2488
2515
|
// src/hooks/useTrackDynamicEffects.ts
|
|
2489
|
-
var
|
|
2516
|
+
var import_react18 = require("react");
|
|
2490
2517
|
function useTrackDynamicEffects() {
|
|
2491
|
-
const [trackEffectsState, setTrackEffectsState] = (0,
|
|
2518
|
+
const [trackEffectsState, setTrackEffectsState] = (0, import_react18.useState)(
|
|
2492
2519
|
/* @__PURE__ */ new Map()
|
|
2493
2520
|
);
|
|
2494
|
-
const trackEffectInstancesRef = (0,
|
|
2495
|
-
const trackGraphNodesRef = (0,
|
|
2496
|
-
const rebuildTrackChain = (0,
|
|
2521
|
+
const trackEffectInstancesRef = (0, import_react18.useRef)(/* @__PURE__ */ new Map());
|
|
2522
|
+
const trackGraphNodesRef = (0, import_react18.useRef)(/* @__PURE__ */ new Map());
|
|
2523
|
+
const rebuildTrackChain = (0, import_react18.useCallback)((trackId, trackEffects) => {
|
|
2497
2524
|
const nodes = trackGraphNodesRef.current.get(trackId);
|
|
2498
2525
|
if (!nodes) return;
|
|
2499
2526
|
const { graphEnd, masterGainNode } = nodes;
|
|
@@ -2523,7 +2550,7 @@ function useTrackDynamicEffects() {
|
|
|
2523
2550
|
currentNode.connect(masterGainNode);
|
|
2524
2551
|
}
|
|
2525
2552
|
}, []);
|
|
2526
|
-
const addEffectToTrack = (0,
|
|
2553
|
+
const addEffectToTrack = (0, import_react18.useCallback)((trackId, effectId) => {
|
|
2527
2554
|
const definition = getEffectDefinition(effectId);
|
|
2528
2555
|
if (!definition) {
|
|
2529
2556
|
console.error(`Unknown effect: ${effectId}`);
|
|
@@ -2552,7 +2579,7 @@ function useTrackDynamicEffects() {
|
|
|
2552
2579
|
return newState;
|
|
2553
2580
|
});
|
|
2554
2581
|
}, []);
|
|
2555
|
-
const removeEffectFromTrack = (0,
|
|
2582
|
+
const removeEffectFromTrack = (0, import_react18.useCallback)((trackId, instanceId) => {
|
|
2556
2583
|
const instancesMap = trackEffectInstancesRef.current.get(trackId);
|
|
2557
2584
|
const instance = instancesMap == null ? void 0 : instancesMap.get(instanceId);
|
|
2558
2585
|
if (instance) {
|
|
@@ -2569,7 +2596,7 @@ function useTrackDynamicEffects() {
|
|
|
2569
2596
|
return newState;
|
|
2570
2597
|
});
|
|
2571
2598
|
}, []);
|
|
2572
|
-
const updateTrackEffectParameter = (0,
|
|
2599
|
+
const updateTrackEffectParameter = (0, import_react18.useCallback)(
|
|
2573
2600
|
(trackId, instanceId, paramName, value) => {
|
|
2574
2601
|
const instancesMap = trackEffectInstancesRef.current.get(trackId);
|
|
2575
2602
|
const instance = instancesMap == null ? void 0 : instancesMap.get(instanceId);
|
|
@@ -2590,7 +2617,7 @@ function useTrackDynamicEffects() {
|
|
|
2590
2617
|
},
|
|
2591
2618
|
[]
|
|
2592
2619
|
);
|
|
2593
|
-
const toggleBypass = (0,
|
|
2620
|
+
const toggleBypass = (0, import_react18.useCallback)((trackId, instanceId) => {
|
|
2594
2621
|
var _a;
|
|
2595
2622
|
const trackEffects = trackEffectsStateRef.current.get(trackId) || [];
|
|
2596
2623
|
const effect = trackEffects.find((e) => e.instanceId === instanceId);
|
|
@@ -2612,7 +2639,7 @@ function useTrackDynamicEffects() {
|
|
|
2612
2639
|
return newState;
|
|
2613
2640
|
});
|
|
2614
2641
|
}, []);
|
|
2615
|
-
const clearTrackEffects = (0,
|
|
2642
|
+
const clearTrackEffects = (0, import_react18.useCallback)((trackId) => {
|
|
2616
2643
|
const instancesMap = trackEffectInstancesRef.current.get(trackId);
|
|
2617
2644
|
if (instancesMap) {
|
|
2618
2645
|
instancesMap.forEach((inst) => inst.dispose());
|
|
@@ -2624,9 +2651,9 @@ function useTrackDynamicEffects() {
|
|
|
2624
2651
|
return newState;
|
|
2625
2652
|
});
|
|
2626
2653
|
}, []);
|
|
2627
|
-
const trackEffectsStateRef = (0,
|
|
2654
|
+
const trackEffectsStateRef = (0, import_react18.useRef)(trackEffectsState);
|
|
2628
2655
|
trackEffectsStateRef.current = trackEffectsState;
|
|
2629
|
-
const getTrackEffectsFunction = (0,
|
|
2656
|
+
const getTrackEffectsFunction = (0, import_react18.useCallback)(
|
|
2630
2657
|
(trackId) => {
|
|
2631
2658
|
return (graphEnd, masterGainNode, _isOffline) => {
|
|
2632
2659
|
trackGraphNodesRef.current.set(trackId, {
|
|
@@ -2654,12 +2681,12 @@ function useTrackDynamicEffects() {
|
|
|
2654
2681
|
[]
|
|
2655
2682
|
// No dependencies - stable function that reads from refs
|
|
2656
2683
|
);
|
|
2657
|
-
(0,
|
|
2684
|
+
(0, import_react18.useEffect)(() => {
|
|
2658
2685
|
trackEffectsState.forEach((effects, trackId) => {
|
|
2659
2686
|
rebuildTrackChain(trackId, effects);
|
|
2660
2687
|
});
|
|
2661
2688
|
}, [trackEffectsState, rebuildTrackChain]);
|
|
2662
|
-
(0,
|
|
2689
|
+
(0, import_react18.useEffect)(() => {
|
|
2663
2690
|
const trackEffectInstances = trackEffectInstancesRef.current;
|
|
2664
2691
|
return () => {
|
|
2665
2692
|
trackEffectInstances.forEach((instancesMap) => {
|
|
@@ -2669,7 +2696,7 @@ function useTrackDynamicEffects() {
|
|
|
2669
2696
|
trackEffectInstances.clear();
|
|
2670
2697
|
};
|
|
2671
2698
|
}, []);
|
|
2672
|
-
const createOfflineTrackEffectsFunction = (0,
|
|
2699
|
+
const createOfflineTrackEffectsFunction = (0, import_react18.useCallback)(
|
|
2673
2700
|
(trackId) => {
|
|
2674
2701
|
const trackEffects = trackEffectsState.get(trackId) || [];
|
|
2675
2702
|
const nonBypassedEffects = trackEffects.filter((e) => !e.bypassed);
|
|
@@ -2713,7 +2740,7 @@ function useTrackDynamicEffects() {
|
|
|
2713
2740
|
}
|
|
2714
2741
|
|
|
2715
2742
|
// src/hooks/useExportWav.ts
|
|
2716
|
-
var
|
|
2743
|
+
var import_react19 = require("react");
|
|
2717
2744
|
var import_playout2 = require("@waveform-playlist/playout");
|
|
2718
2745
|
|
|
2719
2746
|
// src/utils/wavEncoder.ts
|
|
@@ -2787,10 +2814,10 @@ function downloadBlob(blob, filename) {
|
|
|
2787
2814
|
|
|
2788
2815
|
// src/hooks/useExportWav.ts
|
|
2789
2816
|
function useExportWav() {
|
|
2790
|
-
const [isExporting, setIsExporting] = (0,
|
|
2791
|
-
const [progress, setProgress] = (0,
|
|
2792
|
-
const [error, setError] = (0,
|
|
2793
|
-
const exportWav = (0,
|
|
2817
|
+
const [isExporting, setIsExporting] = (0, import_react19.useState)(false);
|
|
2818
|
+
const [progress, setProgress] = (0, import_react19.useState)(0);
|
|
2819
|
+
const [error, setError] = (0, import_react19.useState)(null);
|
|
2820
|
+
const exportWav = (0, import_react19.useCallback)(
|
|
2794
2821
|
(_0, _1, ..._2) => __async(null, [_0, _1, ..._2], function* (tracks, trackStates, options = {}) {
|
|
2795
2822
|
const {
|
|
2796
2823
|
filename = "export",
|
|
@@ -3102,23 +3129,23 @@ function generateFadeCurve(startValue, endValue, numPoints, curveType) {
|
|
|
3102
3129
|
}
|
|
3103
3130
|
|
|
3104
3131
|
// src/hooks/useAnimationFrameLoop.ts
|
|
3105
|
-
var
|
|
3132
|
+
var import_react20 = require("react");
|
|
3106
3133
|
var useAnimationFrameLoop = () => {
|
|
3107
|
-
const animationFrameRef = (0,
|
|
3108
|
-
const stopAnimationFrameLoop = (0,
|
|
3134
|
+
const animationFrameRef = (0, import_react20.useRef)(null);
|
|
3135
|
+
const stopAnimationFrameLoop = (0, import_react20.useCallback)(() => {
|
|
3109
3136
|
if (animationFrameRef.current !== null) {
|
|
3110
3137
|
cancelAnimationFrame(animationFrameRef.current);
|
|
3111
3138
|
animationFrameRef.current = null;
|
|
3112
3139
|
}
|
|
3113
3140
|
}, []);
|
|
3114
|
-
const startAnimationFrameLoop = (0,
|
|
3141
|
+
const startAnimationFrameLoop = (0, import_react20.useCallback)(
|
|
3115
3142
|
(callback) => {
|
|
3116
3143
|
stopAnimationFrameLoop();
|
|
3117
3144
|
animationFrameRef.current = requestAnimationFrame(callback);
|
|
3118
3145
|
},
|
|
3119
3146
|
[stopAnimationFrameLoop]
|
|
3120
3147
|
);
|
|
3121
|
-
(0,
|
|
3148
|
+
(0, import_react20.useEffect)(() => {
|
|
3122
3149
|
return () => {
|
|
3123
3150
|
stopAnimationFrameLoop();
|
|
3124
3151
|
};
|
|
@@ -3131,7 +3158,7 @@ var useAnimationFrameLoop = () => {
|
|
|
3131
3158
|
};
|
|
3132
3159
|
|
|
3133
3160
|
// src/hooks/useWaveformDataCache.ts
|
|
3134
|
-
var
|
|
3161
|
+
var import_react21 = require("react");
|
|
3135
3162
|
|
|
3136
3163
|
// src/workers/peaksWorker.ts
|
|
3137
3164
|
var import_waveform_data2 = __toESM(require("waveform-data"));
|
|
@@ -3363,20 +3390,20 @@ function createPeaksWorker() {
|
|
|
3363
3390
|
|
|
3364
3391
|
// src/hooks/useWaveformDataCache.ts
|
|
3365
3392
|
function useWaveformDataCache(tracks, baseScale) {
|
|
3366
|
-
const [cache, setCache] = (0,
|
|
3367
|
-
const [isGenerating, setIsGenerating] = (0,
|
|
3368
|
-
const workerRef = (0,
|
|
3369
|
-
const generatedByBufferRef = (0,
|
|
3370
|
-
const inflightByBufferRef = (0,
|
|
3371
|
-
const subscribersByBufferRef = (0,
|
|
3372
|
-
const pendingCountRef = (0,
|
|
3373
|
-
const getWorker = (0,
|
|
3393
|
+
const [cache, setCache] = (0, import_react21.useState)(() => /* @__PURE__ */ new Map());
|
|
3394
|
+
const [isGenerating, setIsGenerating] = (0, import_react21.useState)(false);
|
|
3395
|
+
const workerRef = (0, import_react21.useRef)(null);
|
|
3396
|
+
const generatedByBufferRef = (0, import_react21.useRef)(/* @__PURE__ */ new WeakMap());
|
|
3397
|
+
const inflightByBufferRef = (0, import_react21.useRef)(/* @__PURE__ */ new WeakMap());
|
|
3398
|
+
const subscribersByBufferRef = (0, import_react21.useRef)(/* @__PURE__ */ new WeakMap());
|
|
3399
|
+
const pendingCountRef = (0, import_react21.useRef)(0);
|
|
3400
|
+
const getWorker = (0, import_react21.useCallback)(() => {
|
|
3374
3401
|
if (!workerRef.current) {
|
|
3375
3402
|
workerRef.current = createPeaksWorker();
|
|
3376
3403
|
}
|
|
3377
3404
|
return workerRef.current;
|
|
3378
3405
|
}, []);
|
|
3379
|
-
(0,
|
|
3406
|
+
(0, import_react21.useEffect)(() => {
|
|
3380
3407
|
let cancelled = false;
|
|
3381
3408
|
const generatedByBuffer = generatedByBufferRef.current;
|
|
3382
3409
|
const inflightByBuffer = inflightByBufferRef.current;
|
|
@@ -3481,7 +3508,7 @@ function useWaveformDataCache(tracks, baseScale) {
|
|
|
3481
3508
|
setIsGenerating(false);
|
|
3482
3509
|
};
|
|
3483
3510
|
}, [tracks, baseScale, getWorker]);
|
|
3484
|
-
(0,
|
|
3511
|
+
(0, import_react21.useEffect)(() => {
|
|
3485
3512
|
return () => {
|
|
3486
3513
|
var _a;
|
|
3487
3514
|
(_a = workerRef.current) == null ? void 0 : _a.terminate();
|
|
@@ -3492,8 +3519,8 @@ function useWaveformDataCache(tracks, baseScale) {
|
|
|
3492
3519
|
}
|
|
3493
3520
|
|
|
3494
3521
|
// src/hooks/useDynamicTracks.ts
|
|
3495
|
-
var
|
|
3496
|
-
var
|
|
3522
|
+
var import_react22 = require("react");
|
|
3523
|
+
var import_core4 = require("@waveform-playlist/core");
|
|
3497
3524
|
var import_playout3 = require("@waveform-playlist/playout");
|
|
3498
3525
|
function getSourceName(source) {
|
|
3499
3526
|
var _a, _b, _c, _d, _e;
|
|
@@ -3527,13 +3554,13 @@ function decodeSource(source, audioContext, signal) {
|
|
|
3527
3554
|
});
|
|
3528
3555
|
}
|
|
3529
3556
|
function useDynamicTracks() {
|
|
3530
|
-
const [tracks, setTracks] = (0,
|
|
3531
|
-
const [loadingCount, setLoadingCount] = (0,
|
|
3532
|
-
const [errors, setErrors] = (0,
|
|
3533
|
-
const cancelledRef = (0,
|
|
3534
|
-
const loadingIdsRef = (0,
|
|
3535
|
-
const abortControllersRef = (0,
|
|
3536
|
-
(0,
|
|
3557
|
+
const [tracks, setTracks] = (0, import_react22.useState)([]);
|
|
3558
|
+
const [loadingCount, setLoadingCount] = (0, import_react22.useState)(0);
|
|
3559
|
+
const [errors, setErrors] = (0, import_react22.useState)([]);
|
|
3560
|
+
const cancelledRef = (0, import_react22.useRef)(false);
|
|
3561
|
+
const loadingIdsRef = (0, import_react22.useRef)(/* @__PURE__ */ new Set());
|
|
3562
|
+
const abortControllersRef = (0, import_react22.useRef)(/* @__PURE__ */ new Map());
|
|
3563
|
+
(0, import_react22.useEffect)(() => {
|
|
3537
3564
|
const controllers = abortControllersRef.current;
|
|
3538
3565
|
return () => {
|
|
3539
3566
|
cancelledRef.current = true;
|
|
@@ -3543,11 +3570,11 @@ function useDynamicTracks() {
|
|
|
3543
3570
|
controllers.clear();
|
|
3544
3571
|
};
|
|
3545
3572
|
}, []);
|
|
3546
|
-
const addTracks = (0,
|
|
3573
|
+
const addTracks = (0, import_react22.useCallback)((sources) => {
|
|
3547
3574
|
if (sources.length === 0) return;
|
|
3548
3575
|
const audioContext = (0, import_playout3.getGlobalAudioContext)();
|
|
3549
3576
|
const placeholders = sources.map((source) => ({
|
|
3550
|
-
track: (0,
|
|
3577
|
+
track: (0, import_core4.createTrack)({ name: `${getSourceName(source)} (loading...)`, clips: [] }),
|
|
3551
3578
|
source
|
|
3552
3579
|
}));
|
|
3553
3580
|
setTracks((prev) => [...prev, ...placeholders.map((p) => p.track)]);
|
|
@@ -3559,7 +3586,7 @@ function useDynamicTracks() {
|
|
|
3559
3586
|
(() => __async(null, null, function* () {
|
|
3560
3587
|
try {
|
|
3561
3588
|
const { audioBuffer, name } = yield decodeSource(source, audioContext, controller.signal);
|
|
3562
|
-
const clip = (0,
|
|
3589
|
+
const clip = (0, import_core4.createClipFromSeconds)({
|
|
3563
3590
|
audioBuffer,
|
|
3564
3591
|
startTime: 0,
|
|
3565
3592
|
duration: audioBuffer.duration,
|
|
@@ -3593,7 +3620,7 @@ function useDynamicTracks() {
|
|
|
3593
3620
|
}))();
|
|
3594
3621
|
}
|
|
3595
3622
|
}, []);
|
|
3596
|
-
const removeTrack = (0,
|
|
3623
|
+
const removeTrack = (0, import_react22.useCallback)((trackId) => {
|
|
3597
3624
|
setTracks((prev) => prev.filter((t) => t.id !== trackId));
|
|
3598
3625
|
const controller = abortControllersRef.current.get(trackId);
|
|
3599
3626
|
if (controller) {
|
|
@@ -3615,24 +3642,24 @@ function useDynamicTracks() {
|
|
|
3615
3642
|
}
|
|
3616
3643
|
|
|
3617
3644
|
// src/hooks/useOutputMeter.ts
|
|
3618
|
-
var
|
|
3645
|
+
var import_react23 = require("react");
|
|
3619
3646
|
var import_playout4 = require("@waveform-playlist/playout");
|
|
3620
|
-
var
|
|
3647
|
+
var import_core5 = require("@waveform-playlist/core");
|
|
3621
3648
|
var import_worklets = require("@waveform-playlist/worklets");
|
|
3622
3649
|
var PEAK_DECAY = 0.98;
|
|
3623
3650
|
function useOutputMeter(options = {}) {
|
|
3624
3651
|
const { channelCount = 2, updateRate = 60, isPlaying = false } = options;
|
|
3625
|
-
const [levels, setLevels] = (0,
|
|
3626
|
-
const [peakLevels, setPeakLevels] = (0,
|
|
3627
|
-
const [rmsLevels, setRmsLevels] = (0,
|
|
3628
|
-
const workletNodeRef = (0,
|
|
3629
|
-
const smoothedPeakRef = (0,
|
|
3630
|
-
const [meterError, setMeterError] = (0,
|
|
3631
|
-
const resetPeak = (0,
|
|
3652
|
+
const [levels, setLevels] = (0, import_react23.useState)(() => new Array(channelCount).fill(0));
|
|
3653
|
+
const [peakLevels, setPeakLevels] = (0, import_react23.useState)(() => new Array(channelCount).fill(0));
|
|
3654
|
+
const [rmsLevels, setRmsLevels] = (0, import_react23.useState)(() => new Array(channelCount).fill(0));
|
|
3655
|
+
const workletNodeRef = (0, import_react23.useRef)(null);
|
|
3656
|
+
const smoothedPeakRef = (0, import_react23.useRef)(new Array(channelCount).fill(0));
|
|
3657
|
+
const [meterError, setMeterError] = (0, import_react23.useState)(null);
|
|
3658
|
+
const resetPeak = (0, import_react23.useCallback)(
|
|
3632
3659
|
() => setPeakLevels(new Array(channelCount).fill(0)),
|
|
3633
3660
|
[channelCount]
|
|
3634
3661
|
);
|
|
3635
|
-
(0,
|
|
3662
|
+
(0, import_react23.useEffect)(() => {
|
|
3636
3663
|
if (!isPlaying) {
|
|
3637
3664
|
const zeros = new Array(channelCount).fill(0);
|
|
3638
3665
|
smoothedPeakRef.current = new Array(channelCount).fill(0);
|
|
@@ -3641,7 +3668,7 @@ function useOutputMeter(options = {}) {
|
|
|
3641
3668
|
setPeakLevels(zeros);
|
|
3642
3669
|
}
|
|
3643
3670
|
}, [isPlaying, channelCount]);
|
|
3644
|
-
(0,
|
|
3671
|
+
(0, import_react23.useEffect)(() => {
|
|
3645
3672
|
let isMounted = true;
|
|
3646
3673
|
const setup = () => __async(null, null, function* () {
|
|
3647
3674
|
const context = (0, import_playout4.getGlobalContext)();
|
|
@@ -3672,8 +3699,8 @@ function useOutputMeter(options = {}) {
|
|
|
3672
3699
|
const rmsValues = [];
|
|
3673
3700
|
for (let ch = 0; ch < peak.length; ch++) {
|
|
3674
3701
|
smoothed[ch] = Math.max(peak[ch], ((_a = smoothed[ch]) != null ? _a : 0) * PEAK_DECAY);
|
|
3675
|
-
peakValues.push((0,
|
|
3676
|
-
rmsValues.push((0,
|
|
3702
|
+
peakValues.push((0, import_core5.gainToNormalized)(smoothed[ch]));
|
|
3703
|
+
rmsValues.push((0, import_core5.gainToNormalized)(rms[ch]));
|
|
3677
3704
|
}
|
|
3678
3705
|
setLevels(peakValues);
|
|
3679
3706
|
setRmsLevels(rmsValues);
|
|
@@ -3713,10 +3740,10 @@ function useOutputMeter(options = {}) {
|
|
|
3713
3740
|
|
|
3714
3741
|
// src/WaveformPlaylistContext.tsx
|
|
3715
3742
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
3716
|
-
var PlaybackAnimationContext = (0,
|
|
3717
|
-
var PlaylistStateContext = (0,
|
|
3718
|
-
var PlaylistControlsContext = (0,
|
|
3719
|
-
var PlaylistDataContext = (0,
|
|
3743
|
+
var PlaybackAnimationContext = (0, import_react24.createContext)(null);
|
|
3744
|
+
var PlaylistStateContext = (0, import_react24.createContext)(null);
|
|
3745
|
+
var PlaylistControlsContext = (0, import_react24.createContext)(null);
|
|
3746
|
+
var PlaylistDataContext = (0, import_react24.createContext)(null);
|
|
3720
3747
|
var WaveformPlaylistProvider = ({
|
|
3721
3748
|
tracks,
|
|
3722
3749
|
timescale = false,
|
|
@@ -3739,18 +3766,19 @@ var WaveformPlaylistProvider = ({
|
|
|
3739
3766
|
soundFontCache,
|
|
3740
3767
|
deferEngineRebuild = false,
|
|
3741
3768
|
indefinitePlayback = false,
|
|
3769
|
+
sampleRate: sampleRateProp,
|
|
3742
3770
|
children
|
|
3743
3771
|
}) => {
|
|
3744
3772
|
var _a, _b, _c, _d;
|
|
3745
3773
|
const progressBarWidth = progressBarWidthProp != null ? progressBarWidthProp : barWidth + barGap;
|
|
3746
|
-
const indefinitePlaybackRef = (0,
|
|
3774
|
+
const indefinitePlaybackRef = (0, import_react24.useRef)(indefinitePlayback);
|
|
3747
3775
|
indefinitePlaybackRef.current = indefinitePlayback;
|
|
3748
|
-
const stableZoomLevels = (0,
|
|
3776
|
+
const stableZoomLevels = (0, import_react24.useMemo)(
|
|
3749
3777
|
() => zoomLevels,
|
|
3750
3778
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3751
3779
|
[zoomLevels == null ? void 0 : zoomLevels.join(",")]
|
|
3752
3780
|
);
|
|
3753
|
-
const annotations = (0,
|
|
3781
|
+
const annotations = (0, import_react24.useMemo)(() => {
|
|
3754
3782
|
if (!(annotationList == null ? void 0 : annotationList.annotations)) return [];
|
|
3755
3783
|
if (process.env.NODE_ENV !== "production" && annotationList.annotations.length > 0) {
|
|
3756
3784
|
const first = annotationList.annotations[0];
|
|
@@ -3763,48 +3791,60 @@ var WaveformPlaylistProvider = ({
|
|
|
3763
3791
|
}
|
|
3764
3792
|
return annotationList.annotations;
|
|
3765
3793
|
}, [annotationList == null ? void 0 : annotationList.annotations]);
|
|
3766
|
-
const annotationsRef = (0,
|
|
3794
|
+
const annotationsRef = (0, import_react24.useRef)(annotations);
|
|
3767
3795
|
annotationsRef.current = annotations;
|
|
3768
|
-
const [activeAnnotationId, setActiveAnnotationIdState] = (0,
|
|
3769
|
-
const [isPlaying, setIsPlaying] = (0,
|
|
3770
|
-
const [currentTime, setCurrentTime] = (0,
|
|
3771
|
-
const [duration, setDuration] = (0,
|
|
3772
|
-
const [audioBuffers, setAudioBuffers] = (0,
|
|
3773
|
-
const [peaksDataArray, setPeaksDataArray] = (0,
|
|
3774
|
-
const [trackStates, setTrackStates] = (0,
|
|
3775
|
-
const [isAutomaticScroll, setIsAutomaticScroll] = (0,
|
|
3776
|
-
const [continuousPlay, setContinuousPlayState] = (0,
|
|
3796
|
+
const [activeAnnotationId, setActiveAnnotationIdState] = (0, import_react24.useState)(null);
|
|
3797
|
+
const [isPlaying, setIsPlaying] = (0, import_react24.useState)(false);
|
|
3798
|
+
const [currentTime, setCurrentTime] = (0, import_react24.useState)(0);
|
|
3799
|
+
const [duration, setDuration] = (0, import_react24.useState)(0);
|
|
3800
|
+
const [audioBuffers, setAudioBuffers] = (0, import_react24.useState)([]);
|
|
3801
|
+
const [peaksDataArray, setPeaksDataArray] = (0, import_react24.useState)([]);
|
|
3802
|
+
const [trackStates, setTrackStates] = (0, import_react24.useState)([]);
|
|
3803
|
+
const [isAutomaticScroll, setIsAutomaticScroll] = (0, import_react24.useState)(automaticScroll);
|
|
3804
|
+
const [continuousPlay, setContinuousPlayState] = (0, import_react24.useState)(
|
|
3777
3805
|
(_a = annotationList == null ? void 0 : annotationList.isContinuousPlay) != null ? _a : false
|
|
3778
3806
|
);
|
|
3779
|
-
const [linkEndpoints, setLinkEndpoints] = (0,
|
|
3780
|
-
const [annotationsEditable, setAnnotationsEditable] = (0,
|
|
3781
|
-
const [isReady, setIsReady] = (0,
|
|
3782
|
-
const engineRef = (0,
|
|
3783
|
-
const audioInitializedRef = (0,
|
|
3784
|
-
const isPlayingRef = (0,
|
|
3807
|
+
const [linkEndpoints, setLinkEndpoints] = (0, import_react24.useState)((_b = annotationList == null ? void 0 : annotationList.linkEndpoints) != null ? _b : false);
|
|
3808
|
+
const [annotationsEditable, setAnnotationsEditable] = (0, import_react24.useState)((_c = annotationList == null ? void 0 : annotationList.editable) != null ? _c : false);
|
|
3809
|
+
const [isReady, setIsReady] = (0, import_react24.useState)(false);
|
|
3810
|
+
const engineRef = (0, import_react24.useRef)(null);
|
|
3811
|
+
const audioInitializedRef = (0, import_react24.useRef)(false);
|
|
3812
|
+
const isPlayingRef = (0, import_react24.useRef)(false);
|
|
3785
3813
|
isPlayingRef.current = isPlaying;
|
|
3786
|
-
const playStartPositionRef = (0,
|
|
3787
|
-
const currentTimeRef = (0,
|
|
3788
|
-
const tracksRef = (0,
|
|
3789
|
-
const soundFontCacheRef = (0,
|
|
3814
|
+
const playStartPositionRef = (0, import_react24.useRef)(0);
|
|
3815
|
+
const currentTimeRef = (0, import_react24.useRef)(0);
|
|
3816
|
+
const tracksRef = (0, import_react24.useRef)(tracks);
|
|
3817
|
+
const soundFontCacheRef = (0, import_react24.useRef)(soundFontCache);
|
|
3790
3818
|
soundFontCacheRef.current = soundFontCache;
|
|
3791
|
-
const trackStatesRef = (0,
|
|
3792
|
-
const playbackStartTimeRef = (0,
|
|
3793
|
-
const audioStartPositionRef = (0,
|
|
3794
|
-
const playbackEndTimeRef = (0,
|
|
3795
|
-
const scrollContainerRef = (0,
|
|
3796
|
-
const isAutomaticScrollRef = (0,
|
|
3797
|
-
const continuousPlayRef = (0,
|
|
3798
|
-
const activeAnnotationIdRef = (0,
|
|
3799
|
-
const engineTracksRef = (0,
|
|
3800
|
-
const lastTracksVersionRef = (0,
|
|
3801
|
-
const skipEngineDisposeRef = (0,
|
|
3802
|
-
const isDraggingRef = (0,
|
|
3803
|
-
const prevTracksRef = (0,
|
|
3804
|
-
const samplesPerPixelRef = (0,
|
|
3805
|
-
const
|
|
3806
|
-
typeof AudioContext
|
|
3807
|
-
|
|
3819
|
+
const trackStatesRef = (0, import_react24.useRef)(trackStates);
|
|
3820
|
+
const playbackStartTimeRef = (0, import_react24.useRef)(0);
|
|
3821
|
+
const audioStartPositionRef = (0, import_react24.useRef)(0);
|
|
3822
|
+
const playbackEndTimeRef = (0, import_react24.useRef)(null);
|
|
3823
|
+
const scrollContainerRef = (0, import_react24.useRef)(null);
|
|
3824
|
+
const isAutomaticScrollRef = (0, import_react24.useRef)(false);
|
|
3825
|
+
const continuousPlayRef = (0, import_react24.useRef)((_d = annotationList == null ? void 0 : annotationList.isContinuousPlay) != null ? _d : false);
|
|
3826
|
+
const activeAnnotationIdRef = (0, import_react24.useRef)(null);
|
|
3827
|
+
const engineTracksRef = (0, import_react24.useRef)(null);
|
|
3828
|
+
const lastTracksVersionRef = (0, import_react24.useRef)(0);
|
|
3829
|
+
const skipEngineDisposeRef = (0, import_react24.useRef)(false);
|
|
3830
|
+
const isDraggingRef = (0, import_react24.useRef)(false);
|
|
3831
|
+
const prevTracksRef = (0, import_react24.useRef)([]);
|
|
3832
|
+
const samplesPerPixelRef = (0, import_react24.useRef)(initialSamplesPerPixel);
|
|
3833
|
+
const [initialSampleRate] = (0, import_react24.useState)(() => {
|
|
3834
|
+
if (typeof AudioContext === "undefined") return sampleRateProp != null ? sampleRateProp : 48e3;
|
|
3835
|
+
try {
|
|
3836
|
+
if (sampleRateProp !== void 0) {
|
|
3837
|
+
return (0, import_playout5.configureGlobalContext)({ sampleRate: sampleRateProp });
|
|
3838
|
+
}
|
|
3839
|
+
return (0, import_playout5.getGlobalAudioContext)().sampleRate;
|
|
3840
|
+
} catch (err) {
|
|
3841
|
+
console.warn(
|
|
3842
|
+
"[waveform-playlist] Failed to configure AudioContext: " + String(err) + " \u2014 falling back to " + (sampleRateProp != null ? sampleRateProp : 48e3) + " Hz"
|
|
3843
|
+
);
|
|
3844
|
+
return sampleRateProp != null ? sampleRateProp : 48e3;
|
|
3845
|
+
}
|
|
3846
|
+
});
|
|
3847
|
+
const sampleRateRef = (0, import_react24.useRef)(initialSampleRate);
|
|
3808
3848
|
const { timeFormat, setTimeFormat, formatTime: formatTime2 } = useTimeFormat();
|
|
3809
3849
|
const zoom = useZoomControls({ engineRef, initialSamplesPerPixel });
|
|
3810
3850
|
const { samplesPerPixel, onEngineState: onZoomEngineState } = zoom;
|
|
@@ -3841,21 +3881,28 @@ var WaveformPlaylistProvider = ({
|
|
|
3841
3881
|
onEngineState: onSelectedTrackEngineState,
|
|
3842
3882
|
selectedTrackIdRef
|
|
3843
3883
|
} = useSelectedTrack({ engineRef });
|
|
3884
|
+
const {
|
|
3885
|
+
canUndo,
|
|
3886
|
+
canRedo,
|
|
3887
|
+
undo,
|
|
3888
|
+
redo,
|
|
3889
|
+
onEngineState: onUndoEngineState
|
|
3890
|
+
} = useUndoState({ engineRef });
|
|
3844
3891
|
const { animationFrameRef, startAnimationFrameLoop, stopAnimationFrameLoop } = useAnimationFrameLoop();
|
|
3845
|
-
const baseScale = (0,
|
|
3892
|
+
const baseScale = (0, import_react24.useMemo)(
|
|
3846
3893
|
() => Math.min(...stableZoomLevels != null ? stableZoomLevels : [256, 512, 1024, 2048, 4096, 8192]),
|
|
3847
3894
|
[stableZoomLevels]
|
|
3848
3895
|
);
|
|
3849
3896
|
const { cache: waveformDataCache } = useWaveformDataCache(tracks, baseScale);
|
|
3850
|
-
const setContinuousPlay = (0,
|
|
3897
|
+
const setContinuousPlay = (0, import_react24.useCallback)((value) => {
|
|
3851
3898
|
continuousPlayRef.current = value;
|
|
3852
3899
|
setContinuousPlayState(value);
|
|
3853
3900
|
}, []);
|
|
3854
|
-
const setActiveAnnotationId = (0,
|
|
3901
|
+
const setActiveAnnotationId = (0, import_react24.useCallback)((value) => {
|
|
3855
3902
|
activeAnnotationIdRef.current = value;
|
|
3856
3903
|
setActiveAnnotationIdState(value);
|
|
3857
3904
|
}, []);
|
|
3858
|
-
const setLoopRegionFromSelection = (0,
|
|
3905
|
+
const setLoopRegionFromSelection = (0, import_react24.useCallback)(() => {
|
|
3859
3906
|
var _a2, _b2;
|
|
3860
3907
|
const start = (_a2 = selectionStartRef.current) != null ? _a2 : 0;
|
|
3861
3908
|
const end = (_b2 = selectionEndRef.current) != null ? _b2 : 0;
|
|
@@ -3863,10 +3910,10 @@ var WaveformPlaylistProvider = ({
|
|
|
3863
3910
|
setLoopRegion(start, end);
|
|
3864
3911
|
}
|
|
3865
3912
|
}, [setLoopRegion, selectionStartRef, selectionEndRef]);
|
|
3866
|
-
(0,
|
|
3913
|
+
(0, import_react24.useEffect)(() => {
|
|
3867
3914
|
isAutomaticScrollRef.current = isAutomaticScroll;
|
|
3868
3915
|
}, [isAutomaticScroll]);
|
|
3869
|
-
(0,
|
|
3916
|
+
(0, import_react24.useEffect)(() => {
|
|
3870
3917
|
trackStatesRef.current = trackStates;
|
|
3871
3918
|
}, [trackStates]);
|
|
3872
3919
|
tracksRef.current = tracks;
|
|
@@ -3877,7 +3924,7 @@ var WaveformPlaylistProvider = ({
|
|
|
3877
3924
|
return current === pt;
|
|
3878
3925
|
});
|
|
3879
3926
|
skipEngineDisposeRef.current = isEngineTracks || isDraggingRef.current || isIncrementalAdd;
|
|
3880
|
-
(0,
|
|
3927
|
+
(0, import_react24.useEffect)(() => {
|
|
3881
3928
|
if (!scrollContainerRef.current || duration === 0) return;
|
|
3882
3929
|
const container = scrollContainerRef.current;
|
|
3883
3930
|
const oldSamplesPerPixel = samplesPerPixelRef.current;
|
|
@@ -3893,8 +3940,8 @@ var WaveformPlaylistProvider = ({
|
|
|
3893
3940
|
container.scrollLeft = newScrollLeft;
|
|
3894
3941
|
samplesPerPixelRef.current = newSamplesPerPixel;
|
|
3895
3942
|
}, [samplesPerPixel, duration]);
|
|
3896
|
-
const pendingResumeRef = (0,
|
|
3897
|
-
(0,
|
|
3943
|
+
const pendingResumeRef = (0, import_react24.useRef)(null);
|
|
3944
|
+
(0, import_react24.useEffect)(() => {
|
|
3898
3945
|
var _a2, _b2, _c2, _d2;
|
|
3899
3946
|
if (isEngineTracks || isDraggingRef.current) {
|
|
3900
3947
|
if (isEngineTracks) {
|
|
@@ -4069,6 +4116,7 @@ var WaveformPlaylistProvider = ({
|
|
|
4069
4116
|
onSelectedTrackEngineState(state);
|
|
4070
4117
|
onZoomEngineState(state);
|
|
4071
4118
|
onVolumeEngineState(state);
|
|
4119
|
+
onUndoEngineState(state);
|
|
4072
4120
|
if (!suppressTracksMirroring && state.tracksVersion !== lastTracksVersionRef.current) {
|
|
4073
4121
|
lastTracksVersionRef.current = state.tracksVersion;
|
|
4074
4122
|
engineTracksRef.current = state.tracks;
|
|
@@ -4126,6 +4174,7 @@ var WaveformPlaylistProvider = ({
|
|
|
4126
4174
|
onSelectedTrackEngineState,
|
|
4127
4175
|
onZoomEngineState,
|
|
4128
4176
|
onVolumeEngineState,
|
|
4177
|
+
onUndoEngineState,
|
|
4129
4178
|
onTracksChange,
|
|
4130
4179
|
masterVolumeRef,
|
|
4131
4180
|
selectionStartRef,
|
|
@@ -4137,7 +4186,7 @@ var WaveformPlaylistProvider = ({
|
|
|
4137
4186
|
soundFontCache,
|
|
4138
4187
|
deferEngineRebuild
|
|
4139
4188
|
]);
|
|
4140
|
-
(0,
|
|
4189
|
+
(0, import_react24.useEffect)(() => {
|
|
4141
4190
|
if (tracks.length === 0) return;
|
|
4142
4191
|
const allTrackPeaks = tracks.map((track) => {
|
|
4143
4192
|
const clipPeaks = track.clips.map((clip) => {
|
|
@@ -4145,15 +4194,28 @@ var WaveformPlaylistProvider = ({
|
|
|
4145
4194
|
let peaks;
|
|
4146
4195
|
if (clip.waveformData) {
|
|
4147
4196
|
try {
|
|
4197
|
+
const wdRate = clip.waveformData.sample_rate;
|
|
4198
|
+
const clipRate = clip.sampleRate;
|
|
4199
|
+
let peakOffset = clip.offsetSamples;
|
|
4200
|
+
let peakDuration = clip.durationSamples;
|
|
4201
|
+
let peakSpp = samplesPerPixel;
|
|
4202
|
+
if (wdRate !== clipRate && clipRate > 0 && wdRate > 0) {
|
|
4203
|
+
const ratio = wdRate / clipRate;
|
|
4204
|
+
peakOffset = Math.round(clip.offsetSamples * ratio);
|
|
4205
|
+
peakDuration = Math.round(clip.durationSamples * ratio);
|
|
4206
|
+
peakSpp = Math.max(1, Math.round(samplesPerPixel * ratio));
|
|
4207
|
+
}
|
|
4148
4208
|
peaks = extractPeaksFromWaveformDataFull(
|
|
4149
4209
|
clip.waveformData,
|
|
4150
|
-
|
|
4210
|
+
peakSpp,
|
|
4151
4211
|
mono,
|
|
4152
|
-
|
|
4153
|
-
|
|
4212
|
+
peakOffset,
|
|
4213
|
+
peakDuration
|
|
4154
4214
|
);
|
|
4155
4215
|
} catch (err) {
|
|
4156
|
-
console.warn(
|
|
4216
|
+
console.warn(
|
|
4217
|
+
"[waveform-playlist] Failed to extract peaks from waveformData: " + String(err)
|
|
4218
|
+
);
|
|
4157
4219
|
}
|
|
4158
4220
|
}
|
|
4159
4221
|
if (!peaks) {
|
|
@@ -4168,7 +4230,9 @@ var WaveformPlaylistProvider = ({
|
|
|
4168
4230
|
clip.durationSamples
|
|
4169
4231
|
);
|
|
4170
4232
|
} catch (err) {
|
|
4171
|
-
console.warn(
|
|
4233
|
+
console.warn(
|
|
4234
|
+
"[waveform-playlist] Failed to extract peaks from cache: " + String(err)
|
|
4235
|
+
);
|
|
4172
4236
|
}
|
|
4173
4237
|
}
|
|
4174
4238
|
}
|
|
@@ -4203,8 +4267,8 @@ var WaveformPlaylistProvider = ({
|
|
|
4203
4267
|
});
|
|
4204
4268
|
setPeaksDataArray(allTrackPeaks);
|
|
4205
4269
|
}, [tracks, samplesPerPixel, mono, waveformDataCache, deferEngineRebuild]);
|
|
4206
|
-
const getPlaybackTimeFallbackWarnedRef = (0,
|
|
4207
|
-
const getPlaybackTime = (0,
|
|
4270
|
+
const getPlaybackTimeFallbackWarnedRef = (0, import_react24.useRef)(false);
|
|
4271
|
+
const getPlaybackTime = (0, import_react24.useCallback)(() => {
|
|
4208
4272
|
var _a2, _b2;
|
|
4209
4273
|
if (engineRef.current) {
|
|
4210
4274
|
return engineRef.current.getCurrentTime();
|
|
@@ -4218,7 +4282,7 @@ var WaveformPlaylistProvider = ({
|
|
|
4218
4282
|
const elapsed = (0, import_tone4.getContext)().currentTime - ((_a2 = playbackStartTimeRef.current) != null ? _a2 : 0);
|
|
4219
4283
|
return ((_b2 = audioStartPositionRef.current) != null ? _b2 : 0) + elapsed;
|
|
4220
4284
|
}, []);
|
|
4221
|
-
const startAnimationLoop = (0,
|
|
4285
|
+
const startAnimationLoop = (0, import_react24.useCallback)(() => {
|
|
4222
4286
|
const updateTime = () => {
|
|
4223
4287
|
const time = getPlaybackTime();
|
|
4224
4288
|
currentTimeRef.current = time;
|
|
@@ -4287,7 +4351,7 @@ var WaveformPlaylistProvider = ({
|
|
|
4287
4351
|
startAnimationFrameLoop(updateTime);
|
|
4288
4352
|
}, [duration, setActiveAnnotationId, startAnimationFrameLoop, getPlaybackTime]);
|
|
4289
4353
|
const stopAnimationLoop = stopAnimationFrameLoop;
|
|
4290
|
-
(0,
|
|
4354
|
+
(0, import_react24.useEffect)(() => {
|
|
4291
4355
|
const reschedulePlayback = () => __async(null, null, function* () {
|
|
4292
4356
|
if (isPlaying && animationFrameRef.current && engineRef.current) {
|
|
4293
4357
|
if (continuousPlay) {
|
|
@@ -4312,7 +4376,7 @@ var WaveformPlaylistProvider = ({
|
|
|
4312
4376
|
stopAnimationLoop();
|
|
4313
4377
|
});
|
|
4314
4378
|
}, [continuousPlay, isPlaying, startAnimationLoop, stopAnimationLoop, animationFrameRef]);
|
|
4315
|
-
(0,
|
|
4379
|
+
(0, import_react24.useEffect)(() => {
|
|
4316
4380
|
const resumePlayback = () => __async(null, null, function* () {
|
|
4317
4381
|
if (pendingResumeRef.current && engineRef.current) {
|
|
4318
4382
|
const { position } = pendingResumeRef.current;
|
|
@@ -4336,7 +4400,7 @@ var WaveformPlaylistProvider = ({
|
|
|
4336
4400
|
stopAnimationLoop();
|
|
4337
4401
|
});
|
|
4338
4402
|
}, [tracks, startAnimationLoop, stopAnimationLoop]);
|
|
4339
|
-
const play = (0,
|
|
4403
|
+
const play = (0, import_react24.useCallback)(
|
|
4340
4404
|
(startTime, playDuration) => __async(null, null, function* () {
|
|
4341
4405
|
if (!engineRef.current) return;
|
|
4342
4406
|
const actualStartTime = startTime != null ? startTime : currentTimeRef.current;
|
|
@@ -4367,7 +4431,7 @@ var WaveformPlaylistProvider = ({
|
|
|
4367
4431
|
}),
|
|
4368
4432
|
[startAnimationLoop, stopAnimationLoop]
|
|
4369
4433
|
);
|
|
4370
|
-
const pause = (0,
|
|
4434
|
+
const pause = (0, import_react24.useCallback)(() => {
|
|
4371
4435
|
if (!engineRef.current) return;
|
|
4372
4436
|
const pauseTime = getPlaybackTime();
|
|
4373
4437
|
engineRef.current.pause();
|
|
@@ -4376,7 +4440,7 @@ var WaveformPlaylistProvider = ({
|
|
|
4376
4440
|
currentTimeRef.current = pauseTime;
|
|
4377
4441
|
setCurrentTime(pauseTime);
|
|
4378
4442
|
}, [stopAnimationLoop, getPlaybackTime]);
|
|
4379
|
-
const stop = (0,
|
|
4443
|
+
const stop = (0, import_react24.useCallback)(() => {
|
|
4380
4444
|
if (!engineRef.current) return;
|
|
4381
4445
|
engineRef.current.stop();
|
|
4382
4446
|
setIsPlaying(false);
|
|
@@ -4385,7 +4449,7 @@ var WaveformPlaylistProvider = ({
|
|
|
4385
4449
|
setCurrentTime(playStartPositionRef.current);
|
|
4386
4450
|
setActiveAnnotationId(null);
|
|
4387
4451
|
}, [stopAnimationLoop, setActiveAnnotationId]);
|
|
4388
|
-
const seekTo = (0,
|
|
4452
|
+
const seekTo = (0, import_react24.useCallback)(
|
|
4389
4453
|
(time) => {
|
|
4390
4454
|
const clampedTime = Math.max(0, Math.min(time, duration));
|
|
4391
4455
|
currentTimeRef.current = clampedTime;
|
|
@@ -4396,7 +4460,7 @@ var WaveformPlaylistProvider = ({
|
|
|
4396
4460
|
},
|
|
4397
4461
|
[duration, isPlaying, play]
|
|
4398
4462
|
);
|
|
4399
|
-
const setTrackMute = (0,
|
|
4463
|
+
const setTrackMute = (0, import_react24.useCallback)(
|
|
4400
4464
|
(trackIndex, muted) => {
|
|
4401
4465
|
var _a2;
|
|
4402
4466
|
const trackId = (_a2 = tracksRef.current[trackIndex]) == null ? void 0 : _a2.id;
|
|
@@ -4410,7 +4474,7 @@ var WaveformPlaylistProvider = ({
|
|
|
4410
4474
|
},
|
|
4411
4475
|
[trackStates]
|
|
4412
4476
|
);
|
|
4413
|
-
const setTrackSolo = (0,
|
|
4477
|
+
const setTrackSolo = (0, import_react24.useCallback)(
|
|
4414
4478
|
(trackIndex, soloed) => {
|
|
4415
4479
|
var _a2;
|
|
4416
4480
|
const trackId = (_a2 = tracksRef.current[trackIndex]) == null ? void 0 : _a2.id;
|
|
@@ -4424,7 +4488,7 @@ var WaveformPlaylistProvider = ({
|
|
|
4424
4488
|
},
|
|
4425
4489
|
[trackStates]
|
|
4426
4490
|
);
|
|
4427
|
-
const setTrackVolume = (0,
|
|
4491
|
+
const setTrackVolume = (0, import_react24.useCallback)(
|
|
4428
4492
|
(trackIndex, volume2) => {
|
|
4429
4493
|
var _a2;
|
|
4430
4494
|
const trackId = (_a2 = tracksRef.current[trackIndex]) == null ? void 0 : _a2.id;
|
|
@@ -4438,7 +4502,7 @@ var WaveformPlaylistProvider = ({
|
|
|
4438
4502
|
},
|
|
4439
4503
|
[trackStates]
|
|
4440
4504
|
);
|
|
4441
|
-
const setTrackPan = (0,
|
|
4505
|
+
const setTrackPan = (0, import_react24.useCallback)(
|
|
4442
4506
|
(trackIndex, pan) => {
|
|
4443
4507
|
var _a2;
|
|
4444
4508
|
const trackId = (_a2 = tracksRef.current[trackIndex]) == null ? void 0 : _a2.id;
|
|
@@ -4452,7 +4516,7 @@ var WaveformPlaylistProvider = ({
|
|
|
4452
4516
|
},
|
|
4453
4517
|
[trackStates]
|
|
4454
4518
|
);
|
|
4455
|
-
const setSelection = (0,
|
|
4519
|
+
const setSelection = (0, import_react24.useCallback)(
|
|
4456
4520
|
(start, end) => {
|
|
4457
4521
|
setSelectionEngine(start, end);
|
|
4458
4522
|
currentTimeRef.current = start;
|
|
@@ -4465,12 +4529,12 @@ var WaveformPlaylistProvider = ({
|
|
|
4465
4529
|
},
|
|
4466
4530
|
[isPlaying, setSelectionEngine]
|
|
4467
4531
|
);
|
|
4468
|
-
const setScrollContainer = (0,
|
|
4532
|
+
const setScrollContainer = (0, import_react24.useCallback)((element) => {
|
|
4469
4533
|
scrollContainerRef.current = element;
|
|
4470
4534
|
}, []);
|
|
4471
|
-
const onAnnotationsChangeRef = (0,
|
|
4535
|
+
const onAnnotationsChangeRef = (0, import_react24.useRef)(onAnnotationsChange);
|
|
4472
4536
|
onAnnotationsChangeRef.current = onAnnotationsChange;
|
|
4473
|
-
const setAnnotations = (0,
|
|
4537
|
+
const setAnnotations = (0, import_react24.useCallback)(
|
|
4474
4538
|
(action) => {
|
|
4475
4539
|
const updated = typeof action === "function" ? action(annotationsRef.current) : action;
|
|
4476
4540
|
if (!onAnnotationsChangeRef.current) {
|
|
@@ -4488,7 +4552,7 @@ var WaveformPlaylistProvider = ({
|
|
|
4488
4552
|
const sampleRate = sampleRateRef.current;
|
|
4489
4553
|
const timeScaleHeight = timescale ? 30 : 0;
|
|
4490
4554
|
const minimumPlaylistHeight = tracks.length * waveHeight + timeScaleHeight;
|
|
4491
|
-
const animationValue = (0,
|
|
4555
|
+
const animationValue = (0, import_react24.useMemo)(
|
|
4492
4556
|
() => ({
|
|
4493
4557
|
isPlaying,
|
|
4494
4558
|
currentTime,
|
|
@@ -4506,7 +4570,7 @@ var WaveformPlaylistProvider = ({
|
|
|
4506
4570
|
getPlaybackTime
|
|
4507
4571
|
]
|
|
4508
4572
|
);
|
|
4509
|
-
const stateValue = (0,
|
|
4573
|
+
const stateValue = (0, import_react24.useMemo)(
|
|
4510
4574
|
() => ({
|
|
4511
4575
|
continuousPlay,
|
|
4512
4576
|
linkEndpoints,
|
|
@@ -4520,7 +4584,9 @@ var WaveformPlaylistProvider = ({
|
|
|
4520
4584
|
selectedTrackId,
|
|
4521
4585
|
loopStart,
|
|
4522
4586
|
loopEnd,
|
|
4523
|
-
indefinitePlayback
|
|
4587
|
+
indefinitePlayback,
|
|
4588
|
+
canUndo,
|
|
4589
|
+
canRedo
|
|
4524
4590
|
}),
|
|
4525
4591
|
[
|
|
4526
4592
|
continuousPlay,
|
|
@@ -4535,20 +4601,22 @@ var WaveformPlaylistProvider = ({
|
|
|
4535
4601
|
selectedTrackId,
|
|
4536
4602
|
loopStart,
|
|
4537
4603
|
loopEnd,
|
|
4538
|
-
indefinitePlayback
|
|
4604
|
+
indefinitePlayback,
|
|
4605
|
+
canUndo,
|
|
4606
|
+
canRedo
|
|
4539
4607
|
]
|
|
4540
4608
|
);
|
|
4541
|
-
const setCurrentTimeControl = (0,
|
|
4609
|
+
const setCurrentTimeControl = (0, import_react24.useCallback)(
|
|
4542
4610
|
(time) => {
|
|
4543
4611
|
currentTimeRef.current = time;
|
|
4544
4612
|
setCurrentTime(time);
|
|
4545
4613
|
},
|
|
4546
4614
|
[currentTimeRef]
|
|
4547
4615
|
);
|
|
4548
|
-
const setAutomaticScrollControl = (0,
|
|
4616
|
+
const setAutomaticScrollControl = (0, import_react24.useCallback)((enabled) => {
|
|
4549
4617
|
setIsAutomaticScroll(enabled);
|
|
4550
4618
|
}, []);
|
|
4551
|
-
const controlsValue = (0,
|
|
4619
|
+
const controlsValue = (0, import_react24.useMemo)(
|
|
4552
4620
|
() => ({
|
|
4553
4621
|
// Playback controls
|
|
4554
4622
|
play,
|
|
@@ -4586,7 +4654,10 @@ var WaveformPlaylistProvider = ({
|
|
|
4586
4654
|
setLoopEnabled,
|
|
4587
4655
|
setLoopRegion,
|
|
4588
4656
|
setLoopRegionFromSelection,
|
|
4589
|
-
clearLoopRegion
|
|
4657
|
+
clearLoopRegion,
|
|
4658
|
+
// Undo/redo
|
|
4659
|
+
undo,
|
|
4660
|
+
redo
|
|
4590
4661
|
}),
|
|
4591
4662
|
[
|
|
4592
4663
|
play,
|
|
@@ -4616,10 +4687,12 @@ var WaveformPlaylistProvider = ({
|
|
|
4616
4687
|
setLoopEnabled,
|
|
4617
4688
|
setLoopRegion,
|
|
4618
4689
|
setLoopRegionFromSelection,
|
|
4619
|
-
clearLoopRegion
|
|
4690
|
+
clearLoopRegion,
|
|
4691
|
+
undo,
|
|
4692
|
+
redo
|
|
4620
4693
|
]
|
|
4621
4694
|
);
|
|
4622
|
-
const dataValue = (0,
|
|
4695
|
+
const dataValue = (0, import_react24.useMemo)(
|
|
4623
4696
|
() => ({
|
|
4624
4697
|
duration,
|
|
4625
4698
|
audioBuffers,
|
|
@@ -4675,28 +4748,28 @@ var WaveformPlaylistProvider = ({
|
|
|
4675
4748
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_styled_components.ThemeProvider, { theme: mergedTheme, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PlaybackAnimationContext.Provider, { value: animationValue, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PlaylistStateContext.Provider, { value: stateValue, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PlaylistControlsContext.Provider, { value: controlsValue, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PlaylistDataContext.Provider, { value: dataValue, children }) }) }) }) });
|
|
4676
4749
|
};
|
|
4677
4750
|
var usePlaybackAnimation = () => {
|
|
4678
|
-
const context = (0,
|
|
4751
|
+
const context = (0, import_react24.useContext)(PlaybackAnimationContext);
|
|
4679
4752
|
if (!context) {
|
|
4680
4753
|
throw new Error("usePlaybackAnimation must be used within WaveformPlaylistProvider");
|
|
4681
4754
|
}
|
|
4682
4755
|
return context;
|
|
4683
4756
|
};
|
|
4684
4757
|
var usePlaylistState = () => {
|
|
4685
|
-
const context = (0,
|
|
4758
|
+
const context = (0, import_react24.useContext)(PlaylistStateContext);
|
|
4686
4759
|
if (!context) {
|
|
4687
4760
|
throw new Error("usePlaylistState must be used within WaveformPlaylistProvider");
|
|
4688
4761
|
}
|
|
4689
4762
|
return context;
|
|
4690
4763
|
};
|
|
4691
4764
|
var usePlaylistControls = () => {
|
|
4692
|
-
const context = (0,
|
|
4765
|
+
const context = (0, import_react24.useContext)(PlaylistControlsContext);
|
|
4693
4766
|
if (!context) {
|
|
4694
4767
|
throw new Error("usePlaylistControls must be used within WaveformPlaylistProvider");
|
|
4695
4768
|
}
|
|
4696
4769
|
return context;
|
|
4697
4770
|
};
|
|
4698
4771
|
var usePlaylistData = () => {
|
|
4699
|
-
const context = (0,
|
|
4772
|
+
const context = (0, import_react24.useContext)(PlaylistDataContext);
|
|
4700
4773
|
if (!context) {
|
|
4701
4774
|
throw new Error("usePlaylistData must be used within WaveformPlaylistProvider");
|
|
4702
4775
|
}
|
|
@@ -4704,15 +4777,15 @@ var usePlaylistData = () => {
|
|
|
4704
4777
|
};
|
|
4705
4778
|
|
|
4706
4779
|
// src/MediaElementPlaylistContext.tsx
|
|
4707
|
-
var
|
|
4780
|
+
var import_react25 = require("react");
|
|
4708
4781
|
var import_styled_components2 = require("styled-components");
|
|
4709
4782
|
var import_media_element_playout = require("@waveform-playlist/media-element-playout");
|
|
4710
4783
|
var import_ui_components3 = require("@waveform-playlist/ui-components");
|
|
4711
4784
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
4712
|
-
var MediaElementAnimationContext = (0,
|
|
4713
|
-
var MediaElementStateContext = (0,
|
|
4714
|
-
var MediaElementControlsContext = (0,
|
|
4715
|
-
var MediaElementDataContext = (0,
|
|
4785
|
+
var MediaElementAnimationContext = (0, import_react25.createContext)(null);
|
|
4786
|
+
var MediaElementStateContext = (0, import_react25.createContext)(null);
|
|
4787
|
+
var MediaElementControlsContext = (0, import_react25.createContext)(null);
|
|
4788
|
+
var MediaElementDataContext = (0, import_react25.createContext)(null);
|
|
4716
4789
|
var MediaElementPlaylistProvider = ({
|
|
4717
4790
|
track,
|
|
4718
4791
|
samplesPerPixel: initialSamplesPerPixel = 1024,
|
|
@@ -4734,12 +4807,12 @@ var MediaElementPlaylistProvider = ({
|
|
|
4734
4807
|
}) => {
|
|
4735
4808
|
var _a;
|
|
4736
4809
|
const progressBarWidth = progressBarWidthProp != null ? progressBarWidthProp : barWidth + barGap;
|
|
4737
|
-
const [isPlaying, setIsPlaying] = (0,
|
|
4738
|
-
const [currentTime, setCurrentTime] = (0,
|
|
4739
|
-
const [duration, setDuration] = (0,
|
|
4740
|
-
const [peaksDataArray, setPeaksDataArray] = (0,
|
|
4741
|
-
const [playbackRate, setPlaybackRateState] = (0,
|
|
4742
|
-
const annotations = (0,
|
|
4810
|
+
const [isPlaying, setIsPlaying] = (0, import_react25.useState)(false);
|
|
4811
|
+
const [currentTime, setCurrentTime] = (0, import_react25.useState)(0);
|
|
4812
|
+
const [duration, setDuration] = (0, import_react25.useState)(0);
|
|
4813
|
+
const [peaksDataArray, setPeaksDataArray] = (0, import_react25.useState)([]);
|
|
4814
|
+
const [playbackRate, setPlaybackRateState] = (0, import_react25.useState)(initialPlaybackRate);
|
|
4815
|
+
const annotations = (0, import_react25.useMemo)(() => {
|
|
4743
4816
|
if (!(annotationList == null ? void 0 : annotationList.annotations)) return [];
|
|
4744
4817
|
if (process.env.NODE_ENV !== "production" && annotationList.annotations.length > 0) {
|
|
4745
4818
|
const first = annotationList.annotations[0];
|
|
@@ -4752,41 +4825,41 @@ var MediaElementPlaylistProvider = ({
|
|
|
4752
4825
|
}
|
|
4753
4826
|
return annotationList.annotations;
|
|
4754
4827
|
}, [annotationList == null ? void 0 : annotationList.annotations]);
|
|
4755
|
-
const annotationsRef = (0,
|
|
4828
|
+
const annotationsRef = (0, import_react25.useRef)(annotations);
|
|
4756
4829
|
annotationsRef.current = annotations;
|
|
4757
|
-
const [activeAnnotationId, setActiveAnnotationIdState] = (0,
|
|
4758
|
-
const [continuousPlay, setContinuousPlayState] = (0,
|
|
4830
|
+
const [activeAnnotationId, setActiveAnnotationIdState] = (0, import_react25.useState)(null);
|
|
4831
|
+
const [continuousPlay, setContinuousPlayState] = (0, import_react25.useState)(
|
|
4759
4832
|
(_a = annotationList == null ? void 0 : annotationList.isContinuousPlay) != null ? _a : false
|
|
4760
4833
|
);
|
|
4761
|
-
const [samplesPerPixel] = (0,
|
|
4762
|
-
const [isAutomaticScroll, setIsAutomaticScroll] = (0,
|
|
4763
|
-
const playoutRef = (0,
|
|
4764
|
-
const currentTimeRef = (0,
|
|
4765
|
-
const continuousPlayRef = (0,
|
|
4766
|
-
const activeAnnotationIdRef = (0,
|
|
4767
|
-
const scrollContainerRef = (0,
|
|
4768
|
-
const isAutomaticScrollRef = (0,
|
|
4769
|
-
const samplesPerPixelRef = (0,
|
|
4834
|
+
const [samplesPerPixel] = (0, import_react25.useState)(initialSamplesPerPixel);
|
|
4835
|
+
const [isAutomaticScroll, setIsAutomaticScroll] = (0, import_react25.useState)(automaticScroll);
|
|
4836
|
+
const playoutRef = (0, import_react25.useRef)(null);
|
|
4837
|
+
const currentTimeRef = (0, import_react25.useRef)(0);
|
|
4838
|
+
const continuousPlayRef = (0, import_react25.useRef)(continuousPlay);
|
|
4839
|
+
const activeAnnotationIdRef = (0, import_react25.useRef)(null);
|
|
4840
|
+
const scrollContainerRef = (0, import_react25.useRef)(null);
|
|
4841
|
+
const isAutomaticScrollRef = (0, import_react25.useRef)(automaticScroll);
|
|
4842
|
+
const samplesPerPixelRef = (0, import_react25.useRef)(initialSamplesPerPixel);
|
|
4770
4843
|
const { startAnimationFrameLoop, stopAnimationFrameLoop } = useAnimationFrameLoop();
|
|
4771
|
-
(0,
|
|
4844
|
+
(0, import_react25.useEffect)(() => {
|
|
4772
4845
|
continuousPlayRef.current = continuousPlay;
|
|
4773
4846
|
}, [continuousPlay]);
|
|
4774
|
-
(0,
|
|
4847
|
+
(0, import_react25.useEffect)(() => {
|
|
4775
4848
|
isAutomaticScrollRef.current = isAutomaticScroll;
|
|
4776
4849
|
}, [isAutomaticScroll]);
|
|
4777
|
-
const setActiveAnnotationId = (0,
|
|
4850
|
+
const setActiveAnnotationId = (0, import_react25.useCallback)((value) => {
|
|
4778
4851
|
activeAnnotationIdRef.current = value;
|
|
4779
4852
|
setActiveAnnotationIdState(value);
|
|
4780
4853
|
}, []);
|
|
4781
|
-
const setContinuousPlay = (0,
|
|
4854
|
+
const setContinuousPlay = (0, import_react25.useCallback)((value) => {
|
|
4782
4855
|
continuousPlayRef.current = value;
|
|
4783
4856
|
setContinuousPlayState(value);
|
|
4784
4857
|
}, []);
|
|
4785
|
-
const setScrollContainer = (0,
|
|
4858
|
+
const setScrollContainer = (0, import_react25.useCallback)((element) => {
|
|
4786
4859
|
scrollContainerRef.current = element;
|
|
4787
4860
|
}, []);
|
|
4788
4861
|
const sampleRate = track.waveformData.sample_rate;
|
|
4789
|
-
(0,
|
|
4862
|
+
(0, import_react25.useEffect)(() => {
|
|
4790
4863
|
var _a2, _b;
|
|
4791
4864
|
const playout = new import_media_element_playout.MediaElementPlayout({
|
|
4792
4865
|
playbackRate: initialPlaybackRate,
|
|
@@ -4833,7 +4906,7 @@ var MediaElementPlaylistProvider = ({
|
|
|
4833
4906
|
stopAnimationFrameLoop,
|
|
4834
4907
|
setActiveAnnotationId
|
|
4835
4908
|
]);
|
|
4836
|
-
(0,
|
|
4909
|
+
(0, import_react25.useEffect)(() => {
|
|
4837
4910
|
var _a2;
|
|
4838
4911
|
try {
|
|
4839
4912
|
const extractedPeaks = extractPeaksFromWaveformData(
|
|
@@ -4862,7 +4935,7 @@ var MediaElementPlaylistProvider = ({
|
|
|
4862
4935
|
console.warn("[waveform-playlist] Failed to extract peaks from waveform data:", err);
|
|
4863
4936
|
}
|
|
4864
4937
|
}, [track.waveformData, track.name, samplesPerPixel, sampleRate]);
|
|
4865
|
-
const startAnimationLoop = (0,
|
|
4938
|
+
const startAnimationLoop = (0, import_react25.useCallback)(() => {
|
|
4866
4939
|
const updateTime = () => {
|
|
4867
4940
|
var _a2, _b, _c;
|
|
4868
4941
|
const time = (_b = (_a2 = playoutRef.current) == null ? void 0 : _a2.getCurrentTime()) != null ? _b : 0;
|
|
@@ -4905,7 +4978,7 @@ var MediaElementPlaylistProvider = ({
|
|
|
4905
4978
|
startAnimationFrameLoop(updateTime);
|
|
4906
4979
|
}, [setActiveAnnotationId, sampleRate, startAnimationFrameLoop]);
|
|
4907
4980
|
const stopAnimationLoop = stopAnimationFrameLoop;
|
|
4908
|
-
const play = (0,
|
|
4981
|
+
const play = (0, import_react25.useCallback)(
|
|
4909
4982
|
(startTime) => {
|
|
4910
4983
|
if (!playoutRef.current) return;
|
|
4911
4984
|
const actualStartTime = startTime != null ? startTime : currentTimeRef.current;
|
|
@@ -4915,14 +4988,14 @@ var MediaElementPlaylistProvider = ({
|
|
|
4915
4988
|
},
|
|
4916
4989
|
[startAnimationLoop]
|
|
4917
4990
|
);
|
|
4918
|
-
const pause = (0,
|
|
4991
|
+
const pause = (0, import_react25.useCallback)(() => {
|
|
4919
4992
|
if (!playoutRef.current) return;
|
|
4920
4993
|
playoutRef.current.pause();
|
|
4921
4994
|
setIsPlaying(false);
|
|
4922
4995
|
stopAnimationLoop();
|
|
4923
4996
|
setCurrentTime(playoutRef.current.getCurrentTime());
|
|
4924
4997
|
}, [stopAnimationLoop]);
|
|
4925
|
-
const stop = (0,
|
|
4998
|
+
const stop = (0, import_react25.useCallback)(() => {
|
|
4926
4999
|
if (!playoutRef.current) return;
|
|
4927
5000
|
playoutRef.current.stop();
|
|
4928
5001
|
setIsPlaying(false);
|
|
@@ -4931,7 +5004,7 @@ var MediaElementPlaylistProvider = ({
|
|
|
4931
5004
|
setCurrentTime(0);
|
|
4932
5005
|
setActiveAnnotationId(null);
|
|
4933
5006
|
}, [stopAnimationLoop, setActiveAnnotationId]);
|
|
4934
|
-
const seekTo = (0,
|
|
5007
|
+
const seekTo = (0, import_react25.useCallback)(
|
|
4935
5008
|
(time) => {
|
|
4936
5009
|
const clampedTime = Math.max(0, Math.min(time, duration));
|
|
4937
5010
|
currentTimeRef.current = clampedTime;
|
|
@@ -4942,7 +5015,7 @@ var MediaElementPlaylistProvider = ({
|
|
|
4942
5015
|
},
|
|
4943
5016
|
[duration]
|
|
4944
5017
|
);
|
|
4945
|
-
const setPlaybackRate = (0,
|
|
5018
|
+
const setPlaybackRate = (0, import_react25.useCallback)((rate) => {
|
|
4946
5019
|
const clampedRate = Math.max(0.5, Math.min(2, rate));
|
|
4947
5020
|
setPlaybackRateState(clampedRate);
|
|
4948
5021
|
if (playoutRef.current) {
|
|
@@ -4950,7 +5023,7 @@ var MediaElementPlaylistProvider = ({
|
|
|
4950
5023
|
}
|
|
4951
5024
|
}, []);
|
|
4952
5025
|
const timeScaleHeight = timescale ? 30 : 0;
|
|
4953
|
-
const animationValue = (0,
|
|
5026
|
+
const animationValue = (0, import_react25.useMemo)(
|
|
4954
5027
|
() => ({
|
|
4955
5028
|
isPlaying,
|
|
4956
5029
|
currentTime,
|
|
@@ -4958,7 +5031,7 @@ var MediaElementPlaylistProvider = ({
|
|
|
4958
5031
|
}),
|
|
4959
5032
|
[isPlaying, currentTime]
|
|
4960
5033
|
);
|
|
4961
|
-
const stateValue = (0,
|
|
5034
|
+
const stateValue = (0, import_react25.useMemo)(
|
|
4962
5035
|
() => ({
|
|
4963
5036
|
continuousPlay,
|
|
4964
5037
|
annotations,
|
|
@@ -4968,9 +5041,9 @@ var MediaElementPlaylistProvider = ({
|
|
|
4968
5041
|
}),
|
|
4969
5042
|
[continuousPlay, annotations, activeAnnotationId, playbackRate, isAutomaticScroll]
|
|
4970
5043
|
);
|
|
4971
|
-
const onAnnotationsChangeRef = (0,
|
|
5044
|
+
const onAnnotationsChangeRef = (0, import_react25.useRef)(onAnnotationsChange);
|
|
4972
5045
|
onAnnotationsChangeRef.current = onAnnotationsChange;
|
|
4973
|
-
const setAnnotations = (0,
|
|
5046
|
+
const setAnnotations = (0, import_react25.useCallback)(
|
|
4974
5047
|
(action) => {
|
|
4975
5048
|
const updated = typeof action === "function" ? action(annotationsRef.current) : action;
|
|
4976
5049
|
if (!onAnnotationsChangeRef.current) {
|
|
@@ -4985,7 +5058,7 @@ var MediaElementPlaylistProvider = ({
|
|
|
4985
5058
|
},
|
|
4986
5059
|
[]
|
|
4987
5060
|
);
|
|
4988
|
-
const controlsValue = (0,
|
|
5061
|
+
const controlsValue = (0, import_react25.useMemo)(
|
|
4989
5062
|
() => ({
|
|
4990
5063
|
play,
|
|
4991
5064
|
pause,
|
|
@@ -5013,7 +5086,7 @@ var MediaElementPlaylistProvider = ({
|
|
|
5013
5086
|
setScrollContainer
|
|
5014
5087
|
]
|
|
5015
5088
|
);
|
|
5016
|
-
const dataValue = (0,
|
|
5089
|
+
const dataValue = (0, import_react25.useMemo)(
|
|
5017
5090
|
() => ({
|
|
5018
5091
|
duration,
|
|
5019
5092
|
peaksDataArray,
|
|
@@ -5048,28 +5121,28 @@ var MediaElementPlaylistProvider = ({
|
|
|
5048
5121
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_styled_components2.ThemeProvider, { theme: mergedTheme, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(MediaElementAnimationContext.Provider, { value: animationValue, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(MediaElementStateContext.Provider, { value: stateValue, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(MediaElementControlsContext.Provider, { value: controlsValue, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(MediaElementDataContext.Provider, { value: dataValue, children }) }) }) }) });
|
|
5049
5122
|
};
|
|
5050
5123
|
var useMediaElementAnimation = () => {
|
|
5051
|
-
const context = (0,
|
|
5124
|
+
const context = (0, import_react25.useContext)(MediaElementAnimationContext);
|
|
5052
5125
|
if (!context) {
|
|
5053
5126
|
throw new Error("useMediaElementAnimation must be used within MediaElementPlaylistProvider");
|
|
5054
5127
|
}
|
|
5055
5128
|
return context;
|
|
5056
5129
|
};
|
|
5057
5130
|
var useMediaElementState = () => {
|
|
5058
|
-
const context = (0,
|
|
5131
|
+
const context = (0, import_react25.useContext)(MediaElementStateContext);
|
|
5059
5132
|
if (!context) {
|
|
5060
5133
|
throw new Error("useMediaElementState must be used within MediaElementPlaylistProvider");
|
|
5061
5134
|
}
|
|
5062
5135
|
return context;
|
|
5063
5136
|
};
|
|
5064
5137
|
var useMediaElementControls = () => {
|
|
5065
|
-
const context = (0,
|
|
5138
|
+
const context = (0, import_react25.useContext)(MediaElementControlsContext);
|
|
5066
5139
|
if (!context) {
|
|
5067
5140
|
throw new Error("useMediaElementControls must be used within MediaElementPlaylistProvider");
|
|
5068
5141
|
}
|
|
5069
5142
|
return context;
|
|
5070
5143
|
};
|
|
5071
5144
|
var useMediaElementData = () => {
|
|
5072
|
-
const context = (0,
|
|
5145
|
+
const context = (0, import_react25.useContext)(MediaElementDataContext);
|
|
5073
5146
|
if (!context) {
|
|
5074
5147
|
throw new Error("useMediaElementData must be used within MediaElementPlaylistProvider");
|
|
5075
5148
|
}
|
|
@@ -5077,7 +5150,7 @@ var useMediaElementData = () => {
|
|
|
5077
5150
|
};
|
|
5078
5151
|
|
|
5079
5152
|
// src/components/PlaybackControls.tsx
|
|
5080
|
-
var
|
|
5153
|
+
var import_react26 = require("react");
|
|
5081
5154
|
var import_ui_components4 = require("@waveform-playlist/ui-components");
|
|
5082
5155
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
5083
5156
|
var PlayButton = ({ className }) => {
|
|
@@ -5213,7 +5286,7 @@ var ClearAllButton = ({
|
|
|
5213
5286
|
className
|
|
5214
5287
|
}) => {
|
|
5215
5288
|
const { stop } = usePlaylistControls();
|
|
5216
|
-
const handleClick = (0,
|
|
5289
|
+
const handleClick = (0, import_react26.useCallback)(() => {
|
|
5217
5290
|
stop();
|
|
5218
5291
|
onClearAll();
|
|
5219
5292
|
}, [stop, onClearAll]);
|
|
@@ -5241,7 +5314,7 @@ var ZoomOutButton = ({
|
|
|
5241
5314
|
};
|
|
5242
5315
|
|
|
5243
5316
|
// src/components/ContextualControls.tsx
|
|
5244
|
-
var
|
|
5317
|
+
var import_react27 = require("react");
|
|
5245
5318
|
var import_ui_components6 = require("@waveform-playlist/ui-components");
|
|
5246
5319
|
var import_styled_components3 = __toESM(require("styled-components"));
|
|
5247
5320
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
@@ -5274,11 +5347,11 @@ var PositionDisplay = import_styled_components3.default.span`
|
|
|
5274
5347
|
`;
|
|
5275
5348
|
var AudioPosition = ({ className }) => {
|
|
5276
5349
|
var _a;
|
|
5277
|
-
const timeRef = (0,
|
|
5278
|
-
const animationFrameRef = (0,
|
|
5350
|
+
const timeRef = (0, import_react27.useRef)(null);
|
|
5351
|
+
const animationFrameRef = (0, import_react27.useRef)(null);
|
|
5279
5352
|
const { isPlaying, currentTimeRef, getPlaybackTime } = usePlaybackAnimation();
|
|
5280
5353
|
const { timeFormat: format } = usePlaylistData();
|
|
5281
|
-
(0,
|
|
5354
|
+
(0, import_react27.useEffect)(() => {
|
|
5282
5355
|
const updateTime = () => {
|
|
5283
5356
|
var _a2;
|
|
5284
5357
|
if (timeRef.current) {
|
|
@@ -5301,7 +5374,7 @@ var AudioPosition = ({ className }) => {
|
|
|
5301
5374
|
}
|
|
5302
5375
|
};
|
|
5303
5376
|
}, [isPlaying, format, currentTimeRef, getPlaybackTime]);
|
|
5304
|
-
(0,
|
|
5377
|
+
(0, import_react27.useEffect)(() => {
|
|
5305
5378
|
var _a2;
|
|
5306
5379
|
if (!isPlaying && timeRef.current) {
|
|
5307
5380
|
timeRef.current.textContent = (0, import_ui_components6.formatTime)((_a2 = currentTimeRef.current) != null ? _a2 : 0, format);
|
|
@@ -5336,11 +5409,11 @@ var AutomaticScrollCheckbox = ({ className }) => {
|
|
|
5336
5409
|
};
|
|
5337
5410
|
|
|
5338
5411
|
// src/AnnotationIntegrationContext.tsx
|
|
5339
|
-
var
|
|
5340
|
-
var AnnotationIntegrationContext = (0,
|
|
5412
|
+
var import_react28 = require("react");
|
|
5413
|
+
var AnnotationIntegrationContext = (0, import_react28.createContext)(null);
|
|
5341
5414
|
var AnnotationIntegrationProvider = AnnotationIntegrationContext.Provider;
|
|
5342
5415
|
function useAnnotationIntegration() {
|
|
5343
|
-
const context = (0,
|
|
5416
|
+
const context = (0, import_react28.useContext)(AnnotationIntegrationContext);
|
|
5344
5417
|
if (!context) {
|
|
5345
5418
|
throw new Error(
|
|
5346
5419
|
"useAnnotationIntegration must be used within <AnnotationProvider>. Install @waveform-playlist/annotations and wrap your app with <AnnotationProvider>. See: https://waveform-playlist.naomiaro.com/docs/guides/annotations"
|
|
@@ -5426,22 +5499,22 @@ var ExportWavButton = ({
|
|
|
5426
5499
|
};
|
|
5427
5500
|
|
|
5428
5501
|
// src/contexts/ClipInteractionContext.tsx
|
|
5429
|
-
var
|
|
5430
|
-
var ClipInteractionContext = (0,
|
|
5502
|
+
var import_react29 = require("react");
|
|
5503
|
+
var ClipInteractionContext = (0, import_react29.createContext)(false);
|
|
5431
5504
|
var ClipInteractionContextProvider = ClipInteractionContext.Provider;
|
|
5432
5505
|
function useClipInteractionEnabled() {
|
|
5433
|
-
return (0,
|
|
5506
|
+
return (0, import_react29.useContext)(ClipInteractionContext);
|
|
5434
5507
|
}
|
|
5435
5508
|
|
|
5436
5509
|
// src/components/PlaylistVisualization.tsx
|
|
5437
|
-
var
|
|
5510
|
+
var import_react33 = require("react");
|
|
5438
5511
|
var import_react_dom = require("react-dom");
|
|
5439
5512
|
var import_styled_components6 = __toESM(require("styled-components"));
|
|
5440
5513
|
var import_playout6 = require("@waveform-playlist/playout");
|
|
5441
5514
|
var import_ui_components9 = require("@waveform-playlist/ui-components");
|
|
5442
5515
|
|
|
5443
5516
|
// src/components/AnimatedPlayhead.tsx
|
|
5444
|
-
var
|
|
5517
|
+
var import_react30 = require("react");
|
|
5445
5518
|
var import_styled_components4 = __toESM(require("styled-components"));
|
|
5446
5519
|
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
5447
5520
|
var PlayheadLine = import_styled_components4.default.div.attrs((props) => ({
|
|
@@ -5459,11 +5532,11 @@ var PlayheadLine = import_styled_components4.default.div.attrs((props) => ({
|
|
|
5459
5532
|
will-change: transform;
|
|
5460
5533
|
`;
|
|
5461
5534
|
var AnimatedPlayhead = ({ color = "#ff0000" }) => {
|
|
5462
|
-
const playheadRef = (0,
|
|
5463
|
-
const animationFrameRef = (0,
|
|
5535
|
+
const playheadRef = (0, import_react30.useRef)(null);
|
|
5536
|
+
const animationFrameRef = (0, import_react30.useRef)(null);
|
|
5464
5537
|
const { isPlaying, currentTimeRef, getPlaybackTime } = usePlaybackAnimation();
|
|
5465
5538
|
const { samplesPerPixel, sampleRate, progressBarWidth } = usePlaylistData();
|
|
5466
|
-
(0,
|
|
5539
|
+
(0, import_react30.useEffect)(() => {
|
|
5467
5540
|
const updatePosition = () => {
|
|
5468
5541
|
var _a;
|
|
5469
5542
|
if (playheadRef.current) {
|
|
@@ -5487,7 +5560,7 @@ var AnimatedPlayhead = ({ color = "#ff0000" }) => {
|
|
|
5487
5560
|
}
|
|
5488
5561
|
};
|
|
5489
5562
|
}, [isPlaying, sampleRate, samplesPerPixel, currentTimeRef, getPlaybackTime]);
|
|
5490
|
-
(0,
|
|
5563
|
+
(0, import_react30.useEffect)(() => {
|
|
5491
5564
|
var _a;
|
|
5492
5565
|
if (!isPlaying && playheadRef.current) {
|
|
5493
5566
|
const time = (_a = currentTimeRef.current) != null ? _a : 0;
|
|
@@ -5499,9 +5572,9 @@ var AnimatedPlayhead = ({ color = "#ff0000" }) => {
|
|
|
5499
5572
|
};
|
|
5500
5573
|
|
|
5501
5574
|
// src/components/ChannelWithProgress.tsx
|
|
5502
|
-
var
|
|
5575
|
+
var import_react31 = require("react");
|
|
5503
5576
|
var import_styled_components5 = __toESM(require("styled-components"));
|
|
5504
|
-
var
|
|
5577
|
+
var import_core6 = require("@waveform-playlist/core");
|
|
5505
5578
|
var import_ui_components8 = require("@waveform-playlist/ui-components");
|
|
5506
5579
|
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
5507
5580
|
var ChannelWrapper = import_styled_components5.default.div`
|
|
@@ -5557,19 +5630,19 @@ var ChannelWithProgress = (_a) => {
|
|
|
5557
5630
|
"clipSampleRate",
|
|
5558
5631
|
"clipOffsetSeconds"
|
|
5559
5632
|
]);
|
|
5560
|
-
const progressRef = (0,
|
|
5561
|
-
const animationFrameRef = (0,
|
|
5633
|
+
const progressRef = (0, import_react31.useRef)(null);
|
|
5634
|
+
const animationFrameRef = (0, import_react31.useRef)(null);
|
|
5562
5635
|
const theme = (0, import_ui_components8.useTheme)();
|
|
5563
5636
|
const { waveHeight } = (0, import_ui_components8.usePlaylistInfo)();
|
|
5564
5637
|
const { isPlaying, currentTimeRef, getPlaybackTime } = usePlaybackAnimation();
|
|
5565
5638
|
const { samplesPerPixel, sampleRate } = usePlaylistData();
|
|
5566
5639
|
const progressColor = (theme == null ? void 0 : theme.waveProgressColor) || "rgba(0, 0, 0, 0.1)";
|
|
5567
|
-
const clipPixelWidth = (0,
|
|
5640
|
+
const clipPixelWidth = (0, import_core6.clipPixelWidth)(
|
|
5568
5641
|
clipStartSample,
|
|
5569
5642
|
clipDurationSamples,
|
|
5570
5643
|
samplesPerPixel
|
|
5571
5644
|
);
|
|
5572
|
-
(0,
|
|
5645
|
+
(0, import_react31.useEffect)(() => {
|
|
5573
5646
|
const updateProgress = () => {
|
|
5574
5647
|
var _a2;
|
|
5575
5648
|
if (progressRef.current) {
|
|
@@ -5611,7 +5684,7 @@ var ChannelWithProgress = (_a) => {
|
|
|
5611
5684
|
currentTimeRef,
|
|
5612
5685
|
getPlaybackTime
|
|
5613
5686
|
]);
|
|
5614
|
-
(0,
|
|
5687
|
+
(0, import_react31.useEffect)(() => {
|
|
5615
5688
|
var _a2;
|
|
5616
5689
|
if (!isPlaying && progressRef.current) {
|
|
5617
5690
|
const currentTime = (_a2 = currentTimeRef.current) != null ? _a2 : 0;
|
|
@@ -5696,11 +5769,11 @@ var ChannelWithProgress = (_a) => {
|
|
|
5696
5769
|
};
|
|
5697
5770
|
|
|
5698
5771
|
// src/SpectrogramIntegrationContext.tsx
|
|
5699
|
-
var
|
|
5700
|
-
var SpectrogramIntegrationContext = (0,
|
|
5772
|
+
var import_react32 = require("react");
|
|
5773
|
+
var SpectrogramIntegrationContext = (0, import_react32.createContext)(null);
|
|
5701
5774
|
var SpectrogramIntegrationProvider = SpectrogramIntegrationContext.Provider;
|
|
5702
5775
|
function useSpectrogramIntegration() {
|
|
5703
|
-
const context = (0,
|
|
5776
|
+
const context = (0, import_react32.useContext)(SpectrogramIntegrationContext);
|
|
5704
5777
|
if (!context) {
|
|
5705
5778
|
throw new Error(
|
|
5706
5779
|
"useSpectrogramIntegration must be used within <SpectrogramProvider>. Install @waveform-playlist/spectrogram and wrap your app with <SpectrogramProvider>."
|
|
@@ -5780,7 +5853,7 @@ var PlaylistVisualization = ({
|
|
|
5780
5853
|
isLoopEnabled,
|
|
5781
5854
|
indefinitePlayback
|
|
5782
5855
|
} = usePlaylistState();
|
|
5783
|
-
const annotationIntegration = (0,
|
|
5856
|
+
const annotationIntegration = (0, import_react33.useContext)(AnnotationIntegrationContext);
|
|
5784
5857
|
const {
|
|
5785
5858
|
setAnnotations: _setAnnotations,
|
|
5786
5859
|
setActiveAnnotationId,
|
|
@@ -5810,8 +5883,8 @@ var PlaylistVisualization = ({
|
|
|
5810
5883
|
isReady,
|
|
5811
5884
|
mono
|
|
5812
5885
|
} = usePlaylistData();
|
|
5813
|
-
const spectrogram = (0,
|
|
5814
|
-
const perTrackSpectrogramHelpers = (0,
|
|
5886
|
+
const spectrogram = (0, import_react33.useContext)(SpectrogramIntegrationContext);
|
|
5887
|
+
const perTrackSpectrogramHelpers = (0, import_react33.useMemo)(() => {
|
|
5815
5888
|
if (!spectrogram)
|
|
5816
5889
|
return /* @__PURE__ */ new Map();
|
|
5817
5890
|
const helpers = /* @__PURE__ */ new Map();
|
|
@@ -5830,7 +5903,7 @@ var PlaylistVisualization = ({
|
|
|
5830
5903
|
});
|
|
5831
5904
|
return helpers;
|
|
5832
5905
|
}, [tracks, spectrogram]);
|
|
5833
|
-
const workerCanvasApi = (0,
|
|
5906
|
+
const workerCanvasApi = (0, import_react33.useMemo)(() => {
|
|
5834
5907
|
if (!(spectrogram == null ? void 0 : spectrogram.spectrogramWorkerApi)) return void 0;
|
|
5835
5908
|
return {
|
|
5836
5909
|
registerCanvas: spectrogram.spectrogramWorkerApi.registerCanvas.bind(
|
|
@@ -5841,11 +5914,11 @@ var PlaylistVisualization = ({
|
|
|
5841
5914
|
)
|
|
5842
5915
|
};
|
|
5843
5916
|
}, [spectrogram == null ? void 0 : spectrogram.spectrogramWorkerApi]);
|
|
5844
|
-
const [settingsModalTrackId, setSettingsModalTrackId] = (0,
|
|
5845
|
-
const [isSelecting, setIsSelecting] = (0,
|
|
5846
|
-
const mouseDownTimeRef = (0,
|
|
5847
|
-
const scrollContainerRef = (0,
|
|
5848
|
-
const handleScrollContainerRef = (0,
|
|
5917
|
+
const [settingsModalTrackId, setSettingsModalTrackId] = (0, import_react33.useState)(null);
|
|
5918
|
+
const [isSelecting, setIsSelecting] = (0, import_react33.useState)(false);
|
|
5919
|
+
const mouseDownTimeRef = (0, import_react33.useRef)(0);
|
|
5920
|
+
const scrollContainerRef = (0, import_react33.useRef)(null);
|
|
5921
|
+
const handleScrollContainerRef = (0, import_react33.useCallback)(
|
|
5849
5922
|
(element) => {
|
|
5850
5923
|
scrollContainerRef.current = element;
|
|
5851
5924
|
setScrollContainer(element);
|
|
@@ -5883,7 +5956,7 @@ var PlaylistVisualization = ({
|
|
|
5883
5956
|
);
|
|
5884
5957
|
}
|
|
5885
5958
|
});
|
|
5886
|
-
const selectTrack = (0,
|
|
5959
|
+
const selectTrack = (0, import_react33.useCallback)(
|
|
5887
5960
|
(trackIndex) => {
|
|
5888
5961
|
if (trackIndex >= 0 && trackIndex < tracks.length) {
|
|
5889
5962
|
const track = tracks[trackIndex];
|
|
@@ -6324,7 +6397,7 @@ var PlaylistVisualization = ({
|
|
|
6324
6397
|
};
|
|
6325
6398
|
|
|
6326
6399
|
// src/components/PlaylistAnnotationList.tsx
|
|
6327
|
-
var
|
|
6400
|
+
var import_react34 = require("react");
|
|
6328
6401
|
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
6329
6402
|
var PlaylistAnnotationList = ({
|
|
6330
6403
|
height,
|
|
@@ -6339,7 +6412,7 @@ var PlaylistAnnotationList = ({
|
|
|
6339
6412
|
const integration = useAnnotationIntegration();
|
|
6340
6413
|
const { setAnnotations } = usePlaylistControls();
|
|
6341
6414
|
const resolvedConfig = annotationListConfig != null ? annotationListConfig : { linkEndpoints, continuousPlay };
|
|
6342
|
-
const handleAnnotationUpdate = (0,
|
|
6415
|
+
const handleAnnotationUpdate = (0, import_react34.useCallback)(
|
|
6343
6416
|
(updatedAnnotations) => {
|
|
6344
6417
|
setAnnotations(updatedAnnotations);
|
|
6345
6418
|
onAnnotationUpdate == null ? void 0 : onAnnotationUpdate(updatedAnnotations);
|
|
@@ -6423,8 +6496,8 @@ var Waveform = ({
|
|
|
6423
6496
|
};
|
|
6424
6497
|
|
|
6425
6498
|
// src/components/MediaElementPlaylist.tsx
|
|
6426
|
-
var
|
|
6427
|
-
var
|
|
6499
|
+
var import_react37 = require("react");
|
|
6500
|
+
var import_react38 = require("@dnd-kit/react");
|
|
6428
6501
|
var import_modifiers = require("@dnd-kit/abstract/modifiers");
|
|
6429
6502
|
var import_ui_components11 = require("@waveform-playlist/ui-components");
|
|
6430
6503
|
|
|
@@ -6448,7 +6521,7 @@ var noDropAnimationPlugins = (defaults) => {
|
|
|
6448
6521
|
};
|
|
6449
6522
|
|
|
6450
6523
|
// src/components/AnimatedMediaElementPlayhead.tsx
|
|
6451
|
-
var
|
|
6524
|
+
var import_react35 = require("react");
|
|
6452
6525
|
var import_styled_components7 = __toESM(require("styled-components"));
|
|
6453
6526
|
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
6454
6527
|
var PlayheadLine2 = import_styled_components7.default.div`
|
|
@@ -6465,11 +6538,11 @@ var PlayheadLine2 = import_styled_components7.default.div`
|
|
|
6465
6538
|
var AnimatedMediaElementPlayhead = ({
|
|
6466
6539
|
color = "#ff0000"
|
|
6467
6540
|
}) => {
|
|
6468
|
-
const playheadRef = (0,
|
|
6469
|
-
const animationFrameRef = (0,
|
|
6541
|
+
const playheadRef = (0, import_react35.useRef)(null);
|
|
6542
|
+
const animationFrameRef = (0, import_react35.useRef)(null);
|
|
6470
6543
|
const { isPlaying, currentTimeRef } = useMediaElementAnimation();
|
|
6471
6544
|
const { samplesPerPixel, sampleRate, progressBarWidth } = useMediaElementData();
|
|
6472
|
-
(0,
|
|
6545
|
+
(0, import_react35.useEffect)(() => {
|
|
6473
6546
|
const updatePosition = () => {
|
|
6474
6547
|
var _a;
|
|
6475
6548
|
if (playheadRef.current) {
|
|
@@ -6493,7 +6566,7 @@ var AnimatedMediaElementPlayhead = ({
|
|
|
6493
6566
|
}
|
|
6494
6567
|
};
|
|
6495
6568
|
}, [isPlaying, sampleRate, samplesPerPixel, currentTimeRef]);
|
|
6496
|
-
(0,
|
|
6569
|
+
(0, import_react35.useEffect)(() => {
|
|
6497
6570
|
var _a;
|
|
6498
6571
|
if (!isPlaying && playheadRef.current) {
|
|
6499
6572
|
const time = (_a = currentTimeRef.current) != null ? _a : 0;
|
|
@@ -6505,7 +6578,7 @@ var AnimatedMediaElementPlayhead = ({
|
|
|
6505
6578
|
};
|
|
6506
6579
|
|
|
6507
6580
|
// src/components/ChannelWithMediaElementProgress.tsx
|
|
6508
|
-
var
|
|
6581
|
+
var import_react36 = require("react");
|
|
6509
6582
|
var import_styled_components8 = __toESM(require("styled-components"));
|
|
6510
6583
|
var import_ui_components10 = require("@waveform-playlist/ui-components");
|
|
6511
6584
|
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
@@ -6545,14 +6618,14 @@ var ChannelWithMediaElementProgress = (_a) => {
|
|
|
6545
6618
|
"clipStartSample",
|
|
6546
6619
|
"clipDurationSamples"
|
|
6547
6620
|
]);
|
|
6548
|
-
const progressRef = (0,
|
|
6549
|
-
const animationFrameRef = (0,
|
|
6621
|
+
const progressRef = (0, import_react36.useRef)(null);
|
|
6622
|
+
const animationFrameRef = (0, import_react36.useRef)(null);
|
|
6550
6623
|
const theme = (0, import_ui_components10.useTheme)();
|
|
6551
6624
|
const { waveHeight } = (0, import_ui_components10.usePlaylistInfo)();
|
|
6552
6625
|
const { isPlaying, currentTimeRef } = useMediaElementAnimation();
|
|
6553
6626
|
const { samplesPerPixel, sampleRate } = useMediaElementData();
|
|
6554
6627
|
const progressColor = (theme == null ? void 0 : theme.waveProgressColor) || "rgba(0, 0, 0, 0.1)";
|
|
6555
|
-
(0,
|
|
6628
|
+
(0, import_react36.useEffect)(() => {
|
|
6556
6629
|
const updateProgress = () => {
|
|
6557
6630
|
var _a2;
|
|
6558
6631
|
if (progressRef.current) {
|
|
@@ -6594,7 +6667,7 @@ var ChannelWithMediaElementProgress = (_a) => {
|
|
|
6594
6667
|
smartChannelProps.length,
|
|
6595
6668
|
currentTimeRef
|
|
6596
6669
|
]);
|
|
6597
|
-
(0,
|
|
6670
|
+
(0, import_react36.useEffect)(() => {
|
|
6598
6671
|
var _a2;
|
|
6599
6672
|
if (!isPlaying && progressRef.current) {
|
|
6600
6673
|
const currentTime = (_a2 = currentTimeRef.current) != null ? _a2 : 0;
|
|
@@ -6673,7 +6746,7 @@ var MediaElementPlaylist = ({
|
|
|
6673
6746
|
const theme = (0, import_ui_components11.useTheme)();
|
|
6674
6747
|
const { isPlaying } = useMediaElementAnimation();
|
|
6675
6748
|
const { annotations, activeAnnotationId } = useMediaElementState();
|
|
6676
|
-
const annotationIntegration = (0,
|
|
6749
|
+
const annotationIntegration = (0, import_react37.useContext)(AnnotationIntegrationContext);
|
|
6677
6750
|
const { play, seekTo, setActiveAnnotationId, setAnnotations, setScrollContainer } = useMediaElementControls();
|
|
6678
6751
|
const {
|
|
6679
6752
|
duration,
|
|
@@ -6689,11 +6762,11 @@ var MediaElementPlaylist = ({
|
|
|
6689
6762
|
fadeIn,
|
|
6690
6763
|
fadeOut
|
|
6691
6764
|
} = useMediaElementData();
|
|
6692
|
-
const [selectionStart, setSelectionStart] = (0,
|
|
6693
|
-
const [selectionEnd, setSelectionEnd] = (0,
|
|
6694
|
-
const [isSelecting, setIsSelecting] = (0,
|
|
6695
|
-
const scrollContainerRef = (0,
|
|
6696
|
-
const handleScrollContainerRef = (0,
|
|
6765
|
+
const [selectionStart, setSelectionStart] = (0, import_react37.useState)(0);
|
|
6766
|
+
const [selectionEnd, setSelectionEnd] = (0, import_react37.useState)(0);
|
|
6767
|
+
const [isSelecting, setIsSelecting] = (0, import_react37.useState)(false);
|
|
6768
|
+
const scrollContainerRef = (0, import_react37.useRef)(null);
|
|
6769
|
+
const handleScrollContainerRef = (0, import_react37.useCallback)(
|
|
6697
6770
|
(el) => {
|
|
6698
6771
|
scrollContainerRef.current = el;
|
|
6699
6772
|
setScrollContainer(el);
|
|
@@ -6701,7 +6774,7 @@ var MediaElementPlaylist = ({
|
|
|
6701
6774
|
[setScrollContainer]
|
|
6702
6775
|
);
|
|
6703
6776
|
const tracksFullWidth = Math.floor(duration * sampleRate / samplesPerPixel);
|
|
6704
|
-
const handleAnnotationClick = (0,
|
|
6777
|
+
const handleAnnotationClick = (0, import_react37.useCallback)(
|
|
6705
6778
|
(annotation) => __async(null, null, function* () {
|
|
6706
6779
|
setActiveAnnotationId(annotation.id);
|
|
6707
6780
|
try {
|
|
@@ -6716,7 +6789,7 @@ var MediaElementPlaylist = ({
|
|
|
6716
6789
|
}),
|
|
6717
6790
|
[setActiveAnnotationId, play]
|
|
6718
6791
|
);
|
|
6719
|
-
const handleAnnotationUpdate = (0,
|
|
6792
|
+
const handleAnnotationUpdate = (0, import_react37.useCallback)(
|
|
6720
6793
|
(updatedAnnotations) => {
|
|
6721
6794
|
setAnnotations(updatedAnnotations);
|
|
6722
6795
|
onAnnotationUpdate == null ? void 0 : onAnnotationUpdate(updatedAnnotations);
|
|
@@ -6730,8 +6803,8 @@ var MediaElementPlaylist = ({
|
|
|
6730
6803
|
duration,
|
|
6731
6804
|
linkEndpoints: linkEndpointsProp
|
|
6732
6805
|
});
|
|
6733
|
-
const mouseDownTimeRef = (0,
|
|
6734
|
-
const handleMouseDown = (0,
|
|
6806
|
+
const mouseDownTimeRef = (0, import_react37.useRef)(0);
|
|
6807
|
+
const handleMouseDown = (0, import_react37.useCallback)(
|
|
6735
6808
|
(e) => {
|
|
6736
6809
|
const rect = e.currentTarget.getBoundingClientRect();
|
|
6737
6810
|
const x = e.clientX - rect.left;
|
|
@@ -6743,7 +6816,7 @@ var MediaElementPlaylist = ({
|
|
|
6743
6816
|
},
|
|
6744
6817
|
[samplesPerPixel, sampleRate]
|
|
6745
6818
|
);
|
|
6746
|
-
const handleMouseMove = (0,
|
|
6819
|
+
const handleMouseMove = (0, import_react37.useCallback)(
|
|
6747
6820
|
(e) => {
|
|
6748
6821
|
if (!isSelecting) return;
|
|
6749
6822
|
const rect = e.currentTarget.getBoundingClientRect();
|
|
@@ -6753,7 +6826,7 @@ var MediaElementPlaylist = ({
|
|
|
6753
6826
|
},
|
|
6754
6827
|
[isSelecting, samplesPerPixel, sampleRate]
|
|
6755
6828
|
);
|
|
6756
|
-
const handleMouseUp = (0,
|
|
6829
|
+
const handleMouseUp = (0, import_react37.useCallback)(
|
|
6757
6830
|
(e) => {
|
|
6758
6831
|
if (!isSelecting) return;
|
|
6759
6832
|
setIsSelecting(false);
|
|
@@ -6885,7 +6958,7 @@ var MediaElementPlaylist = ({
|
|
|
6885
6958
|
);
|
|
6886
6959
|
}),
|
|
6887
6960
|
annotations.length > 0 && annotationIntegration && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
6888
|
-
|
|
6961
|
+
import_react38.DragDropProvider,
|
|
6889
6962
|
{
|
|
6890
6963
|
onDragStart,
|
|
6891
6964
|
onDragMove,
|
|
@@ -6939,7 +7012,7 @@ var MediaElementPlaylist = ({
|
|
|
6939
7012
|
};
|
|
6940
7013
|
|
|
6941
7014
|
// src/components/MediaElementAnnotationList.tsx
|
|
6942
|
-
var
|
|
7015
|
+
var import_react39 = require("react");
|
|
6943
7016
|
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
6944
7017
|
var MediaElementAnnotationList = ({
|
|
6945
7018
|
height,
|
|
@@ -6955,7 +7028,7 @@ var MediaElementAnnotationList = ({
|
|
|
6955
7028
|
const integration = useAnnotationIntegration();
|
|
6956
7029
|
const { setAnnotations } = useMediaElementControls();
|
|
6957
7030
|
const resolvedConfig = annotationListConfig != null ? annotationListConfig : { linkEndpoints: false, continuousPlay };
|
|
6958
|
-
const handleAnnotationUpdate = (0,
|
|
7031
|
+
const handleAnnotationUpdate = (0, import_react39.useCallback)(
|
|
6959
7032
|
(updatedAnnotations) => {
|
|
6960
7033
|
setAnnotations(updatedAnnotations);
|
|
6961
7034
|
onAnnotationUpdate == null ? void 0 : onAnnotationUpdate(updatedAnnotations);
|
|
@@ -7030,6 +7103,7 @@ var KeyboardShortcuts = ({
|
|
|
7030
7103
|
playback = false,
|
|
7031
7104
|
clipSplitting = false,
|
|
7032
7105
|
annotations = false,
|
|
7106
|
+
undo: undoEnabled = false,
|
|
7033
7107
|
additionalShortcuts = []
|
|
7034
7108
|
}) => {
|
|
7035
7109
|
const { tracks, samplesPerPixel, playoutRef, duration } = usePlaylistData();
|
|
@@ -7039,7 +7113,7 @@ var KeyboardShortcuts = ({
|
|
|
7039
7113
|
activeAnnotationId,
|
|
7040
7114
|
continuousPlay
|
|
7041
7115
|
} = usePlaylistState();
|
|
7042
|
-
const { setAnnotations, setActiveAnnotationId, scrollContainerRef, play } = usePlaylistControls();
|
|
7116
|
+
const { setAnnotations, setActiveAnnotationId, scrollContainerRef, play, undo, redo } = usePlaylistControls();
|
|
7043
7117
|
const { splitClipAtPlayhead } = useClipSplitting({
|
|
7044
7118
|
tracks,
|
|
7045
7119
|
samplesPerPixel,
|
|
@@ -7054,6 +7128,14 @@ var KeyboardShortcuts = ({
|
|
|
7054
7128
|
preventDefault: true
|
|
7055
7129
|
});
|
|
7056
7130
|
}
|
|
7131
|
+
if (undoEnabled) {
|
|
7132
|
+
allAdditional.push(
|
|
7133
|
+
{ key: "z", ctrlKey: true, shiftKey: false, action: undo, description: "Undo" },
|
|
7134
|
+
{ key: "z", metaKey: true, shiftKey: false, action: undo, description: "Undo" },
|
|
7135
|
+
{ key: "z", ctrlKey: true, shiftKey: true, action: redo, description: "Redo" },
|
|
7136
|
+
{ key: "z", metaKey: true, shiftKey: true, action: redo, description: "Redo" }
|
|
7137
|
+
);
|
|
7138
|
+
}
|
|
7057
7139
|
if (additionalShortcuts.length > 0) {
|
|
7058
7140
|
allAdditional.push(...additionalShortcuts);
|
|
7059
7141
|
}
|
|
@@ -7076,10 +7158,10 @@ var KeyboardShortcuts = ({
|
|
|
7076
7158
|
};
|
|
7077
7159
|
|
|
7078
7160
|
// src/components/ClipInteractionProvider.tsx
|
|
7079
|
-
var
|
|
7080
|
-
var
|
|
7161
|
+
var import_react40 = __toESM(require("react"));
|
|
7162
|
+
var import_react41 = require("@dnd-kit/react");
|
|
7081
7163
|
var import_modifiers2 = require("@dnd-kit/abstract/modifiers");
|
|
7082
|
-
var
|
|
7164
|
+
var import_core8 = require("@waveform-playlist/core");
|
|
7083
7165
|
var import_ui_components12 = require("@waveform-playlist/ui-components");
|
|
7084
7166
|
|
|
7085
7167
|
// src/modifiers/ClipCollisionModifier.ts
|
|
@@ -7108,7 +7190,7 @@ var ClipCollisionModifier = _ClipCollisionModifier;
|
|
|
7108
7190
|
|
|
7109
7191
|
// src/modifiers/SnapToGridModifier.ts
|
|
7110
7192
|
var import_abstract2 = require("@dnd-kit/abstract");
|
|
7111
|
-
var
|
|
7193
|
+
var import_core7 = require("@waveform-playlist/core");
|
|
7112
7194
|
var _SnapToGridModifier = class _SnapToGridModifier extends import_abstract2.Modifier {
|
|
7113
7195
|
apply(operation) {
|
|
7114
7196
|
const { transform, source } = operation;
|
|
@@ -7129,18 +7211,18 @@ var _SnapToGridModifier = class _SnapToGridModifier extends import_abstract2.Mod
|
|
|
7129
7211
|
}
|
|
7130
7212
|
const { snapTo, bpm, timeSignature, sampleRate } = this.options;
|
|
7131
7213
|
if (snapTo === "off") return transform;
|
|
7132
|
-
const gridTicks = snapTo === "bar" ? (0,
|
|
7214
|
+
const gridTicks = snapTo === "bar" ? (0, import_core7.ticksPerBar)(timeSignature) : (0, import_core7.ticksPerBeat)(timeSignature);
|
|
7133
7215
|
if (startSample !== void 0) {
|
|
7134
7216
|
const proposedSamples = startSample + transform.x * samplesPerPixel;
|
|
7135
|
-
const proposedTicks = (0,
|
|
7136
|
-
const snappedTicks2 = (0,
|
|
7137
|
-
const snappedSamples2 = (0,
|
|
7217
|
+
const proposedTicks = (0, import_core7.samplesToTicks)(proposedSamples, bpm, sampleRate);
|
|
7218
|
+
const snappedTicks2 = (0, import_core7.snapToGrid)(proposedTicks, gridTicks);
|
|
7219
|
+
const snappedSamples2 = (0, import_core7.ticksToSamples)(snappedTicks2, bpm, sampleRate);
|
|
7138
7220
|
return { x: (snappedSamples2 - startSample) / samplesPerPixel, y: 0 };
|
|
7139
7221
|
}
|
|
7140
7222
|
const deltaSamples = transform.x * samplesPerPixel;
|
|
7141
|
-
const deltaTicks = (0,
|
|
7142
|
-
const snappedTicks = (0,
|
|
7143
|
-
const snappedSamples = (0,
|
|
7223
|
+
const deltaTicks = (0, import_core7.samplesToTicks)(deltaSamples, bpm, sampleRate);
|
|
7224
|
+
const snappedTicks = (0, import_core7.snapToGrid)(deltaTicks, gridTicks);
|
|
7225
|
+
const snappedSamples = (0, import_core7.ticksToSamples)(snappedTicks, bpm, sampleRate);
|
|
7144
7226
|
return { x: snappedSamples / samplesPerPixel, y: 0 };
|
|
7145
7227
|
}
|
|
7146
7228
|
};
|
|
@@ -7161,21 +7243,21 @@ var ClipInteractionProvider = ({
|
|
|
7161
7243
|
const beatsAndBars = (0, import_ui_components12.useBeatsAndBars)();
|
|
7162
7244
|
const useBeatsSnap = snap && beatsAndBars != null && beatsAndBars.scaleMode === "beats" && beatsAndBars.snapTo !== "off";
|
|
7163
7245
|
const useTimescaleSnap = snap && !useBeatsSnap;
|
|
7164
|
-
(0,
|
|
7246
|
+
(0, import_react40.useEffect)(() => {
|
|
7165
7247
|
if (onTracksChange == null) {
|
|
7166
7248
|
console.warn(
|
|
7167
7249
|
"[waveform-playlist] ClipInteractionProvider: onTracksChange is not set on WaveformPlaylistProvider. Drag and trim edits will not be persisted."
|
|
7168
7250
|
);
|
|
7169
7251
|
}
|
|
7170
7252
|
}, [onTracksChange]);
|
|
7171
|
-
const snapSamplePosition = (0,
|
|
7253
|
+
const snapSamplePosition = (0, import_react40.useMemo)(() => {
|
|
7172
7254
|
if (useBeatsSnap && beatsAndBars) {
|
|
7173
7255
|
const { bpm, timeSignature, snapTo } = beatsAndBars;
|
|
7174
|
-
const gridTicks = snapTo === "bar" ? (0,
|
|
7256
|
+
const gridTicks = snapTo === "bar" ? (0, import_core8.ticksPerBar)(timeSignature) : (0, import_core8.ticksPerBeat)(timeSignature);
|
|
7175
7257
|
return (samplePos) => {
|
|
7176
|
-
const ticks = (0,
|
|
7177
|
-
const snapped = (0,
|
|
7178
|
-
return (0,
|
|
7258
|
+
const ticks = (0, import_core8.samplesToTicks)(samplePos, bpm, sampleRate);
|
|
7259
|
+
const snapped = (0, import_core8.snapToGrid)(ticks, gridTicks);
|
|
7260
|
+
return (0, import_core8.ticksToSamples)(snapped, bpm, sampleRate);
|
|
7179
7261
|
};
|
|
7180
7262
|
}
|
|
7181
7263
|
if (useTimescaleSnap) {
|
|
@@ -7197,7 +7279,7 @@ var ClipInteractionProvider = ({
|
|
|
7197
7279
|
isDraggingRef,
|
|
7198
7280
|
snapSamplePosition
|
|
7199
7281
|
});
|
|
7200
|
-
const onDragStart =
|
|
7282
|
+
const onDragStart = import_react40.default.useCallback(
|
|
7201
7283
|
(event) => {
|
|
7202
7284
|
var _a, _b, _c;
|
|
7203
7285
|
const trackIndex = (_c = (_b = (_a = event.operation) == null ? void 0 : _a.source) == null ? void 0 : _b.data) == null ? void 0 : _c.trackIndex;
|
|
@@ -7208,7 +7290,7 @@ var ClipInteractionProvider = ({
|
|
|
7208
7290
|
},
|
|
7209
7291
|
[handleDragStart, tracks, setSelectedTrackId]
|
|
7210
7292
|
);
|
|
7211
|
-
const modifiers = (0,
|
|
7293
|
+
const modifiers = (0, import_react40.useMemo)(() => {
|
|
7212
7294
|
const mods = [import_modifiers2.RestrictToHorizontalAxis];
|
|
7213
7295
|
if (useBeatsSnap && beatsAndBars) {
|
|
7214
7296
|
mods.push(
|
|
@@ -7234,7 +7316,7 @@ var ClipInteractionProvider = ({
|
|
|
7234
7316
|
return mods;
|
|
7235
7317
|
}, [useBeatsSnap, useTimescaleSnap, beatsAndBars, tracks, samplesPerPixel, sampleRate]);
|
|
7236
7318
|
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(ClipInteractionContextProvider, { value: true, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
7237
|
-
|
|
7319
|
+
import_react41.DragDropProvider,
|
|
7238
7320
|
{
|
|
7239
7321
|
sensors,
|
|
7240
7322
|
onDragStart,
|