1
0
Fork 0

Respect assert_process_allocs in standalones

This fixes #29.
This commit is contained in:
Robbert van der Helm 2022-09-07 18:29:58 +02:00
parent 591f3710bd
commit 910a90d47a

View file

@ -386,12 +386,17 @@ impl<P: Plugin, B: Backend> Wrapper<P, B> {
) { ) {
self.clone().backend.borrow_mut().run( self.clone().backend.borrow_mut().run(
move |buffer, transport, input_events, output_events| { move |buffer, transport, input_events, output_events| {
// TODO: This process wrapper should actually be in the backends (since the backends
// should also not allocate in their audio callbacks), but that's a bit more
// erorr prone
process_wrapper(|| {
if should_terminate.load(Ordering::SeqCst) { if should_terminate.load(Ordering::SeqCst) {
return false; return false;
} }
let sample_rate = self.buffer_config.sample_rate; let sample_rate = self.buffer_config.sample_rate;
if let ProcessStatus::Error(err) = self.plugin.write().process( let mut plugin = self.plugin.write();
if let ProcessStatus::Error(err) = plugin.process(
buffer, buffer,
// TODO: Provide extra inputs and outputs in the JACk backend // TODO: Provide extra inputs and outputs in the JACk backend
&mut AuxiliaryBuffers { &mut AuxiliaryBuffers {
@ -415,28 +420,29 @@ impl<P: Plugin, B: Backend> Wrapper<P, B> {
// Any output note events are now in a vector that can be processed by the // Any output note events are now in a vector that can be processed by the
// audio/MIDI backend // audio/MIDI backend
// We'll always write these events to the first sample, so even when we add note output we // We'll always write these events to the first sample, so even when we add note
// shouldn't have to think about interleaving events here // output we shouldn't have to think about interleaving events here
let mut parameter_values_changed = false; let mut parameter_values_changed = false;
while let Some((param_ptr, normalized_value)) = self.unprocessed_param_changes.pop() while let Some((param_ptr, normalized_value)) =
self.unprocessed_param_changes.pop()
{ {
unsafe { param_ptr.set_normalized_value(normalized_value) }; unsafe { param_ptr.set_normalized_value(normalized_value) };
unsafe { param_ptr.update_smoother(sample_rate, false) }; unsafe { param_ptr.update_smoother(sample_rate, false) };
parameter_values_changed = true; parameter_values_changed = true;
} }
// Allow the editor to react to the new parameter values if the editor uses a reactive data // Allow the editor to react to the new parameter values if the editor uses a
// binding model // reactive data binding model
if parameter_values_changed { if parameter_values_changed {
self.notify_param_values_changed(); self.notify_param_values_changed();
} }
// After processing audio, we'll check if the editor has sent us updated plugin state. // After processing audio, we'll check if the editor has sent us updated plugin
// We'll restore that here on the audio thread to prevent changing the values during the // state. We'll restore that here on the audio thread to prevent changing the
// process call and also to prevent inconsistent state when the host also wants to load // values during the process call and also to prevent inconsistent state when
// plugin state. // the host also wants to load plugin state.
// FIXME: Zero capacity channels allocate on receiving, find a better alternative that // FIXME: Zero capacity channels allocate on receiving, find a better
// doesn't do that // alternative that doesn't do that
let updated_state = permit_alloc(|| self.updated_state_receiver.try_recv()); let updated_state = permit_alloc(|| self.updated_state_receiver.try_recv());
if let Ok(state) = updated_state { if let Ok(state) = updated_state {
unsafe { unsafe {
@ -450,12 +456,12 @@ impl<P: Plugin, B: Backend> Wrapper<P, B> {
self.notify_param_values_changed(); self.notify_param_values_changed();
// TODO: Normally we'd also call initialize after deserializing state, but that's // TODO: Normally we'd also call initialize after deserializing state, but
// not guaranteed to be realtime safe. Should we do it anyways? // that's not guaranteed to be realtime safe. Should we do it anyways?
self.plugin.write().reset(); self.plugin.write().reset();
// We'll pass the state object back to the GUI thread so deallocation can happen // We'll pass the state object back to the GUI thread so deallocation can
// there without potentially blocking the audio thread // happen there without potentially blocking the audio thread
if let Err(err) = self.updated_state_sender.send(state) { if let Err(err) = self.updated_state_sender.send(state) {
nih_debug_assert_failure!( nih_debug_assert_failure!(
"Failed to send state object back to GUI thread: {}", "Failed to send state object back to GUI thread: {}",
@ -465,6 +471,7 @@ impl<P: Plugin, B: Backend> Wrapper<P, B> {
} }
true true
})
}, },
); );
} }