72 lines
2.2 KiB
Rust
72 lines
2.2 KiB
Rust
use crate::{config::NanoKeys, interaction_server::InteractionServer};
|
|
use crossbeam_channel::Sender;
|
|
use midir::{Ignore, MidiInput};
|
|
use regex::Regex;
|
|
use std::thread::{self, JoinHandle};
|
|
use std::time;
|
|
|
|
const CLIENT_NAME: &str = "PicoKontroller";
|
|
const PORT_NAME: &str = "PicoController Input";
|
|
|
|
pub struct MidiClient {
|
|
pub device_name: String,
|
|
pub out_channel: Sender<KeyEvent>,
|
|
}
|
|
|
|
pub type KeyEvent = (NanoKeys, u8);
|
|
|
|
impl InteractionServer for MidiClient {
|
|
fn start(self) -> JoinHandle<()> {
|
|
thread::spawn(move || {
|
|
self.exec();
|
|
})
|
|
}
|
|
}
|
|
|
|
impl MidiClient {
|
|
pub fn new(device_name: String, out_channel: Sender<KeyEvent>) -> MidiClient {
|
|
MidiClient {
|
|
device_name,
|
|
out_channel,
|
|
}
|
|
}
|
|
|
|
fn exec(self) {
|
|
let port_filter = Regex::new(&self.device_name).expect("Creating RegEx failed");
|
|
|
|
let mut midi_in = MidiInput::new(CLIENT_NAME).expect("Creating Midi device failed");
|
|
midi_in.ignore(Ignore::None);
|
|
|
|
let in_ports = midi_in.ports();
|
|
let in_port = in_ports
|
|
.iter()
|
|
.find(|p| port_filter.is_match(&midi_in.port_name(p).unwrap()))
|
|
.expect("Couldn't find a port matching the supplied RegEx");
|
|
|
|
// _conn_in needs to be a named parameter, because it needs to be kept alive until the end of the scope
|
|
let _conn_in = midi_in.connect(
|
|
in_port,
|
|
PORT_NAME,
|
|
move |_, message, _| {
|
|
let key = NanoKeys::try_from(message[1]).unwrap();
|
|
let state = message[2];
|
|
let _ = self.out_channel.send((key, state));
|
|
},
|
|
(),
|
|
);
|
|
loop {
|
|
// sleep forever, callback functions happen on separate thread
|
|
// couldn't reuse this thread, since _conn_in needs to be alive in this scope
|
|
std::thread::sleep(time::Duration::from_secs(u64::MAX));
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn list_ports() -> () {
|
|
let midi_in = MidiInput::new(CLIENT_NAME).expect("Creating Midi device failed");
|
|
let in_ports = midi_in.ports();
|
|
println!("All available midi devices:");
|
|
for (_, p) in in_ports.iter().enumerate() {
|
|
println!("{}", midi_in.port_name(p).unwrap());
|
|
}
|
|
}
|