use std::collections::HashMap;
use crate::builtin_types::*;
use crate::parameter::*;
use std::collections::BTreeSet;
use ruffbox_synth::building_blocks::SynthParameterLabel;
use crate::parser::{BuiltIn, EvaluatedExpr, FunctionMap};
use crate::{OutputMode, SampleAndWavematrixSet};
use parking_lot::Mutex;
use std::sync;
pub fn load_part(
_: &FunctionMap,
tail: &mut Vec<EvaluatedExpr>,
_: &sync::Arc<GlobalParameters>,
_: &sync::Arc<Mutex<SampleAndWavematrixSet>>,
_: OutputMode,
) -> Option<EvaluatedExpr> {
let mut tail_drain = tail.drain(..).skip(1);
let mut gens = Vec::new();
let mut proxies = Vec::new();
let name: String = if let Some(EvaluatedExpr::Symbol(s)) = tail_drain.next() {
s
} else {
return None;
};
for c in tail_drain {
match c {
EvaluatedExpr::BuiltIn(BuiltIn::Generator(g)) => gens.push(g),
EvaluatedExpr::BuiltIn(BuiltIn::GeneratorList(mut gl)) => gens.append(&mut gl),
EvaluatedExpr::BuiltIn(BuiltIn::PartProxy(p)) => proxies.push(p),
EvaluatedExpr::BuiltIn(BuiltIn::ProxyList(mut pl)) => proxies.append(&mut pl),
_ => {}
}
}
Some(EvaluatedExpr::BuiltIn(BuiltIn::Command(Command::LoadPart(
(name, Part::Combined(gens, proxies)),
))))
}
pub fn define_midi_callback(
_: &FunctionMap,
tail: &mut Vec<EvaluatedExpr>,
_: &sync::Arc<GlobalParameters>,
_: &sync::Arc<Mutex<SampleAndWavematrixSet>>,
_: OutputMode,
) -> Option<EvaluatedExpr> {
let mut tail_drain = tail.drain(..).skip(1);
let key: u8 = if let Some(EvaluatedExpr::Float(s)) = tail_drain.next() {
s as u8
} else {
return None;
};
if let Some(EvaluatedExpr::BuiltIn(BuiltIn::Command(c))) = tail_drain.next() {
Some(EvaluatedExpr::BuiltIn(BuiltIn::DefineMidiCallback(key, c)))
} else {
None
}
}
#[allow(clippy::unnecessary_unwrap)]
pub fn load_sample_as_wavematrix(
_: &FunctionMap,
tail: &mut Vec<EvaluatedExpr>,
_: &sync::Arc<GlobalParameters>,
_: &sync::Arc<Mutex<SampleAndWavematrixSet>>,
_: OutputMode,
) -> Option<EvaluatedExpr> {
let mut tail_drain = tail.drain(..).skip(1);
let mut key: Option<String> = None;
let mut path: Option<String> = None;
let mut method: Option<String> = Some("zerocrossing_fixed_stretch_inverse".to_string());
let mut matrix_size: Option<(usize, usize)> = None;
let mut start: Option<f32> = Some(0.0);
while let Some(c) = tail_drain.next() {
if let EvaluatedExpr::Keyword(k) = c {
if k.as_str() == "key" {
if let Some(EvaluatedExpr::Symbol(n)) = tail_drain.next() {
key = Some(n);
}
}
if k.as_str() == "start" {
if let Some(EvaluatedExpr::Float(f)) = tail_drain.next() {
start = Some(f);
}
}
if k.as_str() == "path" {
if let Some(EvaluatedExpr::String(s)) = tail_drain.next() {
path = Some(s);
}
}
if k.as_str() == "method" {
if let Some(EvaluatedExpr::Symbol(s)) = tail_drain.next() {
method = Some(s);
}
}
if k.as_str() == "size" {
if let Some(EvaluatedExpr::Float(x)) = tail_drain.next() {
if let Some(EvaluatedExpr::Float(y)) = tail_drain.next() {
matrix_size = Some((x as usize, y as usize));
}
}
}
}
}
if key.is_some() && path.is_some() && matrix_size.is_some() {
Some(EvaluatedExpr::BuiltIn(BuiltIn::Command(
Command::LoadSampleAsWavematrix(
key.unwrap(),
path.unwrap(),
method.unwrap(),
matrix_size.unwrap(),
start.unwrap(),
),
)))
} else {
None
}
}
pub fn freeze_buffer(
_: &FunctionMap,
tail: &mut Vec<EvaluatedExpr>,
_: &sync::Arc<GlobalParameters>,
_: &sync::Arc<Mutex<SampleAndWavematrixSet>>,
_: OutputMode,
) -> Option<EvaluatedExpr> {
let mut tail_drain = tail.drain(..).skip(1);
let mut inbuf: usize = 0;
let mut freezbuf: usize = 0;
while let Some(c) = tail_drain.next() {
match c {
EvaluatedExpr::Keyword(k) => {
if k.as_str() == "in" {
if let Some(EvaluatedExpr::Float(n)) = tail_drain.next() {
if n as usize > 0 {
inbuf = n as usize - 1;
}
}
}
}
EvaluatedExpr::Float(f) => {
if f as usize > 0 {
freezbuf = f as usize - 1;
}
}
_ => {}
}
}
Some(EvaluatedExpr::BuiltIn(BuiltIn::Command(
Command::FreezeBuffer(freezbuf, inbuf),
)))
}
pub fn load_sample(
_: &FunctionMap,
tail: &mut Vec<EvaluatedExpr>,
_: &sync::Arc<GlobalParameters>,
_: &sync::Arc<Mutex<SampleAndWavematrixSet>>,
_: OutputMode,
) -> Option<EvaluatedExpr> {
let mut tail_drain = tail.drain(..).skip(1);
let mut collect_keywords = false;
let mut keywords: Vec<String> = Vec::new();
let mut path: String = "".to_string();
let mut set: String = "".to_string();
while let Some(c) = tail_drain.next() {
if collect_keywords {
if let EvaluatedExpr::Symbol(ref s) = c {
keywords.push(s.to_string());
continue;
} else {
collect_keywords = false;
}
}
if let EvaluatedExpr::Keyword(k) = c {
match k.as_str() {
"keywords" => {
collect_keywords = true;
continue;
}
"set" => {
if let Some(EvaluatedExpr::Symbol(n)) = tail_drain.next() {
set = n.to_string();
}
}
"path" => {
if let Some(EvaluatedExpr::String(n)) = tail_drain.next() {
path = n.to_string();
}
}
_ => println!("{}", k),
}
}
}
Some(EvaluatedExpr::BuiltIn(BuiltIn::Command(
Command::LoadSample((set, keywords, path)),
)))
}
pub fn load_sample_sets(
_: &FunctionMap,
tail: &mut Vec<EvaluatedExpr>,
_: &sync::Arc<GlobalParameters>,
_: &sync::Arc<Mutex<SampleAndWavematrixSet>>,
_: OutputMode,
) -> Option<EvaluatedExpr> {
let mut tail_drain = tail.drain(..).skip(1);
let path = if let EvaluatedExpr::String(n) = tail_drain.next().unwrap() {
n
} else {
"".to_string()
};
Some(EvaluatedExpr::BuiltIn(BuiltIn::Command(
Command::LoadSampleSets(path),
)))
}
pub fn load_sample_set(
_: &FunctionMap,
tail: &mut Vec<EvaluatedExpr>,
_: &sync::Arc<GlobalParameters>,
_: &sync::Arc<Mutex<SampleAndWavematrixSet>>,
_: OutputMode,
) -> Option<EvaluatedExpr> {
let mut tail_drain = tail.drain(..).skip(1);
let path = if let EvaluatedExpr::String(n) = tail_drain.next().unwrap() {
n
} else {
"".to_string()
};
Some(EvaluatedExpr::BuiltIn(BuiltIn::Command(
Command::LoadSampleSet(path),
)))
}
pub fn tmod(
_: &FunctionMap,
tail: &mut Vec<EvaluatedExpr>,
_: &sync::Arc<GlobalParameters>,
_: &sync::Arc<Mutex<SampleAndWavematrixSet>>,
_: OutputMode,
) -> Option<EvaluatedExpr> {
let mut tail_drain = tail.drain(..).skip(1);
Some(EvaluatedExpr::BuiltIn(BuiltIn::Command(Command::Tmod(
match tail_drain.next() {
Some(EvaluatedExpr::BuiltIn(BuiltIn::Parameter(p))) => p,
Some(EvaluatedExpr::Float(f)) => DynVal::with_value(f),
_ => DynVal::with_value(1.0),
},
))))
}
pub fn latency(
_: &FunctionMap,
tail: &mut Vec<EvaluatedExpr>,
_: &sync::Arc<GlobalParameters>,
_: &sync::Arc<Mutex<SampleAndWavematrixSet>>,
_: OutputMode,
) -> Option<EvaluatedExpr> {
let mut tail_drain = tail.drain(..).skip(1);
Some(EvaluatedExpr::BuiltIn(BuiltIn::Command(Command::Latency(
match tail_drain.next() {
Some(EvaluatedExpr::BuiltIn(BuiltIn::Parameter(p))) => p,
Some(EvaluatedExpr::Float(f)) => DynVal::with_value(f),
_ => DynVal::with_value(0.05),
},
))))
}
pub fn bpm(
_: &FunctionMap,
tail: &mut Vec<EvaluatedExpr>,
_: &sync::Arc<GlobalParameters>,
_: &sync::Arc<Mutex<SampleAndWavematrixSet>>,
_: OutputMode,
) -> Option<EvaluatedExpr> {
let mut tail_drain = tail.drain(..).skip(1);
Some(EvaluatedExpr::BuiltIn(BuiltIn::Command(Command::Bpm(
match tail_drain.next() {
Some(EvaluatedExpr::Float(f)) => 60000.0 / f,
_ => 200.0,
},
))))
}
pub fn default_duration(
_: &FunctionMap,
tail: &mut Vec<EvaluatedExpr>,
_: &sync::Arc<GlobalParameters>,
_: &sync::Arc<Mutex<SampleAndWavematrixSet>>,
_: OutputMode,
) -> Option<EvaluatedExpr> {
let mut tail_drain = tail.drain(..).skip(1);
Some(EvaluatedExpr::BuiltIn(BuiltIn::Command(
Command::DefaultDuration(match tail_drain.next() {
Some(EvaluatedExpr::Float(f)) => f,
_ => 200.0,
}),
)))
}
pub fn globres(
_: &FunctionMap,
tail: &mut Vec<EvaluatedExpr>,
_: &sync::Arc<GlobalParameters>,
_: &sync::Arc<Mutex<SampleAndWavematrixSet>>,
_: OutputMode,
) -> Option<EvaluatedExpr> {
let mut tail_drain = tail.drain(..).skip(1);
Some(EvaluatedExpr::BuiltIn(BuiltIn::Command(Command::GlobRes(
match tail_drain.next() {
Some(EvaluatedExpr::Float(f)) => f,
_ => 400000.0,
},
))))
}
pub fn reverb(
_: &FunctionMap,
tail: &mut Vec<EvaluatedExpr>,
_: &sync::Arc<GlobalParameters>,
_: &sync::Arc<Mutex<SampleAndWavematrixSet>>,
_: OutputMode,
) -> Option<EvaluatedExpr> {
let mut tail_drain = tail.drain(..).skip(1);
let mut param_map = HashMap::new();
while let Some(c) = tail_drain.next() {
match c {
EvaluatedExpr::Keyword(k) => match k.as_str() {
"damp" => {
if let Some(EvaluatedExpr::Float(f)) = tail_drain.next() {
param_map.insert(
SynthParameterLabel::ReverbDampening,
ParameterValue::Scalar(DynVal::with_value(f)),
);
}
}
"mix" => {
if let Some(EvaluatedExpr::Float(f)) = tail_drain.next() {
param_map.insert(
SynthParameterLabel::ReverbMix,
ParameterValue::Scalar(DynVal::with_value(f.clamp(0.01, 0.99))),
);
}
}
"roomsize" => {
if let Some(EvaluatedExpr::Float(f)) = tail_drain.next() {
param_map.insert(
SynthParameterLabel::ReverbRoomsize,
ParameterValue::Scalar(DynVal::with_value(f.clamp(0.01, 0.99))),
);
}
}
_ => println!("{}", k),
},
_ => println! {"ignored"},
}
}
Some(EvaluatedExpr::BuiltIn(BuiltIn::Command(
Command::GlobalRuffboxParams(param_map),
)))
}
pub fn delay(
_: &FunctionMap,
tail: &mut Vec<EvaluatedExpr>,
_: &sync::Arc<GlobalParameters>,
_: &sync::Arc<Mutex<SampleAndWavematrixSet>>,
_: OutputMode,
) -> Option<EvaluatedExpr> {
let mut tail_drain = tail.drain(..).skip(1);
let mut param_map = HashMap::new();
while let Some(c) = tail_drain.next() {
match c {
EvaluatedExpr::Keyword(k) => match k.as_str() {
"damp-freq" => match tail_drain.next() {
Some(EvaluatedExpr::Float(f)) => {
param_map.insert(
SynthParameterLabel::DelayDampeningFrequency,
ParameterValue::Scalar(DynVal::with_value(f.clamp(20.0, 18000.0))),
);
}
Some(EvaluatedExpr::BuiltIn(BuiltIn::Parameter(p))) => {
param_map.insert(
SynthParameterLabel::DelayDampeningFrequency,
ParameterValue::Scalar(p),
);
}
Some(EvaluatedExpr::BuiltIn(BuiltIn::Modulator(m))) => {
param_map.insert(SynthParameterLabel::DelayDampeningFrequency, m);
}
_ => {}
},
"feedback" | "fb" => match tail_drain.next() {
Some(EvaluatedExpr::Float(f)) => {
param_map.insert(
SynthParameterLabel::DelayFeedback,
ParameterValue::Scalar(DynVal::with_value(f.clamp(0.01, 0.99))),
);
}
Some(EvaluatedExpr::BuiltIn(BuiltIn::Parameter(p))) => {
param_map.insert(
SynthParameterLabel::DelayFeedback,
ParameterValue::Scalar(p),
);
}
Some(EvaluatedExpr::BuiltIn(BuiltIn::Modulator(m))) => {
param_map.insert(SynthParameterLabel::DelayFeedback, m);
}
_ => {}
},
"mix" => {
if let Some(EvaluatedExpr::Float(f)) = tail_drain.next() {
param_map.insert(
SynthParameterLabel::DelayMix,
ParameterValue::Scalar(DynVal::with_value(f.clamp(0.01, 0.99))),
);
}
}
"time" | "t" => match tail_drain.next() {
Some(EvaluatedExpr::Float(f)) => {
param_map.insert(
SynthParameterLabel::DelayTime,
ParameterValue::Scalar(DynVal::with_value(
(f / 1000.0).clamp(0.01, 1.99),
)),
);
}
Some(EvaluatedExpr::BuiltIn(BuiltIn::Parameter(p))) => {
param_map.insert(SynthParameterLabel::DelayTime, ParameterValue::Scalar(p));
}
Some(EvaluatedExpr::BuiltIn(BuiltIn::Modulator(m))) => {
param_map.insert(SynthParameterLabel::DelayTime, m);
}
_ => {}
},
"rate" | "r" => match tail_drain.next() {
Some(EvaluatedExpr::Float(f)) => {
param_map.insert(
SynthParameterLabel::DelayRate,
ParameterValue::Scalar(DynVal::with_value(
(f / 1000.0).clamp(0.01, 1.99),
)),
);
}
Some(EvaluatedExpr::BuiltIn(BuiltIn::Parameter(p))) => {
param_map.insert(SynthParameterLabel::DelayRate, ParameterValue::Scalar(p));
}
Some(EvaluatedExpr::BuiltIn(BuiltIn::Modulator(m))) => {
param_map.insert(SynthParameterLabel::DelayRate, m);
}
_ => {}
},
_ => println!("{}", k),
},
_ => println! {"ignored"},
}
}
Some(EvaluatedExpr::BuiltIn(BuiltIn::Command(
Command::GlobalRuffboxParams(param_map),
)))
}
pub fn export_dot(
_: &FunctionMap,
tail: &mut Vec<EvaluatedExpr>,
_: &sync::Arc<GlobalParameters>,
_: &sync::Arc<Mutex<SampleAndWavematrixSet>>,
_: OutputMode,
) -> Option<EvaluatedExpr> {
let mut tail_drain = tail.drain(..).skip(1);
let filename = if let Some(EvaluatedExpr::String(s)) = tail_drain.next() {
s
} else {
return None;
};
match tail_drain.next() {
Some(EvaluatedExpr::BuiltIn(BuiltIn::Generator(g))) => Some(EvaluatedExpr::BuiltIn(
BuiltIn::Command(Command::ExportDotStatic((filename, g))),
)),
Some(EvaluatedExpr::Keyword(k)) => {
match k.as_str() {
"part" => {
if let Some(EvaluatedExpr::Symbol(part_name)) = tail_drain.next() {
Some(EvaluatedExpr::BuiltIn(BuiltIn::Command(
Command::ExportDotPart((filename, part_name)),
)))
} else {
None
}
}
"live" => {
let mut id_tags = BTreeSet::new();
while let Some(EvaluatedExpr::Symbol(si)) = tail_drain.next() {
id_tags.insert(si);
}
Some(EvaluatedExpr::BuiltIn(BuiltIn::Command(
Command::ExportDotRunning((filename, id_tags)),
)))
}
_ => None,
}
}
_ => None,
}
}
pub fn once(
_: &FunctionMap,
tail: &mut Vec<EvaluatedExpr>,
_: &sync::Arc<GlobalParameters>,
_: &sync::Arc<Mutex<SampleAndWavematrixSet>>,
_: OutputMode,
) -> Option<EvaluatedExpr> {
let tail_drain = tail.drain(..).skip(1);
let mut sound_events = Vec::new();
let mut control_events = Vec::new();
for c in tail_drain {
match c {
EvaluatedExpr::BuiltIn(BuiltIn::SoundEvent(mut e)) => {
sound_events.push(e.get_static());
}
EvaluatedExpr::BuiltIn(BuiltIn::ControlEvent(c)) => control_events.push(c),
_ => {}
}
}
Some(EvaluatedExpr::BuiltIn(BuiltIn::Command(Command::Once((
sound_events,
control_events,
)))))
}
pub fn step_part(
_: &FunctionMap,
tail: &mut Vec<EvaluatedExpr>,
_: &sync::Arc<GlobalParameters>,
_: &sync::Arc<Mutex<SampleAndWavematrixSet>>,
_: OutputMode,
) -> Option<EvaluatedExpr> {
let mut tail_drain = tail.drain(..).skip(1);
if let Some(EvaluatedExpr::Symbol(s)) = tail_drain.next() {
Some(EvaluatedExpr::BuiltIn(BuiltIn::Command(Command::StepPart(
s,
))))
} else {
None
}
}
pub fn clear(
_: &FunctionMap,
_: &mut Vec<EvaluatedExpr>,
_: &sync::Arc<GlobalParameters>,
_: &sync::Arc<Mutex<SampleAndWavematrixSet>>,
_: OutputMode,
) -> Option<EvaluatedExpr> {
Some(EvaluatedExpr::BuiltIn(BuiltIn::Command(Command::Clear)))
}
pub fn connect_visualizer(
_: &FunctionMap,
_: &mut Vec<EvaluatedExpr>,
_: &sync::Arc<GlobalParameters>,
_: &sync::Arc<Mutex<SampleAndWavematrixSet>>,
_: OutputMode,
) -> Option<EvaluatedExpr> {
Some(EvaluatedExpr::BuiltIn(BuiltIn::Command(
Command::ConnectVisualizer,
)))
}
pub fn start_recording(
_: &FunctionMap,
tail: &mut Vec<EvaluatedExpr>,
_: &sync::Arc<GlobalParameters>,
_: &sync::Arc<Mutex<SampleAndWavematrixSet>>,
_: OutputMode,
) -> Option<EvaluatedExpr> {
let mut tail_drain = tail.drain(..).skip(1);
let prefix = if let Some(EvaluatedExpr::String(s)) = tail_drain.next() {
Some(s)
} else {
None
};
let mut rec_input = false;
while let Some(c) = tail_drain.next() {
if let EvaluatedExpr::Keyword(k) = c {
if k.as_str() == "input" {
if let Some(EvaluatedExpr::Boolean(b)) = tail_drain.next() {
rec_input = b;
}
}
}
}
Some(EvaluatedExpr::BuiltIn(BuiltIn::Command(
Command::StartRecording(prefix, rec_input),
)))
}
pub fn stop_recording(
_: &FunctionMap,
_: &mut Vec<EvaluatedExpr>,
_: &sync::Arc<GlobalParameters>,
_: &sync::Arc<Mutex<SampleAndWavematrixSet>>,
_: OutputMode,
) -> Option<EvaluatedExpr> {
Some(EvaluatedExpr::BuiltIn(BuiltIn::Command(
Command::StopRecording,
)))
}