1
0
Fork 0

Change NON_AUTOMATABLE semantics and add HIDDEN

This now lets you have parameters that cannot be automated but that are
still changeable through the generic UI.
This commit is contained in:
Robbert van der Helm 2022-05-22 12:37:30 +02:00
parent 985db44503
commit e1d4be2a03
8 changed files with 87 additions and 26 deletions

19
BREAKING_CHANGES.md Normal file
View file

@ -0,0 +1,19 @@
# Breaking changes
Since there is no stable release yet, there is also no proper changelog yet. But
since not everyone might want to dive through commit messages to find out what's
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-05-22]
- Previously calling `param.non_automatable()` when constructing a parameter
also made the parameter hidden. Hiding a parameter is now done through
`param.hide()`, while `param.non_automatable()` simply makes it so that the
parameter can only be changed manually and not through automation or
modulation.
## ...
Who knows what happened at this point!

View file

@ -31,13 +31,17 @@ bitflags::bitflags! {
/// you don't have a bypass parameter, then NIH-plug will add one for you. You will need to /// you don't have a bypass parameter, then NIH-plug will add one for you. You will need to
/// implement this yourself if your plugin introduces latency. /// implement this yourself if your plugin introduces latency.
const BYPASS = 1 << 0; const BYPASS = 1 << 0;
/// The parameter cannot be automated from the host. Setting this flag also prevents it from /// The parameter cannot be changed from an automation lane. The parameter can however still
/// showing up in the host's own generic UI for this plugin. The parameter can still be /// be manually changed by the user from either the plugin's own GUI or from the host's
/// changed from the plugin's editor GUI. /// generic UI.
const NON_AUTOMATABLE = 1 << 1; const NON_AUTOMATABLE = 1 << 1;
/// Hides the parameter in the host's generic UI for this plugin. This also implies
/// `NON_AUTOMATABLE`. Setting this does not prevent you from changing the parameter in the
/// plugin's editor GUI.
const HIDDEN = 1 << 2;
/// Don't show this parameter when generating a generic UI for the plugin using one of /// Don't show this parameter when generating a generic UI for the plugin using one of
/// NIH-plug's generic UI widgets. /// NIH-plug's generic UI widgets.
const HIDE_IN_GENERIC_UI = 1 << 2; const HIDE_IN_GENERIC_UI = 1 << 3;
} }
} }

View file

