midi-keys/src/bin/main.rs

58 lines
1.7 KiB
Rust

use std::io::stdin;
use anyhow::{anyhow, Result};
use midir::{MidiInput, MidiInputPort};
fn main() {
match run() {
Ok(_) => {}
Err(err) => {
println!("Ended with error: {}", err);
}
}
}
fn run() -> Result<()> {
let midi_in = MidiInput::new("keyboard")?;
let midi_device = find_first_midi_device(&midi_in)?;
let port_name = midi_in.port_name(&midi_device)?;
let _midi_connection = match midi_in.connect(&midi_device, &port_name, handle_midi_event, ()) {
Ok(m) => m,
Err(err) => return Err(anyhow!("failed to connect to device: {}", err)),
};
// TODO: instead, listen for a signal like control-d
let mut buf = String::new();
stdin().read_line(&mut buf)?;
Ok(())
}
fn handle_midi_event(timestamp: u64, message: &[u8], _extra_data: &mut ()) {
let hex_msg = hex::encode(message);
println!("{timestamp} > {hex_msg}");
}
/// Finds the first MIDI input port which corresponds to a physical MIDI device
/// connected to this computer.
fn find_first_midi_device(midi_in: &MidiInput) -> Result<MidiInputPort> {
let ports = midi_in.ports();
// "Midi Through" is automatically created by the snd-seq-dummy kernel module.
// We can ignore it, since it's not a physical MIDI device, which is what we
// are looking for.
//
// Source: https://www.reddit.com/r/linuxaudio/comments/jsrl31/comment/gc16qwu/
let mut physical_ports = ports.iter().filter(|p| {
midi_in
.port_name(p)
.map_or(false, |n| !n.starts_with("Midi Through:"))
});
physical_ports
.next()
.cloned()
.ok_or(anyhow!("no physical MIDI devices found"))
}