diff --git a/plugins/examples/gain/src/lib.rs b/plugins/examples/gain/src/lib.rs index 9842c2a5..164eac6f 100644 --- a/plugins/examples/gain/src/lib.rs +++ b/plugins/examples/gain/src/lib.rs @@ -111,7 +111,7 @@ impl Plugin for Gain { &mut self, _bus_config: &BusConfig, _buffer_config: &BufferConfig, - _context: &impl ProcessContext, + _context: &mut impl ProcessContext, ) -> bool { // This plugin doesn't need any special initialization, but if you need to do anything // expensive then this would be the place. State is kept around while when the host @@ -119,7 +119,11 @@ impl Plugin for Gain { true } - fn process(&mut self, buffer: &mut Buffer, _context: &impl ProcessContext) -> ProcessStatus { + fn process( + &mut self, + buffer: &mut Buffer, + _context: &mut impl ProcessContext, + ) -> ProcessStatus { for samples in buffer.iter_mut() { // Smoothing is optionally built into the parameters themselves let gain = self.params.gain.smoothed.next(); diff --git a/plugins/examples/sine/src/lib.rs b/plugins/examples/sine/src/lib.rs index e0725a15..08d54dd5 100644 --- a/plugins/examples/sine/src/lib.rs +++ b/plugins/examples/sine/src/lib.rs @@ -145,14 +145,14 @@ impl Plugin for Sine { &mut self, _bus_config: &BusConfig, buffer_config: &BufferConfig, - _context: &impl ProcessContext, + _context: &mut impl ProcessContext, ) -> bool { self.sample_rate = buffer_config.sample_rate; true } - fn process(&mut self, buffer: &mut Buffer, context: &impl ProcessContext) -> ProcessStatus { + fn process(&mut self, buffer: &mut Buffer, context: &mut impl ProcessContext) -> ProcessStatus { let mut next_event = context.next_midi_event(); for (sample_id, samples) in buffer.iter_mut().enumerate() { // Smoothing is optionally built into the parameters themselves diff --git a/src/context.rs b/src/context.rs index 682b7378..ce2f0892 100644 --- a/src/context.rs +++ b/src/context.rs @@ -48,7 +48,7 @@ pub trait ProcessContext { /// TODO: Rethink this API, both in terms of ergonomics, and if we can do this in a way that /// doesn't require locks (because of the thread safe-ness, which we don't really need /// here) - fn next_midi_event(&self) -> Option; + fn next_midi_event(&mut self) -> Option; // // TODO: Add this next // fn set_parameter

(&self, param: &P, value: P::Plain) diff --git a/src/plugin.rs b/src/plugin.rs index d73b9ae4..f4789c97 100644 --- a/src/plugin.rs +++ b/src/plugin.rs @@ -88,7 +88,7 @@ pub trait Plugin: Default + Send + Sync { &mut self, bus_config: &BusConfig, buffer_config: &BufferConfig, - context: &impl ProcessContext, + context: &mut impl ProcessContext, ) -> bool { true } @@ -103,7 +103,7 @@ pub trait Plugin: Default + Send + Sync { /// TODO: Provide a way to access auxiliary input channels if the IO configuration is /// assymetric /// TODO: Pass transport and other context information to the plugin - fn process(&mut self, buffer: &mut Buffer, context: &impl ProcessContext) -> ProcessStatus; + fn process(&mut self, buffer: &mut Buffer, context: &mut impl ProcessContext) -> ProcessStatus; } /// Provides auxiliary metadata needed for a VST3 plugin. diff --git a/src/wrapper/vst3.rs b/src/wrapper/vst3.rs index 5df4fe1e..fc53e90d 100644 --- a/src/wrapper/vst3.rs +++ b/src/wrapper/vst3.rs @@ -20,7 +20,7 @@ use crossbeam::atomic::AtomicCell; use lazy_static::lazy_static; -use parking_lot::RwLock; +use parking_lot::{RwLock, RwLockWriteGuard}; use std::cmp; use std::collections::{HashMap, VecDeque}; use std::ffi::c_void; @@ -152,6 +152,7 @@ pub(crate) struct Wrapper { /// unnecessary atomic operations to lock the uncontested RwLocks. struct WrapperProcessContext<'a, P: Plugin> { inner: &'a WrapperInner

, + input_events_guard: RwLockWriteGuard<'a, VecDeque>, } impl ProcessContext for WrapperProcessContext<'_, P> { @@ -167,10 +168,8 @@ impl ProcessContext for WrapperProcessContext<'_, P> { } } - fn next_midi_event(&self) -> Option { - // TODO: Instead of having to lock this queue, move the lock guard into - // `WrapperProcessContext`. That's the whole reason this was split up. - self.inner.input_events.write().pop_front() + fn next_midi_event(&mut self) -> Option { + self.input_events_guard.pop_front() } } @@ -293,7 +292,10 @@ impl WrapperInner

{ } pub fn make_process_context(&self) -> WrapperProcessContext<'_, P> { - WrapperProcessContext { inner: self } + WrapperProcessContext { + inner: self, + input_events_guard: self.input_events.write(), + } } /// Convenience function for setting a value for a parameter as triggered by a VST3 parameter @@ -607,7 +609,7 @@ impl IComponent for Wrapper

{ self.inner.plugin.write().initialize( &bus_config, &buffer_config, - &self.inner.make_process_context(), + &mut self.inner.make_process_context(), ); } @@ -994,7 +996,7 @@ impl IAudioProcessor for Wrapper

{ if self.inner.plugin.write().initialize( &bus_config, &buffer_config, - &self.inner.make_process_context(), + &mut self.inner.make_process_context(), ) { // Preallocate enough room in the output slices vector so we can convert a `*mut *mut // f32` to a `&mut [&mut f32]` in the process call @@ -1173,7 +1175,7 @@ impl IAudioProcessor for Wrapper

{ .plugin .write() // SAFETY: Same here - .process(&mut output_buffer, &self.inner.make_process_context()) + .process(&mut output_buffer, &mut self.inner.make_process_context()) { ProcessStatus::Error(err) => { nih_debug_assert_failure!("Process error: {}", err);