From f18c92b3b4c15a231859d71243503add03b87c48 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Wed, 16 Mar 2022 17:15:33 +0100 Subject: [PATCH] Support parameter groups for CLAP --- src/wrapper/clap/wrapper.rs | 43 ++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/src/wrapper/clap/wrapper.rs b/src/wrapper/clap/wrapper.rs index 9dab778f..a7aee2f9 100644 --- a/src/wrapper/clap/wrapper.rs +++ b/src/wrapper/clap/wrapper.rs @@ -174,6 +174,10 @@ pub struct Wrapper { /// parameters belonging to the plugin. As long as `plugin` does not get recreated, these /// addresses will remain stable, as they are obtained from a pinned object. param_by_hash: HashMap, + /// The group name of a parameter, indexed by the parameter's hash. Nested groups are delimited + /// by slashes, and they're only used to allow the DAW to display parameters in a tree + /// structure. + param_group_by_hash: HashMap, /// The default normalized parameter value for every parameter in `param_ids`. We need to store /// this in case the host requeries the parmaeter later. This is also indexed by the hash so we /// can retrieve them later for the UI if needed. @@ -420,6 +424,7 @@ impl Wrapper

{ host_params: AtomicRefCell::new(None), param_hashes: Vec::new(), param_by_hash: HashMap::new(), + param_group_by_hash: HashMap::new(), param_defaults_normalized: HashMap::new(), param_id_to_hash: HashMap::new(), param_ptr_to_hash: HashMap::new(), @@ -474,38 +479,45 @@ impl Wrapper

{ // dereference as long as `wrapper.plugin` is alive let param_map = wrapper.plugin.read().params().param_map(); let param_ids = wrapper.plugin.read().params().param_ids(); + let param_groups = wrapper.plugin.read().params().param_groups(); nih_debug_assert!( !param_map.contains_key(BYPASS_PARAM_ID), "The wrapper already adds its own bypass parameter" ); // Only calculate these hashes once, and in the stable order defined by the plugin - let param_id_hashes_ptrs: Vec<_> = param_ids + let param_id_hashes_ptrs_groups: Vec<_> = param_ids .iter() - .filter_map(|id| { - let param_ptr = param_map.get(id)?; - Some((id, hash_param_id(id), param_ptr)) + .map(|id| { + // If any of these keys are missing then that's a bug in the Params implementation + let param_ptr = param_map[id]; + let param_group = ¶m_groups[id]; + (id, hash_param_id(id), param_ptr, param_group) }) .collect(); - wrapper.param_hashes = param_id_hashes_ptrs + wrapper.param_hashes = param_id_hashes_ptrs_groups .iter() - .map(|&(_, hash, _)| hash) + .map(|&(_, hash, _, _)| hash) .collect(); - wrapper.param_by_hash = param_id_hashes_ptrs + wrapper.param_by_hash = param_id_hashes_ptrs_groups .iter() - .map(|&(_, hash, ptr)| (hash, *ptr)) + .map(|&(_, hash, ptr, _)| (hash, ptr)) .collect(); - wrapper.param_defaults_normalized = param_id_hashes_ptrs + wrapper.param_group_by_hash = param_id_hashes_ptrs_groups .iter() - .map(|&(_, hash, ptr)| (hash, unsafe { ptr.normalized_value() })) + .map(|&(_, hash, _, group)| (hash, group.to_string())) .collect(); - wrapper.param_id_to_hash = param_id_hashes_ptrs + wrapper.param_defaults_normalized = param_id_hashes_ptrs_groups .iter() - .map(|&(id, hash, _)| (*id, hash)) + .map(|&(_, hash, ptr, _)| (hash, unsafe { ptr.normalized_value() })) .collect(); - wrapper.param_ptr_to_hash = param_id_hashes_ptrs + wrapper.param_id_to_hash = param_id_hashes_ptrs_groups + .iter() + .map(|&(id, hash, _, _)| (*id, hash)) + .collect(); + wrapper.param_ptr_to_hash = param_id_hashes_ptrs_groups .into_iter() - .map(|(_, hash, ptr)| (*ptr, hash)) + .map(|(_, hash, ptr, _)| (ptr, hash)) .collect(); // Finally, the wrapper needs to contain a reference to itself so we can create GuiContexts @@ -1724,6 +1736,7 @@ impl Wrapper

{ param_info.default_value = 0.0; } else { let param_hash = &wrapper.param_hashes[param_index as usize]; + let param_group = &wrapper.param_group_by_hash[param_hash]; let default_value = &wrapper.param_defaults_normalized[param_hash]; let param_ptr = &wrapper.param_by_hash[param_hash]; let step_count = param_ptr.step_count(); @@ -1736,7 +1749,7 @@ impl Wrapper

{ }; param_info.cookie = ptr::null_mut(); strlcpy(&mut param_info.name, param_ptr.name()); - strlcpy(&mut param_info.module, ""); + strlcpy(&mut param_info.module, param_group); // We don't use the actual minimum and maximum values here because that would not scale // with skewed integer ranges. Instead, just treat all parameters as `[0, 1]` normalized // paramters multiplied by the step size.