extern crate midir;
use std::fs::File;
use std::error::Error;
use std::io::{stdin, stdout, Write, BufRead, BufReader};
use std::thread::sleep;
use std::time::Duration;
use midir::{MidiOutput, MidiIO, MidiOutputConnection};
fn play_note(conn_out: &mut MidiOutputConnection, note: u8, duration: u64) {
const NOTE_ON_MSG: u8 = 0x90;
const NOTE_OFF_MSG: u8 = 0x80;
const VELOCITY: u8 = 0x64;
let _ = conn_out.send(&[NOTE_ON_MSG, note, VELOCITY]);
sleep(Duration::from_millis(duration * 150));
let _ = conn_out.send(&[NOTE_OFF_MSG, note, VELOCITY]);
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut buf = String::new();
let midi_out = MidiOutput::new("midir forwarding output")?;
let out_port = select_port(&midi_out, "output")?;
let out_port_name = midi_out.port_name(&out_port)?;
let mut conn_out = midi_out.connect(&out_port, "midir-forward")?;
println!("out port: {}", out_port_name);
let mut reader = BufReader::new(File::open("/tmp/ff")?); // named pipe
loop {
reader.read_line(&mut buf);
print!("{}", buf);
if buf.len() > 0 {
buf.pop();
if buf == "qqq".to_string() {
println!("quit");
break;
}
match buf.parse(){
Ok(num) => play_note(&mut conn_out, num, 1),
Err(_e) => ()
}
}
buf.clear();
}
Ok(())
}
fn select_port<T: MidiIO>(midi_io: &T, descr: &str) -> Result<T::Port, Box<dyn Error>> {
println!("Available {} ports:", descr);
let midi_ports = midi_io.ports();
for (i, p) in midi_ports.iter().enumerate() {
println!("{}: {}", i, midi_io.port_name(p)?);
}
print!("Please select {} port: ", descr);
stdout().flush()?;
let mut input = String::new();
stdin().read_line(&mut input)?;
let port = midi_ports.get(input.trim().parse::<usize>()?)
.ok_or("Invalid port number")?;
Ok(port.clone())
}