1
0
Fork 0

Refactor GUIs to use param's own default value

This removes the need to pass a lot of these `ParamSetter`s and
`GuiContext`s around. We also don't need explicit events to reset a
parameter anymore since you can get this information from the parameter
itself.
This commit is contained in:
Robbert van der Helm 2022-03-21 13:09:51 +01:00
parent a844051054
commit f084f14095
18 changed files with 54 additions and 168 deletions

View file

@ -124,9 +124,8 @@ impl<'a, P: Param> ParamSlider<'a, P> {
/// Begin and end drag still need to be called when using this.. /// Begin and end drag still need to be called when using this..
fn reset_param(&self) { fn reset_param(&self) {
let normalized_default = self.setter.default_normalized_param_value(self.param);
self.setter self.setter
.set_parameter_normalized(self.param, normalized_default); .set_parameter(self.param, self.param.default_plain_value());
} }
fn granular_drag(&self, ui: &Ui, drag_delta: Vec2) { fn granular_drag(&self, ui: &Ui, drag_delta: Vec2) {

View file

@ -216,10 +216,6 @@ pub trait IcedEditor: 'static + Send + Sync + Sized {
ParamMessage::SetParameterNormalized(p, v) => unsafe { ParamMessage::SetParameterNormalized(p, v) => unsafe {
context.raw_set_parameter_normalized(p, v) context.raw_set_parameter_normalized(p, v)
}, },
ParamMessage::ResetParameter(p) => unsafe {
let default_value = context.raw_default_normalized_param_value(p);
context.raw_set_parameter_normalized(p, default_value);
},
ParamMessage::EndSetParameter(p) => unsafe { context.raw_end_set_parameter(p) }, ParamMessage::EndSetParameter(p) => unsafe { context.raw_end_set_parameter(p) },
} }
} }

View file

@ -27,9 +27,6 @@ pub enum ParamMessage {
/// Set a parameter to a new normalized value. This needs to be surrounded by a matching /// Set a parameter to a new normalized value. This needs to be surrounded by a matching
/// `BeginSetParameter` and `EndSetParameter`. /// `BeginSetParameter` and `EndSetParameter`.
SetParameterNormalized(ParamPtr, f32), SetParameterNormalized(ParamPtr, f32),
/// Reset a parameter to its default value. This needs to be surrounded by a matching
/// `BeginSetParameter` and `EndSetParameter`.
ResetParameter(ParamPtr),
/// End an automation gesture for a parameter. /// End an automation gesture for a parameter.
EndSetParameter(ParamPtr), EndSetParameter(ParamPtr),
} }

View file

