1use alloc::collections::BTreeMap;
2use alloc::vec::Vec;
3use core::marker::PhantomData;
4use core::ptr::NonNull;
5
6use super::super::sources::instrument::Instrument;
7use super::super::SoundCompletionCallback;
8use super::sequence_track::{SequenceTrack, SequenceTrackMut};
9use crate::callback_builder::Constructed;
10use crate::callbacks::RegisteredCallback;
11use crate::capi_state::CApiState;
12use crate::ctypes::*;
13use crate::error::Error;
14use crate::null_terminated::ToNullTerminatedString;
15
16pub struct Sequence {
18 ptr: NonNull<CSoundSequence>,
19 finished_callback: Option<RegisteredCallback>,
20
21 user_created_tracks: Vec<NonNull<CSequenceTrack>>,
24 instruments: BTreeMap<u32, Instrument>,
27}
28impl Sequence {
29 fn from_ptr(ptr: *mut CSoundSequence) -> Self {
30 Sequence {
31 ptr: NonNull::new(ptr).unwrap(),
32 finished_callback: None,
33 user_created_tracks: Vec::new(),
34 instruments: BTreeMap::new(),
35 }
36 }
37
38 pub(crate) fn new() -> Self {
40 let ptr = unsafe { Self::fns().newSequence.unwrap()() };
41 Self::from_ptr(ptr)
42 }
43
44 pub fn from_midi_file(path: &str) -> Result<Self, Error> {
49 let mut seq = Self::new();
50 let r = unsafe {
51 Self::fns().loadMidiFile.unwrap()(seq.cptr_mut(), path.to_null_terminated_utf8().as_ptr())
52 };
53 match r {
54 0 => Err(Error::LoadMidiFileError),
55 _ => {
56 seq.create_instrument_for_each_track();
57 Ok(seq)
58 }
59 }
60 }
61
62 fn create_instrument_for_each_track(&mut self) {
65 let mut instruments = BTreeMap::new();
66 let mut count = self.tracks_count();
67 let mut index = 0;
68 while count > 0 {
69 let track_ptr = unsafe { Sequence::fns().getTrackAtIndex.unwrap()(self.cptr_mut(), index) };
72 if !track_ptr.is_null() {
73 count -= 1;
74 if !self.instruments.contains_key(&index) {
75 assert!(unsafe { SequenceTrack::fns().getInstrument.unwrap()(track_ptr) }.is_null());
76 let mut instrument = Instrument::new();
77 unsafe { SequenceTrack::fns().setInstrument.unwrap()(track_ptr, instrument.cptr_mut()) };
78 instruments.insert(index, instrument);
79 }
80 }
81 index += 1;
82 }
83 self.instruments = instruments;
84 }
85
86 pub(crate) fn set_track_instrument(&mut self, index: u32, instrument: Instrument) {
89 self.instruments.insert(index, instrument);
90 }
91 pub(crate) fn track_instrument(&self, index: u32) -> &Instrument {
93 self.instruments.get(&index).unwrap()
94 }
95 pub(crate) fn track_instrument_mut(&mut self, index: u32) -> &mut Instrument {
97 self.instruments.get_mut(&index).unwrap()
98 }
99
100 pub fn play<'a, T, F: Fn(T) + 'static>(
124 &mut self,
125 finished_callback: SoundCompletionCallback<'a, T, F, Constructed>,
126 ) {
127 self.finished_callback = None;
128 let func = finished_callback.into_inner().and_then(|(callbacks, cb)| {
129 let key = self.cptr_mut() as usize;
130 let (func, reg) = callbacks.add_sequence_finished(key, cb);
131 self.finished_callback = Some(reg);
132 Some(func)
133 });
134 unsafe { Self::fns().play.unwrap()(self.cptr_mut(), func, core::ptr::null_mut()) }
135 }
136
137 pub fn stop(&mut self) {
139 unsafe { Self::fns().stop.unwrap()(self.cptr_mut()) }
140 }
141
142 pub fn all_notes_off(&mut self) {
144 unsafe { Self::fns().allNotesOff.unwrap()(self.cptr_mut()) }
145 }
146
147 pub fn is_playing(&self) -> bool {
149 unsafe { Self::fns().isPlaying.unwrap()(self.cptr() as *mut _) != 0 }
151 }
152
153 pub fn set_current_step(&mut self, time: u32) {
157 unsafe { Self::fns().setTime.unwrap()(self.cptr_mut(), time) }
158 }
159 pub fn current_step(&self) -> u32 {
163 unsafe { Self::fns().getTime.unwrap()(self.cptr() as *mut _) }
165 }
166
167 pub fn set_tempo(&mut self, steps_per_second: i32) {
169 unsafe { Self::fns().setTempo.unwrap()(self.cptr_mut(), steps_per_second) }
170 }
171 pub fn tempo(&mut self) -> i32 {
173 unsafe { Self::fns().getTempo.unwrap()(self.cptr() as *mut _) }
175 }
176
177 pub fn steps_count(&self) -> u32 {
181 unsafe { Self::fns().getLength.unwrap()(self.cptr() as *mut _) }
183 }
184
185 pub fn tracks_count(&self) -> u32 {
187 let c = unsafe { Self::fns().getTrackCount.unwrap()(self.cptr() as *mut _) };
189 c as u32
192 }
193
194 pub fn tracks<'a>(&'a self) -> impl Iterator<Item = SequenceTrack> + 'a {
196 SequenceTrackIter {
197 sequence: self,
198 next_index: 0,
199 count_left: self.tracks_count() as usize,
200 count_total: self.tracks_count() as usize,
201 }
202 }
203 pub fn tracks_mut<'a>(&'a mut self) -> impl Iterator<Item = SequenceTrackMut<'a>> + 'a {
205 SequenceTrackIterMut {
206 sequence: NonNull::new(self).unwrap(),
207 next_index: 0,
208 count_left: self.tracks_count() as usize,
209 count_total: self.tracks_count() as usize,
210 _marker: PhantomData,
211 }
212 }
213
214 pub fn create_track_at_index(&mut self, index: u32) -> SequenceTrackMut<'_> {
217 let track_ptr = unsafe { SequenceTrack::fns().newTrack.unwrap()() };
218 assert!(!track_ptr.is_null());
219 unsafe { Sequence::fns().setTrackAtIndex.unwrap()(self.cptr_mut(), track_ptr, index) };
220 let mut instrument = Instrument::new();
221 unsafe { SequenceTrack::fns().setInstrument.unwrap()(track_ptr, instrument.cptr_mut()) };
222 self.instruments.insert(index, instrument);
223 SequenceTrackMut::new(track_ptr, index, self, self.track_instrument_mut(index))
224 }
225 pub fn track_at_index(&self, index: u32) -> Option<SequenceTrack> {
227 if self.instruments.contains_key(&index) {
228 let track_ptr =
230 unsafe { Sequence::fns().getTrackAtIndex.unwrap()(self.cptr() as *mut _, index) };
231 assert!(!track_ptr.is_null());
232 Some(SequenceTrack::new(
233 track_ptr,
234 index,
235 self.track_instrument(index),
236 ))
237 } else {
238 None
239 }
240 }
241 pub fn track_at_index_mut(&mut self, index: u32) -> Option<SequenceTrackMut<'_>> {
243 if self.instruments.contains_key(&index) {
244 let track_ptr = unsafe { Sequence::fns().getTrackAtIndex.unwrap()(self.cptr_mut(), index) };
245 assert!(!track_ptr.is_null());
246 Some(SequenceTrackMut::new(
247 track_ptr,
248 index,
249 self,
250 self.track_instrument_mut(index),
251 ))
252 } else {
253 None
254 }
255 }
256
257 pub fn set_loops(&mut self, start_step: u32, end_step: u32, count: i32) {
261 unsafe {
264 Self::fns().setLoops.unwrap()(self.cptr_mut(), start_step as i32, end_step as i32, count)
265 }
266 }
267
268 pub(crate) fn cptr(&self) -> *const CSoundSequence {
269 self.ptr.as_ptr()
270 }
271 pub(crate) fn cptr_mut(&mut self) -> *mut CSoundSequence {
272 self.ptr.as_ptr()
273 }
274 pub(crate) fn fns() -> &'static craydate_sys::playdate_sound_sequence {
275 unsafe { &*CApiState::get().csound.sequence }
276 }
277}
278
279impl Drop for Sequence {
280 fn drop(&mut self) {
281 unsafe { Self::fns().freeSequence.unwrap()(self.cptr_mut()) }
283 for ptr in self.user_created_tracks.drain(..) {
285 unsafe { SequenceTrack::fns().freeTrack.unwrap()(ptr.as_ptr()) }
286 }
287 }
288}
289
290struct SequenceTrackIter<'a> {
291 sequence: &'a Sequence,
292 next_index: u32,
293 count_left: usize,
294 count_total: usize,
295}
296impl<'a> Iterator for SequenceTrackIter<'a> {
297 type Item = SequenceTrack<'a>;
298
299 fn next(&mut self) -> Option<Self::Item> {
300 if self.count_left == 0 {
301 None
302 } else {
303 loop {
304 let index = self.next_index;
305 self.next_index += 1;
306 let track_ptr = unsafe {
307 Sequence::fns().getTrackAtIndex.unwrap()(self.sequence.cptr() as *mut _, index)
309 };
310 if !track_ptr.is_null() {
311 self.count_left -= 1;
312 return Some(SequenceTrack::new(
313 track_ptr,
314 index,
315 self.sequence.track_instrument(index),
316 ));
317 }
318 }
319 }
320 }
321
322 fn size_hint(&self) -> (usize, Option<usize>) {
323 (self.count_total, Some(self.count_total))
324 }
325}
326impl ExactSizeIterator for SequenceTrackIter<'_> {}
327impl core::iter::FusedIterator for SequenceTrackIter<'_> {}
328
329struct SequenceTrackIterMut<'a> {
330 sequence: NonNull<Sequence>,
331 next_index: u32,
332 count_left: usize,
333 count_total: usize,
334 _marker: PhantomData<&'a Sequence>,
335}
336impl<'a> Iterator for SequenceTrackIterMut<'a> {
337 type Item = SequenceTrackMut<'a>;
338
339 fn next(&mut self) -> Option<Self::Item> {
340 if self.count_left == 0 {
341 None
342 } else {
343 loop {
344 let index = self.next_index;
345 self.next_index += 1;
346 let track_ptr = unsafe {
347 Sequence::fns().getTrackAtIndex.unwrap()(self.sequence.as_mut().cptr_mut(), index)
348 };
349 if !track_ptr.is_null() {
350 self.count_left -= 1;
351 return Some(SequenceTrackMut::new(
352 track_ptr,
353 index,
354 self.sequence.as_ptr(),
355 unsafe { self.sequence.as_mut().track_instrument_mut(index) },
356 ));
357 }
358 }
359 }
360 }
361
362 fn size_hint(&self) -> (usize, Option<usize>) {
363 (self.count_total, Some(self.count_total))
364 }
365}
366impl ExactSizeIterator for SequenceTrackIterMut<'_> {}
367impl core::iter::FusedIterator for SequenceTrackIterMut<'_> {}