From 9e4406c66af5098d09b1b7418532ba1093225eae Mon Sep 17 00:00:00 2001 From: unspeaker Date: Thu, 9 Jan 2025 18:48:39 +0100 Subject: [PATCH] implement ConnectPort --- jack/src/jack_port.rs | 61 +++++++++++++++++++++++++++++++++++++ midi/src/midi_player.rs | 11 +++++-- src/main.rs | 67 +++++------------------------------------ tek/src/groovebox.rs | 2 +- 4 files changed, 77 insertions(+), 64 deletions(-) diff --git a/jack/src/jack_port.rs b/jack/src/jack_port.rs index 650458a5..31839b93 100644 --- a/jack/src/jack_port.rs +++ b/jack/src/jack_port.rs @@ -82,6 +82,67 @@ impl RegisterPort for Arc> { } } +pub trait ConnectPort { + fn port_by_name (&self, name: impl AsRef) -> Option>; + fn connect_ports (&self, source: &Port, target: &Port) + -> Usually<()>; + fn connect_midi_from (&self, input: &Port, ports: &[impl AsRef]) -> Usually<()> { + for port in ports.iter() { + let port = port.as_ref(); + if let Some(port) = self.port_by_name(port).as_ref() { + self.connect_ports(port, input)?; + } else { + panic!("Missing MIDI output: {port}. Use jack_lsp to list all port names."); + } + } + Ok(()) + } + fn connect_midi_to (&self, output: &Port, ports: &[impl AsRef]) -> Usually<()> { + for port in ports.iter() { + let port = port.as_ref(); + if let Some(port) = self.port_by_name(port).as_ref() { + self.connect_ports(output, port)?; + } else { + panic!("Missing MIDI input: {port}. Use jack_lsp to list all port names."); + } + } + Ok(()) + } + fn connect_audio_from (&self, input: &Port, ports: &[impl AsRef]) -> Usually<()> { + for port in ports.iter() { + let port = port.as_ref(); + if let Some(port) = self.port_by_name(port).as_ref() { + self.connect_ports(port, input)?; + } else { + panic!("Missing MIDI output: {port}. Use jack_lsp to list all port names."); + } + } + Ok(()) + } + fn connect_audio_to (&self, output: &Port, ports: &[impl AsRef]) -> Usually<()> { + for port in ports.iter() { + let port = port.as_ref(); + if let Some(port) = self.port_by_name(port).as_ref() { + self.connect_ports(output, port)?; + } else { + panic!("Missing MIDI input: {port}. Use jack_lsp to list all port names."); + } + } + Ok(()) + } +} + +impl ConnectPort for Arc> { + fn port_by_name (&self, name: impl AsRef) -> Option> { + self.read().unwrap().client().port_by_name(name.as_ref()) + } + fn connect_ports (&self, source: &Port, target: &Port) + -> Usually<()> + { + Ok(self.read().unwrap().client().connect_ports(source, target)?) + } +} + ///// Collection of JACK ports as [AudioIn]/[AudioOut]/[MidiIn]/[MidiOut]. //#[derive(Default, Debug)] //pub struct JackPorts { diff --git a/midi/src/midi_player.rs b/midi/src/midi_player.rs index 0260d50a..43789a54 100644 --- a/midi/src/midi_player.rs +++ b/midi/src/midi_player.rs @@ -49,15 +49,19 @@ impl MidiPlayer { pub fn new ( jack: &Arc>, name: impl AsRef, + clip: Option<&Arc>>, midi_from: &[impl AsRef], midi_to: &[impl AsRef], ) -> Usually { let name = name.as_ref(); let midi_in = jack.midi_in(&format!("M/{name}"), midi_from)?; + jack.connect_midi_from(&midi_in, midi_from)?; let midi_out = jack.midi_out(&format!("{name}/M"), midi_to)?; + jack.connect_midi_to(&midi_out, midi_to)?; + let clock = Clock::from(jack); Ok(Self { - clock: Clock::from(jack), - play_phrase: None, + play_phrase: Some((Moment::zero(&clock.timebase), clip.cloned())), + next_phrase: None, recording: false, monitoring: false, @@ -67,9 +71,10 @@ impl MidiPlayer { midi_ins: vec![midi_in], midi_outs: vec![midi_out], notes_out: RwLock::new([false;128]).into(), + note_buf: vec![0;8], reset: true, - note_buf: vec![0;8], + clock, }) } pub fn play_status (&self) -> impl Content { diff --git a/src/main.rs b/src/main.rs index b9b3f635..b216307b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -105,23 +105,20 @@ pub fn main () -> Usually<()> { }))?)?, TekMode::Sequencer { - midi_from, - midi_to, .. + midi_from, midi_to, .. } => engine.run(&jack.activate_with(|jack|Ok({ let clock = Clock::from(jack); - let phrase = Arc::new(RwLock::new(MidiClip::new( + let clip = Arc::new(RwLock::new(MidiClip::new( "Clip", true, 4 * clock.timebase.ppq.get() as usize, None, Some(ItemColor::random().into()) ))); - let midi_in = jack.read().unwrap().register_port("i", MidiIn::default())?; - connect_from(jack, &midi_in, &midi_from)?; - let midi_out = jack.read().unwrap().register_port("o", MidiOut::default())?; - connect_to(jack, &midi_out, &midi_to)?; + let player = MidiPlayer::new(&jack, name, Some(&clip), &midi_from, &midi_to)?; Sequencer { _jack: jack.clone(), - pool: PoolModel::from(&phrase), - editor: MidiEditor::from(&phrase), - player: MidiPlayer::new(&clock, &phrase, &[midi_in], &[midi_out])?, + clock: player.clock.clone(), + player, + editor: MidiEditor::from(&clip), + pool: PoolModel::from(&clip), compact: true, transport: true, selectors: true, @@ -130,7 +127,6 @@ pub fn main () -> Usually<()> { note_buf: vec![], perf: PerfModel::default(), status: true, - clock, } }))?)?, @@ -224,55 +220,6 @@ pub fn main () -> Usually<()> { }) } -#[allow(unused)] -fn connect_from (jack: &JackConnection, input: &Port, ports: &[String]) -> Usually<()> { - for port in ports.iter() { - if let Some(port) = jack.port_by_name(port).as_ref() { - jack.client().connect_ports(port, input)?; - } else { - panic!("Missing MIDI output: {port}. Use jack_lsp to list all port names."); - } - } - Ok(()) -} - -#[allow(unused)] -fn connect_to (jack: &JackConnection, output: &Port, ports: &[String]) -> Usually<()> { - for port in ports.iter() { - if let Some(port) = jack.port_by_name(port).as_ref() { - jack.client().connect_ports(output, port)?; - } else { - panic!("Missing MIDI input: {port}. Use jack_lsp to list all port names."); - } - } - Ok(()) -} - -#[allow(unused)] -fn connect_audio_from (jack: &JackConnection, input: &Port, ports: &[String]) -> Usually<()> { - for port in ports.iter() { - if let Some(port) = jack.port_by_name(port).as_ref() { - jack.client().connect_ports(port, input)?; - } else { - panic!("Missing MIDI output: {port}. Use jack_lsp to list all port names."); - } - } - Ok(()) -} - -#[allow(unused)] -fn connect_audio_to (jack: &JackConnection, output: &Port, ports: &[String]) -> Usually<()> { - for port in ports.iter() { - if let Some(port) = jack.port_by_name(port).as_ref() { - jack.client().connect_ports(output, port)?; - } else { - panic!("Missing MIDI input: {port}. Use jack_lsp to list all port names."); - } - } - Ok(()) -} - - #[test] fn verify_cli () { use clap::CommandFactory; TekCli::command().debug_assert(); diff --git a/tek/src/groovebox.rs b/tek/src/groovebox.rs index 026ea606..1f686372 100644 --- a/tek/src/groovebox.rs +++ b/tek/src/groovebox.rs @@ -10,7 +10,7 @@ use MidiEditCommand::*; use MidiPoolCommand::*; pub struct Groovebox { - _jack: Arc>, + pub _jack: Arc>, pub player: MidiPlayer, pub pool: PoolModel, pub editor: MidiEditor,