devalang_core/core/audio/loader/
trigger.rs

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