wip: enabling autoconnecting ports

This commit is contained in:
🪞👃🪞 2025-01-09 20:40:26 +01:00
parent c23f52c87b
commit fe70b57dc1
10 changed files with 375 additions and 424 deletions

View file

@ -15,67 +15,38 @@ pub struct TekCli {
#[arg(short='s', long, default_value_t = true)] sync_follow: bool,
/// Initial tempo in beats per minute
#[arg(short='b', long, default_value = None)] bpm: Option<f64>,
/// Whether to include a transport toolbar (default: true)
#[arg(short='t', long, default_value_t = true)] show_clock: bool,
/// MIDI outs to connect to (multiple instances accepted)
#[arg(short='I', long)] midi_from: Vec<String>,
/// MIDI outs to connect to (multiple instances accepted)
#[arg(short='i', long)] midi_from_re: Vec<String>,
/// MIDI ins to connect to (multiple instances accepted)
#[arg(short='O', long)] midi_to: Vec<String>,
/// MIDI ins to connect to (multiple instances accepted)
#[arg(short='o', long)] midi_to_re: Vec<String>,
/// Audio outs to connect to left input
#[arg(short='l', long)] l_from: Vec<String>,
/// Audio outs to connect to right input
#[arg(short='r', long)] r_from: Vec<String>,
/// Audio ins to connect from left output
#[arg(short='L', long)] l_to: Vec<String>,
/// Audio ins to connect from right output
#[arg(short='R', long)] r_to: Vec<String>,
}
#[derive(Debug, Clone, Subcommand)]
pub enum TekMode {
/// A standalone transport view.
/// A standalone transport clock.
Clock,
/// A MIDI sequencer.
Sequencer {
/// Whether to include a transport toolbar (default: true)
#[arg(short='t', long, default_value_t = true)] show_clock: bool,
/// MIDI outs to connect to (multiple instances accepted)
#[arg(short='i', long)] midi_from: Vec<String>,
/// MIDI ins to connect to (multiple instances accepted)
#[arg(short='o', long)] midi_to: Vec<String>,
},
Sequencer,
/// A MIDI-controlled audio sampler.
Sampler {
/// MIDI outs to connect to (multiple instances accepted)
#[arg(short='i', long)] midi_from: Vec<String>,
/// Audio outs to connect to left input
#[arg(short='l', long)] l_from: Vec<String>,
/// Audio outs to connect to right input
#[arg(short='r', long)] r_from: Vec<String>,
/// Audio ins to connect from left output
#[arg(short='L', long)] l_to: Vec<String>,
/// Audio ins to connect from right output
#[arg(short='R', long)] r_to: Vec<String>,
},
Sampler,
/// Sequencer and sampler together.
Groovebox {
/// Whether to include a transport toolbar (default: true)
#[arg(short='t', long, default_value_t = true)] show_clock: bool,
/// MIDI outs to connect to (multiple instances accepted)
#[arg(short='i', long)] midi_from: Vec<String>,
/// MIDI ins to connect to (multiple instances accepted)
#[arg(short='o', long)] midi_to: Vec<String>,
/// Audio outs to connect to left input
#[arg(short='l', long)] l_from: Vec<String>,
/// Audio outs to connect to right input
#[arg(short='r', long)] r_from: Vec<String>,
/// Audio ins to connect from left output
#[arg(short='L', long)] l_to: Vec<String>,
/// Audio ins to connect from right output
#[arg(short='R', long)] r_to: Vec<String>,
},
Groovebox,
/// Multi-track MIDI sequencer.
Arranger {
/// Whether to include a transport toolbar (default: true)
#[arg(short='t', long, default_value_t = true)] show_clock: bool,
/// MIDI outs to connect to (multiple instances accepted)
#[arg(short='i', long)] midi_from: Vec<String>,
/// MIDI ins to connect to (multiple instances accepted)
#[arg(short='o', long)] midi_to: Vec<String>,
/// Audio outs to connect to left input
#[arg(short='l', long)] l_from: Vec<String>,
/// Audio outs to connect to right input
#[arg(short='r', long)] r_from: Vec<String>,
/// Audio ins to connect from left output
#[arg(short='L', long)] l_to: Vec<String>,
/// Audio ins to connect from right output
#[arg(short='R', long)] r_to: Vec<String>,
/// Number of tracks
#[arg(short = 'x', long, default_value_t = 16)] tracks: usize,
/// Width of tracks
@ -97,6 +68,12 @@ pub fn main () -> Usually<()> {
let name = cli.name.as_ref().map_or("tek", |x|x.as_str());
let jack = JackConnection::new(name)?;
let engine = Tui::new()?;
let mut midi_froms = vec![];
let mut midi_tos = vec![];
for port in cli.midi_from.iter() { midi_froms.push(PortConnection::exact(port.into())) }
for port in cli.midi_from_re.iter() { midi_froms.push(PortConnection::regexp(port.into())) }
for port in cli.midi_to.iter() { midi_tos.push(PortConnection::exact(port.into())) }
for port in cli.midi_to_re.iter() { midi_tos.push(PortConnection::regexp(port.into())) }
Ok(match cli.mode {
TekMode::Clock => engine.run(&jack.activate_with(|jack|Ok(TransportTui {
@ -104,15 +81,11 @@ pub fn main () -> Usually<()> {
jack: jack.clone()
}))?)?,
TekMode::Sequencer {
midi_from, midi_to, ..
} => engine.run(&jack.activate_with(|jack|Ok({
let clock = Clock::from(jack);
let clip = Arc::new(RwLock::new(MidiClip::new(
"Clip", true, 4 * clock.timebase.ppq.get() as usize,
None, Some(ItemColor::random().into())
)));
let player = MidiPlayer::new(&jack, name, Some(&clip), &midi_from, &midi_to)?;
TekMode::Sequencer => engine.run(&jack.activate_with(|jack|Ok({
let length = 384;
let color = Some(ItemColor::random().into());
let clip = Arc::new(RwLock::new(MidiClip::new("Clip", true, length, None, color)));
let player = MidiPlayer::new(&jack, name, Some(&clip), &midi_froms, &midi_tos)?;
Sequencer {
_jack: jack.clone(),
clock: player.clock.clone(),
@ -130,9 +103,7 @@ pub fn main () -> Usually<()> {
}
}))?)?,
TekMode::Sampler {
midi_from, l_from, r_from, l_to, r_to, ..
} => engine.run(&jack.activate_with(|jack|Ok(
TekMode::Sampler => engine.run(&jack.activate_with(|jack|Ok(
SamplerTui {
cursor: (0, 0),
editing: None,
@ -141,53 +112,29 @@ pub fn main () -> Usually<()> {
note_lo: 36.into(),
note_pt: 36.into(),
color: ItemPalette::from(Color::Rgb(64, 128, 32)),
state: Sampler::new(jack, &"sampler",
&midi_from,
&[&l_from, &r_from],
&[&l_to, &r_to],
)?,
state: Sampler::new(jack, &"sampler", &midi_froms, &[&l_from, &r_from], &[&l_to, &r_to])?,
}
))?)?,
TekMode::Groovebox {
midi_from, midi_to, l_from, r_from, l_to, r_to, ..
} => engine.run(&jack.activate_with(|jack|Ok({
let ppq = 96;
let phrase = Arc::new(RwLock::new(MidiClip::new(
"Clip",
true,
4 * ppq,
None,
Some(ItemColor::random().into())
)));
let mut player = MidiPlayer::new(jack, &"sequencer", Some(&phrase),
&midi_from,
&midi_to
)?;
player.play_phrase = Some((Moment::zero(&player.clock.timebase), Some(phrase.clone())));
let sampler = Sampler::new(jack, &"sampler",
&midi_from,
&[&l_from, &r_from],
&[&l_to, &r_to ],
)?;
jack.read().unwrap().client().connect_ports(
&player.midi_outs[0],
&sampler.midi_in
)?;
TekMode::Groovebox => engine.run(&jack.activate_with(|jack|Ok({
let length = 384;
let color = Some(ItemColor::random().into());
let clip = Arc::new(RwLock::new(MidiClip::new("Clip", true, length, None, color)));
let mut player = MidiPlayer::new(jack, &"sequencer", Some(&clip), &midi_froms, &midi_tos)?;
let sampler = Sampler::new(jack, &"sampler", &midi_froms, &[&l_from, &r_from], &[&l_to, &r_to])?;
jack.read().unwrap().client().connect_ports(&player.midi_outs[0].port, &sampler.midi_in.port)?;
let app = Groovebox {
player,
sampler,
_jack: jack.clone(),
pool: PoolModel::from(&phrase),
editor: MidiEditor::from(&phrase),
pool: PoolModel::from(&clip),
editor: MidiEditor::from(&clip),
compact: true,
status: true,
size: Measure::new(),
midi_buf: vec![vec![];65536],
note_buf: vec![],
perf: PerfModel::default(),
_jack: jack.clone(),
};
if let Some(bpm) = cli.bpm {
app.clock().timebase.bpm.set(bpm);
@ -207,14 +154,13 @@ pub fn main () -> Usually<()> {
app
}))?)?,
TekMode::Arranger {
scenes, tracks, track_width, midi_from, midi_to, ..
} => engine.run(&jack.activate_with(|jack|Ok({
let mut app = Arranger::new(jack);
app.tracks_add(tracks, track_width, midi_from.as_slice(), midi_to.as_slice())?;
app.scenes_add(scenes)?;
app
}))?)?,
TekMode::Arranger { scenes, tracks, track_width, .. } =>
engine.run(&jack.activate_with(|jack|Ok({
let mut app = Arranger::new(jack);
app.tracks_add(tracks, track_width, &midi_froms, &midi_tos)?;
app.scenes_add(scenes)?;
app
}))?)?,
_ => todo!()
})