|
1 | 1 | use anyhow::Result; |
2 | 2 | use futures::future; |
3 | 3 | use mpris_server::{Metadata, Property}; |
| 4 | +use rand::seq::SliceRandom; |
4 | 5 |
|
5 | 6 | use crate::{ |
6 | | - app::{ActiveSection, ActiveTab, AppError, Track, VolumeDirection}, |
| 7 | + app::{ActiveSection, ActiveTab, AppError, RepeatMode, ShuffleMode, Track, VolumeDirection}, |
7 | 8 | mpris_handler::track_to_metadata, |
8 | 9 | }; |
9 | 10 |
|
@@ -59,14 +60,61 @@ impl App { |
59 | 60 | self.subsonic_client.scrobble(&track, false).await?; |
60 | 61 | Ok(()) |
61 | 62 | } |
| 63 | + pub fn enable_shuffle(&mut self) { |
| 64 | + if self.queue_tab.data.is_empty() { |
| 65 | + return; |
| 66 | + } |
| 67 | + let mut rng = rand::thread_rng(); |
| 68 | + let mut indices: Vec<usize> = (0..self.queue_tab.len()).collect(); |
| 69 | + indices.shuffle(&mut rng); |
| 70 | + // Put current_track as first track |
| 71 | + if let Some(pos) = indices.iter().position(|&i| i == self.playing_index) { |
| 72 | + indices.swap(0, pos) |
| 73 | + }; |
| 74 | + self.shuffle_order = indices; |
| 75 | + self.shuffle_position = 0; |
| 76 | + self.shuffle_mode = ShuffleMode::On; |
| 77 | + } |
| 78 | + pub fn disable_shuffle(&mut self) { |
| 79 | + self.shuffle_mode = ShuffleMode::Off; |
| 80 | + self.shuffle_order.clear(); |
| 81 | + } |
| 82 | + pub fn toggle_shuffle(&mut self) { |
| 83 | + match self.shuffle_mode { |
| 84 | + ShuffleMode::Off => self.enable_shuffle(), |
| 85 | + ShuffleMode::On => self.disable_shuffle(), |
| 86 | + } |
| 87 | + } |
| 88 | + pub fn toggle_repeat(&mut self) { |
| 89 | + self.on_repeat = match self.on_repeat { |
| 90 | + RepeatMode::None => RepeatMode::One, |
| 91 | + RepeatMode::One => RepeatMode::All, |
| 92 | + RepeatMode::All => RepeatMode::None, |
| 93 | + } |
| 94 | + } |
62 | 95 | pub async fn play_next(&mut self) -> Result<(), AppError> { |
63 | 96 | if self.current_track.is_none() { |
64 | 97 | return Err(AppError::NoTrackLoaded); |
65 | 98 | } |
| 99 | + if self.shuffle_mode == ShuffleMode::On && !self.shuffle_order.is_empty() { |
| 100 | + self.shuffle_position = (self.shuffle_position + 1) % self.shuffle_order.len(); |
| 101 | + let idx = self.shuffle_order[self.shuffle_position]; |
| 102 | + self.play_from_queue(idx).await?; |
| 103 | + return Ok(()); |
| 104 | + } |
66 | 105 | if self.queue_tab.data.is_empty() { |
67 | 106 | return Err(AppError::EmptyQueue); |
68 | 107 | } else if self.playing_index < self.queue_tab.data.len() - 1 { |
69 | | - self.play_from_queue(self.playing_index + 1).await?; |
| 108 | + match self.on_repeat { |
| 109 | + RepeatMode::One => { |
| 110 | + self.play_selected(self.playing_index).await?; |
| 111 | + } |
| 112 | + RepeatMode::None => { |
| 113 | + self.playing_index += 1; |
| 114 | + self.play_from_queue(self.playing_index).await?; |
| 115 | + } |
| 116 | + RepeatMode::All => {} |
| 117 | + } |
70 | 118 | } else { |
71 | 119 | self.player.lock().await.stop()?; |
72 | 120 | self.is_playing = false; |
@@ -156,15 +204,24 @@ impl App { |
156 | 204 | self.subsonic_client |
157 | 205 | .scrobble(self.current_track.as_ref().unwrap(), true) |
158 | 206 | .await?; |
159 | | - if self.on_repeat { |
160 | | - self.play_selected(self.playing_index).await?; |
161 | | - } else if self.playing_index < self.queue_tab.data.len().saturating_sub(1) { |
162 | | - self.play_next().await?; |
163 | | - } else { |
164 | | - self.is_playing = false; |
165 | | - self.current_track = None; |
166 | | - self.metadata = Metadata::default(); |
167 | | - self.sync_mpris().await; |
| 207 | + match self.on_repeat { |
| 208 | + RepeatMode::One => { |
| 209 | + self.play_selected(self.playing_index).await?; |
| 210 | + } |
| 211 | + RepeatMode::All => { |
| 212 | + let next = (self.playing_index + 1) % self.queue_tab.len(); |
| 213 | + self.play_from_queue(next).await?; |
| 214 | + } |
| 215 | + RepeatMode::None => { |
| 216 | + if self.playing_index < self.queue_tab.data.len().saturating_sub(1) { |
| 217 | + self.play_next().await?; |
| 218 | + } else { |
| 219 | + self.is_playing = false; |
| 220 | + self.current_track = None; |
| 221 | + self.metadata = Metadata::default(); |
| 222 | + self.sync_mpris().await; |
| 223 | + } |
| 224 | + } |
168 | 225 | } |
169 | 226 | Ok(()) |
170 | 227 | } |
|
0 commit comments