summaryrefslogtreecommitdiff
path: root/apps/web/src/core/managers
diff options
context:
space:
mode:
Diffstat (limited to 'apps/web/src/core/managers')
-rw-r--r--apps/web/src/core/managers/audio-manager.ts23
-rw-r--r--apps/web/src/core/managers/playback-manager.ts44
-rw-r--r--apps/web/src/core/managers/timeline-manager.ts12
3 files changed, 36 insertions, 43 deletions
diff --git a/apps/web/src/core/managers/audio-manager.ts b/apps/web/src/core/managers/audio-manager.ts
index 545565be..d0716aad 100644
--- a/apps/web/src/core/managers/audio-manager.ts
+++ b/apps/web/src/core/managers/audio-manager.ts
@@ -1,9 +1,6 @@
import type { EditorCore } from "@/core";
import { TICKS_PER_SECOND } from "@/wasm";
-import {
- clampRetimeRate,
- shouldMaintainPitch,
-} from "@/retime/rate";
+import { clampRetimeRate, shouldMaintainPitch } from "@/retime/rate";
import type { AudioClipSource } from "@/media/audio";
import { createAudioContext, collectAudioClips } from "@/media/audio";
import {
@@ -56,10 +53,8 @@ export class AudioManager {
this.editor.playback.subscribe(this.handlePlaybackChange),
this.editor.timeline.subscribe(this.handleTimelineChange),
this.editor.media.subscribe(this.handleTimelineChange),
+ this.editor.playback.onSeek(this.handleSeek),
);
- if (typeof window !== "undefined") {
- window.addEventListener("playback-seek", this.handleSeek);
- }
}
dispose(): void {
@@ -68,9 +63,6 @@ export class AudioManager {
unsub();
}
this.unsubscribers = [];
- if (typeof window !== "undefined") {
- window.removeEventListener("playback-seek", this.handleSeek);
- }
this.disposeSinks();
this.preparedClipBuffers.clear();
this.decodedBuffers.clear();
@@ -102,17 +94,14 @@ export class AudioManager {
}
};
- private handleSeek = (event: Event): void => {
- const detail = (event as CustomEvent<{ time: number }>).detail;
- if (!detail) return;
-
+ private handleSeek = (time: number): void => {
if (this.editor.playback.getIsScrubbing()) {
this.stopPlayback();
return;
}
if (this.editor.playback.getIsPlaying()) {
- void this.startPlayback({ time: detail.time / TICKS_PER_SECOND });
+ void this.startPlayback({ time: time / TICKS_PER_SECOND });
return;
}
@@ -126,7 +115,9 @@ export class AudioManager {
if (!this.editor.playback.getIsPlaying()) return;
- void this.startPlayback({ time: this.editor.playback.getCurrentTime() / TICKS_PER_SECOND });
+ void this.startPlayback({
+ time: this.editor.playback.getCurrentTime() / TICKS_PER_SECOND,
+ });
};
private ensureAudioContext(): AudioContext | null {
diff --git a/apps/web/src/core/managers/playback-manager.ts b/apps/web/src/core/managers/playback-manager.ts
index 1ea09826..a243dc19 100644
--- a/apps/web/src/core/managers/playback-manager.ts
+++ b/apps/web/src/core/managers/playback-manager.ts
@@ -10,6 +10,8 @@ export class PlaybackManager {
private previousVolume = 1;
private isScrubbing = false;
private listeners = new Set<() => void>();
+ private updateListeners = new Set<(time: number) => void>();
+ private seekListeners = new Set<(time: number) => void>();
private playbackTimer: number | null = null;
private playbackStartWallTime = 0;
private playbackStartTime = 0;
@@ -67,7 +69,7 @@ export class PlaybackManager {
this.playbackStartTime = this.currentTime;
}
this.notify();
- this.dispatchSeekEvent(this.currentTime);
+ this.notifySeek(this.currentTime);
}
setVolume({ volume }: { volume: number }): void {
@@ -133,6 +135,16 @@ export class PlaybackManager {
return () => this.listeners.delete(listener);
}
+ onUpdate(listener: (time: number) => void): () => void {
+ this.updateListeners.add(listener);
+ return () => this.updateListeners.delete(listener);
+ }
+
+ onSeek(listener: (time: number) => void): () => void {
+ this.seekListeners.add(listener);
+ return () => this.seekListeners.delete(listener);
+ }
+
private reconcileTimelineScope(): void {
const maxTime = this.editor.timeline.getTotalDuration();
const nextTime = this.clampTimeToTimeline(this.currentTime);
@@ -152,7 +164,7 @@ export class PlaybackManager {
this.notify();
if (timeChanged) {
- this.dispatchSeekEvent(this.currentTime);
+ this.notifySeek(this.currentTime);
}
}
@@ -196,12 +208,12 @@ export class PlaybackManager {
this.pause();
this.currentTime = maxTime;
this.notify();
- this.dispatchSeekEvent(maxTime);
+ this.notifySeek(maxTime);
return;
}
this.currentTime = newTime;
- this.dispatchUpdateEvent(newTime);
+ this.notifyUpdate(newTime);
this.playbackTimer = requestAnimationFrame(this.updateTime);
};
@@ -210,27 +222,15 @@ export class PlaybackManager {
return Math.max(0, Math.min(maxTime, time));
}
- private dispatchSeekEvent(time: number): void {
- if (typeof window === "undefined") {
- return;
+ private notifySeek(time: number): void {
+ for (const fn of this.seekListeners) {
+ fn(time);
}
-
- window.dispatchEvent(
- new CustomEvent("playback-seek", {
- detail: { time },
- }),
- );
}
- private dispatchUpdateEvent(time: number): void {
- if (typeof window === "undefined") {
- return;
+ private notifyUpdate(time: number): void {
+ for (const fn of this.updateListeners) {
+ fn(time);
}
-
- window.dispatchEvent(
- new CustomEvent("playback-update", {
- detail: { time },
- }),
- );
}
}
diff --git a/apps/web/src/core/managers/timeline-manager.ts b/apps/web/src/core/managers/timeline-manager.ts
index dbc3332b..6f54c5aa 100644
--- a/apps/web/src/core/managers/timeline-manager.ts
+++ b/apps/web/src/core/managers/timeline-manager.ts
@@ -9,6 +9,7 @@ import type {
RetimeConfig,
} from "@/timeline";
import { calculateTotalDuration } from "@/timeline";
+import { TimelineDragSource } from "@/timeline/drag-source";
import { findTrackInSceneTracks } from "@/timeline/track-element-update";
import {
canElementBeHidden,
@@ -67,6 +68,7 @@ export class TimelineManager {
private listeners = new Set<() => void>();
private previewOverlay = new Map<string, Partial<TimelineElement>>();
private previewTracks: SceneTracks | null = null;
+ public readonly dragSource = new TimelineDragSource();
constructor(private editor: EditorCore) {}
@@ -706,11 +708,11 @@ export class TimelineManager {
previewElements({
updates,
}: {
- updates: Array<{
- trackId: string;
- elementId: string;
- updates: Partial<TimelineElement>;
- }>;
+ updates: readonly {
+ readonly trackId: string;
+ readonly elementId: string;
+ readonly updates: Partial<TimelineElement>;
+ }[];
}): void {
let changedOverlayCount = 0;
for (const { elementId, updates: elementUpdates } of updates) {