1use crate::model::Id;
8
9pub mod decoder;
10pub mod exact_output;
11pub mod exact_session;
12pub mod format;
13pub mod gain_plan;
14pub mod loudness;
15pub mod normalization;
16pub mod output;
17pub mod session;
18pub mod shuffle;
19pub mod stream;
20
21#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
23pub enum Repeat {
24 #[default]
26 Off,
27 One,
29 All,
31}
32
33#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
35pub enum Transport {
36 #[default]
38 Stopped,
39 Playing,
41 Paused,
43}
44
45#[derive(Clone, Debug)]
47pub struct Queue {
48 tracks: Vec<Id>,
49 order: Vec<usize>,
50 previous_cycle: Option<(Vec<usize>, Option<u64>)>,
51 next_cycle: Option<(Vec<usize>, Option<u64>)>,
52 cursor: Option<usize>,
53 seed: Option<u64>,
54 repeat: Repeat,
55 transport: Transport,
56 position_ms: u64,
57}
58
59impl Queue {
60 pub fn new(tracks: Vec<Id>, seed: Option<u64>) -> Self {
65 let mut order: Vec<usize> = (0..tracks.len()).collect();
66 if let Some(seed) = seed {
67 shuffle(&mut order, seed);
68 }
69 Self {
70 tracks,
71 order,
72 previous_cycle: None,
73 next_cycle: None,
74 cursor: None,
75 seed,
76 repeat: Repeat::Off,
77 transport: Transport::Stopped,
78 position_ms: 0,
79 }
80 }
81
82 pub fn selection(&self) -> &[Id] {
84 &self.tracks
85 }
86
87 pub fn ordered_tracks(&self) -> impl Iterator<Item = Id> + '_ {
89 self.order.iter().map(|&index| self.tracks[index])
90 }
91
92 pub fn seed(&self) -> Option<u64> {
94 self.seed
95 }
96
97 pub fn current(&self) -> Option<Id> {
99 self.cursor.map(|cursor| self.tracks[self.order[cursor]])
100 }
101
102 pub fn cursor(&self) -> Option<usize> {
104 self.cursor
105 }
106
107 pub fn current_entry(&self) -> Option<usize> {
109 self.cursor.map(|cursor| self.order[cursor])
110 }
111
112 pub fn select_entry(&mut self, entry: usize) -> bool {
115 let Some(cursor) = self.order.iter().position(|&index| index == entry) else {
116 return false;
117 };
118 self.cursor = Some(cursor);
119 self.position_ms = 0;
120 true
121 }
122
123 pub fn order(&self) -> &[usize] {
125 &self.order
126 }
127
128 pub fn reorder(&mut self, order: Vec<usize>, seed: Option<u64>) -> Result<(), &'static str> {
134 self.validate_order(&order)?;
135 let prefix_len = self.cursor.map_or(0, |cursor| cursor + 1);
136 let mut retained = vec![false; self.tracks.len()];
137 for &entry in &self.order[..prefix_len] {
138 retained[entry] = true;
139 }
140 self.order.truncate(prefix_len);
141 self.order
142 .extend(order.into_iter().filter(|&entry| !retained[entry]));
143 self.seed = seed;
144 self.previous_cycle = None;
145 self.next_cycle = None;
146 Ok(())
147 }
148
149 pub fn set_next_order(
154 &mut self,
155 order: Vec<usize>,
156 seed: Option<u64>,
157 ) -> Result<bool, &'static str> {
158 self.validate_order(&order)?;
159 if self.next_cycle.is_some() {
160 return Ok(false);
161 }
162 self.next_cycle = Some((order, seed));
163 Ok(true)
164 }
165
166 pub fn next_seed(&self) -> Option<u64> {
168 self.seed
169 .map(|seed| seed.wrapping_add(0x9e37_79b9_7f4a_7c15))
170 }
171
172 fn validate_order(&self, order: &[usize]) -> Result<(), &'static str> {
173 if order.len() != self.tracks.len() {
174 return Err("playback order must contain every selection occurrence");
175 }
176 let mut seen = vec![false; self.tracks.len()];
177 for &entry in order {
178 let Some(present) = seen.get_mut(entry) else {
179 return Err("playback order has an out-of-range occurrence");
180 };
181 if *present {
182 return Err("playback order repeats a selection occurrence");
183 }
184 *present = true;
185 }
186 Ok(())
187 }
188
189 pub fn transport(&self) -> Transport {
191 self.transport
192 }
193
194 pub fn position_ms(&self) -> u64 {
196 self.position_ms
197 }
198
199 pub fn set_position_ms(&mut self, position_ms: u64) -> bool {
202 if self.cursor.is_none() {
203 return false;
204 }
205 self.position_ms = position_ms;
206 true
207 }
208
209 pub fn set_repeat(&mut self, repeat: Repeat) {
211 self.repeat = repeat;
212 }
213
214 pub fn repeat(&self) -> Repeat {
216 self.repeat
217 }
218
219 pub fn play(&mut self) -> Option<Id> {
221 if self.cursor.is_none() && !self.order.is_empty() {
222 self.cursor = Some(0);
223 }
224 let current = self.current()?;
225 self.transport = Transport::Playing;
226 Some(current)
227 }
228
229 pub fn pause(&mut self) {
231 if self.transport == Transport::Playing {
232 self.transport = Transport::Paused;
233 }
234 }
235
236 pub fn stop(&mut self) {
238 self.transport = Transport::Stopped;
239 self.position_ms = 0;
240 }
241
242 pub fn skip_next(&mut self) -> Option<Id> {
245 self.advance(false)
246 }
247
248 pub fn finished(&mut self) -> Option<Id> {
250 if self.transport != Transport::Playing || self.cursor.is_none() {
251 return None;
252 }
253 self.advance(true)
254 }
255
256 fn advance(&mut self, natural_end: bool) -> Option<Id> {
257 if self.order.is_empty() {
258 self.stop();
259 return None;
260 }
261 if natural_end && self.repeat == Repeat::One && self.cursor.is_some() {
262 self.position_ms = 0;
263 return self.current();
264 }
265 let next = self.cursor.map_or(0, |cursor| cursor + 1);
266 if next == self.order.len() {
267 if self.repeat == Repeat::All {
268 let (order, seed) = self.next_cycle.take().unwrap_or_else(|| {
269 let seed = self.next_seed();
270 let mut order: Vec<usize> = (0..self.tracks.len()).collect();
271 if let Some(seed) = seed {
272 shuffle(&mut order, seed);
273 }
274 (order, seed)
275 });
276 let old_order = std::mem::replace(&mut self.order, order);
277 self.previous_cycle = Some((old_order, self.seed));
278 self.seed = seed;
279 self.cursor = Some(0);
280 } else {
281 self.cursor = None;
282 self.stop();
283 return None;
284 }
285 } else {
286 self.cursor = Some(next);
287 }
288 self.position_ms = 0;
289 self.current()
290 }
291
292 pub fn previous(&mut self) -> Option<Id> {
295 let cursor = self.cursor?;
296 if self.position_ms <= 3_000 {
297 if cursor > 0 {
298 self.cursor = Some(cursor - 1);
299 } else if let Some((order, seed)) = self.previous_cycle.take() {
300 let forward_order = std::mem::replace(&mut self.order, order);
301 self.next_cycle = Some((forward_order, self.seed));
302 self.seed = seed;
303 self.cursor = Some(self.order.len() - 1);
304 }
305 }
306 self.position_ms = 0;
307 self.current()
308 }
309}
310
311fn next_random(state: &mut u64) -> u64 {
313 *state = state.wrapping_add(0x9e37_79b9_7f4a_7c15);
314 let mut bits = *state;
315 bits = (bits ^ (bits >> 30)).wrapping_mul(0xbf58_476d_1ce4_e5b9);
316 bits = (bits ^ (bits >> 27)).wrapping_mul(0x94d0_49bb_1331_11eb);
317 bits ^ (bits >> 31)
318}
319
320fn shuffle(order: &mut [usize], seed: u64) {
321 let mut state = seed;
322 for upper in (2..=order.len()).rev() {
323 let bound = upper as u64;
324 let threshold = bound.wrapping_neg() % bound;
325 let index = loop {
326 let value = next_random(&mut state);
327 if value >= threshold {
328 break (value % bound) as usize;
329 }
330 };
331 order.swap(upper - 1, index);
332 }
333}
334
335#[cfg(test)]
336#[path = "playback_tests.rs"]
337mod tests;
338
339pub mod waveform;