use std::error::Error; use std::thread; use std::collections::BTreeMap; use std::sync::{Arc, Mutex}; use crate::Cli; use jack::{ Control, AsyncClient, Client, ClientStatus, ClientOptions, ClosureProcessHandler, NotificationHandler, ProcessScope, ProcessHandler, Frames, Port, PortId, AudioIn, AudioOut, MidiIn, MidiOut, Transport }; pub struct Jack { client: Option, ClosureProcessHandlerControl + Send>> >>, pub transport: Option, audio_ins: BTreeMap>, audio_outs: BTreeMap>, midi_ins: BTreeMap>, midi_outs: BTreeMap>, } impl Jack { pub fn init_from_cli (options: &Cli) -> Result>, Box> { let jack = Self::init(&options.jack_client_name)?; { let jack = jack.clone(); let mut jack = jack.lock().unwrap(); for port in options.jack_audio_ins.iter() { jack.add_audio_in(port)?; } for port in options.jack_audio_outs.iter() { jack.add_audio_out(port)?; } for port in options.jack_midi_ins.iter() { jack.add_midi_in(port)?; } for port in options.jack_midi_outs.iter() { jack.add_midi_out(port)?; } } Ok(jack.clone()) } fn init (name: &str) -> Result>, Box> { let jack = Arc::new(Mutex::new(Self { client: None, transport: None, audio_ins: BTreeMap::new(), audio_outs: BTreeMap::new(), midi_ins: BTreeMap::new(), midi_outs: BTreeMap::new(), })); let (client, status) = Client::new(name, ClientOptions::NO_START_SERVER)?; println!("Client status: {status:?}"); let jack1 = jack.clone(); let mut jack1 = jack1.lock().unwrap(); let jack2 = jack.clone(); jack1.transport = Some(client.transport()); jack1.client = Some(client.activate_async( Box::new(Notifications), ClosureProcessHandler::new(Box::new( move |_client: &Client, _ps: &ProcessScope| -> Control { let jack = jack2.lock().expect("Failed to lock jack mutex"); jack.read_inputs(); jack.write_outputs(); Control::Continue } ) as BoxControl + Send>) )?); Ok(jack) } fn start (&self) { } fn process (&self, _: &Client, ps: &ProcessScope) -> Control { Control::Continue } fn add_audio_in (&mut self, name: &str) -> Result<&mut Self, Box> { let port = self.client .as_ref() .expect("Not initialized.") .as_client() .register_port(name, AudioIn::default())?; self.audio_ins.insert(name.into(), port); Ok(self) } fn add_audio_out (&mut self, name: &str) -> Result<&mut Self, Box> { let port = self.client .as_ref() .expect("Not initialized.") .as_client() .register_port(name, AudioOut::default())?; self.audio_outs.insert(name.into(), port); Ok(self) } fn add_midi_in (&mut self, name: &str) -> Result<&mut Self, Box> { let port = self.client .as_ref() .expect("Not initialized.") .as_client() .register_port(name, MidiIn::default())?; self.midi_ins.insert(name.into(), port); Ok(self) } fn add_midi_out (&mut self, name: &str) -> Result<&mut Self, Box> { let port = self.client .as_ref() .expect("Not initialized.") .as_client() .register_port(name, MidiOut::default())?; self.midi_outs.insert(name.into(), port); Ok(self) } fn read_inputs (&self) { // read input buffers //println!("read"); } fn write_outputs (&self) { // clear output buffers // write output buffers //println!("write"); } } struct Notifications; impl NotificationHandler for Notifications { fn thread_init (&self, _: &Client) { } fn shutdown (&mut self, status: ClientStatus, reason: &str) { } fn freewheel (&mut self, _: &Client, is_enabled: bool) { } fn sample_rate (&mut self, _: &Client, _: Frames) -> Control { Control::Quit } fn client_registration (&mut self, _: &Client, name: &str, is_reg: bool) { } fn port_registration (&mut self, _: &Client, port_id: PortId, is_reg: bool) { } fn port_rename (&mut self, _: &Client, id: PortId, old: &str, new: &str) -> Control { Control::Continue } fn ports_connected (&mut self, _: &Client, id_a: PortId, id_b: PortId, are: bool) { } fn graph_reorder (&mut self, _: &Client) -> Control { Control::Continue } fn xrun (&mut self, _: &Client) -> Control { Control::Continue } }