#![feature(portable_simd)]
use std::{fmt::Debug, path::Path};
use heapless::spsc::{Consumer, Producer};
use crate::{
builder::ValidationError,
config::Config,
executor::OutputView,
midi::MidiRuntimeFrontend,
msg::LegatoMsg,
node::Inputs,
params::{ParamError, ParamKey, ParamStoreFrontend},
runtime::{Runtime, RuntimeFrontend},
};
pub mod builder;
pub mod config;
pub mod connection;
pub mod context;
pub mod dsl;
pub mod executor;
pub mod graph;
pub mod harness;
pub mod math;
pub mod midi;
pub mod msg;
pub mod node;
pub mod out;
pub mod params;
pub mod pipes;
pub mod ports;
pub mod registry;
pub mod resources;
pub mod ring;
pub mod runtime;
pub mod sample;
pub mod simd;
pub mod spec;
pub mod nodes;
#[derive(Debug, PartialEq, Clone)]
pub enum LegatoError {
ValidationError(ValidationError),
ParamError(ParamError),
}
pub struct LegatoApp {
runtime: Runtime,
midi_runtime_frontend: Option<MidiRuntimeFrontend>,
consumer: Consumer<'static, LegatoMsg>,
}
impl LegatoApp {
pub fn new(runtime: Runtime, receiver: Consumer<'static, LegatoMsg>) -> Self {
Self {
runtime,
midi_runtime_frontend: None,
consumer: receiver,
}
}
pub fn next_block(&mut self, external_inputs: Option<&Inputs>) -> OutputView<'_> {
if let Some(midi_runtime) = &self.midi_runtime_frontend {
let ctx = self.runtime.get_context_mut();
ctx.clear_midi();
while let Some(msg) = midi_runtime.recv() {
if let Err(e) = ctx.insert_midi_msg(msg) {
eprintln!("{:?}", e);
}
}
}
while let Some(msg) = self.consumer.dequeue() {
self.runtime.handle_msg(msg);
}
self.runtime.next_block(external_inputs)
}
pub fn set_midi_runtime(&mut self, rt: MidiRuntimeFrontend) {
self.midi_runtime_frontend = Some(rt);
}
pub fn get_config(&self) -> Config {
self.runtime.get_config()
}
}
impl Debug for LegatoApp {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("LegatoApp")
.field("runtime", &self.runtime)
.finish()
}
}
pub struct LegatoFrontend {
runtime_frontend: RuntimeFrontend,
param_store_frontend: ParamStoreFrontend,
producer: Producer<'static, LegatoMsg>,
}
impl LegatoFrontend {
pub fn new(
runtime_frontend: RuntimeFrontend,
param_store_frontend: ParamStoreFrontend,
producer: Producer<'static, LegatoMsg>,
) -> Self {
Self {
runtime_frontend,
param_store_frontend,
producer,
}
}
pub fn load_sample(
&mut self,
sampler: &String,
path: &Path,
chans: usize,
sr: u32,
) -> Result<(), sample::AudioSampleError> {
self.runtime_frontend.load_sample(
sampler,
path.to_str().expect("Path not found!"),
chans,
sr,
)
}
pub fn set_param(&mut self, name: &'static str, val: f32) -> Result<(), ParamError> {
if let Ok(key) = self.param_store_frontend.get_key(name) {
return self.param_store_frontend.set_param(key, val);
}
Err(ParamError::ParamNotFound)
}
pub fn get_param_key(&self, param_name: &'static str) -> Result<ParamKey, ParamError> {
self.param_store_frontend.get_key(param_name)
}
pub fn send_msg(&mut self, msg: LegatoMsg) {
let _ = self.producer.enqueue(msg);
}
}