music_player_tracklist/
lib.rs

1#[cfg(test)]
2mod tests;
3
4use music_player_entity::track::Model as Track;
5use rand::seq::SliceRandom;
6
7#[derive(Default, Debug, Clone, PartialEq)]
8pub struct PlaybackState {
9    pub position_ms: u32,
10    pub is_playing: bool,
11}
12
13#[derive(Debug, Clone)]
14pub struct Tracklist {
15    tracks: Vec<Track>,
16    played: Vec<Track>,
17    current_track: Option<Track>,
18    playback_state: PlaybackState,
19}
20
21impl Tracklist {
22    pub fn new(tracks: Vec<Track>) -> Self {
23        Self {
24            tracks,
25            played: Vec::new(),
26            current_track: None,
27            playback_state: PlaybackState::default(),
28        }
29    }
30    pub fn new_empty() -> Self {
31        Self {
32            tracks: Vec::new(),
33            played: Vec::new(),
34            current_track: None,
35            playback_state: PlaybackState::default(),
36        }
37    }
38
39    pub fn add_track(&mut self, track: Track) {
40        self.tracks.push(track);
41    }
42
43    pub fn next_track(&mut self) -> Option<Track> {
44        if self.tracks.is_empty() {
45            return None;
46        }
47
48        let next_track = self.tracks.remove(0);
49        self.current_track = Some(next_track.clone());
50        self.played.push(next_track.clone());
51        Some(next_track)
52    }
53
54    pub fn previous_track(&mut self) -> Option<Track> {
55        if self.played.len() < 2 {
56            return None;
57        }
58
59        let previous_track = self.played.pop().unwrap();
60        self.tracks.insert(0, previous_track.clone());
61
62        if self.played.is_empty() {
63            self.current_track = None;
64            return None;
65        }
66
67        let previous_track = self.played.pop().unwrap();
68        self.current_track = Some(previous_track.clone());
69
70        self.played.push(previous_track.clone());
71
72        Some(previous_track)
73    }
74
75    pub fn current_track(&self) -> (Option<Track>, usize) {
76        (self.current_track.clone(), self.played.len())
77    }
78
79    pub fn tracks(&self) -> (Vec<Track>, Vec<Track>) {
80        (self.played.clone(), self.tracks.clone())
81    }
82
83    pub fn is_empty(&self) -> bool {
84        self.tracks.is_empty()
85    }
86
87    pub fn len(&self) -> usize {
88        self.tracks.len()
89    }
90
91    pub fn clear(&mut self) {
92        self.tracks.clear();
93        self.played.clear();
94    }
95
96    pub fn remove_track(&mut self, track: Track) {
97        self.tracks.retain(|t| t.id != track.id);
98        self.played.retain(|t| t.id != track.id);
99    }
100
101    pub fn remove_track_at(&mut self, index: usize) {
102        if index >= self.played.len() {
103            self.tracks.remove(index - self.played.len());
104            return;
105        }
106        self.played.remove(index);
107    }
108
109    pub fn insert(&mut self, index: usize, track: Track) {
110        self.tracks.insert(index, track);
111    }
112
113    pub fn insert_tracks(&mut self, index: usize, tracks: Vec<Track>) {
114        self.tracks.splice(index..index, tracks);
115    }
116
117    pub fn insert_next(&mut self, track: Track) {
118        self.tracks.insert(0, track);
119    }
120
121    pub fn queue(&mut self, tracks: Vec<Track>) {
122        self.tracks.extend(tracks);
123    }
124
125    pub fn shuffle(&mut self) {
126        self.tracks.shuffle(&mut rand::thread_rng());
127    }
128
129    pub fn play_track_at(&mut self, index: usize) -> (Option<Track>, usize) {
130        if index >= (self.tracks.len() + self.played.len()) {
131            return (None, 0);
132        }
133
134        self.played = [self.played.clone(), self.tracks.clone()].concat();
135        self.tracks = self.played.split_off(index);
136
137        if index > 1 && index < self.played.len() - 1 {
138            self.next_track();
139        }
140        self.next_track();
141        self.current_track()
142    }
143
144    pub fn playback_state(&self) -> PlaybackState {
145        self.playback_state.clone()
146    }
147
148    pub fn set_playback_state(&mut self, playback_state: PlaybackState) {
149        self.playback_state = playback_state;
150    }
151
152    pub fn stop(&mut self) {
153        self.current_track = None;
154        self.playback_state.is_playing = false;
155    }
156
157    pub fn load_tracks(&mut self, tracks: Vec<Track>) {
158        self.clear();
159        self.tracks = tracks;
160    }
161}