Skip to main content

maolan_plugin_host/
util.rs

1//! Simple utility types extracted from maolan-engine for standalone plugin hosting.
2
3use std::cell::UnsafeCell;
4
5/// Single-threaded mutex (no actual locking, just a cell wrapper).
6/// The plugin host processes audio on one thread, so this is safe.
7pub struct SimpleMutex<T> {
8    data: UnsafeCell<T>,
9}
10
11unsafe impl<T: Send> Send for SimpleMutex<T> {}
12unsafe impl<T: Send> Sync for SimpleMutex<T> {}
13
14impl<T> SimpleMutex<T> {
15    pub fn new(data: T) -> Self {
16        SimpleMutex {
17            data: UnsafeCell::new(data),
18        }
19    }
20
21    #[allow(clippy::mut_from_ref)]
22    pub fn lock(&self) -> &mut T {
23        unsafe { &mut *self.data.get() }
24    }
25}
26
27/// Audio port buffer used by in-process plugin wrappers.
28pub struct AudioPort {
29    pub buffer: std::sync::Arc<SimpleMutex<Vec<f32>>>,
30    pub finished: std::sync::Arc<SimpleMutex<bool>>,
31}
32
33impl AudioPort {
34    pub fn new(size: usize) -> Self {
35        Self {
36            buffer: std::sync::Arc::new(SimpleMutex::new(vec![0.0; size])),
37            finished: std::sync::Arc::new(SimpleMutex::new(false)),
38        }
39    }
40
41    pub fn setup(&self) {
42        // No-op for standalone AudioPort (connections are managed externally).
43    }
44
45    pub fn process(&self) {
46        // No-op for standalone AudioPort (audio is copied directly from SHM).
47    }
48}
49
50/// MIDI event with sample frame offset.
51#[derive(Debug, Clone, PartialEq)]
52pub struct MidiEvent {
53    pub frame: u32,
54    pub data: Vec<u8>,
55}
56
57impl MidiEvent {
58    pub fn new(frame: u32, data: Vec<u8>) -> Self {
59        Self { frame, data }
60    }
61}