use std::convert::Infallible;
use sim_lib_midi_core::{MidiEvent, MidiSink, MidiSource};
use crate::{LiveMidiError, RingMidiBuffer};
const DEFAULT_TPQ: u32 = 480;
const DEFAULT_CAPACITY: usize = 1024;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum LiveMidiDirection {
Source,
Sink,
Duplex,
}
impl LiveMidiDirection {
fn sink_enabled(self) -> bool {
matches!(self, Self::Sink | Self::Duplex)
}
}
#[derive(Debug)]
pub struct LiveMidiSession {
ring: RingMidiBuffer,
direction: LiveMidiDirection,
}
impl LiveMidiSession {
pub fn modeled(direction: LiveMidiDirection) -> Result<Self, LiveMidiError> {
Self::with_ring(DEFAULT_TPQ, DEFAULT_CAPACITY, direction)
}
pub fn with_ring(
tpq: u32,
capacity: usize,
direction: LiveMidiDirection,
) -> Result<Self, LiveMidiError> {
Ok(Self {
ring: RingMidiBuffer::new(tpq, capacity)?,
direction,
})
}
pub fn direction(&self) -> LiveMidiDirection {
self.direction
}
pub fn source_mut(&mut self) -> &mut dyn MidiSource<Err = Infallible> {
&mut self.ring
}
pub fn sink_mut(&mut self) -> Option<&mut dyn MidiSink<Err = Infallible>> {
if self.direction.sink_enabled() {
Some(&mut self.ring)
} else {
None
}
}
pub fn enqueue_from_callback(&mut self, event: &MidiEvent) -> Result<(), Infallible> {
self.ring.write(event)
}
pub fn close(self) -> Result<(), LiveMidiError> {
Ok(())
}
}