1use bbx_core::spsc::{Consumer, Producer, SpscRingBuffer};
7
8use crate::message::MidiMessage;
9
10pub struct MidiBufferProducer {
12 producer: Producer<MidiMessage>,
13}
14
15impl MidiBufferProducer {
16 #[inline]
20 pub fn try_send(&mut self, message: MidiMessage) -> bool {
21 self.producer.try_push(message).is_ok()
22 }
23
24 #[inline]
26 pub fn is_full(&self) -> bool {
27 self.producer.is_full()
28 }
29}
30
31pub struct MidiBufferConsumer {
35 consumer: Consumer<MidiMessage>,
36}
37
38impl MidiBufferConsumer {
39 #[inline]
43 pub fn try_pop(&mut self) -> Option<MidiMessage> {
44 self.consumer.try_pop()
45 }
46
47 #[inline]
51 pub fn drain_into(&mut self, buffer: &mut Vec<MidiMessage>) -> usize {
52 let mut count = 0;
53 while let Some(msg) = self.consumer.try_pop() {
54 buffer.push(msg);
55 count += 1;
56 }
57 count
58 }
59
60 #[inline]
62 pub fn is_empty(&self) -> bool {
63 self.consumer.is_empty()
64 }
65}
66
67pub fn midi_buffer(capacity: usize) -> (MidiBufferProducer, MidiBufferConsumer) {
89 let (producer, consumer) = SpscRingBuffer::new(capacity);
90 (MidiBufferProducer { producer }, MidiBufferConsumer { consumer })
91}
92
93#[cfg(test)]
94mod tests {
95 use super::*;
96
97 #[test]
98 fn test_send_receive() {
99 let (mut producer, mut consumer) = midi_buffer(8);
100
101 let msg = MidiMessage::new([0x90, 60, 100]);
102 assert!(producer.try_send(msg));
103
104 let received = consumer.try_pop().expect("should have message");
105 assert_eq!(received.get_note_number(), Some(60));
106 assert!(consumer.try_pop().is_none());
107 }
108
109 #[test]
110 fn test_buffer_overflow() {
111 let (mut producer, _consumer) = midi_buffer(2);
112
113 let msg = MidiMessage::new([0x90, 60, 100]);
114 assert!(producer.try_send(msg));
115 assert!(producer.try_send(msg));
116 assert!(!producer.try_send(msg));
117 assert!(producer.is_full());
118 }
119
120 #[test]
121 fn test_drain_into() {
122 let (mut producer, mut consumer) = midi_buffer(8);
123
124 producer.try_send(MidiMessage::new([0x90, 60, 100]));
125 producer.try_send(MidiMessage::new([0x90, 64, 80]));
126 producer.try_send(MidiMessage::new([0x80, 60, 0]));
127
128 let mut buffer = Vec::new();
129 let count = consumer.drain_into(&mut buffer);
130
131 assert_eq!(count, 3);
132 assert_eq!(buffer.len(), 3);
133 assert_eq!(buffer[0].get_note_number(), Some(60));
134 assert_eq!(buffer[1].get_note_number(), Some(64));
135 assert_eq!(buffer[2].get_note_number(), Some(60));
136 assert!(consumer.is_empty());
137 }
138
139 #[test]
140 fn test_is_empty() {
141 let (mut producer, mut consumer) = midi_buffer(4);
142
143 assert!(consumer.is_empty());
144
145 producer.try_send(MidiMessage::new([0x90, 60, 100]));
146 assert!(!consumer.is_empty());
147
148 consumer.try_pop();
149 assert!(consumer.is_empty());
150 }
151}