Skip to main content

proteus_lib/
player.rs

1use rodio::buffer::SamplesBuffer;
2use rodio::{OutputStream, Sink};
3use std::sync::atomic::{AtomicBool, Ordering};
4use std::sync::{Arc, Mutex};
5use std::thread;
6use std::time::Duration;
7
8use crate::effects::effects::clone_samples_buffer;
9use crate::prot::Prot;
10use crate::reporter::{Report, Reporter};
11use crate::timer;
12use crate::{info::Info, player_engine::PlayerEngine};
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub enum PlayerState {
16    Init,
17    Resuming,
18    Playing,
19    Pausing,
20    Paused,
21    Stopping,
22    Stopped,
23    Finished,
24}
25
26#[derive(Clone)]
27pub struct Player {
28    pub info: Info,
29    pub finished_tracks: Arc<Mutex<Vec<i32>>>,
30    pub ts: Arc<Mutex<f64>>,
31    state: Arc<Mutex<PlayerState>>,
32    abort: Arc<AtomicBool>,
33    playback_thread_exists: Arc<AtomicBool>,
34    duration: Arc<Mutex<f64>>,
35    prot: Arc<Mutex<Prot>>,
36    audio_heard: Arc<AtomicBool>,
37    volume: Arc<Mutex<f32>>,
38    sink: Arc<Mutex<Sink>>,
39    audition_source: Arc<Mutex<Option<SamplesBuffer<f32>>>>,
40    reporter: Option<Arc<Mutex<Reporter>>>,
41}
42
43impl Player {
44    pub fn new(file_path: &String) -> Self {
45        let this = Self::new_from_path_or_paths(Some(file_path), None);
46        this
47    }
48
49    pub fn new_from_file_paths(file_paths: &Vec<Vec<String>>) -> Self {
50        let this = Self::new_from_path_or_paths(None, Some(file_paths));
51        this
52    }
53
54    pub fn new_from_path_or_paths(path: Option<&String>, paths: Option<&Vec<Vec<String>>>) -> Self {
55        let (prot, info) = match path {
56            Some(path) => {
57                let prot = Arc::new(Mutex::new(Prot::new(path)));
58                let info = Info::new(path.clone());
59                (prot, info)
60            }
61            None => {
62                let prot = Arc::new(Mutex::new(Prot::new_from_file_paths(paths.unwrap())));
63                let locked_prot = prot.lock().unwrap();
64                let info = Info::new_from_file_paths(locked_prot.get_file_paths_dictionary());
65                drop(locked_prot);
66                (prot, info)
67            }
68        };
69
70        let (_stream, stream_handle) = OutputStream::try_default().unwrap();
71        let sink: Arc<Mutex<Sink>> = Arc::new(Mutex::new(Sink::try_new(&stream_handle).unwrap()));
72        let (_stream, audition_stream_handle) = OutputStream::try_default().unwrap();
73        let audition_sink = Arc::new(Mutex::new(Sink::try_new(&audition_stream_handle).unwrap()));
74
75        let mut this = Self {
76            info,
77            finished_tracks: Arc::new(Mutex::new(Vec::new())),
78            state: Arc::new(Mutex::new(PlayerState::Stopped)),
79            abort: Arc::new(AtomicBool::new(false)),
80            ts: Arc::new(Mutex::new(0.0)),
81            playback_thread_exists: Arc::new(AtomicBool::new(true)),
82            duration: Arc::new(Mutex::new(0.0)),
83            audio_heard: Arc::new(AtomicBool::new(false)),
84            volume: Arc::new(Mutex::new(0.8)),
85            sink,
86            audition_source: Arc::new(Mutex::new(None)),
87            prot,
88            reporter: None,
89        };
90
91        this.initialize_thread(None);
92
93        this
94    }
95
96    fn audition(&self, length: Duration) {
97        let audition_source_mutex = self.audition_source.clone();
98
99        // Create new thread to audition
100        thread::spawn(move || {
101            // Wait until audition source is ready
102            while audition_source_mutex.lock().unwrap().is_none() {
103                thread::sleep(Duration::from_millis(10));
104            }
105
106            let audition_source_option = audition_source_mutex.lock().unwrap().take();
107            let audition_source = audition_source_option.unwrap();
108
109            let (_stream, audition_stream_handle) = OutputStream::try_default().unwrap();
110            let audition_sink = Sink::try_new(&audition_stream_handle).unwrap();
111            audition_sink.pause();
112            audition_sink.set_volume(0.8);
113            audition_sink.append(audition_source);
114            audition_sink.play();
115            thread::sleep(length);
116            audition_sink.pause();
117        });
118    }
119
120    fn initialize_thread(&mut self, ts: Option<f64>) {
121        // Empty finished_tracks
122        let mut finished_tracks = self.finished_tracks.lock().unwrap();
123        finished_tracks.clear();
124        drop(finished_tracks);
125
126        // ===== Set play options ===== //
127        self.abort.store(false, Ordering::SeqCst);
128        self.playback_thread_exists.store(true, Ordering::SeqCst);
129
130        // ===== Clone variables ===== //
131        let play_state = self.state.clone();
132        let abort = self.abort.clone();
133        let playback_thread_exists = self.playback_thread_exists.clone();
134        let time_passed = self.ts.clone();
135
136        let duration = self.duration.clone();
137        let prot = self.prot.clone();
138
139        let audio_heard = self.audio_heard.clone();
140        let volume = self.volume.clone();
141        let sink_mutex = self.sink.clone();
142        let audition_source_mutex = self.audition_source.clone();
143        let channels = 1.0 * self.info.channels as f64;
144
145        audio_heard.store(false, Ordering::Relaxed);
146
147        // clear audition source
148        let mut audition_source = audition_source_mutex.lock().unwrap();
149        *audition_source = None;
150        drop(audition_source);
151
152        // ===== Start playback ===== //
153        thread::spawn(move || {
154            // ===================== //
155            // Set playback_thread_exists to true
156            // ===================== //
157            playback_thread_exists.store(true, Ordering::Relaxed);
158
159            // ===================== //
160            // Initialize engine & sink
161            // ===================== //
162            let start_time = match ts {
163                Some(ts) => ts,
164                None => 0.0,
165            };
166            let mut engine = PlayerEngine::new(prot, Some(abort.clone()), start_time);
167            let (_stream, stream_handle) = OutputStream::try_default().unwrap();
168            // let sink_mutex = Arc::new(Mutex::new(Sink::try_new(&stream_handle).unwrap()));
169
170            let mut sink = sink_mutex.lock().unwrap();
171            *sink = Sink::try_new(&stream_handle).unwrap();
172            sink.pause();
173            sink.set_volume(*volume.lock().unwrap());
174            drop(sink);
175
176            // ===================== //
177            // Set duration from engine
178            // ===================== //
179            let mut duration = duration.lock().unwrap();
180            *duration = engine.get_duration();
181            drop(duration);
182
183            // ===================== //
184            // Initialize chunk_lengths & time_passed
185            // ===================== //
186            let chunk_lengths = Arc::new(Mutex::new(Vec::new()));
187            let mut time_passed_unlocked = time_passed.lock().unwrap();
188            *time_passed_unlocked = start_time;
189            drop(time_passed_unlocked);
190
191            let pause_sink = |sink: &Sink, fade_length_out_seconds: f32| {
192                let timestamp = *time_passed.lock().unwrap();
193
194                let fade_increments = sink.volume() / (fade_length_out_seconds * 100.0);
195                // Fade out and pause sink
196                while sink.volume() > 0.0 && timestamp != start_time {
197                    sink.set_volume(sink.volume() - fade_increments);
198                    thread::sleep(Duration::from_millis(10));
199                }
200                sink.pause();
201            };
202
203            let resume_sink = |sink: &Sink, fade_length_in_seconds: f32| {
204                let volume = *volume.lock().unwrap();
205                let fade_increments = (volume - sink.volume()) / (fade_length_in_seconds * 100.0);
206                // Fade in and play sink
207                sink.play();
208                while sink.volume() < volume {
209                    sink.set_volume(sink.volume() + fade_increments);
210                    thread::sleep(Duration::from_millis(5));
211                }
212            };
213
214            // ===================== //
215            // Start sink with fade in
216            // ===================== //
217            // resume_sink(&sink_mutex.lock().unwrap(), 0.1);
218
219            // ===================== //
220            // Check if the player should be paused or not
221            // ===================== //
222            let check_details = || {
223                if abort.load(Ordering::SeqCst) {
224                    let sink = sink_mutex.lock().unwrap();
225                    pause_sink(&sink, 0.1);
226                    sink.clear();
227                    drop(sink);
228
229                    return false;
230                }
231
232                let sink = sink_mutex.lock().unwrap();
233                let state = play_state.lock().unwrap().clone();
234                if state == PlayerState::Pausing {
235                    pause_sink(&sink, 0.1);
236                    play_state.lock().unwrap().clone_from(&PlayerState::Paused);
237                }
238                if state == PlayerState::Resuming {
239                    resume_sink(&sink, 0.1);
240                    play_state.lock().unwrap().clone_from(&PlayerState::Playing);
241                }
242                drop(sink);
243
244                true
245            };
246
247            // ===================== //
248            // Update chunk_lengths / time_passed
249            // ===================== //
250            let time_chunks_mutex = Arc::new(Mutex::new(start_time));
251            let timer_mut = Arc::new(Mutex::new(timer::Timer::new()));
252            let mut timer = timer_mut.lock().unwrap();
253            timer.start();
254            drop(timer);
255
256            let update_chunk_lengths = || {
257                if abort.load(Ordering::SeqCst) {
258                    return;
259                }
260
261                let mut chunk_lengths = chunk_lengths.lock().unwrap();
262                let mut time_passed_unlocked = time_passed.lock().unwrap();
263                let mut time_chunks_passed = time_chunks_mutex.lock().unwrap();
264                let mut timer = timer_mut.lock().unwrap();
265                // Check how many chunks have been played (chunk_lengths.len() - sink.len())
266                // since the last time this function was called
267                // and add that to time_passed
268                let sink = sink_mutex.lock().unwrap();
269                let chunks_played = chunk_lengths.len() - sink.len();
270
271                for _ in 0..chunks_played {
272                    timer.reset();
273                    timer.start();
274                    *time_chunks_passed += chunk_lengths.remove(0);
275                }
276
277                if sink.is_paused() {
278                    timer.pause();
279                } else {
280                    timer.un_pause();
281                }
282
283                *time_passed_unlocked = *time_chunks_passed + timer.get_time().as_secs_f64();
284
285                drop(sink);
286                drop(chunk_lengths);
287                drop(time_passed_unlocked);
288                drop(time_chunks_passed);
289                drop(timer);
290            };
291
292            // ===================== //
293            // Update sink for each chunk received from engine
294            // ===================== //
295            let update_sink = |(mixer, length_in_seconds): (SamplesBuffer<f32>, f64)| {
296                audio_heard.store(true, Ordering::Relaxed);
297
298                let mut audition_source = audition_source_mutex.lock().unwrap();
299                let sink = sink_mutex.lock().unwrap();
300                let mut chunk_lengths = chunk_lengths.lock().unwrap();
301
302                let total_time = chunk_lengths.iter().sum::<f64>();
303
304                // If total_time is less than 0.2 seconds, audition the chunk
305                if audition_source.is_none() {
306                    let (mixer_clone, mixer) = clone_samples_buffer(mixer);
307                    *audition_source = Some(mixer_clone);
308                    drop(audition_source);
309                    sink.append(mixer);
310                } else {
311                    sink.append(mixer);
312                }
313                drop(sink);
314
315                chunk_lengths.push(length_in_seconds);
316                drop(chunk_lengths);
317
318                update_chunk_lengths();
319                check_details();
320            };
321
322            engine.reception_loop(&update_sink);
323
324            // ===================== //
325            // Wait until all tracks are finished playing in sink
326            // ===================== //
327            loop {
328                update_chunk_lengths();
329                if !check_details() {
330                    break;
331                }
332
333                let sink = sink_mutex.lock().unwrap();
334                let sink_empty = sink.empty();
335                drop(sink);
336                // If all tracks are finished buffering and sink is finished playing, exit the loop
337                if sink_empty && engine.finished_buffering() {
338                    break;
339                }
340
341                thread::sleep(Duration::from_millis(10));
342            }
343
344            // ===================== //
345            // Set playback_thread_exists to false
346            // ===================== //
347            playback_thread_exists.store(false, Ordering::Relaxed);
348        });
349    }
350
351    pub fn play_at(&mut self, ts: f64) {
352        let mut timestamp = self.ts.lock().unwrap();
353        *timestamp = ts;
354        drop(timestamp);
355
356        self.kill_current();
357        // self.stop.store(false, Ordering::SeqCst);
358        self.initialize_thread(Some(ts));
359
360        self.resume();
361
362        // Wait until audio is heard
363        while !self.audio_heard.load(Ordering::Relaxed) {
364            thread::sleep(Duration::from_millis(10));
365        }
366    }
367
368    pub fn play(&mut self) {
369        let thread_exists = self.playback_thread_exists.load(Ordering::SeqCst);
370        // self.stop.store(false, Ordering::SeqCst);
371
372        if !thread_exists {
373            self.initialize_thread(None);
374        }
375
376        self.resume();
377
378        // Wait until audio is heard
379        while !self.audio_heard.load(Ordering::Relaxed) {
380            thread::sleep(Duration::from_millis(10));
381        }
382    }
383
384    pub fn pause(&self) {
385        self.state.lock().unwrap().clone_from(&PlayerState::Pausing);
386    }
387
388    pub fn resume(&self) {
389        self.state
390            .lock()
391            .unwrap()
392            .clone_from(&PlayerState::Resuming);
393    }
394
395    pub fn kill_current(&self) {
396        self.state
397            .lock()
398            .unwrap()
399            .clone_from(&PlayerState::Stopping);
400        self.abort.store(true, Ordering::SeqCst);
401
402        while !self.thread_finished() {
403            thread::sleep(Duration::from_millis(10));
404        }
405
406        self.state.lock().unwrap().clone_from(&PlayerState::Stopped);
407    }
408
409    pub fn stop(&self) {
410        self.kill_current();
411        self.ts.lock().unwrap().clone_from(&0.0);
412    }
413
414    pub fn is_playing(&self) -> bool {
415        let state = self.state.lock().unwrap();
416        *state == PlayerState::Playing
417    }
418
419    pub fn is_paused(&self) -> bool {
420        let state = self.state.lock().unwrap();
421        *state == PlayerState::Paused
422    }
423
424    pub fn get_time(&self) -> f64 {
425        let ts = self.ts.lock().unwrap();
426        *ts
427    }
428
429    fn thread_finished(&self) -> bool {
430        let playback_thread_exists = self.playback_thread_exists.load(Ordering::SeqCst);
431        !playback_thread_exists
432    }
433
434    pub fn is_finished(&self) -> bool {
435        self.thread_finished()
436        // let state = self.state.lock().unwrap();
437        // *state == PlayerState::Finished
438    }
439
440    pub fn sleep_until_end(&self) {
441        loop {
442            if self.thread_finished() {
443                break;
444            }
445            thread::sleep(Duration::from_millis(100));
446        }
447    }
448
449    pub fn get_duration(&self) -> f64 {
450        let duration = self.duration.lock().unwrap();
451        *duration
452    }
453
454    pub fn seek(&mut self, ts: f64) {
455        let mut timestamp = self.ts.lock().unwrap();
456        *timestamp = ts;
457        drop(timestamp);
458
459        let state = self.state.lock().unwrap().clone();
460
461        self.kill_current();
462        self.state.lock().unwrap().clone_from(&state);
463        self.initialize_thread(Some(ts));
464
465        match state {
466            PlayerState::Playing => self.resume(),
467            PlayerState::Paused => {
468                self.audition(Duration::from_millis(100));
469            }
470            _ => {}
471        }
472    }
473
474    pub fn refresh_tracks(&mut self) {
475        let mut prot = self.prot.lock().unwrap();
476        prot.refresh_tracks();
477        drop(prot);
478
479        // If stopped, return
480        if self.thread_finished() {
481            return;
482        }
483
484        // Kill current thread and start
485        // new thread at the current timestamp
486        let ts = self.get_time();
487        self.seek(ts);
488
489        // If previously playing, resume
490        if self.is_playing() {
491            self.resume();
492        }
493
494        // Wait until audio is heard
495        while !self.audio_heard.load(Ordering::Relaxed) {
496            thread::sleep(Duration::from_millis(10));
497        }
498    }
499
500    pub fn shuffle(&mut self) {
501        self.refresh_tracks();
502    }
503
504    pub fn set_volume(&mut self, new_volume: f32) {
505        let sink = self.sink.lock().unwrap();
506        sink.set_volume(new_volume);
507        drop(sink);
508
509        let mut volume = self.volume.lock().unwrap();
510        *volume = new_volume;
511        drop(volume);
512    }
513
514    pub fn get_volume(&self) -> f32 {
515        *self.volume.lock().unwrap()
516    }
517
518    pub fn get_ids(&self) -> Vec<String> {
519        let prot = self.prot.lock().unwrap();
520
521        return prot.get_ids();
522    }
523
524    pub fn set_reporting(
525        &mut self,
526        reporting: Arc<Mutex<dyn Fn(Report) + Send>>,
527        reporting_interval: Duration,
528    ) {
529        if self.reporter.is_some() {
530            self.reporter.as_ref().unwrap().lock().unwrap().stop();
531        }
532
533        let reporter = Arc::new(Mutex::new(Reporter::new(
534            Arc::new(Mutex::new(self.clone())),
535            reporting,
536            reporting_interval,
537        )));
538
539        reporter.lock().unwrap().start();
540
541        self.reporter = Some(reporter);
542    }
543}