Move BoolParam to its own module
This commit is contained in:
parent
287576d064
commit
5a26756765
165
src/param.rs
165
src/param.rs
|
@ -3,17 +3,18 @@
|
||||||
//! example.
|
//! example.
|
||||||
|
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use self::range::Range;
|
use self::range::Range;
|
||||||
|
|
||||||
// Parameter types
|
// Parameter types
|
||||||
|
mod boolean;
|
||||||
mod plain;
|
mod plain;
|
||||||
|
|
||||||
pub mod internals;
|
pub mod internals;
|
||||||
pub mod range;
|
pub mod range;
|
||||||
pub mod smoothing;
|
pub mod smoothing;
|
||||||
|
|
||||||
|
pub use boolean::BoolParam;
|
||||||
pub use plain::{FloatParam, IntParam};
|
pub use plain::{FloatParam, IntParam};
|
||||||
|
|
||||||
// Re-export for the [EnumParam]
|
// Re-export for the [EnumParam]
|
||||||
|
@ -75,28 +76,6 @@ pub trait Param: Display {
|
||||||
fn as_ptr(&self) -> internals::ParamPtr;
|
fn as_ptr(&self) -> internals::ParamPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A simple boolean parmaeter.
|
|
||||||
#[repr(C, align(4))]
|
|
||||||
pub struct BoolParam {
|
|
||||||
/// The field's current, normalized value. Should be initialized with the default value.
|
|
||||||
pub value: bool,
|
|
||||||
|
|
||||||
/// Optional callback for listening to value changes. The argument passed to this function is
|
|
||||||
/// the parameter's new value. This should not do anything expensive as it may be called
|
|
||||||
/// multiple times in rapid succession, and it can be run from both the GUI and the audio
|
|
||||||
/// thread.
|
|
||||||
pub value_changed: Option<Arc<dyn Fn(bool) + Send + Sync>>,
|
|
||||||
|
|
||||||
/// The parameter's human readable display name.
|
|
||||||
pub name: &'static str,
|
|
||||||
/// Optional custom conversion function from a boolean value to a string.
|
|
||||||
pub value_to_string: Option<Arc<dyn Fn(bool) -> String + Send + Sync>>,
|
|
||||||
/// Optional custom conversion function from a string to a boolean value. If the string cannot
|
|
||||||
/// be parsed, then this should return a `None`. If this happens while the parameter is being
|
|
||||||
/// updated then the update will be canceled.
|
|
||||||
pub string_to_value: Option<Arc<dyn Fn(&str) -> Option<bool> + Send + Sync>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An [IntParam]-backed categorical parameter that allows convenient conversion to and from a
|
/// An [IntParam]-backed categorical parameter that allows convenient conversion to and from a
|
||||||
/// simple enum. This enum must derive the re-exported [EnumIter] and [EnumMessage] and [Display]
|
/// simple enum. This enum must derive the re-exported [EnumIter] and [EnumMessage] and [Display]
|
||||||
/// traits. You can use the `#[strum(message = "Foo Bar")]` to override the name of the variant.
|
/// traits. You can use the `#[strum(message = "Foo Bar")]` to override the name of the variant.
|
||||||
|
@ -112,19 +91,6 @@ pub struct EnumParam<T: EnumIter + EnumMessage + Eq + Copy + Display> {
|
||||||
variants: Vec<(T, String)>,
|
variants: Vec<(T, String)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::derivable_impls)]
|
|
||||||
impl Default for BoolParam {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
|
||||||
value: false,
|
|
||||||
value_changed: None,
|
|
||||||
name: "",
|
|
||||||
value_to_string: None,
|
|
||||||
string_to_value: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: EnumIter + EnumMessage + Eq + Copy + Display + Default> Default for EnumParam<T> {
|
impl<T: EnumIter + EnumMessage + Eq + Copy + Display + Default> Default for EnumParam<T> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let variants: Vec<_> = Self::build_variants();
|
let variants: Vec<_> = Self::build_variants();
|
||||||
|
@ -147,82 +113,6 @@ impl<T: EnumIter + EnumMessage + Eq + Copy + Display + Default> Default for Enum
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Param for BoolParam {
|
|
||||||
type Plain = bool;
|
|
||||||
|
|
||||||
fn update_smoother(&mut self, _sample_rate: f32, _init: bool) {
|
|
||||||
// Can't really smooth a binary parameter now can you
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_from_string(&mut self, string: &str) -> bool {
|
|
||||||
let value = match &self.string_to_value {
|
|
||||||
Some(f) => f(string),
|
|
||||||
None => Some(string.eq_ignore_ascii_case("true") || string.eq_ignore_ascii_case("on")),
|
|
||||||
};
|
|
||||||
|
|
||||||
match value {
|
|
||||||
Some(plain) => {
|
|
||||||
self.set_plain_value(plain);
|
|
||||||
true
|
|
||||||
}
|
|
||||||
None => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn plain_value(&self) -> Self::Plain {
|
|
||||||
self.value
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_plain_value(&mut self, plain: Self::Plain) {
|
|
||||||
self.value = plain;
|
|
||||||
if let Some(f) = &self.value_changed {
|
|
||||||
f(plain);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn normalized_value(&self) -> f32 {
|
|
||||||
self.preview_normalized(self.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_normalized_value(&mut self, normalized: f32) {
|
|
||||||
self.set_plain_value(self.preview_plain(normalized));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn normalized_value_to_string(&self, normalized: f32, _include_unit: bool) -> String {
|
|
||||||
let value = self.preview_plain(normalized);
|
|
||||||
match (value, &self.value_to_string) {
|
|
||||||
(v, Some(f)) => f(v),
|
|
||||||
(true, None) => String::from("On"),
|
|
||||||
(false, None) => String::from("Off"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn string_to_normalized_value(&self, string: &str) -> Option<f32> {
|
|
||||||
let value = match &self.string_to_value {
|
|
||||||
Some(f) => f(string),
|
|
||||||
None => Some(string.eq_ignore_ascii_case("true") || string.eq_ignore_ascii_case("on")),
|
|
||||||
}?;
|
|
||||||
|
|
||||||
Some(self.preview_normalized(value))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn preview_normalized(&self, plain: Self::Plain) -> f32 {
|
|
||||||
if plain {
|
|
||||||
1.0
|
|
||||||
} else {
|
|
||||||
0.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn preview_plain(&self, normalized: f32) -> Self::Plain {
|
|
||||||
normalized > 0.5
|
|
||||||
}
|
|
||||||
|
|
||||||
fn as_ptr(&self) -> internals::ParamPtr {
|
|
||||||
internals::ParamPtr::BoolParam(self as *const BoolParam as *mut BoolParam)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: EnumIter + EnumMessage + Eq + Copy + Display> Param for EnumParam<T> {
|
impl<T: EnumIter + EnumMessage + Eq + Copy + Display> Param for EnumParam<T> {
|
||||||
type Plain = T;
|
type Plain = T;
|
||||||
|
|
||||||
|
@ -287,63 +177,12 @@ impl<T: EnumIter + EnumMessage + Eq + Copy + Display> Param for EnumParam<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for BoolParam {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
match (self.value, &self.value_to_string) {
|
|
||||||
(v, Some(func)) => write!(f, "{}", func(v)),
|
|
||||||
(true, None) => write!(f, "On"),
|
|
||||||
(false, None) => write!(f, "Off"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: EnumIter + EnumMessage + Eq + Copy + Display> Display for EnumParam<T> {
|
impl<T: EnumIter + EnumMessage + Eq + Copy + Display> Display for EnumParam<T> {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
write!(f, "{}", self.variants[self.inner.plain_value() as usize].1)
|
write!(f, "{}", self.variants[self.inner.plain_value() as usize].1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BoolParam {
|
|
||||||
/// Build a new [Self]. Use the other associated functions to modify the behavior of the
|
|
||||||
/// parameter.
|
|
||||||
pub fn new(name: &'static str, default: bool) -> Self {
|
|
||||||
Self {
|
|
||||||
value: default,
|
|
||||||
name,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Run a callback whenever this parameter's value changes. The argument passed to this function
|
|
||||||
/// is the parameter's new value. This should not do anything expensive as it may be called
|
|
||||||
/// multiple times in rapid succession, and it can be run from both the GUI and the audio
|
|
||||||
/// thread.
|
|
||||||
pub fn with_callback(mut self, callback: Arc<dyn Fn(bool) + Send + Sync>) -> Self {
|
|
||||||
self.value_changed = Some(callback);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Use a custom conversion function to convert the boolean value to a string.
|
|
||||||
pub fn with_value_to_string(
|
|
||||||
mut self,
|
|
||||||
callback: Arc<dyn Fn(bool) -> String + Send + Sync>,
|
|
||||||
) -> Self {
|
|
||||||
self.value_to_string = Some(callback);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Use a custom conversion function to convert from a string to a boolean value. If the string
|
|
||||||
/// cannot be parsed, then this should return a `None`. If this happens while the parameter is
|
|
||||||
/// being updated then the update will be canceled.
|
|
||||||
pub fn with_string_to_value(
|
|
||||||
mut self,
|
|
||||||
callback: Arc<dyn Fn(&str) -> Option<bool> + Send + Sync>,
|
|
||||||
) -> Self {
|
|
||||||
self.string_to_value = Some(callback);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: EnumIter + EnumMessage + Eq + Copy + Display> EnumParam<T> {
|
impl<T: EnumIter + EnumMessage + Eq + Copy + Display> EnumParam<T> {
|
||||||
/// Build a new [Self]. Use the other associated functions to modify the behavior of the
|
/// Build a new [Self]. Use the other associated functions to modify the behavior of the
|
||||||
/// parameter.
|
/// parameter.
|
||||||
|
|
169
src/param/boolean.rs
Normal file
169
src/param/boolean.rs
Normal file
|
@ -0,0 +1,169 @@
|
||||||
|
//! Simple boolean parameters.
|
||||||
|
|
||||||
|
use std::fmt::Display;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use super::internals::ParamPtr;
|
||||||
|
use super::Param;
|
||||||
|
|
||||||
|
/// A simple boolean parmaeter.
|
||||||
|
#[repr(C, align(4))]
|
||||||
|
pub struct BoolParam {
|
||||||
|
/// The field's current, normalized value. Should be initialized with the default value.
|
||||||
|
pub value: bool,
|
||||||
|
|
||||||
|
/// Optional callback for listening to value changes. The argument passed to this function is
|
||||||
|
/// the parameter's new value. This should not do anything expensive as it may be called
|
||||||
|
/// multiple times in rapid succession, and it can be run from both the GUI and the audio
|
||||||
|
/// thread.
|
||||||
|
pub value_changed: Option<Arc<dyn Fn(bool) + Send + Sync>>,
|
||||||
|
|
||||||
|
/// The parameter's human readable display name.
|
||||||
|
pub name: &'static str,
|
||||||
|
/// Optional custom conversion function from a boolean value to a string.
|
||||||
|
pub value_to_string: Option<Arc<dyn Fn(bool) -> String + Send + Sync>>,
|
||||||
|
/// Optional custom conversion function from a string to a boolean value. If the string cannot
|
||||||
|
/// be parsed, then this should return a `None`. If this happens while the parameter is being
|
||||||
|
/// updated then the update will be canceled.
|
||||||
|
pub string_to_value: Option<Arc<dyn Fn(&str) -> Option<bool> + Send + Sync>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::derivable_impls)]
|
||||||
|
impl Default for BoolParam {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
value: false,
|
||||||
|
value_changed: None,
|
||||||
|
name: "",
|
||||||
|
value_to_string: None,
|
||||||
|
string_to_value: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for BoolParam {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match (self.value, &self.value_to_string) {
|
||||||
|
(v, Some(func)) => write!(f, "{}", func(v)),
|
||||||
|
(true, None) => write!(f, "On"),
|
||||||
|
(false, None) => write!(f, "Off"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Param for BoolParam {
|
||||||
|
type Plain = bool;
|
||||||
|
|
||||||
|
fn update_smoother(&mut self, _sample_rate: f32, _init: bool) {
|
||||||
|
// Can't really smooth a binary parameter now can you
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_from_string(&mut self, string: &str) -> bool {
|
||||||
|
let value = match &self.string_to_value {
|
||||||
|
Some(f) => f(string),
|
||||||
|
None => Some(string.eq_ignore_ascii_case("true") || string.eq_ignore_ascii_case("on")),
|
||||||
|
};
|
||||||
|
|
||||||
|
match value {
|
||||||
|
Some(plain) => {
|
||||||
|
self.set_plain_value(plain);
|
||||||
|
true
|
||||||
|
}
|
||||||
|
None => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn plain_value(&self) -> Self::Plain {
|
||||||
|
self.value
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_plain_value(&mut self, plain: Self::Plain) {
|
||||||
|
self.value = plain;
|
||||||
|
if let Some(f) = &self.value_changed {
|
||||||
|
f(plain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn normalized_value(&self) -> f32 {
|
||||||
|
self.preview_normalized(self.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_normalized_value(&mut self, normalized: f32) {
|
||||||
|
self.set_plain_value(self.preview_plain(normalized));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn normalized_value_to_string(&self, normalized: f32, _include_unit: bool) -> String {
|
||||||
|
let value = self.preview_plain(normalized);
|
||||||
|
match (value, &self.value_to_string) {
|
||||||
|
(v, Some(f)) => f(v),
|
||||||
|
(true, None) => String::from("On"),
|
||||||
|
(false, None) => String::from("Off"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn string_to_normalized_value(&self, string: &str) -> Option<f32> {
|
||||||
|
let value = match &self.string_to_value {
|
||||||
|
Some(f) => f(string),
|
||||||
|
None => Some(string.eq_ignore_ascii_case("true") || string.eq_ignore_ascii_case("on")),
|
||||||
|
}?;
|
||||||
|
|
||||||
|
Some(self.preview_normalized(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn preview_normalized(&self, plain: Self::Plain) -> f32 {
|
||||||
|
if plain {
|
||||||
|
1.0
|
||||||
|
} else {
|
||||||
|
0.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn preview_plain(&self, normalized: f32) -> Self::Plain {
|
||||||
|
normalized > 0.5
|
||||||
|
}
|
||||||
|
|
||||||
|
fn as_ptr(&self) -> ParamPtr {
|
||||||
|
ParamPtr::BoolParam(self as *const BoolParam as *mut BoolParam)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BoolParam {
|
||||||
|
/// Build a new [Self]. Use the other associated functions to modify the behavior of the
|
||||||
|
/// parameter.
|
||||||
|
pub fn new(name: &'static str, default: bool) -> Self {
|
||||||
|
Self {
|
||||||
|
value: default,
|
||||||
|
name,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Run a callback whenever this parameter's value changes. The argument passed to this function
|
||||||
|
/// is the parameter's new value. This should not do anything expensive as it may be called
|
||||||
|
/// multiple times in rapid succession, and it can be run from both the GUI and the audio
|
||||||
|
/// thread.
|
||||||
|
pub fn with_callback(mut self, callback: Arc<dyn Fn(bool) + Send + Sync>) -> Self {
|
||||||
|
self.value_changed = Some(callback);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Use a custom conversion function to convert the boolean value to a string.
|
||||||
|
pub fn with_value_to_string(
|
||||||
|
mut self,
|
||||||
|
callback: Arc<dyn Fn(bool) -> String + Send + Sync>,
|
||||||
|
) -> Self {
|
||||||
|
self.value_to_string = Some(callback);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Use a custom conversion function to convert from a string to a boolean value. If the string
|
||||||
|
/// cannot be parsed, then this should return a `None`. If this happens while the parameter is
|
||||||
|
/// being updated then the update will be canceled.
|
||||||
|
pub fn with_string_to_value(
|
||||||
|
mut self,
|
||||||
|
callback: Arc<dyn Fn(&str) -> Option<bool> + Send + Sync>,
|
||||||
|
) -> Self {
|
||||||
|
self.string_to_value = Some(callback);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue