music_player_tracklist/
lib.rs1#[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}