From 019742b3ea455e6d8c2bad1e0229dcac5f2a8c5f Mon Sep 17 00:00:00 2001 From: Hykilpikonna Date: Wed, 15 Mar 2023 20:22:28 -0400 Subject: [PATCH] [+] Rust main --- src/main.rs | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 src/main.rs diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..8053442 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,75 @@ +use std::io::{BufRead, BufReader}; +use std::process::exit; + +use anyhow::Result; +use log::info; +use midir::MidiOutput; +use midir::os::unix::VirtualOutput; + +fn start() -> Result<()> { + let midi_out = MidiOutput::new("MIDI Output")?; + let mut conn_out = midi_out.create_virtual("Virtual MIDI Output").unwrap(); + + let serial_port = serialport::new("/dev/cu.usbserial-142140", 9600) + .timeout(std::time::Duration::from_millis(10)) + .open()?; + let mut reader = BufReader::new(serial_port); + + let mut buf = Vec::new(); + + info!("Starting"); + + loop { + match reader.read_until(b'\n', &mut buf) { + Ok(t) => { + if t == 0 { continue } + + // Convert buffer to string + let mut line = String::from_utf8_lossy(&buf).to_string(); + line = line.trim().to_string(); + buf.clear(); + + println!("{}", line); + + // Only process commands + if !line.starts_with("/") { continue } + + // Split command arguments + let args: Vec<&str> = line.split_whitespace().collect(); + + // Command /hit + // Usage example: /hit 60 127 + if args[0] == "/hit" { + let note = args[1].parse::()?; + // let note = 72; // c5 + let velocity = args[2].parse::()?; + conn_out.send(&[0x99, note, velocity]).unwrap(); + + // Since it's an instant hit, we need to send a note off + // Sleep for 10ms to make sure the note off is sent after the note on + // std::thread::sleep(std::time::Duration::from_millis(10)); + conn_out.send(&[0x89, note, 0]).unwrap(); + } + + // Command /pedal <0 = off / 1 = on> + // Usage example: /pedal 0 + if args[0] == "/pedal" { + let pedal = args[1].parse::()? * 127; + conn_out.send(&[0xB0, 64, pedal]).unwrap(); + } + }, + Err(ref e) if e.kind() == std::io::ErrorKind::TimedOut => (), + Err(e) => { + if e.kind() == std::io::ErrorKind::BrokenPipe { + println!("Connection closed."); + exit(0); + } + }, + } + } +} + +fn main() { + pretty_env_logger::init(); + start().expect("Error: Start failed."); +}