use crate::*; use tek_core::edn; /// A sequencer track. #[derive(Debug)] pub struct Track { pub name: String, /// Inputs and outputs of 1st and last device pub ports: JackPorts, /// Device chain pub devices: Vec>, /// Device selector pub device: usize, } impl Track { pub fn new (name: &str) -> Usually { Ok(Self { name: name.to_string(), ports: JackPorts::default(), devices: vec![], device: 0, }) } fn get_device_mut (&self, i: usize) -> Option>>> { self.devices.get(i).map(|d|d.state.write().unwrap()) } pub fn device_mut (&self) -> Option>>> { self.get_device_mut(self.device) } /// Add a device to the end of the chain. pub fn append_device (&mut self, device: JackDevice) -> Usually<&mut JackDevice> { self.devices.push(device); let index = self.devices.len() - 1; Ok(&mut self.devices[index]) } //pub fn connect_first_device (&self) -> Usually<()> { //if let (Some(port), Some(device)) = (&self.midi_out, self.devices.get(0)) { //device.client.as_client().connect_ports(&port, &device.midi_ins()?[0])?; //} //Ok(()) //} //pub fn connect_last_device (&self, app: &Track) -> Usually<()> { //Ok(match self.devices.get(self.devices.len().saturating_sub(1)) { //Some(device) => { //app.audio_out(0).map(|left|device.connect_audio_out(0, &left)).transpose()?; //app.audio_out(1).map(|right|device.connect_audio_out(1, &right)).transpose()?; //() //}, //None => () //}) //} } impl Track { pub fn from_edn <'a, 'e> (args: &[Edn<'e>]) -> Usually> { let mut _gain = 0.0f64; let mut track = Self::new("")?; #[allow(unused_mut)] let mut devices: Vec> = vec![]; edn!(edn in args { Edn::Map(map) => { if let Some(Edn::Str(n)) = map.get(&Edn::Key(SYM_NAME)) { track.name = n.to_string(); } if let Some(Edn::Double(g)) = map.get(&Edn::Key(SYM_GAIN)) { _gain = f64::from(*g); } }, Edn::List(args) => match args.get(0) { // Add a sampler device to the track Some(Edn::Symbol(SYM_SAMPLER)) => { devices.push(Sampler::from_edn(&args[1..])?); panic!( "unsupported in track {}: {:?}; tek_mixer not compiled with feature \"sampler\"", &track.name, args.get(0).unwrap() ) }, // Add a LV2 plugin to the track. Some(Edn::Symbol(SYM_LV2)) => { devices.push(LV2Plugin::from_edn(&args[1..])?); panic!( "unsupported in track {}: {:?}; tek_mixer not compiled with feature \"plugin\"", &track.name, args.get(0).unwrap() ) }, None => panic!("empty list track {}", &track.name), _ => panic!("unexpected in track {}: {:?}", &track.name, args.get(0).unwrap()) }, _ => {} }); for device in devices { track.add_device(device); } Ok(track) } pub fn add_device (&mut self, device: JackDevice) { self.devices.push(device); } } const SYM_NAME: &'static str = ":name"; const SYM_GAIN: &'static str = ":gain"; const SYM_SAMPLER: &'static str = "sampler"; const SYM_LV2: &'static str = "lv2";