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