rill_patchbay/
servo_constructor.rs1use std::sync::Arc;
4
5use rill_core::queues::CommandEnum;
6use rill_core_actor::{ActorRef, ActorSystem};
7
8use crate::automaton::envelope::EnvelopeAutomaton;
9use crate::automaton::lfo::LfoAutomaton;
10use crate::automaton::sequencer::{SequencerAutomaton, Step};
11use crate::engine::Servo;
12use crate::module_def::{AutomatonDef, ModuleDef};
13use crate::module_factory::{ModuleConstructor, ModuleError};
14
15#[cfg(feature = "debug")]
16use crate::debug::PatchbayInspector;
17
18pub struct ServoConstructor;
20
21impl ModuleConstructor for ServoConstructor {
22 fn type_name(&self) -> &'static str {
23 "servo"
24 }
25
26 fn construct(
27 &self,
28 module: &ModuleDef,
29 automaton_defs: &[AutomatonDef],
30 system: &Arc<ActorSystem>,
31 graph_ref: &ActorRef<CommandEnum>,
32 #[cfg(feature = "debug")] inspector: Option<&PatchbayInspector>,
33 ) -> Result<ActorRef<CommandEnum>, ModuleError> {
34 let ModuleDef::Servo(s) = module else {
35 return Err(ModuleError::ConstructionFailed(
36 "ServoConstructor requires ModuleDef::Servo".into(),
37 ));
38 };
39
40 let def = automaton_defs
41 .iter()
42 .find(|a| a.id() == s.automaton_id)
43 .ok_or_else(|| {
44 ModuleError::ConstructionFailed(format!(
45 "servo '{}' references unknown automaton '{}'",
46 s.automaton_id, s.automaton_id
47 ))
48 })?;
49
50 let nid = s.target_node;
51 let mapping = s.mapping.to_parameter_mapping();
52
53 let actor_ref = match def {
54 AutomatonDef::Lfo {
55 id,
56 frequency,
57 amplitude,
58 offset,
59 waveform,
60 } => {
61 let a = LfoAutomaton::new(id, *frequency, *amplitude, *offset, *waveform);
62 let mut servo = Servo::new(
63 id,
64 a,
65 nid,
66 &s.target_param,
67 mapping,
68 s.min,
69 s.max,
70 system.clone(),
71 graph_ref.clone(),
72 );
73 if let Some(ref t) = s.table {
74 servo = servo.with_table(t.clone());
75 }
76 if let Some(ref cs) = s.control_strategy {
77 servo = servo.with_control(*cs);
78 }
79 if let Some(ref cf) = s.conflict_strategy {
80 servo = servo.with_conflict(*cf);
81 }
82 if let Some(ref anchor) = s.target_anchor {
83 servo = servo.with_anchor(anchor.clone());
84 }
85 #[cfg(feature = "debug")]
86 if let Some(inspector) = inspector {
87 let automaton_inspector = servo.inspector();
88 inspector
89 .register_automaton(module.type_name().to_string(), automaton_inspector);
90 }
91 servo.spawn(system)
92 }
93 AutomatonDef::Envelope {
94 id,
95 attack,
96 decay,
97 sustain,
98 release,
99 curve,
100 ..
101 } => {
102 let a = EnvelopeAutomaton::adsr(id, *attack, *decay, *sustain, *release)
103 .with_curve(*curve);
104 let mut servo = Servo::new(
105 id,
106 a,
107 nid,
108 &s.target_param,
109 mapping,
110 s.min,
111 s.max,
112 system.clone(),
113 graph_ref.clone(),
114 );
115 if let Some(ref cs) = s.control_strategy {
116 servo = servo.with_control(*cs);
117 }
118 if let Some(ref cf) = s.conflict_strategy {
119 servo = servo.with_conflict(*cf);
120 }
121 if let Some(ref anchor) = s.target_anchor {
122 servo = servo.with_anchor(anchor.clone());
123 }
124 #[cfg(feature = "debug")]
125 if let Some(inspector) = inspector {
126 let automaton_inspector = servo.inspector();
127 inspector
128 .register_automaton(module.type_name().to_string(), automaton_inspector);
129 }
130 servo.spawn(system)
131 }
132 AutomatonDef::Sequencer {
133 id,
134 steps,
135 play_mode,
136 tempo,
137 } => {
138 let seq_steps: Vec<Step> = steps
139 .iter()
140 .map(|sd| Step {
141 duration: sd.duration,
142 })
143 .collect();
144 let a = SequencerAutomaton::new(id, seq_steps)
145 .with_mode(*play_mode)
146 .with_tempo(*tempo);
147 let mut servo = Servo::new(
148 id,
149 a,
150 nid,
151 &s.target_param,
152 mapping,
153 s.min,
154 s.max,
155 system.clone(),
156 graph_ref.clone(),
157 );
158 if let Some(ref t) = s.table {
159 servo = servo.with_table(t.clone());
160 }
161 if let Some(ref cs) = s.control_strategy {
162 servo = servo.with_control(*cs);
163 }
164 if let Some(ref cf) = s.conflict_strategy {
165 servo = servo.with_conflict(*cf);
166 }
167 if let Some(ref anchor) = s.target_anchor {
168 servo = servo.with_anchor(anchor.clone());
169 }
170 #[cfg(feature = "debug")]
171 if let Some(inspector) = inspector {
172 let automaton_inspector = servo.inspector();
173 inspector
174 .register_automaton(module.type_name().to_string(), automaton_inspector);
175 }
176 servo.spawn(system)
177 }
178 AutomatonDef::NamedFunction { id, .. } => {
179 return Err(ModuleError::ConstructionFailed(format!(
180 "NamedFunction automaton '{}' requires manual setup",
181 id
182 )));
183 }
184 AutomatonDef::Custom { id, type_name, .. } => {
185 return Err(ModuleError::ConstructionFailed(format!(
186 "Custom automaton '{}' (type '{}') not yet supported via ServoConstructor",
187 id, type_name,
188 )));
189 }
190 };
191
192 Ok(actor_ref)
193 }
194
195 fn clone_box(&self) -> Box<dyn ModuleConstructor> {
196 Box::new(ServoConstructor)
197 }
198}