implement ConnectPort

This commit is contained in:
🪞👃🪞 2025-01-09 18:48:39 +01:00
parent 0cca06e054
commit 9e4406c66a
4 changed files with 77 additions and 64 deletions

View file

@ -82,6 +82,67 @@ impl RegisterPort for Arc<RwLock<JackConnection>> {
}
}
pub trait ConnectPort {
fn port_by_name (&self, name: impl AsRef<str>) -> Option<Port<Unowned>>;
fn connect_ports <A: PortSpec, B: PortSpec> (&self, source: &Port<A>, target: &Port<B>)
-> Usually<()>;
fn connect_midi_from (&self, input: &Port<MidiIn>, ports: &[impl AsRef<str>]) -> 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<MidiOut>, ports: &[impl AsRef<str>]) -> 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<AudioIn>, ports: &[impl AsRef<str>]) -> 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<AudioOut>, ports: &[impl AsRef<str>]) -> 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<RwLock<JackConnection>> {
fn port_by_name (&self, name: impl AsRef<str>) -> Option<Port<Unowned>> {
self.read().unwrap().client().port_by_name(name.as_ref())
}
fn connect_ports <A: PortSpec, B: PortSpec> (&self, source: &Port<A>, target: &Port<B>)
-> 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 {

View file

@ -49,15 +49,19 @@ impl MidiPlayer {
pub fn new (
jack: &Arc<RwLock<JackConnection>>,
name: impl AsRef<str>,
clip: Option<&Arc<RwLock<MidiClip>>>,
midi_from: &[impl AsRef<str>],
midi_to: &[impl AsRef<str>],
) -> Usually<Self> {
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<TuiOut> {

View file

@ -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<MidiIn>, 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<MidiOut>, 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<AudioIn>, 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<AudioOut>, 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();

View file

@ -10,7 +10,7 @@ use MidiEditCommand::*;
use MidiPoolCommand::*;
pub struct Groovebox {
_jack: Arc<RwLock<JackConnection>>,
pub _jack: Arc<RwLock<JackConnection>>,
pub player: MidiPlayer,
pub pool: PoolModel,
pub editor: MidiEditor,