1use crate::engine::audio::events::AudioEventList;
2use crate::engine::audio::events::SynthDefinition;
3#[cfg(feature = "cli")]
4use crate::engine::audio::midi_native::MidiManager;
5use crate::engine::events::EventRegistry;
6use crate::engine::functions::FunctionRegistry;
7use crate::engine::special_vars::{SpecialVarContext, is_special_var, resolve_special_var};
8#[cfg(feature = "cli")]
9use crate::language::addons::registry::BankRegistry;
10use crate::language::syntax::ast::{Statement, Value};
11
12#[cfg(not(feature = "cli"))]
14#[allow(dead_code)]
15#[derive(Clone)]
16pub struct BankRegistry;
17
18#[cfg(not(feature = "cli"))]
19impl BankRegistry {
20 pub fn new() -> Self {
21 BankRegistry
22 }
23 pub fn list_banks(&self) -> Vec<(String, StubBank)> {
24 Vec::new()
25 }
26 pub fn resolve_trigger(&self, _var: &str, _prop: &str) -> Option<std::path::PathBuf> {
27 None
28 }
29 pub fn register_bank(
30 &self,
31 _alias: String,
32 _name: &str,
33 _cwd: &std::path::Path,
34 _cwd2: &std::path::Path,
35 ) -> Result<(), anyhow::Error> {
36 Ok(())
37 }
38}
39
40#[cfg(not(feature = "cli"))]
41#[allow(dead_code)]
42#[derive(Clone)]
43pub struct StubBank;
44
45#[cfg(not(feature = "cli"))]
46impl StubBank {
47 pub fn list_triggers(&self) -> Vec<String> {
48 Vec::new()
49 }
50}
51use anyhow::Result;
53use std::collections::HashMap;
54
55pub mod collector;
56pub mod extractor;
57pub mod handler;
58pub mod renderer;
59
60pub struct AudioInterpreter {
61 pub sample_rate: u32,
62 pub bpm: f32,
63 pub function_registry: FunctionRegistry,
64 pub events: AudioEventList,
65 pub variables: HashMap<String, Value>,
66 pub groups: HashMap<String, Vec<Statement>>,
67 pub banks: BankRegistry,
68 pub cursor_time: f32,
69 pub special_vars: SpecialVarContext,
70 pub event_registry: EventRegistry,
71 #[cfg(feature = "cli")]
72 pub midi_manager: Option<std::sync::Arc<std::sync::Mutex<MidiManager>>>,
73 current_statement_location: Option<(usize, usize)>, pub suppress_beat_emit: bool,
77}
78
79impl AudioInterpreter {
80 pub fn new(sample_rate: u32) -> Self {
81 Self {
82 sample_rate,
83 bpm: 120.0,
84 function_registry: FunctionRegistry::new(),
85 events: AudioEventList::new(),
86 variables: HashMap::new(),
87 groups: HashMap::new(),
88 banks: BankRegistry::new(),
89 cursor_time: 0.0,
90 special_vars: SpecialVarContext::new(120.0, sample_rate),
91 event_registry: EventRegistry::new(),
92 #[cfg(feature = "cli")]
93 midi_manager: None,
94 current_statement_location: None,
95 suppress_beat_emit: false,
96 }
97 }
98
99 fn handle_trigger(&mut self, entity: &str) -> Result<()> {
101 handler::handle_trigger(self, entity)
103 }
104
105 fn debug_list_banks(&self) {
107 println!("🔍 Available triggers in BankRegistry:");
108 for (bank_name, bank) in self.banks.list_banks() {
109 println!(" Bank: {}", bank_name);
110 for trigger in bank.list_triggers() {
111 println!(" Trigger: {}", trigger);
112 }
113 }
114 }
115
116 pub fn interpret(&mut self, statements: &[Statement]) -> Result<Vec<f32>> {
117 let total_duration = self.calculate_total_duration(statements)?;
119 self.special_vars.total_duration = total_duration;
120 self.special_vars.update_bpm(self.bpm);
121
122 self.collect_events(statements)?;
124
125 self.render_audio()
129 }
130
131 pub fn events(&self) -> &AudioEventList {
133 &self.events
134 }
135
136 pub fn current_statement_location(&self) -> Option<(usize, usize)> {
138 self.current_statement_location
139 }
140
141 pub fn calculate_total_duration(&self, _statements: &[Statement]) -> Result<f32> {
143 Ok(60.0) }
146
147 pub fn collect_events(&mut self, statements: &[Statement]) -> Result<()> {
148 collector::collect_events(self, statements)
150 }
151 pub fn handle_let(&mut self, name: &str, value: &Value) -> Result<()> {
152 handler::handle_let(self, name, value)
153 }
154
155 pub fn extract_audio_event(
156 &mut self,
157 target: &str,
158 context: &crate::engine::functions::FunctionContext,
159 ) -> Result<()> {
160 extractor::extract_audio_event(self, target, context)
162 }
163
164 pub fn render_audio(&self) -> Result<Vec<f32>> {
165 renderer::render_audio(self)
167 }
168
169 pub fn set_bpm(&mut self, bpm: f32) {
170 self.bpm = bpm.max(1.0).min(999.0);
171 }
172
173 pub fn samples_per_beat(&self) -> usize {
174 ((60.0 / self.bpm) * self.sample_rate as f32) as usize
175 }
176
177 pub fn beat_duration(&self) -> f32 {
179 60.0 / self.bpm
180 }
181
182 pub fn execute_print(&self, value: &Value) -> Result<()> {
185 handler::execute_print(self, value)
186 }
187
188 pub fn interpolate_string(&self, template: &str) -> String {
191 let mut result = template.to_string();
192
193 let re = regex::Regex::new(r"\{([a-zA-Z_][a-zA-Z0-9_]*)\}").unwrap();
195
196 for cap in re.captures_iter(template) {
197 let full_match = &cap[0]; let var_name = &cap[1]; if let Some(value) = self.variables.get(var_name) {
201 let replacement = self.value_to_string(value);
202 result = result.replace(full_match, &replacement);
203 } else {
204 result = result.replace(full_match, &format!("<undefined:{}>", var_name));
206 }
207 }
208
209 result
210 }
211
212 fn value_to_string(&self, value: &Value) -> String {
214 match value {
215 Value::String(s) => {
216 s.trim_matches('"').trim_matches('\'').to_string()
218 }
219 Value::Number(n) => {
220 if n.fract() == 0.0 {
222 format!("{:.0}", n)
223 } else {
224 format!("{}", n)
225 }
226 }
227 Value::Boolean(b) => b.to_string(),
228 Value::Array(arr) => {
229 let items: Vec<String> = arr.iter().map(|v| self.value_to_string(v)).collect();
230 format!("[{}]", items.join(", "))
231 }
232 Value::Identifier(id) => id.clone(),
233 _ => format!("{:?}", value),
234 }
235 }
236
237 pub fn execute_if(
239 &mut self,
240 condition: &Value,
241 body: &[Statement],
242 else_body: &Option<Vec<Statement>>,
243 ) -> Result<()> {
244 handler::execute_if(self, condition, body, else_body)
245 }
246
247 pub fn evaluate_condition(&self, condition: &Value) -> Result<bool> {
250 if let Value::Map(map) = condition {
252 let operator = map
253 .get("operator")
254 .and_then(|v| {
255 if let Value::String(s) = v {
256 Some(s.as_str())
257 } else {
258 None
259 }
260 })
261 .unwrap_or("==");
262
263 let left = map
264 .get("left")
265 .ok_or_else(|| anyhow::anyhow!("Missing left operand"))?;
266 let right = map
267 .get("right")
268 .ok_or_else(|| anyhow::anyhow!("Missing right operand"))?;
269
270 let left_val = self.resolve_value(left);
272 let right_val = self.resolve_value(right);
273
274 match operator {
276 "==" => Ok(self.values_equal(&left_val, &right_val)),
277 "!=" => Ok(!self.values_equal(&left_val, &right_val)),
278 "<" => self.compare_values(&left_val, &right_val, std::cmp::Ordering::Less),
279 ">" => self.compare_values(&left_val, &right_val, std::cmp::Ordering::Greater),
280 "<=" => {
281 let less =
282 self.compare_values(&left_val, &right_val, std::cmp::Ordering::Less)?;
283 let equal = self.values_equal(&left_val, &right_val);
284 Ok(less || equal)
285 }
286 ">=" => {
287 let greater =
288 self.compare_values(&left_val, &right_val, std::cmp::Ordering::Greater)?;
289 let equal = self.values_equal(&left_val, &right_val);
290 Ok(greater || equal)
291 }
292 _ => Err(anyhow::anyhow!("Unknown operator: {}", operator)),
293 }
294 } else {
295 match condition {
297 Value::Boolean(b) => Ok(*b),
298 Value::Number(n) => Ok(*n != 0.0),
299 Value::String(s) => Ok(!s.is_empty()),
300 _ => Ok(false),
301 }
302 }
303 }
304
305 pub fn resolve_value(&self, value: &Value) -> Value {
307 match value {
308 Value::Identifier(name) => {
309 if is_special_var(name) {
311 if let Some(special_val) = resolve_special_var(name, &self.special_vars) {
312 return special_val;
313 }
314 }
315
316 self.variables.get(name).cloned().unwrap_or(Value::Null)
318 }
319 _ => value.clone(),
320 }
321 }
322
323 pub fn execute_event_handlers(&mut self, event_name: &str) -> Result<()> {
325 handler::execute_event_handlers(self, event_name)
326 }
327
328 pub fn values_equal(&self, left: &Value, right: &Value) -> bool {
330 match (left, right) {
331 (Value::Number(a), Value::Number(b)) => (a - b).abs() < 0.0001,
332 (Value::String(a), Value::String(b)) => a == b,
333 (Value::Boolean(a), Value::Boolean(b)) => a == b,
334 (Value::Null, Value::Null) => true,
335 _ => false,
336 }
337 }
338
339 pub fn compare_values(
341 &self,
342 left: &Value,
343 right: &Value,
344 ordering: std::cmp::Ordering,
345 ) -> Result<bool> {
346 match (left, right) {
347 (Value::Number(a), Value::Number(b)) => {
348 Ok(a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Equal) == ordering)
349 }
350 (Value::String(a), Value::String(b)) => Ok(a.cmp(b) == ordering),
351 _ => Err(anyhow::anyhow!("Cannot compare {:?} and {:?}", left, right)),
352 }
353 }
354
355 pub fn handle_assign(&mut self, target: &str, property: &str, value: &Value) -> Result<()> {
357 handler::handle_assign(self, target, property, value)
358 }
359
360 pub fn extract_synth_def_from_map(
362 &self,
363 map: &HashMap<String, Value>,
364 ) -> Result<SynthDefinition> {
365 handler::extract_synth_def_from_map(self, map)
366 }
367
368 pub fn handle_load(&mut self, source: &str, alias: &str) -> Result<()> {
370 handler::handle_load(self, source, alias)
371 }
372
373 pub fn handle_bind(&mut self, source: &str, target: &str, options: &Value) -> Result<()> {
375 handler::handle_bind(self, source, target, options)
376 }
377
378 pub fn extract_pattern_data(
380 &self,
381 value: &Value,
382 ) -> (Option<String>, Option<HashMap<String, f32>>) {
383 handler::extract_pattern_data(self, value)
384 }
385
386 pub fn execute_pattern(
388 &mut self,
389 target: &str,
390 pattern: &str,
391 options: Option<HashMap<String, f32>>,
392 ) -> Result<()> {
393 handler::execute_pattern(self, target, pattern, options)
394 }
395
396 pub fn resolve_sample_uri(&self, target: &str) -> String {
398 handler::resolve_sample_uri(self, target)
399 }
400}