Implement state handling for CLAP
This commit is contained in:
parent
ec452bd41d
commit
7e9eadfc64
|
@ -48,8 +48,8 @@ use crate::buffer::Buffer;
|
|||
use crate::event_loop::{EventLoop, MainThreadExecutor, TASK_QUEUE_CAPACITY};
|
||||
use crate::param::internals::ParamPtr;
|
||||
use crate::plugin::{BufferConfig, BusConfig, ClapPlugin, NoteEvent, ProcessStatus};
|
||||
use crate::wrapper::state;
|
||||
use crate::wrapper::util::{hash_param_id, process_wrapper, strlcpy};
|
||||
use crate::Plugin;
|
||||
|
||||
/// Right now the wrapper adds its own bypass parameter.
|
||||
///
|
||||
|
@ -849,7 +849,7 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
let name = match channel_count {
|
||||
1 => format!("Mono {port_type_name}"),
|
||||
2 => format!("Stereo {port_type_name}"),
|
||||
n => format!("{channel_count} channel {port_type_name}"),
|
||||
n => format!("{n} channel {port_type_name}"),
|
||||
};
|
||||
let port_type = match channel_count {
|
||||
1 => CLAP_PORT_MONO,
|
||||
|
@ -1072,14 +1072,96 @@ impl<P: ClapPlugin> Wrapper<P> {
|
|||
check_null_ptr!(false, plugin, stream);
|
||||
let wrapper = &*(plugin as *const Self);
|
||||
|
||||
todo!()
|
||||
let serialized = state::serialize(
|
||||
wrapper.plugin.read().params(),
|
||||
&wrapper.param_by_hash,
|
||||
&wrapper.param_id_to_hash,
|
||||
BYPASS_PARAM_ID,
|
||||
&wrapper.bypass_state,
|
||||
);
|
||||
match serialized {
|
||||
Ok(serialized) => {
|
||||
let num_bytes_written = ((*stream).write)(
|
||||
stream,
|
||||
serialized.as_ptr() as *const c_void,
|
||||
serialized.len() as u64,
|
||||
);
|
||||
|
||||
nih_debug_assert_eq!(num_bytes_written as usize, serialized.len());
|
||||
true
|
||||
}
|
||||
Err(err) => {
|
||||
nih_debug_assert_failure!("Could not save state: {}", err);
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn ext_state_load(
|
||||
plugin: *const clap_plugin,
|
||||
stream: *mut clap_istream,
|
||||
) -> bool {
|
||||
todo!()
|
||||
check_null_ptr!(false, plugin, stream);
|
||||
let wrapper = &*(plugin as *const Self);
|
||||
|
||||
// CLAP does not have a way to tell you about the size of a stream, so the workaround would
|
||||
// be to keep reading 1 MiB chunks until we reach the end of file, reallocating the buffer
|
||||
// each time as we go.
|
||||
const CHUNK_SIZE: usize = 1 << 20;
|
||||
let mut actual_read_buffer_size = 0usize;
|
||||
let mut read_buffer: Vec<u8> = Vec::with_capacity(CHUNK_SIZE);
|
||||
loop {
|
||||
let num_bytes_read = ((*stream).read)(
|
||||
stream,
|
||||
// Make sure to start reading from where we left off if we're going through this
|
||||
// loop multiple times
|
||||
read_buffer.as_mut_ptr().add(actual_read_buffer_size) as *mut c_void,
|
||||
CHUNK_SIZE as u64,
|
||||
);
|
||||
if num_bytes_read < 0 {
|
||||
nih_debug_assert_failure!("Error while reading plugin state");
|
||||
return false;
|
||||
}
|
||||
|
||||
actual_read_buffer_size += num_bytes_read as usize;
|
||||
if num_bytes_read != CHUNK_SIZE as i64 {
|
||||
// If we read anything below `CHUNK_SIZE` bytes, then we've reached the end of file
|
||||
// on this read
|
||||
break;
|
||||
}
|
||||
|
||||
// Otherwise, reallocate the buffer with enough room for another chunk and try again
|
||||
nih_debug_assert_eq!(num_bytes_read, CHUNK_SIZE as i64);
|
||||
read_buffer.reserve(CHUNK_SIZE);
|
||||
}
|
||||
|
||||
// After reading, trim the additional capacity near the end of the buffer
|
||||
read_buffer.set_len(actual_read_buffer_size as usize);
|
||||
|
||||
let success = state::deserialize(
|
||||
&read_buffer,
|
||||
wrapper.plugin.read().params(),
|
||||
&wrapper.param_by_hash,
|
||||
&wrapper.param_id_to_hash,
|
||||
wrapper.current_buffer_config.load().as_ref(),
|
||||
BYPASS_PARAM_ID,
|
||||
&wrapper.bypass_state,
|
||||
);
|
||||
if !success {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Reinitialize the plugin after loading state so it can respond to the new parameter values
|
||||
let bus_config = wrapper.current_bus_config.load();
|
||||
if let Some(buffer_config) = wrapper.current_buffer_config.load() {
|
||||
wrapper.plugin.write().initialize(
|
||||
&bus_config,
|
||||
&buffer_config,
|
||||
&mut wrapper.make_process_context(),
|
||||
);
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -209,7 +209,7 @@ impl<P: Vst3Plugin> IComponent for Wrapper<P> {
|
|||
);
|
||||
read_buffer.set_len(num_bytes_read as usize);
|
||||
|
||||
// If the size is zero, some hsots will always return `kResultFalse` even if the read was
|
||||
// If the size is zero, some hosts will always return `kResultFalse` even if the read was
|
||||
// 'successful', so we can't check the return value but we can check the number of bytes
|
||||
// read.
|
||||
if read_buffer.len() != stream_byte_size as usize {
|
||||
|
|
Loading…
Reference in a new issue