use std::{collections::VecDeque, convert::Infallible};
use sim_lib_midi_core::{MidiEvent, MidiSink, MidiSource, TrackedMidiEvent, TrackedMidiSource};
use crate::LiveMidiError;
#[derive(Clone, Debug)]
pub struct RingMidiBuffer {
tpq: u32,
capacity: usize,
dropped_events: usize,
events: VecDeque<MidiEvent>,
}
impl RingMidiBuffer {
pub fn new(tpq: u32, capacity: usize) -> Result<Self, LiveMidiError> {
if capacity == 0 {
return Err(LiveMidiError::ZeroCapacity);
}
Ok(Self {
tpq,
capacity,
dropped_events: 0,
events: VecDeque::with_capacity(capacity),
})
}
pub fn capacity(&self) -> usize {
self.capacity
}
pub fn len(&self) -> usize {
self.events.len()
}
pub fn is_empty(&self) -> bool {
self.events.is_empty()
}
pub fn dropped_events(&self) -> usize {
self.dropped_events
}
pub fn clear(&mut self) {
self.events.clear();
}
pub fn snapshot(&self) -> Vec<MidiEvent> {
self.events.iter().cloned().collect()
}
fn push_back(&mut self, event: MidiEvent) {
if self.events.len() == self.capacity {
let _ = self.events.pop_front();
self.dropped_events += 1;
}
self.events.push_back(event);
}
}
impl MidiSource for RingMidiBuffer {
type Err = Infallible;
fn tpq(&self) -> u32 {
self.tpq
}
fn next(&mut self) -> Result<Option<MidiEvent>, Self::Err> {
Ok(self.events.pop_front())
}
}
impl MidiSink for RingMidiBuffer {
type Err = Infallible;
fn tpq(&self) -> u32 {
self.tpq
}
fn write(&mut self, event: &MidiEvent) -> Result<(), Self::Err> {
self.push_back(event.clone());
Ok(())
}
fn flush(&mut self) -> Result<(), Self::Err> {
Ok(())
}
}
#[derive(Clone, Debug)]
pub struct RingTrackedMidiBuffer {
tpq: u32,
capacity: usize,
dropped_events: usize,
last_track: usize,
n_tracks: usize,
events: VecDeque<TrackedMidiEvent>,
}
impl RingTrackedMidiBuffer {
pub fn new(tpq: u32, capacity: usize) -> Result<Self, LiveMidiError> {
if capacity == 0 {
return Err(LiveMidiError::ZeroCapacity);
}
Ok(Self {
tpq,
capacity,
dropped_events: 0,
last_track: 0,
n_tracks: 0,
events: VecDeque::with_capacity(capacity),
})
}
pub fn capacity(&self) -> usize {
self.capacity
}
pub fn len(&self) -> usize {
self.events.len()
}
pub fn is_empty(&self) -> bool {
self.events.is_empty()
}
pub fn last_track(&self) -> usize {
self.last_track
}
pub fn dropped_events(&self) -> usize {
self.dropped_events
}
pub fn clear(&mut self) {
self.events.clear();
self.last_track = 0;
self.n_tracks = 0;
}
pub fn snapshot(&self) -> Vec<TrackedMidiEvent> {
self.events.iter().cloned().collect()
}
pub fn push_tracked_event(&mut self, event: TrackedMidiEvent) {
self.n_tracks = self.n_tracks.max(event.last_track + 1);
if self.events.len() == self.capacity {
let _ = self.events.pop_front();
self.dropped_events += 1;
}
self.events.push_back(event);
}
}
impl MidiSource for RingTrackedMidiBuffer {
type Err = Infallible;
fn tpq(&self) -> u32 {
self.tpq
}
fn next(&mut self) -> Result<Option<MidiEvent>, Self::Err> {
let event = self.events.pop_front();
if let Some(event) = &event {
self.last_track = event.last_track;
}
Ok(event.map(|item| item.event))
}
}
impl TrackedMidiSource for RingTrackedMidiBuffer {
fn last_track(&self) -> usize {
self.last_track
}
fn n_tracks(&self) -> usize {
self.n_tracks
}
fn next_tracked(&mut self) -> Result<Option<TrackedMidiEvent>, Self::Err> {
let event = self.events.pop_front();
if let Some(event) = &event {
self.last_track = event.last_track;
}
Ok(event)
}
}