1use std::{sync::{mpsc, Arc, Mutex}, thread, time::Duration};
2
3use midi_message::MidiMessage;
4use midir::{MidiInput, MidiOutput};
5use anyhow::anyhow;
6pub mod midi_message;
9pub struct Midi;
10
11impl Midi {
12
13 pub fn get_devices() -> anyhow::Result<(Vec<String>, Vec<String>)> {
14 let input = MidiInput::new("inputs")?;
15 let output = MidiOutput::new("outputs")?;
16 let mut input_devices: Vec<String> = vec![];
17 let mut output_devices: Vec<String> = vec![];
18 for (_i, p) in input.ports().iter().enumerate() {
19 input_devices.push(input.port_name(p)?);
20 }
21 for (_i, p) in output.ports().iter().enumerate() {
22 output_devices.push(output.port_name(p)?);
23 }
24 let inputs = input_devices.clone();
25 let outputs = output_devices.clone();
26 Ok((inputs, outputs))
27 }
28
29 pub fn listen_to_device(device: &str, tx: mpsc::Sender<MidiMessage>) -> anyhow::Result<()> {
30 let midi_input = MidiInput::new("inputs")?;
31 let in_port = Self::find_port(&midi_input, device).ok_or_else(|| anyhow!("Midi device not connected"))?;
32
33 let tx = Arc::new(Mutex::new(tx)); let _conn_in = midi_input.connect(&in_port, "midir-read-input",
36 move |stamp, message, _,| {
37 let tx = tx.clone(); let message = message.to_owned(); if let Some(msg) = MidiMessage::from_raw_message(&message, stamp) {
40 let tx = tx.lock().unwrap();
41 tx.send(msg).unwrap(); }
43 },
44 (),
45 );
46
47 loop {
48 thread::sleep(Duration::from_secs(10))
49 }
50 }
51
52 fn find_port<T>(midi_io: &T, device: &str) -> Option<T::Port> where T: midir::MidiIO {
53 let mut device_port: Option<T::Port> = None;
54 for port in midi_io.ports() {
55
56 if let Ok(port_name) = midi_io.port_name(&port) {
57 if port_name.contains(device) {
59 device_port = Some(port);
60 break;
61 }
62 }
63 }
64 device_port
65 }
66
67}
68