From 7e89201c6296583336dc201d322a5912292545c7 Mon Sep 17 00:00:00 2001 From: ozpv <39195175+ozpv@users.noreply.github.com> Date: Wed, 20 May 2026 02:54:51 -0500 Subject: simplify things --- src/audio.rs | 45 ++++---- src/gui.rs | 40 +++---- src/lib.rs | 23 ++--- src/params.rs | 298 +++++++++++++++++++++-------------------------------- src/window_size.rs | 2 +- src/window_type.rs | 26 ++--- 6 files changed, 175 insertions(+), 259 deletions(-) (limited to 'src') diff --git a/src/audio.rs b/src/audio.rs index 64338a1..6ad1a86 100644 --- a/src/audio.rs +++ b/src/audio.rs @@ -1,8 +1,7 @@ -//! Contains all types and implementations related to audio processing and the audio thread. - use crate::{ - RetainPluginMainThread, RetainPluginShared, params::RetainParamsLocal, - retain::retain_top_n_magnitudes, windowed_fft::WindowedRealFft, + RetainPluginMainThread, RetainPluginShared, params::RetainParams, + retain::retain_top_n_magnitudes, window_size::WindowSize, window_type::WindowType, + windowed_fft::WindowedRealFft, }; use clack_extensions::{ audio_ports::{ @@ -12,6 +11,7 @@ use clack_extensions::{ params::PluginAudioProcessorParams, }; use clack_plugin::prelude::*; +use std::sync::Arc; /// Our plugin's audio processor. It lives in the audio thread. /// @@ -19,7 +19,7 @@ use clack_plugin::prelude::*; /// buffer. pub struct RetainPluginAudioProcessor<'a> { /// The local state of the parameters - params: RetainParamsLocal, + params: Arc, /// A reference to the plugin's shared data. shared: &'a RetainPluginShared<'a>, /// Our handle to the host @@ -28,6 +28,10 @@ pub struct RetainPluginAudioProcessor<'a> { fft_left: WindowedRealFft, /// Fft for the right channel fft_right: WindowedRealFft, + /// Previous window type + prev_window_type: Option, + /// Previous window size + prev_window_size: Option, } impl<'a> PluginAudioProcessor<'a, RetainPluginShared<'a>, RetainPluginMainThread<'a>> @@ -39,7 +43,7 @@ impl<'a> PluginAudioProcessor<'a, RetainPluginShared<'a>, RetainPluginMainThread shared: &'a RetainPluginShared<'a>, _audio_config: PluginAudioConfiguration, ) -> Result { - let params = RetainParamsLocal::new(&shared.params); + let params = Arc::clone(&shared.params); let fft_left = WindowedRealFft::new(params.get_window_size().into()); let fft_right = WindowedRealFft::new(params.get_window_size().into()); @@ -51,6 +55,8 @@ impl<'a> PluginAudioProcessor<'a, RetainPluginShared<'a>, RetainPluginMainThread host, fft_left, fft_right, + prev_window_size: None, + prev_window_type: None, }) } @@ -87,18 +93,12 @@ impl<'a> PluginAudioProcessor<'a, RetainPluginShared<'a>, RetainPluginMainThread } } - let prev_window_size = self.params.get_window_size(); - let prev_window_type = self.params.get_window_type().as_byte(); - - // Receive any param updates from the main thread and/or the GUI. - self.params.fetch_updates(&self.shared.params); - // update window size and latency if it has changed // updates fft window sizes only if necessary let window_size = self.params.get_window_size(); - if prev_window_size != window_size { - self.fft_left.window_size(window_size.into()); - self.fft_right.window_size(window_size.into()); + if self.prev_window_size != Some(window_size.clone()) { + self.fft_left.window_size(window_size.clone()); + self.fft_right.window_size(window_size.clone()); if let Some(latency) = self.shared.host.get_extension::() { // should be safe @@ -111,9 +111,9 @@ impl<'a> PluginAudioProcessor<'a, RetainPluginShared<'a>, RetainPluginMainThread // update change in window type if needed let window_type = self.params.get_window_type(); - if prev_window_type != window_type.as_byte() { - self.fft_left.window_function(window_type); - self.fft_right.window_function(window_type); + if self.prev_window_type != Some(window_type.clone()) { + self.fft_left.window_function(&window_type); + self.fft_right.window_function(&window_type); } // Now let's process the audio, while splitting the processing in batches between each @@ -158,11 +158,12 @@ impl<'a> PluginAudioProcessor<'a, RetainPluginShared<'a>, RetainPluginMainThread } } + self.prev_window_size = Some(window_size); + self.prev_window_type = Some(window_type); + // Publish any parameter changes we may have received back to the GUI. - if self.params.push_updates(&self.shared.params) { - // Request the on-main-thread callback, which we use to refresh the UI if it is open - self.host.request_callback(); - } + // Request the on-main-thread callback, which we use to refresh the UI if it is open + self.host.request_callback(); Ok(ProcessStatus::ContinueIfNotQuiet) } diff --git a/src/gui.rs b/src/gui.rs index 1662b79..5780f50 100644 --- a/src/gui.rs +++ b/src/gui.rs @@ -1,9 +1,7 @@ //! Contains all types and implementations related to the plugin's GUI use crate::{ - RetainPluginMainThread, RetainPluginShared, - params::{RetainParamsLocal, RetainParamsShared}, - window_size::WindowSize, + RetainPluginMainThread, RetainPluginShared, params::RetainParams, window_size::WindowSize, window_type::WindowType, }; use baseview::{Size, WindowHandle, WindowOpenOptions, WindowScalePolicy, gl::GlConfig}; @@ -18,17 +16,14 @@ use std::sync::Arc; /// The EGUI application state struct AppState { /// A handle to the shared params state - shared_params: Arc, - /// The local state of the parameters - local_params: RetainParamsLocal, + params: Arc, } impl AppState { /// Initializes a new [`AppState`] from the given shared params state handle - pub fn new(shared_params: &Arc) -> Self { + pub fn new(params: &Arc) -> Self { Self { - local_params: RetainParamsLocal::new(shared_params), - shared_params: Arc::clone(shared_params), + params: Arc::clone(params), } } } @@ -62,8 +57,6 @@ impl RetainPluginGui { tx.send(egui_ctx.clone()).unwrap(); }, |egui_ctx: &Context, _queue: &mut Queue, state: &mut AppState| { - state.local_params.fetch_updates(&state.shared_params); - egui::CentralPanel::default().show(egui_ctx, |ui| { ui.with_layout(Layout::top_down(Align::Center), |ui| { ui.heading("Retain"); @@ -71,8 +64,8 @@ impl RetainPluginGui { ui.horizontal(|ui| { ui.with_layout(Layout::top_down(Align::LEFT), |ui| { - let mut order = state.local_params.get_order(); - let window_size = state.local_params.get_window_size(); + let mut order = state.params.get_order(); + let window_size = state.params.get_window_size().inner(); let slider = ui.add( Slider::new(&mut order, 0..=window_size) @@ -81,12 +74,10 @@ impl RetainPluginGui { ); if slider.changed() { - state.local_params.set_order(order); - state.local_params.push_updates(&state.shared_params); + state.params.set_order(order); } - let mut window_size = - WindowSize::from(state.local_params.get_window_size()); + let mut window_size = state.params.get_window_size(); ComboBox::from_label("Window Size") .selected_text(window_size.as_str()) @@ -99,22 +90,20 @@ impl RetainPluginGui { .selectable_value(&mut window_size, size, display) .changed() { - state.local_params.set_window_size(inner); - state.local_params.push_updates(&state.shared_params); + state.params.set_window_size(inner.into()); } } }); }); ui.with_layout(Layout::top_down(Align::RIGHT), |ui| { - let mut complement = state.local_params.get_complement(); + let mut complement = state.params.get_complement(); if ui.checkbox(&mut complement, "Complement").changed() { - state.local_params.set_complement(complement); - state.local_params.push_updates(&state.shared_params); + state.params.set_complement(complement); } - let window_type = state.local_params.get_window_type(); + let window_type = state.params.get_window_type(); let selected = window_type.as_str(); let mut window_type = window_type.as_byte(); @@ -123,7 +112,7 @@ impl RetainPluginGui { .show_ui(ui, |ui| { for function in WindowType::iter() { let display = function.as_str(); - let bits = function.as_byte(); + let byte = function.as_byte(); if ui .selectable_value( @@ -133,8 +122,7 @@ impl RetainPluginGui { ) .changed() { - state.local_params.set_window_type_from_byte(bits); - state.local_params.push_updates(&state.shared_params); + state.params.set_window_type(byte.into()); } } }); diff --git a/src/lib.rs b/src/lib.rs index e26211f..2878e4f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,4 @@ -use crate::{ - audio::RetainPluginAudioProcessor, - gui::RetainPluginGui, - params::{RetainParamsLocal, RetainParamsShared}, -}; +use crate::{audio::RetainPluginAudioProcessor, gui::RetainPluginGui, params::RetainParams}; use clack_extensions::{ audio_ports::PluginAudioPorts, gui::PluginGui, @@ -52,6 +48,8 @@ impl DefaultPluginFactory for RetainPlugin { fn get_descriptor() -> PluginDescriptor { PluginDescriptor::new("com.haemolacriaa.retain", "Retain") .with_description("Retains only the nth largest magnitude frequencies in the signal") + .with_version("0.1.0") + .with_vendor("haemolacriaa") .with_features([AUDIO_EFFECT, STEREO]) } @@ -63,25 +61,21 @@ impl DefaultPluginFactory for RetainPlugin { _host: HostMainThreadHandle<'a>, shared: &'a Self::Shared<'a>, ) -> Result, PluginError> { - Ok(Self::MainThread { - shared, - params: RetainParamsLocal::new(&shared.params), - gui: None, - }) + Ok(Self::MainThread { shared, gui: None }) } } /// The plugin data that gets shared between the Main Thread and the Audio Thread. pub struct RetainPluginShared<'a> { /// The plugin's parameter values. - params: Arc, + params: Arc, host: HostSharedHandle<'a>, } impl<'a> RetainPluginShared<'a> { fn new(host: HostSharedHandle<'a>) -> Self { RetainPluginShared { - params: Arc::new(RetainParamsShared::new()), + params: Arc::new(RetainParams::new()), host, } } @@ -91,8 +85,6 @@ impl<'a> PluginShared<'a> for RetainPluginShared<'a> {} /// The data that belongs to the main thread of our plugin. pub struct RetainPluginMainThread<'a> { - /// The local state of the parameters - params: RetainParamsLocal, /// A reference to the plugin's shared data. shared: &'a RetainPluginShared<'a>, /// The plugin's GUI state and context @@ -109,8 +101,7 @@ impl<'a> PluginMainThread<'a, RetainPluginShared<'a>> for RetainPluginMainThread impl PluginLatencyImpl for RetainPluginMainThread<'_> { fn get(&mut self) -> u32 { - self.params.fetch_updates(&self.shared.params); - self.params.get_window_size() as u32 + self.shared.params.get_window_size().inner() as u32 } } diff --git a/src/params.rs b/src/params.rs index 605e305..4b57dd6 100644 --- a/src/params.rs +++ b/src/params.rs @@ -1,5 +1,3 @@ -//! Contains all types and implementations related to parameter management. - use crate::{RetainPluginMainThread, window_size::WindowSize, window_type::WindowType}; use clack_extensions::{ params::{ @@ -21,18 +19,14 @@ use std::{ sync::atomic::{AtomicBool, AtomicU8, AtomicUsize, Ordering}, }; -/// The default value of the order parameter. +/// The default values of the parameters. const DEFAULT_ORDER: usize = 1; pub const DEFAULT_WINDOW_SIZE: WindowSize = WindowSize::Size4096; pub const DEFAULT_WINDOW_TYPE: WindowType = WindowType::Hann; const DEFAULT_COMPLEMENT: bool = false; -/// A struct that manages the parameters for our plugin. -/// -/// This struct will be used both by the [`RetainPluginMainThread`] (which the host will use -/// to query the value of our parameters), and by the [`RetainPluginAudioProcessor`], which will -/// actually modulate the audio samples. -pub struct RetainParamsShared { +/// A struct that manages the parameters for the plugin. +pub struct RetainParams { /// The current value of the order parameter. order: AtomicUsize, /// Window size of FFT @@ -43,12 +37,12 @@ pub struct RetainParamsShared { complement: AtomicBool, } -impl RetainParamsShared { +impl RetainParams { /// The unique identifier for the order parameter. pub const PARAM_ORDER_ID: ClapId = ClapId::new(1); pub const PARAM_WINDOW_SIZE_ID: ClapId = ClapId::new(2); pub const PARAM_WINDOW_TYPE_ID: ClapId = ClapId::new(3); - pub const PARAM_COMPLEMENT_ID: ClapId = ClapId::new(3); + pub const PARAM_COMPLEMENT_ID: ClapId = ClapId::new(4); /// Initializes the shared parameter value. pub fn new() -> Self { @@ -59,157 +53,85 @@ impl RetainParamsShared { complement: AtomicBool::new(DEFAULT_COMPLEMENT), } } -} - -/// The local-side of parameter state. -/// -/// This state is local to the current thread (whether it is the main-thread, the UI or the audio -/// thread), it is not shared directly with the others. -/// -/// This allows us to both check for differences, and to only update parameter state when we want -/// to. -pub struct RetainParamsLocal { - /// The local value of the order parameter. - order: usize, - /// The local value of the window size paramter. - window_size: usize, - /// The local value of the type of window function parameter. - window_type: WindowType, - /// The local value of the complement parameter. - complement: bool, -} - -impl RetainParamsLocal { - /// Initializes a new local state from the current shared state. - pub fn new(shared: &RetainParamsShared) -> Self { - Self { - order: shared.order.load(Ordering::Relaxed), - window_size: shared.window_size.load(Ordering::Relaxed), - window_type: WindowType::from_byte(shared.window_type.load(Ordering::Relaxed)), - complement: shared.complement.load(Ordering::Relaxed), - } - } - /// Returns the current local order value. + /// Returns the current order value. #[inline] pub fn get_order(&self) -> usize { - self.order + self.order.load(Ordering::SeqCst) } - /// Sets the current local order to `value`. + /// Sets the current order to `value`. /// - /// It is clamped to the range `0..=100_000`. + /// It is clamped to the range `0..=32_768`. #[inline] - pub fn set_order(&mut self, value: usize) { - self.order = value; + pub fn set_order(&self, value: usize) { + self.order.store(value.clamp(0, 32768), Ordering::SeqCst); } /// Returns the current window size value. #[inline] - pub fn get_window_size(&self) -> usize { - self.window_size + pub fn get_window_size(&self) -> WindowSize { + self.window_size.load(Ordering::SeqCst).into() } /// Sets the current local window size to `value`. #[inline] - pub fn set_window_size(&mut self, value: usize) { - self.window_size = value; + pub fn set_window_size(&self, value: WindowSize) { + self.window_size.store(value.inner(), Ordering::SeqCst); } /// Returns the current local window type. #[inline] - pub fn get_window_type(&self) -> &WindowType { - &self.window_type + pub fn get_window_type(&self) -> WindowType { + self.window_type.load(Ordering::SeqCst).into() } /// Sets the current local window type from `bits`. #[inline] - pub fn set_window_type_from_byte(&mut self, bits: u8) { - self.window_type = WindowType::from_byte(bits); + pub fn set_window_type(&self, window_type: WindowType) { + self.window_type + .store(window_type.as_byte(), Ordering::SeqCst); } /// Returns the current local complement. #[inline] pub fn get_complement(&self) -> bool { - self.complement + self.complement.load(Ordering::SeqCst) } /// Sets the current local complement to `value`. #[inline] - pub fn set_complement(&mut self, value: bool) { - self.complement = value; - } - - /// Fetch updates from the `shared` state. - /// - /// If any of the parameters have been updated, this returns `true`. - #[inline] - pub fn fetch_updates(&mut self, shared: &RetainParamsShared) -> bool { - let latest_order = shared.order.load(Ordering::Relaxed); - let latest_window_size = shared.window_size.load(Ordering::Relaxed); - let latest_window_type = WindowType::from_byte(shared.window_type.load(Ordering::Relaxed)); - let latest_complement = shared.complement.load(Ordering::Relaxed); - - if latest_order != self.order - || latest_window_size != self.order - || latest_window_type != self.window_type - || latest_complement != self.complement - { - self.order = latest_order; - self.window_size = latest_window_size; - self.window_type = latest_window_type; - self.complement = latest_complement; - - true - } else { - false - } - } - - /// Pushes the local parameter values to the `shared` state. - /// - /// If the values were different and an actual update occurred, this returns `true`. - #[inline] - pub fn push_updates(&self, shared: &RetainParamsShared) -> bool { - let previous_order = shared.order.swap(self.order, Ordering::Relaxed); - let previous_window_size = shared.window_size.swap(self.window_size, Ordering::Relaxed); - let previous_window_type = shared - .window_type - .swap(self.window_type.as_byte(), Ordering::Relaxed); - let previous_complement = shared.complement.swap(self.complement, Ordering::Relaxed); - - previous_order != self.order - || previous_window_size != self.window_size - || previous_window_type != self.window_type.as_byte() - || previous_complement != self.complement + pub fn set_complement(&self, value: bool) { + self.complement.store(value, Ordering::SeqCst); } /// Handles incoming events. /// /// If the given event is a matching parameter change event, the order parameter will be /// updated accordingly. - pub fn handle_event(&mut self, event: &UnknownEvent) { + pub fn handle_event(&self, event: &UnknownEvent) { if let Some(CoreEventSpace::ParamValue(event)) = event.as_core_event() { - if event.param_id() == RetainParamsShared::PARAM_ORDER_ID { + if event.param_id() == RetainParams::PARAM_ORDER_ID { self.set_order(event.value() as usize); } - if event.param_id() == RetainParamsShared::PARAM_WINDOW_SIZE_ID { - self.set_window_size(event.value() as usize); + if event.param_id() == RetainParams::PARAM_WINDOW_SIZE_ID { + self.set_window_size((event.value() as usize).into()); } - if event.param_id() == RetainParamsShared::PARAM_WINDOW_TYPE_ID { - self.set_window_type_from_byte(event.value() as u8); + if event.param_id() == RetainParams::PARAM_WINDOW_TYPE_ID { + self.set_window_type((event.value() as u8).into()); } - if event.param_id() == RetainParamsShared::PARAM_COMPLEMENT_ID { + if event.param_id() == RetainParams::PARAM_COMPLEMENT_ID { self.set_complement(event.value() != 0.0); } } } } -/// To save the plugin state (parameter values) using protocol buffers +/// Wrapper that helps save plugin parameters using protocol buffers +/// Updating this will change the schema and break old #[derive(Message)] struct PluginState { #[prost(uint64, tag = "1")] @@ -223,10 +145,10 @@ struct PluginState { } impl PluginState { - fn copied(local_params: &RetainParamsLocal) -> Self { + fn copied(local_params: &RetainParams) -> Self { Self { order: local_params.get_order() as u64, - window_size: local_params.get_window_size() as u32, + window_size: local_params.get_window_size().inner() as u32, window_type: local_params.get_window_type().as_byte() as u32, complement: local_params.get_complement(), } @@ -249,14 +171,12 @@ impl PluginState { } } -/// Implementation of the State extension. +/// To save and load the plugin parameters impl PluginStateImpl for RetainPluginMainThread<'_> { fn save(&mut self, output: &mut OutputStream) -> Result<(), PluginError> { - self.params.fetch_updates(&self.shared.params); - let mut data = vec![]; - let state = PluginState::copied(&self.params); + let state = PluginState::copied(&self.shared.params); state.encode(&mut data)?; @@ -271,13 +191,14 @@ impl PluginStateImpl for RetainPluginMainThread<'_> { let data = PluginState::decode(&data[..])?; - self.params.set_order(data.get_order() as usize); - self.params.set_window_size(data.get_window_size() as usize); - self.params - .set_window_type_from_byte(data.get_window_type_bits()); - self.params.set_complement(data.get_complement()); - - self.params.push_updates(&self.shared.params); + self.shared.params.set_order(data.get_order() as usize); + self.shared + .params + .set_window_size((data.get_window_size() as usize).into()); + self.shared + .params + .set_window_type(data.get_window_type_bits().into()); + self.shared.params.set_complement(data.get_complement()); Ok(()) } @@ -288,92 +209,105 @@ impl PluginMainThreadParams for RetainPluginMainThread<'_> { 4 } + /// `param_index`: The index of the parameter to query. + /// Must be less than the value returned by `count()`. fn get_info(&mut self, param_index: u32, info: &mut ParamInfoWriter) { - if param_index != 0 { + if param_index >= 4 { return; } - info.set(&ParamInfo { - id: RetainParamsShared::PARAM_ORDER_ID, - flags: ParamInfoFlags::IS_AUTOMATABLE | ParamInfoFlags::IS_STEPPED, - cookie: Cookie::default(), - name: b"Order", - module: b"", - min_value: 0.0, - max_value: f64::MAX, - default_value: DEFAULT_ORDER as f64, - }); - - info.set(&ParamInfo { - id: RetainParamsShared::PARAM_WINDOW_SIZE_ID, - flags: ParamInfoFlags::IS_READONLY, - cookie: Cookie::default(), - name: b"Window Size", - module: b"", - min_value: 128.0, - max_value: usize::MAX as f64, - default_value: DEFAULT_WINDOW_SIZE.inner() as f64, - }); - - info.set(&ParamInfo { - id: RetainParamsShared::PARAM_WINDOW_TYPE_ID, - flags: ParamInfoFlags::IS_READONLY, - cookie: Cookie::default(), - name: b"Window Function", - module: b"", - min_value: 0.0, - max_value: 4.0, - default_value: DEFAULT_WINDOW_TYPE.as_byte() as f64, - }); - - info.set(&ParamInfo { - id: RetainParamsShared::PARAM_COMPLEMENT_ID, - flags: ParamInfoFlags::IS_READONLY, - cookie: Cookie::default(), - name: b"Complement", - module: b"", - min_value: 0.0, - max_value: 1.0, - default_value: DEFAULT_COMPLEMENT as u8 as f64, - }); + // cleaner than match is + if param_index == 0 { + info.set(&ParamInfo { + id: RetainParams::PARAM_ORDER_ID, + flags: ParamInfoFlags::IS_AUTOMATABLE | ParamInfoFlags::IS_STEPPED, + cookie: Cookie::default(), + name: b"Order", + module: b"", + min_value: 0.0, + max_value: 32768.0, + default_value: DEFAULT_ORDER as f64, + }); + } + + if param_index == 1 { + info.set(&ParamInfo { + id: RetainParams::PARAM_WINDOW_SIZE_ID, + flags: ParamInfoFlags::IS_READONLY, + cookie: Cookie::default(), + name: b"Window Size", + module: b"", + min_value: 256.0, + max_value: 32768.0, + default_value: DEFAULT_WINDOW_SIZE.inner() as f64, + }); + } + + if param_index == 2 { + info.set(&ParamInfo { + id: RetainParams::PARAM_WINDOW_TYPE_ID, + flags: ParamInfoFlags::IS_READONLY, + cookie: Cookie::default(), + name: b"Window Function", + module: b"", + min_value: 0.0, + max_value: 4.0, + default_value: DEFAULT_WINDOW_TYPE.as_byte() as f64, + }); + } + + if param_index == 3 { + info.set(&ParamInfo { + id: RetainParams::PARAM_COMPLEMENT_ID, + flags: ParamInfoFlags::IS_READONLY, + cookie: Cookie::default(), + name: b"Complement", + module: b"", + min_value: 0.0, + max_value: 1.0, + default_value: DEFAULT_COMPLEMENT as u8 as f64, + }); + } } fn get_value(&mut self, param_id: ClapId) -> Option { match param_id { - RetainParamsShared::PARAM_ORDER_ID => Some(self.params.get_order() as f64), - RetainParamsShared::PARAM_WINDOW_SIZE_ID => Some(self.params.get_window_size() as f64), - RetainParamsShared::PARAM_WINDOW_TYPE_ID => { - Some(self.params.get_window_type().as_byte() as f64) + RetainParams::PARAM_ORDER_ID => Some(self.shared.params.get_order() as f64), + RetainParams::PARAM_WINDOW_SIZE_ID => { + Some(self.shared.params.get_window_size().inner() as f64) + } + RetainParams::PARAM_WINDOW_TYPE_ID => { + Some(self.shared.params.get_window_type().as_byte() as f64) } - RetainParamsShared::PARAM_COMPLEMENT_ID => { - Some(self.params.get_complement() as u8 as f64) + RetainParams::PARAM_COMPLEMENT_ID => { + Some(self.shared.params.get_complement() as u8 as f64) } _ => None, } } - // TODO: update for order fn value_to_text( &mut self, param_id: ClapId, value: f64, writer: &mut ParamDisplayWriter, ) -> std::fmt::Result { - if param_id == RetainParamsShared::PARAM_ORDER_ID { - write!(writer, "{0:.2} %", value * 100.0) + if param_id == RetainParams::PARAM_ORDER_ID { + write!(writer, "{}", value as u64) } else { Err(std::fmt::Error) } } - // TODO: update for order fn text_to_value(&mut self, param_id: ClapId, text: &CStr) -> Option { let text = text.to_str().ok()?; - if param_id == RetainParamsShared::PARAM_ORDER_ID { - let text = text.strip_suffix('%').unwrap_or(text).trim(); - let percentage: f64 = text.parse().ok()?; - Some(percentage / 100.0) + if param_id == RetainParams::PARAM_ORDER_ID { + let max = self.shared.params.get_window_size().inner() as f64; + + let order_value = text.parse::().ok()?; + + Some(order_value.clamp(0.0, max)) } else { None } @@ -385,7 +319,7 @@ impl PluginMainThreadParams for RetainPluginMainThread<'_> { _output_parameter_changes: &mut OutputEvents, ) { for event in input_parameter_changes { - self.params.handle_event(event); + self.shared.params.handle_event(event); } } } diff --git a/src/window_size.rs b/src/window_size.rs index 620a307..c84a137 100644 --- a/src/window_size.rs +++ b/src/window_size.rs @@ -1,7 +1,7 @@ /// The max value of the custom window size is `u32::MAX`. /// The min value of the custom window size is `WindowSize::Size256`. /// This is because it's the maximum latency one can report to a CLAP host. -#[derive(Debug, PartialEq)] +#[derive(Debug, Clone, PartialEq)] pub enum WindowSize { Size256, Size512, diff --git a/src/window_type.rs b/src/window_type.rs index c181c6d..7fb7d58 100644 --- a/src/window_type.rs +++ b/src/window_type.rs @@ -6,7 +6,7 @@ use crate::{ window_size::WindowSize, }; -#[derive(PartialEq)] +#[derive(Clone, PartialEq)] pub enum WindowType { Rectangular, Hann, @@ -47,17 +47,6 @@ impl WindowType { .into_iter() } - pub fn from_byte(bits: u8) -> Self { - match bits { - 0 => Self::Rectangular, - 1 => Self::Hann, - 2 => Self::Hamming, - 3 => Self::BlackmanHarris, - 4 => Self::Sine4, - _ => panic!("Invalid window type"), - } - } - pub fn as_byte(&self) -> u8 { match self { Self::Rectangular => 0, @@ -68,3 +57,16 @@ impl WindowType { } } } + +impl From for WindowType { + fn from(item: u8) -> Self { + match item { + 0 => Self::Rectangular, + 1 => Self::Hann, + 2 => Self::Hamming, + 3 => Self::BlackmanHarris, + 4 => Self::Sine4, + _ => panic!("Invalid window type"), + } + } +} -- cgit v1.2.3