2022-02-07 04:51:46 +11:00
|
|
|
use parking_lot::RwLockWriteGuard;
|
|
|
|
use std::collections::VecDeque;
|
|
|
|
use std::sync::atomic::Ordering;
|
|
|
|
|
|
|
|
use super::inner::{Task, WrapperInner};
|
2022-02-28 22:55:59 +11:00
|
|
|
use crate::context::ProcessContext;
|
|
|
|
use crate::event_loop::EventLoop;
|
2022-03-01 05:21:14 +11:00
|
|
|
use crate::plugin::{NoteEvent, Vst3Plugin};
|
2022-02-07 04:51:46 +11:00
|
|
|
|
|
|
|
/// A [ProcessContext] implementation for the wrapper. This is a separate object so it can hold on
|
|
|
|
/// to lock guards for event queues. Otherwise reading these events would require constant
|
|
|
|
/// unnecessary atomic operations to lock the uncontested RwLocks.
|
2022-03-01 05:21:14 +11:00
|
|
|
pub(crate) struct WrapperProcessContext<'a, P: Vst3Plugin> {
|
2022-03-01 05:45:41 +11:00
|
|
|
pub(super) inner: &'a WrapperInner<P>,
|
|
|
|
pub(super) input_events_guard: RwLockWriteGuard<'a, VecDeque<NoteEvent>>,
|
2022-02-07 04:51:46 +11:00
|
|
|
}
|
|
|
|
|
2022-03-01 05:21:14 +11:00
|
|
|
impl<P: Vst3Plugin> ProcessContext for WrapperProcessContext<'_, P> {
|
2022-02-07 04:51:46 +11:00
|
|
|
fn set_latency_samples(&self, samples: u32) {
|
|
|
|
// Only trigger a restart if it's actually needed
|
|
|
|
let old_latency = self.inner.current_latency.swap(samples, Ordering::SeqCst);
|
|
|
|
if old_latency != samples {
|
|
|
|
let task_posted = unsafe { self.inner.event_loop.read().assume_init_ref() }
|
|
|
|
.do_maybe_async(Task::TriggerRestart(
|
|
|
|
vst3_sys::vst::RestartFlags::kLatencyChanged as i32,
|
|
|
|
));
|
|
|
|
nih_debug_assert!(task_posted, "The task queue is full, dropping task...");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn next_midi_event(&mut self) -> Option<NoteEvent> {
|
|
|
|
self.input_events_guard.pop_front()
|
|
|
|
}
|
|
|
|
}
|