1use crate::space::*;
69use crate::*;
70use sys::LV2_Atom_Event__bindgen_ty_1 as RawTimeStamp;
71use units::prelude::*;
72use urid::*;
73
74pub struct Sequence;
78
79unsafe impl UriBound for Sequence {
80 const URI: &'static [u8] = sys::LV2_ATOM__Sequence;
81}
82
83impl<'a, 'b> Atom<'a, 'b> for Sequence
84where
85 'a: 'b,
86{
87 type ReadParameter = URID<Beat>;
88 type ReadHandle = SequenceIterator<'a>;
89 type WriteParameter = TimeStampURID;
90 type WriteHandle = SequenceWriter<'a, 'b>;
91
92 fn read(body: Space, bpm_urid: URID<Beat>) -> Option<SequenceIterator> {
93 let (header, body) = body.split_type::<sys::LV2_Atom_Sequence_Body>()?;
94 let unit = if header.unit == bpm_urid {
95 TimeStampUnit::BeatsPerMinute
96 } else {
97 TimeStampUnit::Frames
98 };
99 Some(SequenceIterator { space: body, unit })
100 }
101
102 fn init(
103 mut frame: FramedMutSpace<'a, 'b>,
104 unit: TimeStampURID,
105 ) -> Option<SequenceWriter<'a, 'b>> {
106 {
107 let frame = &mut frame as &mut dyn MutSpace;
108 let header = sys::LV2_Atom_Sequence_Body {
109 unit: match unit {
110 TimeStampURID::BeatsPerMinute(urid) => urid.get(),
111 TimeStampURID::Frames(urid) => urid.get(),
112 },
113 pad: 0,
114 };
115 frame.write(&header, true)?;
116 }
117 Some(SequenceWriter {
118 frame,
119 unit: unit.into(),
120 last_stamp: None,
121 })
122 }
123}
124
125#[derive(Clone, Copy, PartialEq, Eq, Debug)]
127pub enum TimeStampUnit {
128 Frames,
129 BeatsPerMinute,
130}
131
132#[derive(Clone, Copy, Debug)]
134pub enum TimeStamp {
135 Frames(i64),
136 BeatsPerMinute(f64),
137}
138
139#[derive(Clone, Copy)]
141pub enum TimeStampURID {
142 Frames(URID<Frame>),
143 BeatsPerMinute(URID<Beat>),
144}
145
146impl From<TimeStampURID> for TimeStampUnit {
147 fn from(urid: TimeStampURID) -> TimeStampUnit {
148 match urid {
149 TimeStampURID::Frames(_) => TimeStampUnit::Frames,
150 TimeStampURID::BeatsPerMinute(_) => TimeStampUnit::BeatsPerMinute,
151 }
152 }
153}
154
155impl TimeStamp {
156 pub fn as_frames(self) -> Option<i64> {
157 match self {
158 Self::Frames(frame) => Some(frame),
159 _ => None,
160 }
161 }
162
163 pub fn as_bpm(self) -> Option<f64> {
164 match self {
165 Self::BeatsPerMinute(bpm) => Some(bpm),
166 _ => None,
167 }
168 }
169}
170
171pub struct SequenceIterator<'a> {
173 space: Space<'a>,
174 unit: TimeStampUnit,
175}
176
177impl<'a> SequenceIterator<'a> {
178 pub fn unit(&self) -> TimeStampUnit {
179 self.unit
180 }
181}
182
183impl<'a> Iterator for SequenceIterator<'a> {
184 type Item = (TimeStamp, UnidentifiedAtom<'a>);
185
186 fn next(&mut self) -> Option<(TimeStamp, UnidentifiedAtom<'a>)> {
187 let (raw_stamp, space) = self.space.split_type::<RawTimeStamp>()?;
188 let stamp = match self.unit {
189 TimeStampUnit::Frames => unsafe { TimeStamp::Frames(raw_stamp.frames) },
190 TimeStampUnit::BeatsPerMinute => unsafe { TimeStamp::BeatsPerMinute(raw_stamp.beats) },
191 };
192 let (atom, space) = space.split_atom()?;
193 self.space = space;
194 Some((stamp, UnidentifiedAtom::new(atom)))
195 }
196}
197
198pub struct SequenceWriter<'a, 'b> {
200 frame: FramedMutSpace<'a, 'b>,
201 unit: TimeStampUnit,
202 last_stamp: Option<TimeStamp>,
203}
204
205impl<'a, 'b> SequenceWriter<'a, 'b> {
206 fn write_time_stamp(&mut self, stamp: TimeStamp) -> Option<()> {
213 let raw_stamp = match self.unit {
214 TimeStampUnit::Frames => {
215 let frames = stamp.as_frames()?;
216 if let Some(last_stamp) = self.last_stamp {
217 if last_stamp.as_frames().unwrap() > frames {
218 return None;
219 }
220 }
221 RawTimeStamp { frames }
222 }
223 TimeStampUnit::BeatsPerMinute => {
224 let beats = stamp.as_bpm()?;
225 if let Some(last_stamp) = self.last_stamp {
226 if last_stamp.as_bpm().unwrap() > beats {
227 return None;
228 }
229 }
230 RawTimeStamp { beats }
231 }
232 };
233 self.last_stamp = Some(stamp);
234 (&mut self.frame as &mut dyn MutSpace)
235 .write(&raw_stamp, true)
236 .map(|_| ())
237 }
238
239 pub fn init<'c, A: Atom<'a, 'c>>(
243 &'c mut self,
244 stamp: TimeStamp,
245 urid: URID<A>,
246 parameter: A::WriteParameter,
247 ) -> Option<A::WriteHandle> {
248 self.write_time_stamp(stamp)?;
249 (&mut self.frame as &mut dyn MutSpace).init(urid, parameter)
250 }
251
252 pub fn forward(&mut self, stamp: TimeStamp, atom: UnidentifiedAtom) -> Option<()> {
258 let data = atom.space.data()?;
259 self.write_time_stamp(stamp)?;
260 self.frame.write_raw(data, true).map(|_| ())
261 }
262}
263
264#[cfg(test)]
265mod tests {
266 use crate::prelude::*;
267 use crate::sequence::*;
268 use std::mem::size_of;
269 use sys::LV2_Atom_Event__bindgen_ty_1 as RawTimeStamp;
270
271 #[derive(URIDCollection)]
272 struct TestURIDCollection {
273 atom: AtomURIDCollection,
274 units: UnitURIDCollection,
275 }
276
277 #[test]
278 fn test_sequence() {
279 let map = HashURIDMapper::new();
280 let urids = TestURIDCollection::from_map(&map).unwrap();
281
282 let mut raw_space: Box<[u8]> = Box::new([0; 256]);
283
284 {
286 let mut space = RootMutSpace::new(raw_space.as_mut());
287 let mut writer = (&mut space as &mut dyn MutSpace)
288 .init(
289 urids.atom.sequence,
290 TimeStampURID::Frames(urids.units.frame),
291 )
292 .unwrap();
293 writer
294 .init::<Int>(TimeStamp::Frames(0), urids.atom.int, 42)
295 .unwrap();
296 writer
297 .init::<Long>(TimeStamp::Frames(1), urids.atom.long, 17)
298 .unwrap();
299 }
300
301 {
303 let (sequence, space) = raw_space.split_at(size_of::<sys::LV2_Atom_Sequence>());
304 let sequence = unsafe { &*(sequence.as_ptr() as *const sys::LV2_Atom_Sequence) };
305 assert_eq!(sequence.atom.type_, urids.atom.sequence);
306 assert_eq!(
307 sequence.atom.size as usize,
308 size_of::<sys::LV2_Atom_Sequence_Body>()
309 + size_of::<RawTimeStamp>()
310 + size_of::<sys::LV2_Atom_Int>()
311 + 4
312 + size_of::<RawTimeStamp>()
313 + size_of::<sys::LV2_Atom_Long>()
314 );
315 assert_eq!(sequence.body.unit, urids.units.frame);
316
317 let (stamp, space) = space.split_at(size_of::<RawTimeStamp>());
318 let stamp = unsafe { *(stamp.as_ptr() as *const RawTimeStamp) };
319 assert_eq!(unsafe { stamp.frames }, 0);
320
321 let (int, space) = space.split_at(size_of::<sys::LV2_Atom_Int>());
322 let int = unsafe { &*(int.as_ptr() as *const sys::LV2_Atom_Int) };
323 assert_eq!(int.atom.type_, urids.atom.int);
324 assert_eq!(int.atom.size as usize, size_of::<i32>());
325 assert_eq!(int.body, 42);
326 let (_, space) = space.split_at(4);
327
328 let (stamp, space) = space.split_at(size_of::<RawTimeStamp>());
329 let stamp = unsafe { *(stamp.as_ptr() as *const RawTimeStamp) };
330 assert_eq!(unsafe { stamp.frames }, 1);
331
332 let (int, _) = space.split_at(size_of::<sys::LV2_Atom_Long>());
333 let int = unsafe { &*(int.as_ptr() as *const sys::LV2_Atom_Long) };
334 assert_eq!(int.atom.type_, urids.atom.long);
335 assert_eq!(int.atom.size as usize, size_of::<i64>());
336 assert_eq!(int.body, 17);
337 }
338
339 {
341 let space = Space::from_slice(raw_space.as_ref());
342 let (body, _) = space.split_atom_body(urids.atom.sequence).unwrap();
343 let mut reader = Sequence::read(body, urids.units.beat).unwrap();
344
345 assert_eq!(reader.unit(), TimeStampUnit::Frames);
346
347 let (stamp, atom) = reader.next().unwrap();
348 match stamp {
349 TimeStamp::Frames(frames) => assert_eq!(frames, 0),
350 _ => panic!("Invalid time stamp!"),
351 }
352 assert_eq!(atom.read::<Int>(urids.atom.int, ()).unwrap(), 42);
353
354 let (stamp, atom) = reader.next().unwrap();
355 match stamp {
356 TimeStamp::Frames(frames) => assert_eq!(frames, 1),
357 _ => panic!("Invalid time stamp!"),
358 }
359 assert_eq!(atom.read::<Long>(urids.atom.long, ()).unwrap(), 17);
360
361 assert!(reader.next().is_none());
362 }
363 }
364}