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