Account for Params::deserialize_fields allocating
When state through `GuiContext`.
This commit is contained in:
parent
a97c8ea554
commit
a202c3801a
|
@ -2362,22 +2362,31 @@ impl<P: ClapPlugin> Wrapper<P> {
|
||||||
// doesn't do that
|
// doesn't do that
|
||||||
let updated_state = permit_alloc(|| wrapper.updated_state_receiver.try_recv());
|
let updated_state = permit_alloc(|| wrapper.updated_state_receiver.try_recv());
|
||||||
if let Ok(mut state) = updated_state {
|
if let Ok(mut state) = updated_state {
|
||||||
state::deserialize_object::<P>(
|
// FIXME: This is obviously not realtime-safe, but loading presets without doing
|
||||||
&mut state,
|
// this could lead to inconsistencies. It's the plugin's responsibility to
|
||||||
wrapper.params.clone(),
|
// not perform any realtime-unsafe work when the initialize function is
|
||||||
state::make_params_getter(&wrapper.param_by_hash, &wrapper.param_id_to_hash),
|
// called a second time if it supports runtime preset loading.
|
||||||
wrapper.current_buffer_config.load().as_ref(),
|
// `state::deserialize_object()` normally never allocates, but if the plugin
|
||||||
);
|
// has persistent non-parameter data then its `deserialize_fields()`
|
||||||
|
// implementation may still allocate.
|
||||||
|
permit_alloc(|| {
|
||||||
|
state::deserialize_object::<P>(
|
||||||
|
&mut state,
|
||||||
|
wrapper.params.clone(),
|
||||||
|
state::make_params_getter(
|
||||||
|
&wrapper.param_by_hash,
|
||||||
|
&wrapper.param_id_to_hash,
|
||||||
|
),
|
||||||
|
wrapper.current_buffer_config.load().as_ref(),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
// NOTE: This needs to be dropped after the `plugin` lock to avoid deadlocks
|
// NOTE: This needs to be dropped after the `plugin` lock to avoid deadlocks
|
||||||
let mut init_context = wrapper.make_init_context();
|
let mut init_context = wrapper.make_init_context();
|
||||||
let audio_io_layout = wrapper.current_audio_io_layout.load();
|
let audio_io_layout = wrapper.current_audio_io_layout.load();
|
||||||
let buffer_config = wrapper.current_buffer_config.load().unwrap();
|
let buffer_config = wrapper.current_buffer_config.load().unwrap();
|
||||||
let mut plugin = wrapper.plugin.lock();
|
let mut plugin = wrapper.plugin.lock();
|
||||||
// FIXME: This is obviously not realtime-safe, but loading presets without doing
|
// See above
|
||||||
// this could lead to inconsistencies. It's the plugin's responsibility to
|
|
||||||
// not perform any realtime-unsafe work when the initialize function is
|
|
||||||
// called a second time if it supports runtime preset loading.
|
|
||||||
permit_alloc(|| {
|
permit_alloc(|| {
|
||||||
plugin.initialize(&audio_io_layout, &buffer_config, &mut init_context)
|
plugin.initialize(&audio_io_layout, &buffer_config, &mut init_context)
|
||||||
});
|
});
|
||||||
|
|
|
@ -515,20 +515,24 @@ impl<P: Plugin, B: Backend<P>> Wrapper<P, B> {
|
||||||
// alternative that 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(mut state) = updated_state {
|
if let Ok(mut state) = updated_state {
|
||||||
unsafe {
|
// FIXME: This is obviously not realtime-safe, but loading presets without
|
||||||
|
// doing this could lead to inconsistencies. It's the plugin's
|
||||||
|
// responsibility to not perform any realtime-unsafe work when the
|
||||||
|
// initialize function is called a second time if it supports
|
||||||
|
// runtime preset loading. `state::deserialize_object()` normally
|
||||||
|
// never allocates, but if the plugin has persistent non-parameter
|
||||||
|
// data then its `deserialize_fields()` implementation may still
|
||||||
|
// allocate.
|
||||||
|
permit_alloc(|| unsafe {
|
||||||
state::deserialize_object::<P>(
|
state::deserialize_object::<P>(
|
||||||
&mut state,
|
&mut state,
|
||||||
self.params.clone(),
|
self.params.clone(),
|
||||||
|param_id| self.param_id_to_ptr.get(param_id).copied(),
|
|param_id| self.param_id_to_ptr.get(param_id).copied(),
|
||||||
Some(&self.buffer_config),
|
Some(&self.buffer_config),
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
|
|
||||||
// FIXME: This is obviously not realtime-safe, but loading presets without
|
// See above
|
||||||
// doing this could lead to inconsistencies. It's the plugin's
|
|
||||||
// responsibility to not perform any realtime-unsafe work when the
|
|
||||||
// initialize function is called a second time if it supports
|
|
||||||
// runtime preset loading.
|
|
||||||
permit_alloc(|| {
|
permit_alloc(|| {
|
||||||
plugin.initialize(
|
plugin.initialize(
|
||||||
&self.audio_io_layout,
|
&self.audio_io_layout,
|
||||||
|
|
|
@ -1795,25 +1795,31 @@ impl<P: Vst3Plugin> IAudioProcessor for Wrapper<P> {
|
||||||
// doesn't do that
|
// doesn't do that
|
||||||
let updated_state = permit_alloc(|| self.inner.updated_state_receiver.try_recv());
|
let updated_state = permit_alloc(|| self.inner.updated_state_receiver.try_recv());
|
||||||
if let Ok(mut state) = updated_state {
|
if let Ok(mut state) = updated_state {
|
||||||
state::deserialize_object::<P>(
|
// FIXME: This is obviously not realtime-safe, but loading presets without doing
|
||||||
&mut state,
|
// this could lead to inconsistencies. It's the plugin's responsibility to
|
||||||
self.inner.params.clone(),
|
// not perform any realtime-unsafe work when the initialize function is
|
||||||
state::make_params_getter(
|
// called a second time if it supports runtime preset loading.
|
||||||
&self.inner.param_by_hash,
|
// `state::deserialize_object()` normally never allocates, but if the plugin
|
||||||
&self.inner.param_id_to_hash,
|
// has persistent non-parameter data then its `deserialize_fields()`
|
||||||
),
|
// implementation may still allocate.
|
||||||
self.inner.current_buffer_config.load().as_ref(),
|
permit_alloc(|| {
|
||||||
);
|
state::deserialize_object::<P>(
|
||||||
|
&mut state,
|
||||||
|
self.inner.params.clone(),
|
||||||
|
state::make_params_getter(
|
||||||
|
&self.inner.param_by_hash,
|
||||||
|
&self.inner.param_id_to_hash,
|
||||||
|
),
|
||||||
|
self.inner.current_buffer_config.load().as_ref(),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
// NOTE: This needs to be dropped after the `plugin` lock to avoid deadlocks
|
// NOTE: This needs to be dropped after the `plugin` lock to avoid deadlocks
|
||||||
let mut init_context = self.inner.make_init_context();
|
let mut init_context = self.inner.make_init_context();
|
||||||
let audio_io_layout = self.inner.current_audio_io_layout.load();
|
let audio_io_layout = self.inner.current_audio_io_layout.load();
|
||||||
let buffer_config = self.inner.current_buffer_config.load().unwrap();
|
let buffer_config = self.inner.current_buffer_config.load().unwrap();
|
||||||
let mut plugin = self.inner.plugin.lock();
|
let mut plugin = self.inner.plugin.lock();
|
||||||
// FIXME: This is obviously not realtime-safe, but loading presets without doing
|
// See above
|
||||||
// this could lead to inconsistencies. It's the plugin's responsibility to
|
|
||||||
// not perform any realtime-unsafe work when the initialize function is
|
|
||||||
// called a second time if it supports runtime preset loading.
|
|
||||||
permit_alloc(|| {
|
permit_alloc(|| {
|
||||||
plugin.initialize(&audio_io_layout, &buffer_config, &mut init_context)
|
plugin.initialize(&audio_io_layout, &buffer_config, &mut init_context)
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue