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