Data Flow Between Threads
Two patterns cover almost all cross-thread traffic: the playback loop, where the audio clock drives video decode and compositing, and session jobs, where background work reports back through a waker and Session::tick.
Playback

- Video. After an edit the UI sends
RenderAheada clone of the project. The thread walks forward from the target frame (and a little behind it), decodes into theSharedFrameCacheunder a global RAM budget, and the UI composites whatever is cached for the current frame. - Audio. The UI builds an immutable
MixSnapshot(clips, channel strips, effects) whose audio buffers come from themix_buffersworkers, and publishes it as anArc<MixerState>. The callback picks it up at the start of a block and runsmix_range, the same pure function the export uses. - Clock. The callback's
positionis the playhead. Without an audio device the clock falls back to wall time.
Session jobs

Import, OTIO import, relink and export all follow this shape. The thread that owns the Session (the UI thread, or the MCP host) starts the job and gets a JobId. The job never touches the session: it writes progress into shared atomics and wakes the owner when done. The owner's next tick() joins the thread and returns SessionEvents, and applying them (for example adding the imported media) goes through the history like any other edit.
Synchronisation primitives
| Primitive | Used for |
|---|---|
std::sync::mpsc | Job queues and results of every worker; RenderAhead commands; recorder chunks; MCP requests |
| Atomics | Playhead, play state, peaks, progress counters, cancel flags |
Mutex | Frame cache, export progress, pending mixer state (callback side: try_lock only) |
Mutex + Condvar | Proxy worker pause; the MCP session slot |
sync_channel (bounded) | Export stages, so decode cannot run far ahead of encode |
tokio::sync::oneshot | The reply to one MCP tool call |
No comments to display
No comments to display