use bevy::prelude::*;
use crossbeam_channel::{Receiver, TryRecvError};
use midir::MidiInputPort;
use midix::events::{FromLiveEventBytes, LiveEvent};
use super::MidiInputError;
#[derive(Event, Debug)]
pub struct MidiData {
pub stamp: Option<u64>,
pub message: LiveEvent<'static>,
}
pub(crate) struct MidiInputConnection {
data: Receiver<MidiData>,
conn: midir::MidiInputConnection<()>,
}
impl MidiInputConnection {
pub fn new(
midir_input: midir::MidiInput,
port: &MidiInputPort,
port_name: &str,
) -> Result<Self, MidiInputError> {
let (sender, receiver) = crossbeam_channel::unbounded::<MidiData>();
let conn = midir_input.connect(
port,
port_name,
{
move |timestamp, data, _| {
let Ok(message) = LiveEvent::from_bytes(data) else {
return;
};
sender
.send(MidiData {
stamp: Some(timestamp),
message,
})
.unwrap();
}
},
(),
)?;
Ok(Self {
data: receiver,
conn,
})
}
pub fn read(&self) -> Result<MidiData, TryRecvError> {
self.data.try_recv()
}
pub fn close(self) -> midir::MidiInput {
let (listener, _) = self.conn.close();
listener
}
}