use helgoboss_midi::{ShortMessage, U7};
use reaper_low::raw;
use std::os::raw::c_int;
use std::ptr::NonNull;
#[derive(Eq, PartialEq, Hash, Debug)]
pub struct MidiInput(pub(crate) NonNull<raw::midi_Input>);
impl MidiInput {
pub fn get_read_buf(&self) -> MidiEventList<'_> {
let raw_evt_list = unsafe { self.0.as_ref().GetReadBuf() };
MidiEventList::new(unsafe { &*raw_evt_list })
}
}
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub struct MidiEventList<'a>(&'a raw::MIDI_eventlist);
impl<'a> MidiEventList<'a> {
pub(super) fn new(raw_evt_list: &'a raw::MIDI_eventlist) -> Self {
MidiEventList(raw_evt_list)
}
pub fn enum_items(&self, bpos: u32) -> impl Iterator<Item = MidiEvent<'a>> {
EnumItems {
raw_list: self.0,
bpos: bpos as i32,
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub struct MidiEvent<'a>(&'a raw::MIDI_event_t);
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub struct MidiMessage<'a>(&'a raw::MIDI_event_t);
impl<'a> MidiEvent<'a> {
pub(crate) unsafe fn new(raw_evt: &'a raw::MIDI_event_t) -> Self {
MidiEvent(raw_evt)
}
pub fn frame_offset(&self) -> u32 {
self.0.frame_offset as u32
}
pub fn message(&self) -> MidiMessage<'a> {
MidiMessage::new(self.0)
}
}
impl<'a> MidiMessage<'a> {
pub(super) fn new(raw_evt: &'a raw::MIDI_event_t) -> Self {
MidiMessage(raw_evt)
}
}
struct EnumItems<'a> {
raw_list: &'a raw::MIDI_eventlist,
bpos: i32,
}
impl<'a> Iterator for EnumItems<'a> {
type Item = MidiEvent<'a>;
fn next(&mut self) -> Option<Self::Item> {
let raw_evt = unsafe { self.raw_list.EnumItems(&mut self.bpos as *mut c_int) };
if raw_evt.is_null() {
return None;
}
let evt = unsafe { MidiEvent::new(&*raw_evt) };
Some(evt)
}
}
impl<'a> ShortMessage for MidiMessage<'a> {
fn status_byte(&self) -> u8 {
self.0.midi_message[0]
}
fn data_byte_1(&self) -> U7 {
unsafe { U7::new_unchecked(self.0.midi_message[1]) }
}
fn data_byte_2(&self) -> U7 {
unsafe { U7::new_unchecked(self.0.midi_message[2]) }
}
}