This commit is contained in:
2026-02-03 03:25:31 +01:00
parent 3380e454df
commit 154cac6547
8 changed files with 125 additions and 32 deletions

View File

@@ -810,10 +810,10 @@ impl SequencerState {
self.speed_overrides.clear();
{
let vars = self.variables.lock();
let vars = self.variables.load();
for id in self.audio_state.active_patterns.keys() {
let key = self.key_cache.speed_key(id.bank, id.pattern);
if let Some(v) = vars.get(key).and_then(|v| v.as_float().ok()) {
if let Some(v) = vars.get(key).and_then(|v: &Value| v.as_float().ok()) {
self.speed_overrides.insert((id.bank, id.pattern), v);
}
}
@@ -931,8 +931,8 @@ impl SequencerState {
};
}
let mut vars = self.variables.lock();
let new_tempo = vars.remove("__tempo__").and_then(|v| v.as_float().ok());
let vars = self.variables.load();
let new_tempo = vars.get("__tempo__").and_then(|v: &Value| v.as_float().ok());
let mut chain_transitions = Vec::new();
for id in completed {
@@ -942,12 +942,29 @@ impl SequencerState {
chain_transitions.push((*id, target));
}
}
vars.remove(chain_key);
}
for id in stopped {
let chain_key = self.key_cache.chain_key(id.bank, id.pattern);
vars.remove(chain_key);
// Remove consumed variables (tempo and chain keys)
let needs_removal = new_tempo.is_some()
|| completed.iter().any(|id| {
let chain_key = self.key_cache.chain_key(id.bank, id.pattern);
vars.contains_key(chain_key)
})
|| stopped.iter().any(|id| {
let chain_key = self.key_cache.chain_key(id.bank, id.pattern);
vars.contains_key(chain_key)
});
if needs_removal {
let mut new_vars = (**vars).clone();
new_vars.remove("__tempo__");
for id in completed {
new_vars.remove(self.key_cache.chain_key(id.bank, id.pattern));
}
for id in stopped {
new_vars.remove(self.key_cache.chain_key(id.bank, id.pattern));
}
self.variables.store(Arc::new(new_vars));
}
VariableReads {
@@ -1316,10 +1333,11 @@ fn parse_midi_command(cmd: &str) -> Option<(MidiCommand, Option<f64>)> {
#[cfg(test)]
mod tests {
use super::*;
use arc_swap::ArcSwap;
use parking_lot::Mutex;
fn make_state() -> SequencerState {
let variables: Variables = Arc::new(Mutex::new(HashMap::new()));
let variables: Variables = Arc::new(ArcSwap::from_pointee(HashMap::new()));
let dict: Dictionary = Arc::new(Mutex::new(HashMap::new()));
let rng: Rng = Arc::new(Mutex::new(
<rand::rngs::StdRng as rand::SeedableRng>::seed_from_u64(0),
@@ -1496,11 +1514,12 @@ mod tests {
// Set chain variable
{
let mut vars = state.variables.lock();
let mut vars = (**state.variables.load()).clone();
vars.insert(
"__chain_0_0__".to_string(),
Value::Str(std::sync::Arc::from("0:1"), None),
);
state.variables.store(Arc::new(vars));
}
// Pattern 0 completes iteration AND gets stopped immediately in the same tick.
@@ -1745,11 +1764,12 @@ mod tests {
// Set chain: 0:0 -> 0:1
{
let mut vars = state.variables.lock();
let mut vars = (**state.variables.load()).clone();
vars.insert(
"__chain_0_0__".to_string(),
Value::Str(std::sync::Arc::from("0:1"), None),
);
state.variables.store(Arc::new(vars));
}
// Pattern 0 (length 1) completes iteration at beat=1.0 AND
@@ -1996,8 +2016,9 @@ mod tests {
// Script fires at beat 1.0 (step 0). Set __tempo__ as if the script did.
{
let mut vars = state.variables.lock();
let mut vars = (**state.variables.load()).clone();
vars.insert("__tempo__".to_string(), Value::Float(140.0, None));
state.variables.store(Arc::new(vars));
}
let output = state.tick(tick_at(1.0, true));