1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
mod url_source;
mod player_engine;
mod pulseaudio;

use std::sync::{Arc, RwLock};

use crossbeam_channel::{unbounded, Receiver, Sender};

use crate::player_engine::{PlayerActions, PlayerEngine, PlayerState, PlayerStatus};

pub struct Player {
    inner_player: Arc<RwLock<PlayerEngine>>,
    tx: Sender<PlayerActions>,
    rx_status: Receiver<PlayerStatus>,
    state: Arc<RwLock<PlayerState>>
}

impl Player {
    pub fn new() -> Self {
        let (tx, rx) = unbounded(); 
        let (tx_status, rx_status) = unbounded(); 
        Player {
            inner_player: Arc::new(
                              RwLock::new(
                                  PlayerEngine::new(
                                      // tx.clone(),
                                      rx.clone(),
                                      tx_status.clone(),
                                      // rx_status.clone()
                                      ))),
            tx,
            rx_status,
            state: Arc::new(RwLock::new(PlayerState {
                playing: true,
                duration: 0.0,
                position: 0.0,
            }))
        }
    }

    pub fn open(&self, src: &str) {
        let player = self.inner_player.clone();
        let path = src.to_string();

        let _ = std::thread::spawn(move || {
            let mut p = player.write().unwrap();
            let _result = p.open(&path);
        });

        let rx1 = self.rx_status.clone();
        let s = self.state.clone();
        let _ = std::thread::spawn(move || {
            loop {
                let a = rx1.try_recv();

                match a {
                    Ok(a) => {
                        let mut state = s.write().unwrap();
                        match a {
                            PlayerStatus::SendPlaying(playing) => {
                                state.playing = playing;
                            }
                            PlayerStatus::SendDuration(duration) => {
                                state.duration = duration;
                            }
                            PlayerStatus::SendPosition(position) => {
                                state.position = position;
                            }
                        }
                    },
                    Err(_) => { 
                    },
                }
            }
        });
    }

    pub fn close(&self) {
    }

    pub fn play(&self) {
        let _ = self.tx.send(PlayerActions::Resume);
    }

    pub fn pause(&self) {
        let _ = self.tx.send(PlayerActions::Pause);
    }

    pub fn toggle_play(&self) {
    }

    /// seek to time from the beginning.
    /// `time` is in seconds
    pub fn seek(&self,time: f64) {
        let _ = self.tx.send(PlayerActions::Seek(time));
    }

    /// seek to time relative from current position
    pub fn seek_relative(&self, dt: f64) {
        let new_pos = self.current_position() + dt;
        let _ = self.tx.send(PlayerActions::Seek(new_pos));

    }

    pub fn current_position(&self) -> f64 {
        self.state.read().unwrap().position
    }

    pub fn duration(&self) -> f64 {
        self.state.read().unwrap().duration
    }

}