use bbx_core::spsc::{Consumer, Producer, SpscRingBuffer};
use crate::message::MidiMessage;
pub struct MidiBufferProducer {
producer: Producer<MidiMessage>,
}
impl MidiBufferProducer {
#[inline]
pub fn try_send(&mut self, message: MidiMessage) -> bool {
self.producer.try_push(message).is_ok()
}
#[inline]
pub fn is_full(&self) -> bool {
self.producer.is_full()
}
}
pub struct MidiBufferConsumer {
consumer: Consumer<MidiMessage>,
}
impl MidiBufferConsumer {
#[inline]
pub fn try_pop(&mut self) -> Option<MidiMessage> {
self.consumer.try_pop()
}
#[inline]
pub fn drain_into(&mut self, buffer: &mut Vec<MidiMessage>) -> usize {
let mut count = 0;
while let Some(msg) = self.consumer.try_pop() {
buffer.push(msg);
count += 1;
}
count
}
#[inline]
pub fn is_empty(&self) -> bool {
self.consumer.is_empty()
}
}
pub fn midi_buffer(capacity: usize) -> (MidiBufferProducer, MidiBufferConsumer) {
let (producer, consumer) = SpscRingBuffer::new(capacity);
(MidiBufferProducer { producer }, MidiBufferConsumer { consumer })
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_send_receive() {
let (mut producer, mut consumer) = midi_buffer(8);
let msg = MidiMessage::new([0x90, 60, 100]);
assert!(producer.try_send(msg));
let received = consumer.try_pop().expect("should have message");
assert_eq!(received.get_note_number(), Some(60));
assert!(consumer.try_pop().is_none());
}
#[test]
fn test_buffer_overflow() {
let (mut producer, _consumer) = midi_buffer(2);
let msg = MidiMessage::new([0x90, 60, 100]);
assert!(producer.try_send(msg));
assert!(producer.try_send(msg));
assert!(!producer.try_send(msg));
assert!(producer.is_full());
}
#[test]
fn test_drain_into() {
let (mut producer, mut consumer) = midi_buffer(8);
producer.try_send(MidiMessage::new([0x90, 60, 100]));
producer.try_send(MidiMessage::new([0x90, 64, 80]));
producer.try_send(MidiMessage::new([0x80, 60, 0]));
let mut buffer = Vec::new();
let count = consumer.drain_into(&mut buffer);
assert_eq!(count, 3);
assert_eq!(buffer.len(), 3);
assert_eq!(buffer[0].get_note_number(), Some(60));
assert_eq!(buffer[1].get_note_number(), Some(64));
assert_eq!(buffer[2].get_note_number(), Some(60));
assert!(consumer.is_empty());
}
#[test]
fn test_is_empty() {
let (mut producer, mut consumer) = midi_buffer(4);
assert!(consumer.is_empty());
producer.try_send(MidiMessage::new([0x90, 60, 100]));
assert!(!consumer.is_empty());
consumer.try_pop();
assert!(consumer.is_empty());
}
}