mirror of
https://github.com/storytold/soundcraft.git
synced 2026-10-26 03:26:49 -06:00
Video (new standalone crate soundcraft-video): - Pure-Rust H.264 (Baseline/Main/High), ProRes (all flavours) and Motion JPEG decoding with ISO-BMFF demux, adapted from FilmCraft's crates; fuzzed with mutated/truncated movies - TrackKind::Video with ClipContent::Video referencing Session.videos; file.import_video adds the picture track and the movie's audio; relinking on open; video.offset/online/list - Video and Video Universe windows, thumbnails on the timeline, background decoding Third-party plugins: - Plugin state (CLAP state ext, VST3 component + controller state) saved in sessions - Hosted instances created, state-loaded and dropped on the UI thread, never the audio thread - Plugin editors: floating CLAP GUIs and VST3 views on macOS (verified with Melodyne) - New isolated FFI crate soundcraft-au-host: Audio Units on macOS (effects and instruments, parameters, latency, MIDI, ClassInfo state), wired into the mixer and plugin browser UI: Window > Renderer (speaker layout with live levels and object positions), Window > UI Customization (interface scale, reduce motion), Window > Configurations > Auto-Update. Fix: saturating sample-index math in clip rendering (hostile stretch values overflowed). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
49 lines
1.7 KiB
Rust
49 lines
1.7 KiB
Rust
//! Plugin editors must be driven from the process main thread, which the standard test harness
|
|
//! never uses, so this test binary has its own `main` (`harness = false`). The fixture's GUI is
|
|
//! window-less: nothing appears on screen.
|
|
|
|
mod common;
|
|
|
|
use soundcraft_dsp::Plugin;
|
|
|
|
const GAIN: &str = "clap:org.soundcraft.test.gain";
|
|
|
|
fn block(p: &mut Box<dyn Plugin>) -> Vec<Vec<f32>> {
|
|
let mut io = vec![vec![1.0f32; 64]; 2];
|
|
p.process(&mut io, 64);
|
|
io
|
|
}
|
|
|
|
fn main() {
|
|
common::fixture_dir();
|
|
let mut p = soundcraft_clap_host::create(GAIN).expect("fixture");
|
|
p.prepare(48_000.0, 64, 2);
|
|
let mut ed = p.editor().expect("editor handle");
|
|
assert!(!ed.is_open());
|
|
ed.open().expect("open on the main thread");
|
|
assert!(ed.is_open());
|
|
ed.open().expect("opening again just raises it");
|
|
// The fixture "edits" the gain in its GUI; the edit arrives as an output event of the next
|
|
// block and is reported (in SoundCraft units) by idle.
|
|
let io = block(&mut p);
|
|
assert!((io[0][10] - 0.25).abs() < 1e-6, "{}", io[0][10]);
|
|
assert_eq!(ed.idle(), vec![("7".to_string(), 0.25)]);
|
|
assert!(ed.idle().is_empty(), "drained");
|
|
ed.close();
|
|
assert!(!ed.is_open());
|
|
// Through the Plugin trait as well.
|
|
p.open_editor().expect("open via the trait");
|
|
assert!(ed.is_open(), "the handle sees the same editor");
|
|
p.close_editor();
|
|
assert!(!ed.is_open());
|
|
// Dropping the instance with its editor open destroys the GUI first (the fixture asserts
|
|
// that); the handle then refuses politely.
|
|
ed.open().expect("reopen");
|
|
drop(p);
|
|
assert!(!ed.is_open());
|
|
assert!(ed.open().is_err());
|
|
assert!(ed.idle().is_empty());
|
|
ed.close();
|
|
println!("editor_main_thread: ok");
|
|
}
|