devalang_core/core/audio/loader/
trigger.rs

1use crate::core::parser::statement::StatementKind;
2use devalang_types::store::VariableTable;
3use devalang_types::{Duration, Value};
4
5pub fn load_trigger(
6    trigger: &Value,
7    duration: &Duration,
8    _effects: &Option<Value>,
9    base_duration: f32,
10    variable_table: VariableTable,
11) -> (String, f32) {
12    let mut trigger_path = String::new();
13    let mut duration_as_secs = 0.0;
14
15    match trigger {
16        Value::String(src) => {
17            trigger_path = src.to_string();
18        }
19        Value::Identifier(src) => {
20            trigger_path = src.to_string();
21        }
22
23        Value::Map(map) => {
24            if let Some(Value::String(src)) = map.get("entity") {
25                trigger_path = format!("devalang://bank/{}", src);
26            } else if let Some(Value::Identifier(src)) = map.get("entity") {
27                trigger_path = format!("devalang://bank/{}", src);
28            } else {
29                eprintln!(
30                    "❌ Trigger map must contain an 'entity' key with a string or identifier value."
31                );
32            }
33        }
34        Value::Sample(src) => {
35            trigger_path = src.to_string();
36        }
37        Value::Statement(stmt) => {
38            if let StatementKind::Trigger {
39                entity,
40                duration: _,
41                effects: _,
42            } = &stmt.kind
43            {
44                trigger_path = entity.clone();
45            } else {
46                eprintln!(
47                    "❌ Trigger statement must be of type 'Trigger', found: {:?}",
48                    stmt.kind
49                );
50            }
51        }
52        _ => {
53            eprintln!(
54                "❌ Invalid trigger type. Expected a string or identifier variable, found: {:?}",
55                trigger
56            );
57        }
58    }
59
60    match duration {
61        Duration::Identifier(duration_identifier) => {
62            if duration_identifier == "auto" {
63                duration_as_secs = base_duration;
64            } else if let Some(Value::Number(num)) = variable_table.get(duration_identifier) {
65                duration_as_secs = *num;
66            } else if let Some(Value::String(num_str)) = variable_table.get(duration_identifier) {
67                duration_as_secs = num_str.parse::<f32>().unwrap_or(base_duration);
68            } else if let Some(Value::Identifier(num_str)) = variable_table.get(duration_identifier)
69            {
70                duration_as_secs = num_str.parse::<f32>().unwrap_or(base_duration);
71            } else {
72                eprintln!("❌ Invalid duration identifier: {}", duration_identifier);
73            }
74        }
75
76        Duration::Number(num) => {
77            duration_as_secs = *num;
78        }
79
80        Duration::Auto => {
81            duration_as_secs = base_duration;
82        }
83
84        Duration::Beat(beat_str) => {
85            let parts: Vec<&str> = beat_str.split('/').collect();
86
87            if parts.len() == 2 {
88                let numerator: f32 = parts[0].parse().unwrap_or(1.0);
89                let denominator: f32 = parts[1].parse().unwrap_or(1.0);
90                duration_as_secs = (numerator / denominator) * base_duration;
91            } else {
92                eprintln!("❌ Invalid beat duration format: {}", beat_str);
93            }
94        }
95    }
96
97    (trigger_path, duration_as_secs)
98}