Move state serialization to a helper function
So we can reuse it for the CLAP wrapper.
This commit is contained in:
parent
bc2332801c
commit
7a3d3b8c8e
|
@ -2,6 +2,12 @@
|
|||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::pin::Pin;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
use crate::param::internals::ParamPtr;
|
||||
use crate::param::Param;
|
||||
use crate::Params;
|
||||
|
||||
/// A plain, unnormalized value for a parameter.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
|
@ -27,3 +33,55 @@ pub(crate) struct State {
|
|||
/// independently of the other fields.
|
||||
pub fields: HashMap<String, String>,
|
||||
}
|
||||
|
||||
/// Serialize a plugin's state to a vector containing JSON data. This can (and should) be shared
|
||||
/// across plugin formats.
|
||||
pub(crate) unsafe fn serialize(
|
||||
plugin_params: Pin<&dyn Params>,
|
||||
param_by_hash: &HashMap<u32, ParamPtr>,
|
||||
param_id_to_hash: &HashMap<&'static str, u32>,
|
||||
bypass_param_id: &str,
|
||||
bypass_state: &AtomicBool,
|
||||
) -> serde_json::Result<Vec<u8>> {
|
||||
// We'll serialize parmaeter values as a simple `string_param_id: display_value` map.
|
||||
let mut params: HashMap<_, _> = param_id_to_hash
|
||||
.iter()
|
||||
.filter_map(|(param_id_str, hash)| {
|
||||
let param_ptr = param_by_hash.get(hash)?;
|
||||
Some((param_id_str, param_ptr))
|
||||
})
|
||||
.map(|(¶m_id_str, ¶m_ptr)| match param_ptr {
|
||||
ParamPtr::FloatParam(p) => (
|
||||
param_id_str.to_string(),
|
||||
ParamValue::F32((*p).plain_value()),
|
||||
),
|
||||
ParamPtr::IntParam(p) => (
|
||||
param_id_str.to_string(),
|
||||
ParamValue::I32((*p).plain_value()),
|
||||
),
|
||||
ParamPtr::BoolParam(p) => (
|
||||
param_id_str.to_string(),
|
||||
ParamValue::Bool((*p).plain_value()),
|
||||
),
|
||||
ParamPtr::EnumParam(p) => (
|
||||
// Enums are serialized based on the active variant's index (which may not be
|
||||
// the same as the discriminator)
|
||||
param_id_str.to_string(),
|
||||
ParamValue::I32((*p).plain_value()),
|
||||
),
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Don't forget about the bypass parameter
|
||||
params.insert(
|
||||
bypass_param_id.to_string(),
|
||||
ParamValue::Bool(bypass_state.load(Ordering::SeqCst)),
|
||||
);
|
||||
|
||||
// The plugin can also persist arbitrary fields alongside its parameters. This is useful for
|
||||
// storing things like sample data.
|
||||
let fields = plugin_params.serialize_fields();
|
||||
|
||||
let plugin_state = State { params, fields };
|
||||
serde_json::to_vec(&plugin_state)
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ use super::view::WrapperView;
|
|||
use crate::param::internals::ParamPtr;
|
||||
use crate::param::Param;
|
||||
use crate::plugin::{BufferConfig, BusConfig, NoteEvent, ProcessStatus, Vst3Plugin};
|
||||
use crate::wrapper::state::{ParamValue, State};
|
||||
use crate::wrapper::state::{self, ParamValue, State};
|
||||
use crate::wrapper::util::{process_wrapper, u16strlcpy};
|
||||
|
||||
// Alias needed for the VST3 attribute macro
|
||||
|
@ -311,49 +311,14 @@ impl<P: Vst3Plugin> IComponent for Wrapper<P> {
|
|||
|
||||
let state = state.upgrade().unwrap();
|
||||
|
||||
// We'll serialize parmaeter values as a simple `string_param_id: display_value` map.
|
||||
let mut params: HashMap<_, _> = self
|
||||
.inner
|
||||
.param_id_to_hash
|
||||
.iter()
|
||||
.filter_map(|(param_id_str, hash)| {
|
||||
let param_ptr = self.inner.param_by_hash.get(hash)?;
|
||||
Some((param_id_str, param_ptr))
|
||||
})
|
||||
.map(|(¶m_id_str, ¶m_ptr)| match param_ptr {
|
||||
ParamPtr::FloatParam(p) => (
|
||||
param_id_str.to_string(),
|
||||
ParamValue::F32((*p).plain_value()),
|
||||
),
|
||||
ParamPtr::IntParam(p) => (
|
||||
param_id_str.to_string(),
|
||||
ParamValue::I32((*p).plain_value()),
|
||||
),
|
||||
ParamPtr::BoolParam(p) => (
|
||||
param_id_str.to_string(),
|
||||
ParamValue::Bool((*p).plain_value()),
|
||||
),
|
||||
ParamPtr::EnumParam(p) => (
|
||||
// Enums are serialized based on the active variant's index (which may not be
|
||||
// the same as the discriminator)
|
||||
param_id_str.to_string(),
|
||||
ParamValue::I32((*p).plain_value()),
|
||||
),
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Don't forget about the bypass parameter
|
||||
params.insert(
|
||||
BYPASS_PARAM_ID.to_string(),
|
||||
ParamValue::Bool(self.inner.bypass_state.load(Ordering::SeqCst)),
|
||||
let serialized = state::serialize(
|
||||
self.inner.plugin.read().params(),
|
||||
&self.inner.param_by_hash,
|
||||
&self.inner.param_id_to_hash,
|
||||
BYPASS_PARAM_ID,
|
||||
&self.inner.bypass_state,
|
||||
);
|
||||
|
||||
// The plugin can also persist arbitrary fields alongside its parameters. This is useful for
|
||||
// storing things like sample data.
|
||||
let fields = self.inner.plugin.read().params().serialize_fields();
|
||||
|
||||
let plugin_state = State { params, fields };
|
||||
match serde_json::to_vec(&plugin_state) {
|
||||
match serialized {
|
||||
Ok(serialized) => {
|
||||
let mut num_bytes_written = 0;
|
||||
let result = state.write(
|
||||
|
|
Loading…
Reference in a new issue