@ -8,7 +8,7 @@ use std::marker::PhantomData;
use std::pin::Pin; use std::pin::Pin;
use nih_plug::param::internals::ParamPtr; use nih_plug::param::internals::ParamPtr;
use nih_plug::prelude::{GuiContext, Param, Params}; use nih_plug::prelude::{Param, Params};
use super::{ParamMessage, ParamSlider}; use super::{ParamMessage, ParamSlider};
use crate::backend::Renderer; use crate::backend::Renderer;
@ -27,7 +27,6 @@ pub trait ParamWidget {
/// Create an [`Element`] for a widget for the specified parameter. /// Create an [`Element`] for a widget for the specified parameter.
fn into_widget_element<'a, P: Param>( fn into_widget_element<'a, P: Param>(
param: &'a P, param: &'a P,
context: &'a dyn GuiContext,
state: &'a mut Self::State, state: &'a mut Self::State,
) -> Element<'a, ParamMessage>; ) -> Element<'a, ParamMessage>;
@ -38,14 +37,13 @@ pub trait ParamWidget {
/// Undefined behavior of the `ParamPtr` does not point to a valid parameter. /// Undefined behavior of the `ParamPtr` does not point to a valid parameter.
unsafe fn into_widget_element_raw<'a>( unsafe fn into_widget_element_raw<'a>(
param: &ParamPtr, param: &ParamPtr,
context: &'a dyn GuiContext,
state: &'a mut Self::State, state: &'a mut Self::State,
) -> Element<'a, ParamMessage> { ) -> Element<'a, ParamMessage> {
match param { match param {
ParamPtr::FloatParam(p) => Self::into_widget_element(&**p, context, state), ParamPtr::FloatParam(p) => Self::into_widget_element(&**p, state),
ParamPtr::IntParam(p) => Self::into_widget_element(&**p, context, state), ParamPtr::IntParam(p) => Self::into_widget_element(&**p, state),
ParamPtr::BoolParam(p) => Self::into_widget_element(&**p, context, state), ParamPtr::BoolParam(p) => Self::into_widget_element(&**p, state),
ParamPtr::EnumParam(p) => Self::into_widget_element(&**p, context, state), ParamPtr::EnumParam(p) => Self::into_widget_element(&**p, state),
} }
} }
} }
@ -62,7 +60,6 @@ pub struct GenericUi<'a, W: ParamWidget> {
state: &'a mut State<W>, state: &'a mut State<W>,
params: Pin<&'a dyn Params>, params: Pin<&'a dyn Params>,
context: &'a dyn GuiContext,
width: Length, width: Length,
height: Length, height: Length,
@ -89,16 +86,11 @@ where
W: ParamWidget, W: ParamWidget,
{ {
/// Creates a new [`GenericUi`] for all provided parameters. /// Creates a new [`GenericUi`] for all provided parameters.
pub fn new( pub fn new(state: &'a mut State<W>, params: Pin<&'a dyn Params>) -> Self {
state: &'a mut State<W>,
params: Pin<&'a dyn Params>,
context: &'a dyn GuiContext,
) -> Self {
Self { Self {
state, state,
params, params,
context,
width: Length::Fill, width: Length::Fill,
height: Length::Fill, height: Length::Fill,
@ -193,9 +185,7 @@ where
.horizontal_alignment(alignment::Horizontal::Right) .horizontal_alignment(alignment::Horizontal::Right)
.vertical_alignment(alignment::Vertical::Center), .vertical_alignment(alignment::Vertical::Center),
) )
.push(unsafe { .push(unsafe { W::into_widget_element_raw(&param_ptr, widget_state) });
W::into_widget_element_raw(&param_ptr, self.context, widget_state)
});
if self.pad_scrollbar { if self.pad_scrollbar {
// There's already spacing applied, so this element doesn't actually need to hae any // There's already spacing applied, so this element doesn't actually need to hae any
// size of its own // size of its own
@ -279,10 +269,9 @@ impl ParamWidget for GenericSlider {
fn into_widget_element<'a, P: Param>( fn into_widget_element<'a, P: Param>(
param: &'a P, param: &'a P,
context: &'a dyn GuiContext,
state: &'a mut Self::State, state: &'a mut Self::State,
) -> Element<'a, ParamMessage> { ) -> Element<'a, ParamMessage> {
ParamSlider::new(state, param, context).into() ParamSlider::new(state, param).into()
} }
} }

View file

@ -1,7 +1,7 @@
//! A slider that integrates with NIH-plug's [`Param`] types. //! A slider that integrates with NIH-plug's [`Param`] types.
use atomic_refcell::AtomicRefCell; use atomic_refcell::AtomicRefCell;
use nih_plug::prelude::{GuiContext, Param, ParamSetter}; use nih_plug::prelude::Param;
use std::borrow::Borrow; use std::borrow::Borrow;
use crate::backend::widget; use crate::backend::widget;
@ -31,9 +31,6 @@ pub struct ParamSlider<'a, P: Param> {
state: &'a mut State, state: &'a mut State,
param: &'a P, param: &'a P,
/// We'll visualize the parameter's current value by drawing the difference between the current
/// normalized value and the default normalized value.
setter: ParamSetter<'a>,
height: Length, height: Length,
width: Length, width: Length,
@ -102,14 +99,11 @@ impl widget::text_input::StyleSheet for TextInputStyle {
impl<'a, P: Param> ParamSlider<'a, P> { impl<'a, P: Param> ParamSlider<'a, P> {
/// Creates a new [`ParamSlider`] for the given parameter. /// Creates a new [`ParamSlider`] for the given parameter.
pub fn new(state: &'a mut State, param: &'a P, context: &'a dyn GuiContext) -> Self { pub fn new(state: &'a mut State, param: &'a P) -> Self {
let setter = ParamSetter::new(context);
Self { Self {
state, state,
param, param,
setter,
width: Length::Units(180), width: Length::Units(180),
height: Length::Units(30), height: Length::Units(30),
@ -328,10 +322,7 @@ impl<'a, P: Param> Widget<ParamMessage, Renderer> for ParamSlider<'a, P> {
self.state.drag_active = false; self.state.drag_active = false;
shell.publish(ParamMessage::BeginSetParameter(self.param.as_ptr())); shell.publish(ParamMessage::BeginSetParameter(self.param.as_ptr()));
self.set_normalized_value( self.set_normalized_value(shell, self.param.default_normalized_value());
shell,
self.setter.default_normalized_param_value(self.param),
);
shell.publish(ParamMessage::EndSetParameter(self.param.as_ptr())); shell.publish(ParamMessage::EndSetParameter(self.param.as_ptr()));
} else if self.state.keyboard_modifiers.shift() { } else if self.state.keyboard_modifiers.shift() {
shell.publish(ParamMessage::BeginSetParameter(self.param.as_ptr())); shell.publish(ParamMessage::BeginSetParameter(self.param.as_ptr()));
@ -494,7 +485,7 @@ impl<'a, P: Param> Widget<ParamMessage, Renderer> for ParamSlider<'a, P> {
// default value lies somewhere in the middle and the parameter is continuous. Otherwise // default value lies somewhere in the middle and the parameter is continuous. Otherwise
// this appraoch looks a bit jarring. // this appraoch looks a bit jarring.
let current_value = self.param.normalized_value(); let current_value = self.param.normalized_value();
let default_value = self.setter.default_normalized_param_value(self.param); let default_value = self.param.default_normalized_value();
let fill_start_x = util::remap_rect_x_t( let fill_start_x = util::remap_rect_x_t(
&bounds_without_borders, &bounds_without_borders,
if self.param.step_count().is_none() && (0.45..=0.55).contains(&default_value) { if self.param.step_count().is_none() && (0.45..=0.55).contains(&default_value) {

View file

@ -2,7 +2,7 @@
use baseview::{WindowHandle, WindowScalePolicy}; use baseview::{WindowHandle, WindowScalePolicy};
use crossbeam::atomic::AtomicCell; use crossbeam::atomic::AtomicCell;
use nih_plug::prelude::{Editor, GuiContext, ParamSetter, ParentWindowHandle}; use nih_plug::prelude::{Editor, GuiContext, ParentWindowHandle};
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc; use std::sync::Arc;
use vizia::{Application, Color, Context, Entity, Model, PropSet, WindowDescription}; use vizia::{Application, Color, Context, Entity, Model, PropSet, WindowDescription};
@ -23,7 +23,7 @@ pub mod widgets;
/// See [VIZIA](https://github.com/vizia/vizia)'s repository for examples on how to use this. /// See [VIZIA](https://github.com/vizia/vizia)'s repository for examples on how to use this.
pub fn create_vizia_editor<F>(vizia_state: Arc<ViziaState>, app: F) -> Option<Box<dyn Editor>> pub fn create_vizia_editor<F>(vizia_state: Arc<ViziaState>, app: F) -> Option<Box<dyn Editor>>
where where
F: Fn(&mut Context, &ParamSetter) + 'static + Send + Sync, F: Fn(&mut Context) + 'static + Send + Sync,
{ {
Some(Box::new(ViziaEditor { Some(Box::new(ViziaEditor {
vizia_state, vizia_state,
@ -66,7 +66,7 @@ impl ViziaState {
struct ViziaEditor { struct ViziaEditor {
vizia_state: Arc<ViziaState>, vizia_state: Arc<ViziaState>,
/// The user's app function. /// The user's app function.
app: Arc<dyn Fn(&mut Context, &ParamSetter) + 'static + Send + Sync>, app: Arc<dyn Fn(&mut Context) + 'static + Send + Sync>,
/// The scaling factor reported by the host, if any. On macOS this will never be set and we /// The scaling factor reported by the host, if any. On macOS this will never be set and we
/// should use the system scaling factor instead. /// should use the system scaling factor instead.
@ -87,8 +87,6 @@ impl Editor for ViziaEditor {
WindowDescription::new().with_inner_size(unscaled_width, unscaled_height); WindowDescription::new().with_inner_size(unscaled_width, unscaled_height);
let window = Application::new(window_description, move |cx| { let window = Application::new(window_description, move |cx| {
let setter = ParamSetter::new(context.as_ref());
// Set some default styles to match the iced integration // Set some default styles to match the iced integration
// TODO: Maybe add a way to override this behavior // TODO: Maybe add a way to override this behavior
// NOTE: vizia's font rendering looks way too dark and thick. Going one font weight // NOTE: vizia's font rendering looks way too dark and thick. Going one font weight
@ -112,7 +110,7 @@ impl Editor for ViziaEditor {
} }
.build(cx); .build(cx);
app(cx, &setter) app(cx)
}) })
.with_scale_policy( .with_scale_policy(
scaling_factor scaling_factor

View file

@ -38,9 +38,6 @@ pub enum ParamEvent<'a, P: Param> {
/// Set a parameter to a new normalized value. This needs to be surrounded by a matching /// Set a parameter to a new normalized value. This needs to be surrounded by a matching
/// `BeginSetParameter` and `EndSetParameter`. /// `BeginSetParameter` and `EndSetParameter`.
SetParameterNormalized(&'a P, f32), SetParameterNormalized(&'a P, f32),
/// Reset a parameter to its default value. This needs to be surrounded by a matching
/// `BeginSetParameter` and `EndSetParameter`.
ResetParameter(&'a P),
/// End an automation gesture for a parameter. /// End an automation gesture for a parameter.
EndSetParameter(&'a P), EndSetParameter(&'a P),
} }
@ -53,9 +50,6 @@ pub enum RawParamEvent {
/// Set a parameter to a new normalized value. This needs to be surrounded by a matching /// Set a parameter to a new normalized value. This needs to be surrounded by a matching
/// `BeginSetParameter` and `EndSetParameter`. /// `BeginSetParameter` and `EndSetParameter`.
SetParameterNormalized(ParamPtr, f32), SetParameterNormalized(ParamPtr, f32),
/// Reset a parameter to its default value. This needs to be surrounded by a matching
/// `BeginSetParameter` and `EndSetParameter`.
ResetParameter(ParamPtr),
/// End an automation gesture for a parameter. /// End an automation gesture for a parameter.
EndSetParameter(ParamPtr), EndSetParameter(ParamPtr),
} }
@ -78,10 +72,6 @@ impl Model for ParamModel {
RawParamEvent::SetParameterNormalized(p, v) => unsafe { RawParamEvent::SetParameterNormalized(p, v) => unsafe {
self.context.raw_set_parameter_normalized(p, v) self.context.raw_set_parameter_normalized(p, v)
}, },
RawParamEvent::ResetParameter(p) => unsafe {
let default_value = self.context.raw_default_normalized_param_value(p);
self.context.raw_set_parameter_normalized(p, default_value);
},
RawParamEvent::EndSetParameter(p) => unsafe { RawParamEvent::EndSetParameter(p) => unsafe {
self.context.raw_end_set_parameter(p) self.context.raw_end_set_parameter(p)
}, },
@ -100,7 +90,6 @@ impl<P: Param> From<ParamEvent<'_, P>> for RawParamEvent {
ParamEvent::SetParameterNormalized(p, v) => { ParamEvent::SetParameterNormalized(p, v) => {
RawParamEvent::SetParameterNormalized(p.as_ptr(), v) RawParamEvent::SetParameterNormalized(p.as_ptr(), v)
} }
ParamEvent::ResetParameter(p) => RawParamEvent::ResetParameter(p.as_ptr()),
ParamEvent::EndSetParameter(p) => RawParamEvent::EndSetParameter(p.as_ptr()), ParamEvent::EndSetParameter(p) => RawParamEvent::EndSetParameter(p.as_ptr()),
} }
} }

View file

@ -1,7 +1,7 @@
//! A slider that integrates with NIH-plug's [`Param`] types. //! A slider that integrates with NIH-plug's [`Param`] types.
use nih_plug::param::internals::ParamPtr; use nih_plug::param::internals::ParamPtr;
use nih_plug::prelude::{Param, ParamSetter}; use nih_plug::prelude::Param;
use vizia::*; use vizia::*;
use super::util::{self, ModifiersExt}; use super::util::{self, ModifiersExt};
@ -76,13 +76,15 @@ enum ParamSliderInternalEvent {
} }
impl Model for ParamSliderInternal { impl Model for ParamSliderInternal {
fn event(&mut self, cx: &mut Context, event: &mut Event) { fn event(&mut self, _cx: &mut Context, event: &mut Event) {
if let Some(param_slider_internal_event) = event.message.downcast() { if let Some(param_slider_internal_event) = event.message.downcast() {
match param_slider_internal_event { match param_slider_internal_event {
ParamSliderInternalEvent::SetStyle(style) => self.style = *style, ParamSliderInternalEvent::SetStyle(style) => self.style = *style,
ParamSliderInternalEvent::SetTextInputActive(value) => { ParamSliderInternalEvent::SetTextInputActive(active) => {
cx.current.set_active(cx, *value); self.text_input_active = *active;
self.text_input_active = *value; if *active {
// TODO: Interact with the Textbox widget
}
} }
} }
} }
@ -92,17 +94,17 @@ impl Model for ParamSliderInternal {
impl ParamSlider { impl ParamSlider {
/// Creates a new [`ParamSlider`] for the given parameter. To accomdate VIZIA's mapping system, /// Creates a new [`ParamSlider`] for the given parameter. To accomdate VIZIA's mapping system,
/// you'll need to provide a lens containing your `Params` implementation object (check out how /// you'll need to provide a lens containing your `Params` implementation object (check out how
/// the `Data` struct is used in `gain_gui_vizia`), the `ParamSetter` for retrieving the /// the `Data` struct is used in `gain_gui_vizia`) and a projection function that maps the
/// parameter's default value, and a projection function that maps the `Params` object to the /// `Params` object to the parameter you want to display a widget for. Parameter changes are
/// parameter you want to display a widget for. /// handled by emitting [`ParamEvent`][super::ParamEvent]s which are automatically handled by
/// the VIZIA wrapper.
/// ///
/// See [`ParamSliderExt`] for additonal options. /// See [`ParamSliderExt`] for additonal options.
pub fn new<'a, L, Params, P, F>( pub fn new<L, Params, P, F>(
cx: &'a mut Context, cx: &mut Context,
params: L, params: L,
setter: &ParamSetter,
params_to_param: F, params_to_param: F,
) -> Handle<'a, ParamSlider> ) -> Handle<'_, ParamSlider>
where where
L: Lens<Target = Params> + Copy, L: Lens<Target = Params> + Copy,
F: 'static + Fn(&Params) -> &P + Copy, F: 'static + Fn(&Params) -> &P + Copy,
@ -117,11 +119,9 @@ impl ParamSlider {
let param_ptr = *params let param_ptr = *params
.map(move |params| params_to_param(params).as_ptr()) .map(move |params| params_to_param(params).as_ptr())
.get(cx); .get(cx);
let default_value = unsafe { let default_value = *params
setter .map(move |params| params_to_param(params).default_normalized_value())
.raw_context .get(cx);
.raw_default_normalized_param_value(param_ptr)
};
let step_count = *params let step_count = *params
.map(move |params| params_to_param(params).step_count()) .map(move |params| params_to_param(params).step_count())
.get(cx); .get(cx);
@ -320,7 +320,10 @@ impl View for ParamSlider {
// Ctrl+Click and double click should reset the parameter instead of initiating // Ctrl+Click and double click should reset the parameter instead of initiating
// a drag operation // a drag operation
cx.emit(RawParamEvent::BeginSetParameter(self.param_ptr)); cx.emit(RawParamEvent::BeginSetParameter(self.param_ptr));
cx.emit(RawParamEvent::ResetParameter(self.param_ptr)); cx.emit(RawParamEvent::SetParameterNormalized(
self.param_ptr,
unsafe { self.param_ptr.default_normalized_value() },
));
cx.emit(RawParamEvent::EndSetParameter(self.param_ptr)); cx.emit(RawParamEvent::EndSetParameter(self.param_ptr));
} else { } else {
self.drag_active = true; self.drag_active = true;

View file

@ -85,13 +85,9 @@ impl IcedEditor for CrispEditor {
} }
fn view(&mut self) -> Element<'_, Self::Message> { fn view(&mut self) -> Element<'_, Self::Message> {
GenericUi::new( GenericUi::new(&mut self.generic_ui_state, self.params.as_ref())
&mut self.generic_ui_state, .pad_scrollbar()
self.params.as_ref(), .map(Message::ParamUpdate)
self.context.as_ref(),
)
.pad_scrollbar()
.map(Message::ParamUpdate)
} }
fn background_color(&self) -> nih_plug_iced::Color { fn background_color(&self) -> nih_plug_iced::Color {

View file

@ -84,12 +84,7 @@ impl IcedEditor for DiopserEditor {
} }
fn view(&mut self) -> Element<'_, Self::Message> { fn view(&mut self) -> Element<'_, Self::Message> {
GenericUi::new( GenericUi::new(&mut self.generic_ui_state, self.params.as_ref()).map(Message::ParamUpdate)
&mut self.generic_ui_state,
self.params.as_ref(),
self.context.as_ref(),
)
.map(Message::ParamUpdate)
} }
fn background_color(&self) -> nih_plug_iced::Color { fn background_color(&self) -> nih_plug_iced::Color {

View file

@ -95,12 +95,8 @@ impl IcedEditor for GainEditor {
.vertical_alignment(alignment::Vertical::Center), .vertical_alignment(alignment::Vertical::Center),
) )
.push( .push(
nih_widgets::ParamSlider::new( nih_widgets::ParamSlider::new(&mut self.gain_slider_state, &self.params.gain)
&mut self.gain_slider_state, .map(Message::ParamUpdate),
&self.params.gain,
self.context.as_ref(),
)
.map(Message::ParamUpdate),
) )
.push(Space::with_height(10.into())) .push(Space::with_height(10.into()))
.push( .push(

View file

@ -32,7 +32,7 @@ pub(crate) fn create(
peak_meter: Arc<AtomicF32>, peak_meter: Arc<AtomicF32>,
editor_state: Arc<ViziaState>, editor_state: Arc<ViziaState>,
) -> Option<Box<dyn Editor>> { ) -> Option<Box<dyn Editor>> {
create_vizia_editor(editor_state, move |cx, setter| { create_vizia_editor(editor_state, move |cx| {
cx.add_theme(STYLE); cx.add_theme(STYLE);
Data { Data {
@ -53,13 +53,13 @@ pub(crate) fn create(
Label::new(cx, "Gain").bottom(Pixels(-1.0)); Label::new(cx, "Gain").bottom(Pixels(-1.0));
VStack::new(cx, |cx| { VStack::new(cx, |cx| {
ParamSlider::new(cx, Data::params, setter, |params| &params.gain); ParamSlider::new(cx, Data::params, |params| &params.gain);
ParamSlider::new(cx, Data::params, setter, |params| &params.gain) ParamSlider::new(cx, Data::params, |params| &params.gain)
.set_style(ParamSliderStyle::FromLeft); .set_style(ParamSliderStyle::FromLeft);
ParamSlider::new(cx, Data::params, setter, |params| &params.foo); ParamSlider::new(cx, Data::params, |params| &params.foo);
ParamSlider::new(cx, Data::params, setter, |params| &params.foo) ParamSlider::new(cx, Data::params, |params| &params.foo)
.set_style(ParamSliderStyle::CurrentStep); .set_style(ParamSliderStyle::CurrentStep);
ParamSlider::new(cx, Data::params, setter, |params| &params.foo) ParamSlider::new(cx, Data::params, |params| &params.foo)
.set_style(ParamSliderStyle::CurrentStepLabeled); .set_style(ParamSliderStyle::CurrentStepLabeled);
}) })
.row_between(Pixels(5.0)); .row_between(Pixels(5.0));

View file

@ -71,16 +71,6 @@ pub trait GuiContext: Send + Sync + 'static {
/// The implementing function still needs to check if `param` actually exists. This function is /// The implementing function still needs to check if `param` actually exists. This function is
/// mostly marked as unsafe for API reasons. /// mostly marked as unsafe for API reasons.
unsafe fn raw_end_set_parameter(&self, param: ParamPtr); unsafe fn raw_end_set_parameter(&self, param: ParamPtr);
/// Retrieve the default value for a parameter, in case you forgot. This does not perform a
/// callback Create a [`ParamSetter`] and use [`ParamSetter::default_param_value()`] instead for
/// a safe, user friendly API.
///
/// # Safety
///
/// The implementing function still needs to check if `param` actually exists. This function is
/// mostly marked as unsafe for API reasons.
unsafe fn raw_default_normalized_param_value(&self, param: ParamPtr) -> f32;
} }
/// Information about the plugin's transport. Depending on the plugin API and the host not all /// Information about the plugin's transport. Depending on the plugin API and the host not all
@ -385,19 +375,4 @@ impl<'a> ParamSetter<'a> {
pub fn end_set_parameter<P: Param>(&self, param: &P) { pub fn end_set_parameter<P: Param>(&self, param: &P) {
unsafe { self.raw_context.raw_end_set_parameter(param.as_ptr()) }; unsafe { self.raw_context.raw_end_set_parameter(param.as_ptr()) };
} }
/// Retrieve the default value for a parameter, in case you forgot. The value is already
/// normalized to `[0, 1]`. This is useful when implementing GUIs, and it does not perform a callback.
pub fn default_normalized_param_value<P: Param>(&self, param: &P) -> f32 {
unsafe {
self.raw_context
.raw_default_normalized_param_value(param.as_ptr())
}
}
/// The same as [`default_normalized_param_value()`][Self::default_normalized_param_value()],
/// but without the normalization.
pub fn default_param_value<P: Param>(&self, param: &P) -> P::Plain {
param.preview_plain(self.default_normalized_param_value(param))
}
} }

View file

@ -75,16 +75,6 @@ impl<P: ClapPlugin> GuiContext for WrapperGuiContext<P> {
None => nih_debug_assert_failure!("Unknown parameter: {:?}", param), None => nih_debug_assert_failure!("Unknown parameter: {:?}", param),
} }
} }
unsafe fn raw_default_normalized_param_value(&self, param: ParamPtr) -> f32 {
match self.wrapper.param_ptr_to_hash.get(&param) {
Some(hash) => self.wrapper.param_defaults_normalized[hash],
None => {
nih_debug_assert_failure!("Unknown parameter: {:?}", param);
0.5
}
}
}
} }
impl<P: ClapPlugin> ProcessContext for WrapperProcessContext<'_, P> { impl<P: ClapPlugin> ProcessContext for WrapperProcessContext<'_, P> {

View file

@ -178,10 +178,6 @@ pub struct Wrapper<P: ClapPlugin> {
/// by slashes, and they're only used to allow the DAW to display parameters in a tree /// by slashes, and they're only used to allow the DAW to display parameters in a tree
/// structure. /// structure.
param_group_by_hash: HashMap<u32, String>, param_group_by_hash: HashMap<u32, String>,
/// 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.
pub param_defaults_normalized: HashMap<u32, f32>,
/// Mappings from string parameter indentifiers to parameter hashes. Useful for debug logging /// Mappings from string parameter indentifiers to parameter hashes. Useful for debug logging
/// and when storing and restoring plugin state. /// and when storing and restoring plugin state.
param_id_to_hash: HashMap<String, u32>, param_id_to_hash: HashMap<String, u32>,
@ -370,10 +366,6 @@ impl<P: ClapPlugin> Wrapper<P> {
.iter() .iter()
.map(|(_, hash, _, group)| (*hash, group.clone())) .map(|(_, hash, _, group)| (*hash, group.clone()))
.collect(); .collect();
let param_defaults_normalized = param_id_hashes_ptrs_groups
.iter()
.map(|(_, hash, ptr, _)| (*hash, unsafe { ptr.normalized_value() }))
.collect();
let param_id_to_hash = param_id_hashes_ptrs_groups let param_id_to_hash = param_id_hashes_ptrs_groups
.iter() .iter()
.map(|(id, hash, _, _)| (id.clone(), *hash)) .map(|(id, hash, _, _)| (id.clone(), *hash))
@ -509,7 +501,6 @@ impl<P: ClapPlugin> Wrapper<P> {
param_hashes, param_hashes,
param_by_hash, param_by_hash,
param_group_by_hash, param_group_by_hash,
param_defaults_normalized,
param_id_to_hash, param_id_to_hash,
param_ptr_to_hash, param_ptr_to_hash,
output_parameter_events: ArrayQueue::new(OUTPUT_EVENT_QUEUE_CAPACITY), output_parameter_events: ArrayQueue::new(OUTPUT_EVENT_QUEUE_CAPACITY),
@ -1746,8 +1737,8 @@ impl<P: ClapPlugin> Wrapper<P> {
} else { } else {
let param_hash = &wrapper.param_hashes[param_index as usize]; let param_hash = &wrapper.param_hashes[param_index as usize];
let param_group = &wrapper.param_group_by_hash[param_hash]; 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 param_ptr = &wrapper.param_by_hash[param_hash];
let default_value = param_ptr.default_normalized_value();
let step_count = param_ptr.step_count(); let step_count = param_ptr.step_count();
param_info.id = *param_hash; param_info.id = *param_hash;
@ -1767,7 +1758,7 @@ impl<P: ClapPlugin> Wrapper<P> {
// range option // range option
// TODO: This should probably be encapsulated in some way so we don't forget about this in one place // TODO: This should probably be encapsulated in some way so we don't forget about this in one place
param_info.max_value = step_count.unwrap_or(1) as f64; param_info.max_value = step_count.unwrap_or(1) as f64;
param_info.default_value = *default_value as f64 * step_count.unwrap_or(1) as f64; param_info.default_value = default_value as f64 * step_count.unwrap_or(1) as f64;
} }
true true

View file

@ -80,16 +80,6 @@ impl<P: Vst3Plugin> GuiContext for WrapperGuiContext<P> {
None => nih_debug_assert_failure!("Component handler not yet set"), None => nih_debug_assert_failure!("Component handler not yet set"),
} }
} }
unsafe fn raw_default_normalized_param_value(&self, param: ParamPtr) -> f32 {
match self.inner.param_ptr_to_hash.get(&param) {
Some(hash) => self.inner.param_defaults_normalized[hash],
None => {
nih_debug_assert_failure!("Unknown parameter: {:?}", param);
0.5
}
}
}
} }
impl<P: Vst3Plugin> ProcessContext for WrapperProcessContext<'_, P> { impl<P: Vst3Plugin> ProcessContext for WrapperProcessContext<'_, P> {

View file

@ -86,10 +86,6 @@ pub(crate) struct WrapperInner<P: Vst3Plugin> {
/// addresses will remain stable, as they are obtained from a pinned object. /// addresses will remain stable, as they are obtained from a pinned object.
pub param_by_hash: HashMap<u32, ParamPtr>, pub param_by_hash: HashMap<u32, ParamPtr>,
pub param_units: ParamUnits, pub param_units: ParamUnits,
/// 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.
pub param_defaults_normalized: HashMap<u32, f32>,
/// Mappings from string parameter indentifiers to parameter hashes. Useful for debug logging /// Mappings from string parameter indentifiers to parameter hashes. Useful for debug logging
/// and when storing and restorign plugin state. /// and when storing and restorign plugin state.
pub param_id_to_hash: HashMap<String, u32>, pub param_id_to_hash: HashMap<String, u32>,
@ -182,10 +178,6 @@ impl<P: Vst3Plugin> WrapperInner<P> {
.map(|(_, hash, _, group_name)| (*hash, group_name.as_str())), .map(|(_, hash, _, group_name)| (*hash, group_name.as_str())),
) )
.expect("Inconsistent parameter groups"); .expect("Inconsistent parameter groups");
let param_defaults_normalized = param_id_hashes_ptrs_groups
.iter()
.map(|(_, hash, ptr, _)| (*hash, unsafe { ptr.normalized_value() }))
.collect();
let param_id_to_hash = param_id_hashes_ptrs_groups let param_id_to_hash = param_id_hashes_ptrs_groups
.iter() .iter()
.map(|(id, hash, _, _)| (id.clone(), *hash)) .map(|(id, hash, _, _)| (id.clone(), *hash))
@ -231,7 +223,6 @@ impl<P: Vst3Plugin> WrapperInner<P> {
param_hashes, param_hashes,
param_by_hash, param_by_hash,
param_units, param_units,
param_defaults_normalized,
param_id_to_hash, param_id_to_hash,
param_ptr_to_hash, param_ptr_to_hash,
}; };

View file

@ -340,15 +340,15 @@ impl<P: Vst3Plugin> IEditController for Wrapper<P> {
.param_units .param_units
.get_vst3_unit_id(*param_hash) .get_vst3_unit_id(*param_hash)
.expect("Inconsistent parameter data"); .expect("Inconsistent parameter data");
let default_value = &self.inner.param_defaults_normalized[param_hash];
let param_ptr = &self.inner.param_by_hash[param_hash]; let param_ptr = &self.inner.param_by_hash[param_hash];
let default_value = param_ptr.default_normalized_value();
info.id = *param_hash; info.id = *param_hash;
u16strlcpy(&mut info.title, param_ptr.name()); u16strlcpy(&mut info.title, param_ptr.name());
u16strlcpy(&mut info.short_title, param_ptr.name()); u16strlcpy(&mut info.short_title, param_ptr.name());
u16strlcpy(&mut info.units, param_ptr.unit()); u16strlcpy(&mut info.units, param_ptr.unit());
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 = vst3_sys::vst::ParameterFlags::kCanAutomate as i32; info.flags = vst3_sys::vst::ParameterFlags::kCanAutomate as i32;
} }