From 56234e4e0749cb059e882180f1ab79e5f1498cfa Mon Sep 17 00:00:00 2001 From: Nicole Tietz-Sokolskaya <me@ntietz.com> Date: Mon, 2 Sep 2024 10:59:31 -0400 Subject: [PATCH] Reads MIDI events and prints them to the terminal --- Cargo.toml | 2 ++ src/main.rs | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 17f1b4b..1291649 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,4 +4,6 @@ version = "0.1.0" edition = "2021" [dependencies] +anyhow = "1.0.86" midir = "0.10.0" +thiserror = "1.0.63" diff --git a/src/main.rs b/src/main.rs index e7a11a9..a6f105b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,59 @@ +use std::io::stdin; +use std::io::Read; + +use anyhow::{anyhow, Result}; +use midir::{MidiInput, MidiInputPort}; + fn main() { - println!("Hello, world!"); + 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 ()) { + println!("{timestamp} > {message:?}") +} + +/// 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(); + + 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")) +} + +// "Midi Through" is automatically created bya 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/