1pub mod action;
7pub mod algorithm;
8mod error;
9pub mod node;
10pub mod param;
11pub mod port;
12pub mod processable;
13pub mod router;
14
15pub use action::*;
17pub use algorithm::*;
18pub use error::*;
19pub use node::*;
20pub use param::*;
21pub use port::*;
22pub use processable::*;
23pub use router::*;
24
25pub const DEFAULT_BLOCK_SIZE: usize = 64;
31
32pub type MonoBlock<T, const BUF_SIZE: usize> = [T; BUF_SIZE];
34
35pub type StereoBlock<T, const BUF_SIZE: usize> = [MonoBlock<T, BUF_SIZE>; 2];
37
38pub type ControlValue<T> = T;
40
41pub mod prelude {
47 pub use super::{
49 NodeCategory,
50 NodeId,
52 NodeMetadata,
53 NodeState,
54
55 NodeTypeId,
56 ParamMetadata,
57
58 ParamRange,
59 ParamType,
60 ParamValue,
61 ParameterError,
62
63 ParameterId,
65 ParameterResult,
66 Port,
67
68 PortDirection,
69 PortId,
71 PortType,
72 ProcessError,
73 ProcessResult,
75 Processor,
76 Router,
77 SignalNode,
79 Sink,
80
81 Source,
82 DEFAULT_BLOCK_SIZE,
84 };
85
86 pub use crate::math::Transcendental;
88}
89
90pub trait IntoParamValue: Sized {
96 fn into_param_value(self) -> ParamValue;
98
99 fn from_param_value(value: ParamValue) -> Option<Self>;
101}
102
103impl IntoParamValue for f32 {
104 fn into_param_value(self) -> ParamValue {
105 ParamValue::Float(self)
106 }
107
108 fn from_param_value(value: ParamValue) -> Option<Self> {
109 value.as_f32()
110 }
111}
112
113impl IntoParamValue for i32 {
114 fn into_param_value(self) -> ParamValue {
115 ParamValue::Int(self)
116 }
117
118 fn from_param_value(value: ParamValue) -> Option<Self> {
119 value.as_i32()
120 }
121}
122
123impl IntoParamValue for bool {
124 fn into_param_value(self) -> ParamValue {
125 ParamValue::Bool(self)
126 }
127
128 fn from_param_value(value: ParamValue) -> Option<Self> {
129 value.as_bool()
130 }
131}
132
133impl IntoParamValue for String {
134 fn into_param_value(self) -> ParamValue {
135 ParamValue::String(self)
136 }
137
138 fn from_param_value(value: ParamValue) -> Option<Self> {
139 match value {
140 ParamValue::String(s) => Some(s),
141 ParamValue::Choice(s) => Some(s),
142 _ => None,
143 }
144 }
145}
146
147pub trait AsAny: 'static {
153 fn as_any(&self) -> &dyn std::any::Any;
155
156 fn as_any_mut(&mut self) -> &mut dyn std::any::Any;
158}
159
160impl<T: 'static> AsAny for T {
161 fn as_any(&self) -> &dyn std::any::Any {
162 self
163 }
164
165 fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
166 self
167 }
168}
169
170#[cfg(test)]
175mod tests {
176 use super::prelude::*;
177 use crate::traits::IntoParamValue;
178
179 #[test]
180 fn test_prelude_imports() {
181 let _node_id = NodeId(0);
183 let _port_id = PortId::signal_in(_node_id, 0);
184 let _param_id = ParameterId::new("test").unwrap();
185
186 let f: f32 = 42.0;
188 let pv = f.into_param_value();
189 assert_eq!(pv.as_f32(), Some(42.0));
190
191 let back = f32::from_param_value(pv);
192 assert_eq!(back, Some(42.0));
193 }
194
195 #[test]
196 fn test_param_value_conversions() {
197 let f = ParamValue::Float(42.0);
198 assert_eq!(f.as_f32(), Some(42.0));
199 assert_eq!(f.as_i32(), Some(42));
200 assert_eq!(f.as_bool(), Some(true));
201
202 let i = ParamValue::Int(0);
203 assert_eq!(i.as_f32(), Some(0.0));
204 assert_eq!(i.as_i32(), Some(0));
205 assert_eq!(i.as_bool(), Some(false));
206
207 let b = ParamValue::Bool(true);
208 assert_eq!(b.as_f32(), Some(1.0));
209 assert_eq!(b.as_i32(), Some(1));
210 assert_eq!(b.as_bool(), Some(true));
211 }
212
213 #[test]
214 fn test_parameter_id_validation() {
215 assert!(ParameterId::new("gain").is_ok());
216 assert!(ParameterId::new("cutoff_freq").is_ok());
217 assert!(ParameterId::new("delay_time_2").is_ok());
218
219 assert!(ParameterId::new("").is_err());
220 assert!(ParameterId::new("1gain").is_err());
221 assert!(ParameterId::new("_gain").is_err());
222 assert!(ParameterId::new("gain.value").is_err());
223 }
224
225 #[test]
226 fn test_port_id_creation() {
227 let node = NodeId(42);
228
229 let signal_in = PortId::signal_in(node, 0);
230 assert_eq!(signal_in.node_id(), node);
231 assert_eq!(signal_in.port_type(), PortType::Signal);
232 assert_eq!(signal_in.direction(), PortDirection::Input);
233 assert_eq!(signal_in.index(), 0);
234 assert!(signal_in.is_input());
235 assert!(signal_in.is_signal());
236
237 let clock_out = PortId::clock_out(node, 0);
238 assert_eq!(clock_out.port_type(), PortType::Clock);
239 assert!(clock_out.is_output());
240 assert!(clock_out.is_clock());
241
242 let feedback_in = PortId::feedback_in(node, 0);
243 assert_eq!(feedback_in.port_type(), PortType::Feedback);
244 assert!(feedback_in.is_input());
245 assert!(feedback_in.is_feedback());
246 }
247
248 #[test]
249 fn test_node_metadata() {
250 let metadata = NodeMetadata {
251 name: "TestNode".to_string(),
252 type_name: None,
253 category: NodeCategory::Processor,
254 description: "A test node".to_string(),
255 author: "Rill".to_string(),
256 version: "1.0".to_string(),
257 signal_inputs: 2,
258 signal_outputs: 2,
259 control_inputs: 1,
260 control_outputs: 0,
261 clock_inputs: 1,
262 clock_outputs: 0,
263 feedback_ports: 0,
264 parameters: vec![],
265 };
266
267 assert_eq!(metadata.name, "TestNode");
268 assert_eq!(metadata.category, NodeCategory::Processor);
269 assert_eq!(metadata.signal_inputs, 2);
270 }
271
272 #[test]
273 fn test_param_range() {
274 let range = ParamRange::new().with_min(0.0).with_max(1.0).with_step(0.1);
275
276 assert!(range.contains(0.5));
277 assert!(!range.contains(1.5));
278 assert_eq!(range.clamp(1.5), 1.0);
279 assert_eq!(range.clamp(-0.5), 0.0);
280 }
281
282 #[test]
283 fn test_default_block_size() {
284 assert_eq!(DEFAULT_BLOCK_SIZE, 64);
285 }
286}