mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 11:46:41 +01:00
implement midi autoconnect for arranger
This commit is contained in:
parent
f1847b62b8
commit
512e466af1
3 changed files with 107 additions and 13 deletions
22
Justfile
22
Justfile
|
|
@ -31,9 +31,31 @@ transport-release:
|
|||
arranger:
|
||||
reset
|
||||
cargo run --bin tek_arranger
|
||||
arranger-ext:
|
||||
reset
|
||||
cargo run --bin tek_arranger -- -n tek \
|
||||
-i "1=Midi-Bridge:nanoKEY Studio 2:(capture_0) nanoKEY Studio nanoKEY Studio _" \
|
||||
-o "1=Midi-Bridge:Komplete Audio 6 1:(playback_0) Komplete Audio 6 MIDI 1" \
|
||||
-i "2=Midi-Bridge:nanoKEY Studio 2:(capture_0) nanoKEY Studio nanoKEY Studio _" \
|
||||
-o "2=Midi-Bridge:Komplete Audio 6 1:(playback_0) Komplete Audio 6 MIDI 1" \
|
||||
-i "3=Midi-Bridge:nanoKEY Studio 2:(capture_0) nanoKEY Studio nanoKEY Studio _" \
|
||||
-o "3=Midi-Bridge:Komplete Audio 6 1:(playback_0) Komplete Audio 6 MIDI 1" \
|
||||
-i "4=Midi-Bridge:nanoKEY Studio 2:(capture_0) nanoKEY Studio nanoKEY Studio _" \
|
||||
-o "4=Midi-Bridge:Komplete Audio 6 1:(playback_0) Komplete Audio 6 MIDI 1"
|
||||
arranger-release:
|
||||
reset
|
||||
cargo run --release --bin tek_arranger
|
||||
arranger-release-ext:
|
||||
reset
|
||||
cargo run --release --bin tek_arranger -- -n tek \
|
||||
-i "1=Midi-Bridge:nanoKEY Studio 2:(capture_0) nanoKEY Studio nanoKEY Studio _" \
|
||||
-o "1=Midi-Bridge:Komplete Audio 6 1:(playback_0) Komplete Audio 6 MIDI 1" \
|
||||
-i "2=Midi-Bridge:nanoKEY Studio 2:(capture_0) nanoKEY Studio nanoKEY Studio _" \
|
||||
-o "2=Midi-Bridge:Komplete Audio 6 1:(playback_0) Komplete Audio 6 MIDI 1" \
|
||||
-i "3=Midi-Bridge:nanoKEY Studio 2:(capture_0) nanoKEY Studio nanoKEY Studio _" \
|
||||
-o "3=Midi-Bridge:Komplete Audio 6 1:(playback_0) Komplete Audio 6 MIDI 1" \
|
||||
-i "4=Midi-Bridge:nanoKEY Studio 2:(capture_0) nanoKEY Studio nanoKEY Studio _" \
|
||||
-o "4=Midi-Bridge:Komplete Audio 6 1:(playback_0) Komplete Audio 6 MIDI 1"
|
||||
|
||||
groovebox:
|
||||
reset
|
||||
|
|
|
|||
|
|
@ -4,22 +4,33 @@ pub fn main () -> Usually<()> {
|
|||
ArrangerCli::parse().run()
|
||||
}
|
||||
|
||||
/// Parses CLI arguments to the `tek_arranger` invocation.
|
||||
/// Launches an interactive MIDI arranger.
|
||||
#[derive(Debug, Parser)]
|
||||
#[command(version, about, long_about = None)]
|
||||
pub struct ArrangerCli {
|
||||
/// Name of JACK client
|
||||
#[arg(short, long)]
|
||||
name: Option<String>,
|
||||
name: Option<String>,
|
||||
|
||||
/// Whether to include a transport toolbar (default: true)
|
||||
#[arg(short, long, default_value_t = true)]
|
||||
transport: bool,
|
||||
|
||||
/// Number of tracks
|
||||
#[arg(short = 'x', long, default_value_t = 4)]
|
||||
tracks: usize,
|
||||
tracks: usize,
|
||||
|
||||
/// Number of scenes
|
||||
#[arg(short, long, default_value_t = 8)]
|
||||
scenes: usize,
|
||||
scenes: usize,
|
||||
|
||||
/// MIDI outs to connect each track to.
|
||||
#[arg(short='i', long)]
|
||||
midi_from: Vec<String>,
|
||||
|
||||
/// MIDI ins to connect each track to.
|
||||
#[arg(short='o', long)]
|
||||
midi_to: Vec<String>,
|
||||
}
|
||||
|
||||
impl ArrangerCli {
|
||||
|
|
@ -31,8 +42,9 @@ impl ArrangerCli {
|
|||
}
|
||||
Tui::run(JackClient::new(client_name.as_str())?.activate_with(|jack|{
|
||||
let mut app = ArrangerTui::try_from(jack)?;
|
||||
let jack = jack.read().unwrap();
|
||||
app.color = ItemPalette::random();
|
||||
add_tracks(&mut app, self.tracks)?;
|
||||
add_tracks(&jack, &mut app, &self)?;
|
||||
add_scenes(&mut app, self.scenes)?;
|
||||
Ok(app)
|
||||
})?)?;
|
||||
|
|
@ -40,7 +52,8 @@ impl ArrangerCli {
|
|||
}
|
||||
}
|
||||
|
||||
fn add_tracks (app: &mut ArrangerTui, n: usize) -> Usually<()> {
|
||||
fn add_tracks (jack: &JackClient, app: &mut ArrangerTui, cli: &ArrangerCli) -> Usually<()> {
|
||||
let n = cli.tracks;
|
||||
let track_color_1 = ItemColor::random();
|
||||
let track_color_2 = ItemColor::random();
|
||||
for i in 0..n {
|
||||
|
|
@ -48,6 +61,60 @@ fn add_tracks (app: &mut ArrangerTui, n: usize) -> Usually<()> {
|
|||
track_color_1.mix(track_color_2, i as f32 / n as f32).into()
|
||||
))?;
|
||||
track.width = 8;
|
||||
let name = track.name.read().unwrap();
|
||||
track.player.midi_ins.push(
|
||||
jack.register_port(&format!("{}I", &name), MidiIn::default())?
|
||||
);
|
||||
track.player.midi_outs.push(
|
||||
jack.register_port(&format!("{}O", &name), MidiOut::default())?
|
||||
);
|
||||
}
|
||||
for connection in cli.midi_from.iter() {
|
||||
let mut split = connection.split("=");
|
||||
let number = split.next().unwrap().trim();
|
||||
if let Ok(track) = number.parse::<usize>() {
|
||||
if track < 1 {
|
||||
panic!("Tracks are zero-indexed")
|
||||
}
|
||||
if track > n {
|
||||
panic!("Tried to connect track {track} or {n}. Pass -t {track} to increase number of tracks.")
|
||||
}
|
||||
if let Some(port) = split.next() {
|
||||
if let Some(port) = jack.port_by_name(&port) {
|
||||
jack.client().connect_ports(&port, &app.tracks[track-1].player.midi_ins[0])?;
|
||||
//jack.client().connect_ports(&port, &app.tracks[track].player.midi_ins[0])?;
|
||||
} else {
|
||||
panic!("Missing MIDI output: {port}. Use jack_lsp to list all port names.");
|
||||
}
|
||||
} else {
|
||||
panic!("No port specified for track {track}. Format is TRACK_NUMBER=PORT_NAME")
|
||||
}
|
||||
} else {
|
||||
panic!("Failed to parse track number: {number}")
|
||||
}
|
||||
}
|
||||
for connection in cli.midi_to.iter() {
|
||||
let mut split = connection.split("=");
|
||||
let number = split.next().unwrap().trim();
|
||||
if let Ok(track) = number.parse::<usize>() {
|
||||
if track < 1 {
|
||||
panic!("Tracks are zero-indexed")
|
||||
}
|
||||
if track > n {
|
||||
panic!("Tried to connect track {track} or {n}. Pass -t {track} to increase number of tracks.")
|
||||
}
|
||||
if let Some(port) = split.next() {
|
||||
if let Some(port) = jack.port_by_name(&port) {
|
||||
jack.client().connect_ports(&app.tracks[track-1].player.midi_outs[0], &port)?;
|
||||
} else {
|
||||
panic!("Missing MIDI input: {port}. Use jack_lsp to list all port names.");
|
||||
}
|
||||
} else {
|
||||
panic!("No port specified for track {track}. Format is TRACK_NUMBER=PORT_NAME")
|
||||
}
|
||||
} else {
|
||||
panic!("Failed to parse track number: {number}")
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,24 +4,29 @@ pub fn main () -> Usually<()> {
|
|||
SequencerCli::parse().run()
|
||||
}
|
||||
|
||||
/// Launches a single interactive MIDI sequencer.
|
||||
#[derive(Debug, Parser)]
|
||||
#[command(version, about, long_about = None)]
|
||||
pub struct SequencerCli {
|
||||
/// Name of JACK client
|
||||
#[arg(short, long)]
|
||||
name: Option<String>,
|
||||
|
||||
/// Whether to include a transport toolbar (default: true)
|
||||
#[arg(short, long, default_value_t = true)]
|
||||
transport: 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>,
|
||||
|
||||
/// Default phrase duration (in pulses; default: 4 * PPQ = 1 bar)
|
||||
#[arg(short, long)]
|
||||
length: Option<usize>,
|
||||
/// Whether to include a transport toolbar (default: true)
|
||||
#[arg(short, long, default_value_t = true)]
|
||||
transport: bool
|
||||
}
|
||||
|
||||
impl SequencerCli {
|
||||
|
|
@ -30,8 +35,8 @@ impl SequencerCli {
|
|||
Tui::run(JackClient::new(name)?.activate_with(|jack|{
|
||||
let mut app = SequencerTui::try_from(jack)?;
|
||||
let jack = jack.read().unwrap();
|
||||
let midi_in = jack.register_port("in", MidiIn::default())?;
|
||||
let midi_out = jack.register_port("out", MidiOut::default())?;
|
||||
let midi_in = jack.register_port("i", MidiIn::default())?;
|
||||
let midi_out = jack.register_port("o", MidiOut::default())?;
|
||||
connect_from(&jack, &midi_in, &self.midi_from)?;
|
||||
connect_to(&jack, &midi_out, &self.midi_to)?;
|
||||
app.player.midi_ins.push(midi_in);
|
||||
|
|
@ -52,7 +57,7 @@ fn connect_from (jack: &JackClient, input: &Port<MidiIn>, ports: &[String]) -> U
|
|||
if let Some(port) = jack.port_by_name(&port) {
|
||||
jack.client().connect_ports(&port, &input)?;
|
||||
} else {
|
||||
panic!("Missing MIDI output: {port}");
|
||||
panic!("Missing MIDI output: {port}. Use jack_lsp to list all port names.");
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
|
@ -63,7 +68,7 @@ fn connect_to (jack: &JackClient, output: &Port<MidiOut>, ports: &[String]) -> U
|
|||
if let Some(port) = jack.port_by_name(&port) {
|
||||
jack.client().connect_ports(&output, &port)?;
|
||||
} else {
|
||||
panic!("Missing MIDI output: {port}");
|
||||
panic!("Missing MIDI input: {port}. Use jack_lsp to list all port names.");
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue