Use BTreeMaps in the state
This ensures that the order is consistent when saving the same state file multiple times.
This commit is contained in:
parent
71efe779a5
commit
5e6e920418
|
@ -6,6 +6,14 @@ new and what's changed, this document lists all breaking changes in reverse
|
|||
chronological order. If a new feature did not require any changes to existing
|
||||
code then it will not be listed here.
|
||||
|
||||
## [2022-07-02]
|
||||
|
||||
- The `Params::serialize_fields()` and `Params::deserialize_fields()` methods
|
||||
and the `State` struct now use `BTreeMap`s instead of `HashMap`s so the order
|
||||
is consistent the plugin's state to JSON multiple times. These things are part
|
||||
of NIH-plug's internals, so unless you're implementing the `Params` trait by
|
||||
hand you will not notice any changes.
|
||||
|
||||
## [2022-06-01]
|
||||
|
||||
- The `ClapPlugin::CLAP_FEATURES` field now uses an array of `ClapFeature`
|
||||
|
|
|
@ -255,8 +255,8 @@ pub fn derive_params(input: TokenStream) -> TokenStream {
|
|||
param_map
|
||||
}
|
||||
|
||||
fn serialize_fields(&self) -> ::std::collections::HashMap<String, String> {
|
||||
let mut serialized = ::std::collections::HashMap::new();
|
||||
fn serialize_fields(&self) -> ::std::collections::BTreeMap<String, String> {
|
||||
let mut serialized = ::std::collections::BTreeMap::new();
|
||||
#(#field_serialize_tokens)*
|
||||
|
||||
let nested_params_fields: &[&dyn Params] = &[#(&self.#nested_params_field_idents),*];
|
||||
|
@ -267,7 +267,7 @@ pub fn derive_params(input: TokenStream) -> TokenStream {
|
|||
serialized
|
||||
}
|
||||
|
||||
fn deserialize_fields(&self, serialized: &::std::collections::HashMap<String, String>) {
|
||||
fn deserialize_fields(&self, serialized: &::std::collections::BTreeMap<String, String>) {
|
||||
for (field_name, data) in serialized {
|
||||
match field_name.as_str() {
|
||||
#(#field_deserialize_tokens)*
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! Implementation details for the parameter management.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use super::{Param, ParamFlags, ParamMut};
|
||||
|
||||
|
@ -59,8 +59,8 @@ pub unsafe trait Params: 'static + Send + Sync {
|
|||
/// Serialize all fields marked with `#[persist = "stable_name"]` into a hash map containing
|
||||
/// JSON-representations of those fields so they can be written to the plugin's state and
|
||||
/// recalled later. This uses [`serialize_field()`] under the hood.
|
||||
fn serialize_fields(&self) -> HashMap<String, String> {
|
||||
HashMap::new()
|
||||
fn serialize_fields(&self) -> BTreeMap<String, String> {
|
||||
BTreeMap::new()
|
||||
}
|
||||
|
||||
/// Restore all fields marked with `#[persist = "stable_name"]` from a hashmap created by
|
||||
|
@ -69,7 +69,7 @@ pub unsafe trait Params: 'static + Send + Sync {
|
|||
/// This gets called when the plugin's state is being restored. This uses [deserialize_field()]
|
||||
/// under the hood.
|
||||
#[allow(unused_variables)]
|
||||
fn deserialize_fields(&self, serialized: &HashMap<String, String>) {}
|
||||
fn deserialize_fields(&self, serialized: &BTreeMap<String, String>) {}
|
||||
}
|
||||
|
||||
/// Internal pointers to parameters. This is an implementation detail used by the wrappers for type
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
//! to plugins through the [`GuiContext`][crate::prelude::GuiContext].
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::param::internals::{ParamPtr, Params};
|
||||
|
@ -25,19 +25,21 @@ pub enum ParamValue {
|
|||
|
||||
/// A plugin's state so it can be restored at a later point. This object can be serialized and
|
||||
/// deserialized using serde.
|
||||
///
|
||||
/// The fields are stored as `BTreeMap`s so the order in the serialized file is consistent.
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct PluginState {
|
||||
/// The plugin's parameter values. These are stored unnormalized. This mean sthe old values will
|
||||
/// be recalled when when the parameter's range gets increased. Doing so may still mess with
|
||||
/// parameter automation though, depending on how the host impelments that.
|
||||
pub params: HashMap<String, ParamValue>,
|
||||
pub params: BTreeMap<String, ParamValue>,
|
||||
/// Arbitrary fields that should be persisted together with the plugin's parameters. Any field
|
||||
/// on the [`Params`][crate::param::internals::Params] struct that's annotated with `#[persist =
|
||||
/// "stable_name"]` will be persisted this way.
|
||||
///
|
||||
/// The individual fields are also serialized as JSON so they can safely be restored
|
||||
/// independently of the other fields.
|
||||
pub fields: HashMap<String, String>,
|
||||
pub fields: BTreeMap<String, String>,
|
||||
}
|
||||
|
||||
/// Create a parameters iterator from the hashtables stored in the plugin wrappers. This avoids
|
||||
|
@ -77,7 +79,7 @@ pub(crate) unsafe fn serialize_object<'a>(
|
|||
// We'll serialize parameter values as a simple `string_param_id: display_value` map.
|
||||
// NOTE: If the plugin is being modulated (and the plugin is a CLAP plugin in Bitwig Studio),
|
||||
// then this should save the values without any modulation applied to it
|
||||
let params: HashMap<_, _> = params_iter
|
||||
let params: BTreeMap<_, _> = params_iter
|
||||
.into_iter()
|
||||
.map(|(param_id_str, param_ptr)| match param_ptr {
|
||||
ParamPtr::FloatParam(p) => (
|
||||
|
|
Loading…
Reference in a new issue