phemios_core/playback/
removal.rs1use super::*;
3pub(super) enum Outcome {
4 Keep,
5 Advance(usize),
6 Stop,
7}
8pub(super) fn edit(state: &mut State, occurrence: usize, paused: bool) -> Result<Outcome, String> {
10 let at = state
11 .queue
12 .iter()
13 .position(|index| *index == occurrence)
14 .ok_or("La liste de lecture a changé.")?;
15 let current = state.index == occurrence;
16 let next = state.queue.get(at + 1).copied();
17 state.queue.remove(at);
18 state.tracks[occurrence] = String::new();
19 if state.queue.is_empty() {
20 state.clear_selection();
21 return Ok(Outcome::Stop);
22 }
23 if !current {
24 return Ok(Outcome::Keep);
25 }
26 state.position = 0;
27 state.duration = None;
28 state.confirmed = false;
29 if let Some(next) = next {
30 state.index = next;
31 state.reference = state.tracks[next].clone();
32 state.status = if paused { "paused" } else { "connecting" };
33 Ok(Outcome::Advance(next))
34 } else {
35 state.status = "idle";
36 state.reference.clear();
37 state.index = state.queue[0];
38 Ok(Outcome::Stop)
39 }
40}
41pub(super) fn reserve_mix(
43 state: &Mutex<State>,
44 current: usize,
45 next: usize,
46) -> Result<bool, String> {
47 let mut state = state.lock().map_err(|_| "État audio indisponible.")?;
48 if !state.queue.contains(&next) {
49 return Ok(false);
50 }
51 state.protected = vec![current, next];
52 Ok(true)
53}
54impl Player {
55 pub fn remove(&self, id: u64, occurrence: usize) -> Result<(), String> {
57 let worker = self.worker.lock().map_err(|_| "Lecteur indisponible.")?;
58 let worker = worker
59 .as_ref()
60 .filter(|worker| !worker.handle.is_finished())
61 .ok_or("Aucune lecture active.")?;
62 let mut state = self.state.lock().map_err(|_| "État audio indisponible.")?;
63 if state.queue_id != id
64 || occurrence >= state.tracks.len()
65 || !state.queue.contains(&occurrence)
66 {
67 return Err("La liste de lecture a changé.".into());
68 }
69 if occurrence != state.index && state.protected.contains(&occurrence) {
70 return Err(
71 "Ce titre participe au fondu en cours. Réessayez à la fin du fondu.".into(),
72 );
73 }
74 if occurrence != state.index {
75 edit(&mut state, occurrence, false)?;
76 return Ok(());
77 }
78 let (done, wait) = mpsc::sync_channel(1);
79 worker
80 .commands
81 .try_send(Command::Remove(occurrence, done))
82 .map_err(|_| "Lecteur occupé, réessayez.")?;
83 self.signals.paused.store(true, Ordering::Relaxed);
84 drop(state);
85 wait.recv_timeout(std::time::Duration::from_secs(15))
86 .map_err(|_| "Retrait de piste interrompu.")?
87 }
88}
89#[cfg(test)]
90#[path = "removal_tests.rs"]
91mod tests;