diff options
| author | salmonik <raisersoft@proton.me> | 2026-05-09 15:14:33 +0200 |
|---|---|---|
| committer | salmonik <raisersoft@proton.me> | 2026-05-09 15:14:33 +0200 |
| commit | b3b7f0f65295f2100eb3c9880e870349c43701a6 (patch) | |
| tree | 1b24e6eecc8d7fbe3720208fb496604fe430ab45 /src/queue.rs | |
| parent | Add TODO for major rewrite phases (diff) | |
| download | rsplayer-b3b7f0f65295f2100eb3c9880e870349c43701a6.tar.gz rsplayer-b3b7f0f65295f2100eb3c9880e870349c43701a6.zip | |
Major rewrite: play command, queue display, and shuffle modes
- Play command: no args queues to end (play only if queue empty + player playing),
-i inserts after current and skips, -n inserts after current, removed -l flag
- Queue display: detect terminal size, use pager only if queue exceeds terminal rows
- Shuffle modes: always remember original queue, restore on 'shuffle none',
album shuffle shuffles within each album's range separately
Diffstat (limited to 'src/queue.rs')
| -rw-r--r-- | src/queue.rs | 85 |
1 files changed, 83 insertions, 2 deletions
diff --git a/src/queue.rs b/src/queue.rs index 9e8e1af..109b748 100644 --- a/src/queue.rs +++ b/src/queue.rs | |||
| @@ -124,6 +124,7 @@ pub struct Queue { | |||
| 124 | position: usize, | 124 | position: usize, |
| 125 | shuffle: ShuffleMode, | 125 | shuffle: ShuffleMode, |
| 126 | shuffled_indices: Vec<usize>, | 126 | shuffled_indices: Vec<usize>, |
| 127 | original_tracks: Vec<Track>, | ||
| 127 | } | 128 | } |
| 128 | 129 | ||
| 129 | impl Default for Queue { | 130 | impl Default for Queue { |
| @@ -139,6 +140,7 @@ impl Queue { | |||
| 139 | position: 0, | 140 | position: 0, |
| 140 | shuffle: ShuffleMode::None, | 141 | shuffle: ShuffleMode::None, |
| 141 | shuffled_indices: Vec::new(), | 142 | shuffled_indices: Vec::new(), |
| 143 | original_tracks: Vec::new(), | ||
| 142 | } | 144 | } |
| 143 | } | 145 | } |
| 144 | 146 | ||
| @@ -162,8 +164,38 @@ impl Queue { | |||
| 162 | } | 164 | } |
| 163 | 165 | ||
| 164 | pub fn set_shuffle(&mut self, mode: ShuffleMode) { | 166 | pub fn set_shuffle(&mut self, mode: ShuffleMode) { |
| 165 | self.shuffle = mode; | 167 | match mode { |
| 166 | self.update_shuffle_indices(); | 168 | ShuffleMode::None => { |
| 169 | self.shuffle = ShuffleMode::None; | ||
| 170 | self.restore_from_original(); | ||
| 171 | } | ||
| 172 | ShuffleMode::All => { | ||
| 173 | self.original_tracks = self.tracks.clone(); | ||
| 174 | self.shuffle = ShuffleMode::All; | ||
| 175 | self.update_shuffle_indices(); | ||
| 176 | } | ||
| 177 | ShuffleMode::Album => { | ||
| 178 | self.original_tracks = self.tracks.clone(); | ||
| 179 | self.shuffle = ShuffleMode::Album; | ||
| 180 | self.update_shuffle_indices_album(); | ||
| 181 | } | ||
| 182 | } | ||
| 183 | } | ||
| 184 | |||
| 185 | fn restore_from_original(&mut self) { | ||
| 186 | if self.original_tracks.is_empty() { | ||
| 187 | self.shuffled_indices.clear(); | ||
| 188 | return; | ||
| 189 | } | ||
| 190 | |||
| 191 | let current_pos = self.position; | ||
| 192 | let played: Vec<Track> = self.tracks[..current_pos].to_vec(); | ||
| 193 | let unplayed_original: Vec<Track> = self.original_tracks[current_pos..].to_vec(); | ||
| 194 | |||
| 195 | self.tracks = played; | ||
| 196 | self.tracks.extend(unplayed_original); | ||
| 197 | self.position = current_pos; | ||
| 198 | self.shuffled_indices.clear(); | ||
| 167 | } | 199 | } |
| 168 | 200 | ||
| 169 | fn update_shuffle_indices(&mut self) { | 201 | fn update_shuffle_indices(&mut self) { |
| @@ -180,6 +212,55 @@ impl Queue { | |||
| 180 | } | 212 | } |
| 181 | } | 213 | } |
| 182 | 214 | ||
| 215 | fn update_shuffle_indices_album(&mut self) { | ||
| 216 | let len = self.tracks.len(); | ||
| 217 | self.shuffled_indices = (0..len).collect(); | ||
| 218 | |||
| 219 | let mut rng = rand::rng(); | ||
| 220 | let pos = self.position.min(len.saturating_sub(1)); | ||
| 221 | |||
| 222 | if pos == 0 && len > 1 { | ||
| 223 | self.shuffle_album_range(0..len, &mut rng); | ||
| 224 | } else if pos + 1 < len { | ||
| 225 | self.shuffle_album_range(pos + 1..len, &mut rng); | ||
| 226 | } | ||
| 227 | } | ||
| 228 | |||
| 229 | fn shuffle_album_range(&mut self, range: std::ops::Range<usize>, rng: &mut impl rand::Rng) { | ||
| 230 | if range.start >= range.end { | ||
| 231 | return; | ||
| 232 | } | ||
| 233 | |||
| 234 | let mut album_ranges: Vec<(usize, usize)> = Vec::new(); | ||
| 235 | let mut current_album: Option<&str> = None; | ||
| 236 | let mut range_start: Option<usize> = None; | ||
| 237 | |||
| 238 | for i in range.clone() { | ||
| 239 | let album = self.tracks.get(i).and_then(|t| t.album.as_deref()); | ||
| 240 | match (current_album, range_start) { | ||
| 241 | (None, None) => { | ||
| 242 | current_album = album; | ||
| 243 | range_start = Some(i); | ||
| 244 | } | ||
| 245 | (Some(_), Some(start)) if album != current_album => { | ||
| 246 | album_ranges.push((start, i)); | ||
| 247 | current_album = album; | ||
| 248 | range_start = Some(i); | ||
| 249 | } | ||
| 250 | _ => {} | ||
| 251 | } | ||
| 252 | } | ||
| 253 | if let Some(start) = range_start { | ||
| 254 | album_ranges.push((start, range.end)); | ||
| 255 | } | ||
| 256 | |||
| 257 | for (start, end) in album_ranges { | ||
| 258 | if start + 1 < end { | ||
| 259 | self.shuffled_indices[start..end].shuffle(rng); | ||
| 260 | } | ||
| 261 | } | ||
| 262 | } | ||
| 263 | |||
| 183 | pub fn current(&self) -> Option<&Track> { | 264 | pub fn current(&self) -> Option<&Track> { |
| 184 | if self.tracks.is_empty() { | 265 | if self.tracks.is_empty() { |
| 185 | None | 266 | None |
