1use std::convert::Infallible;
2
3use crate::{MidiEvent, PumpError, TickTime};
4
5#[derive(Clone, Debug, PartialEq, Eq)]
7pub struct TrackedMidiEvent {
8 pub last_track: usize,
10 pub event: MidiEvent,
12}
13
14pub trait MidiSource {
16 type Err;
18
19 fn tpq(&self) -> u32;
21
22 fn next(&mut self) -> Result<Option<MidiEvent>, Self::Err>;
24}
25
26pub trait TrackedMidiSource: MidiSource {
28 fn last_track(&self) -> usize;
30
31 fn n_tracks(&self) -> usize;
33
34 fn next_tracked(&mut self) -> Result<Option<TrackedMidiEvent>, Self::Err>;
36}
37
38pub trait MidiSink {
40 type Err;
42
43 fn tpq(&self) -> u32;
45
46 fn write(&mut self, event: &MidiEvent) -> Result<(), Self::Err>;
48
49 fn flush(&mut self) -> Result<(), Self::Err>;
51}
52
53#[derive(Clone, Debug, Default)]
55pub struct MemoryMidiSource {
56 tpq: u32,
57 events: Vec<MidiEvent>,
58 cursor: usize,
59}
60
61impl MemoryMidiSource {
62 pub fn new(tpq: u32, mut events: Vec<MidiEvent>) -> Self {
64 events.sort_by_key(|event| event.time.ticks);
65 Self {
66 tpq,
67 events,
68 cursor: 0,
69 }
70 }
71}
72
73#[derive(Clone, Debug, Default)]
76pub struct MemoryTrackedMidiSource {
77 tpq: u32,
78 events: Vec<TrackedMidiEvent>,
79 cursor: usize,
80 last_track: usize,
81 n_tracks: usize,
82}
83
84impl MemoryTrackedMidiSource {
85 pub fn new(tpq: u32, mut events: Vec<TrackedMidiEvent>) -> Self {
88 events.sort_by_key(|item| item.event.time.ticks);
89 let n_tracks = events
90 .iter()
91 .map(|item| item.last_track + 1)
92 .max()
93 .unwrap_or(0);
94 Self {
95 tpq,
96 events,
97 cursor: 0,
98 last_track: 0,
99 n_tracks,
100 }
101 }
102}
103
104impl MidiSource for MemoryMidiSource {
105 type Err = Infallible;
106
107 fn tpq(&self) -> u32 {
108 self.tpq
109 }
110
111 fn next(&mut self) -> Result<Option<MidiEvent>, Self::Err> {
112 let event = self.events.get(self.cursor).cloned();
113 if event.is_some() {
114 self.cursor += 1;
115 }
116 Ok(event)
117 }
118}
119
120impl MidiSource for MemoryTrackedMidiSource {
121 type Err = Infallible;
122
123 fn tpq(&self) -> u32 {
124 self.tpq
125 }
126
127 fn next(&mut self) -> Result<Option<MidiEvent>, Self::Err> {
128 let event = self.events.get(self.cursor).cloned();
129 if let Some(event) = &event {
130 self.last_track = event.last_track;
131 self.cursor += 1;
132 }
133 Ok(event.map(|item| item.event))
134 }
135}
136
137impl TrackedMidiSource for MemoryTrackedMidiSource {
138 fn last_track(&self) -> usize {
139 self.last_track
140 }
141
142 fn n_tracks(&self) -> usize {
143 self.n_tracks
144 }
145
146 fn next_tracked(&mut self) -> Result<Option<TrackedMidiEvent>, Self::Err> {
147 let event = self.events.get(self.cursor).cloned();
148 if let Some(event) = &event {
149 self.last_track = event.last_track;
150 self.cursor += 1;
151 }
152 Ok(event)
153 }
154}
155
156#[derive(Clone, Debug, Default)]
158pub struct MemoryMidiSink {
159 tpq: u32,
160 events: Vec<MidiEvent>,
161}
162
163impl MemoryMidiSink {
164 pub fn new(tpq: u32) -> Self {
166 Self {
167 tpq,
168 events: Vec::new(),
169 }
170 }
171
172 pub fn events(&self) -> &[MidiEvent] {
174 &self.events
175 }
176}
177
178impl MidiSink for MemoryMidiSink {
179 type Err = Infallible;
180
181 fn tpq(&self) -> u32 {
182 self.tpq
183 }
184
185 fn write(&mut self, event: &MidiEvent) -> Result<(), Self::Err> {
186 self.events.push(event.clone());
187 self.events.sort_by_key(|item| item.time.ticks);
188 Ok(())
189 }
190
191 fn flush(&mut self) -> Result<(), Self::Err> {
192 Ok(())
193 }
194}
195
196pub fn pump<S, T>(source: &mut S, sink: &mut T) -> Result<usize, PumpError<S::Err, T::Err>>
203where
204 S: MidiSource,
205 T: MidiSink,
206{
207 let mut count = 0usize;
208 let sink_tpq = sink.tpq();
209 let source_tpq = source.tpq();
210 while let Some(mut event) = source.next().map_err(PumpError::Source)? {
211 if source_tpq != sink_tpq {
212 event.time = event.time.quantize(sink_tpq);
213 } else if event.time.tpq != sink_tpq {
214 event.time = TickTime {
215 ticks: event.time.ticks,
216 tpq: sink_tpq,
217 };
218 }
219 sink.write(&event).map_err(PumpError::Sink)?;
220 count += 1;
221 }
222 sink.flush().map_err(PumpError::Sink)?;
223 Ok(count)
224}