@ -246,14 +246,22 @@ impl BoolParam {
self self
} }
/// Mark the paramter as non-automatable. This means that the parameter cannot be automated from /// Mark the paramter as non-automatable. This means that the parameter cannot be changed from
/// the host. Setting this flag also prevents it from showing up in the host's own generic UI /// an automation lane. The parameter can however still be manually changed by the user from
/// for this plugin. The parameter can still be changed from the plugin's editor GUI. /// either the plugin's own GUI or from the host's generic UI.
pub fn non_automatable(mut self) -> Self { pub fn non_automatable(mut self) -> Self {
self.flags.insert(ParamFlags::NON_AUTOMATABLE); self.flags.insert(ParamFlags::NON_AUTOMATABLE);
self self
} }
/// Hide the parameter in the host's generic UI for this plugin. This also implies
/// `NON_AUTOMATABLE`. Setting this does not prevent you from changing the parameter in the
/// plugin's editor GUI.
pub fn hide(mut self) -> Self {
self.flags.insert(ParamFlags::HIDDEN);
self
}
/// Don't show this parameter when generating a generic UI for the plugin using one of /// Don't show this parameter when generating a generic UI for the plugin using one of
/// NIH-plug's generic UI widgets. /// NIH-plug's generic UI widgets.
pub fn hide_in_generic_ui(mut self) -> Self { pub fn hide_in_generic_ui(mut self) -> Self {

View file

@ -306,14 +306,22 @@ impl<T: Enum + PartialEq + 'static> EnumParam<T> {
self self
} }
/// Mark the paramter as non-automatable. This means that the parameter cannot be automated from /// Mark the paramter as non-automatable. This means that the parameter cannot be changed from
/// the host. Setting this flag also prevents it from showing up in the host's own generic UI /// an automation lane. The parameter can however still be manually changed by the user from
/// for this plugin. The parameter can still be changed from the plugin's editor GUI. /// either the plugin's own GUI or from the host's generic UI.
pub fn non_automatable(mut self) -> Self { pub fn non_automatable(mut self) -> Self {
self.inner.inner = self.inner.inner.non_automatable(); self.inner.inner = self.inner.inner.non_automatable();
self self
} }
/// Hide the parameter in the host's generic UI for this plugin. This also implies
/// `NON_AUTOMATABLE`. Setting this does not prevent you from changing the parameter in the
/// plugin's editor GUI.
pub fn hide(mut self) -> Self {
self.inner.inner = self.inner.inner.hide();
self
}
/// Don't show this parameter when generating a generic UI for the plugin using one of /// Don't show this parameter when generating a generic UI for the plugin using one of
/// NIH-plug's generic UI widgets. /// NIH-plug's generic UI widgets.
pub fn hide_in_generic_ui(mut self) -> Self { pub fn hide_in_generic_ui(mut self) -> Self {

View file

@ -349,14 +349,22 @@ impl FloatParam {
self self
} }
/// Mark the paramter as non-automatable. This means that the parameter cannot be automated from /// Mark the paramter as non-automatable. This means that the parameter cannot be changed from
/// the host. Setting this flag also prevents it from showing up in the host's own generic UI /// an automation lane. The parameter can however still be manually changed by the user from
/// for this plugin. The parameter can still be changed from the plugin's editor GUI. /// either the plugin's own GUI or from the host's generic UI.
pub fn non_automatable(mut self) -> Self { pub fn non_automatable(mut self) -> Self {
self.flags.insert(ParamFlags::NON_AUTOMATABLE); self.flags.insert(ParamFlags::NON_AUTOMATABLE);
self self
} }
/// Hide the parameter in the host's generic UI for this plugin. This also implies
/// `NON_AUTOMATABLE`. Setting this does not prevent you from changing the parameter in the
/// plugin's editor GUI.
pub fn hide(mut self) -> Self {
self.flags.insert(ParamFlags::HIDDEN);
self
}
/// Don't show this parameter when generating a generic UI for the plugin using one of /// Don't show this parameter when generating a generic UI for the plugin using one of
/// NIH-plug's generic UI widgets. /// NIH-plug's generic UI widgets.
pub fn hide_in_generic_ui(mut self) -> Self { pub fn hide_in_generic_ui(mut self) -> Self {

View file

@ -303,14 +303,22 @@ impl IntParam {
self self
} }
/// Mark the paramter as non-automatable. This means that the parameter cannot be automated from /// Mark the paramter as non-automatable. This means that the parameter cannot be changed from
/// the host. Setting this flag also prevents it from showing up in the host's own generic UI /// an automation lane. The parameter can however still be manually changed by the user from
/// for this plugin. The parameter can still be changed from the plugin's editor GUI. /// either the plugin's own GUI or from the host's generic UI.
pub fn non_automatable(mut self) -> Self { pub fn non_automatable(mut self) -> Self {
self.flags.insert(ParamFlags::NON_AUTOMATABLE); self.flags.insert(ParamFlags::NON_AUTOMATABLE);
self self
} }
/// Hide the parameter in the host's generic UI for this plugin. This also implies
/// `NON_AUTOMATABLE`. Setting this does not prevent you from changing the parameter in the
/// plugin's editor GUI.
pub fn hide(mut self) -> Self {
self.flags.insert(ParamFlags::HIDDEN);
self
}
/// Don't show this parameter when generating a generic UI for the plugin using one of /// Don't show this parameter when generating a generic UI for the plugin using one of
/// NIH-plug's generic UI widgets. /// NIH-plug's generic UI widgets.
pub fn hide_in_generic_ui(mut self) -> Self { pub fn hide_in_generic_ui(mut self) -> Self {

View file

@ -2504,6 +2504,7 @@ impl<P: ClapPlugin> Wrapper<P> {
let step_count = param_ptr.step_count(); let step_count = param_ptr.step_count();
let flags = param_ptr.flags(); let flags = param_ptr.flags();
let automatable = !flags.contains(ParamFlags::NON_AUTOMATABLE); let automatable = !flags.contains(ParamFlags::NON_AUTOMATABLE);
let hidden = flags.contains(ParamFlags::HIDDEN);
let is_bypass = flags.contains(ParamFlags::BYPASS); let is_bypass = flags.contains(ParamFlags::BYPASS);
*param_info = std::mem::zeroed(); *param_info = std::mem::zeroed();
@ -2513,11 +2514,13 @@ impl<P: ClapPlugin> Wrapper<P> {
let param_info = &mut *param_info; let param_info = &mut *param_info;
param_info.id = *param_hash; param_info.id = *param_hash;
// TODO: Somehow expose per note/channel/port modulation // TODO: Somehow expose per note/channel/port modulation
param_info.flags = if automatable { param_info.flags = 0;
CLAP_PARAM_IS_AUTOMATABLE | CLAP_PARAM_IS_MODULATABLE if automatable && !hidden {
} else { param_info.flags |= CLAP_PARAM_IS_AUTOMATABLE | CLAP_PARAM_IS_MODULATABLE;
CLAP_PARAM_IS_HIDDEN | CLAP_PARAM_IS_READONLY }
}; if hidden {
param_info.flags |= CLAP_PARAM_IS_HIDDEN | CLAP_PARAM_IS_READONLY;
}
if is_bypass { if is_bypass {
param_info.flags |= CLAP_PARAM_IS_BYPASS param_info.flags |= CLAP_PARAM_IS_BYPASS
} }

View file

@ -451,6 +451,7 @@ impl<P: Vst3Plugin> IEditController for Wrapper<P> {
let default_value = param_ptr.default_normalized_value(); let default_value = param_ptr.default_normalized_value();
let flags = param_ptr.flags(); let flags = param_ptr.flags();
let automatable = !flags.contains(ParamFlags::NON_AUTOMATABLE); let automatable = !flags.contains(ParamFlags::NON_AUTOMATABLE);
let hidden = flags.contains(ParamFlags::HIDDEN);
let is_bypass = flags.contains(ParamFlags::BYPASS); let is_bypass = flags.contains(ParamFlags::BYPASS);
info.id = *param_hash; info.id = *param_hash;
@ -460,11 +461,13 @@ impl<P: Vst3Plugin> IEditController for Wrapper<P> {
info.step_count = param_ptr.step_count().unwrap_or(0) as i32; info.step_count = param_ptr.step_count().unwrap_or(0) as i32;
info.default_normalized_value = default_value as f64; info.default_normalized_value = default_value as f64;
info.unit_id = *param_unit; info.unit_id = *param_unit;
info.flags = if automatable { info.flags = 0;
ParameterFlags::kCanAutomate as i32 if automatable && !hidden {
} else { info.flags |= ParameterFlags::kCanAutomate as i32;
ParameterFlags::kIsReadOnly as i32 | (1 << 4) // kIsHidden }
}; if hidden {
info.flags |= ParameterFlags::kIsReadOnly as i32 | (1 << 4); // kIsHidden
}
if is_bypass { if is_bypass {
info.flags |= ParameterFlags::kIsBypass as i32; info.flags |= ParameterFlags::kIsBypass as i32;
} }