parent
591f3710bd
commit
910a90d47a
1 changed files with 81 additions and 74 deletions
|
@ -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
|
||||||
|
})
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue