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
use crate::Error;
use rodio::Sink;
use std::sync::mpsc;
use std::thread;
struct PlayBytes {
bytes: &'static [u8],
loop_forever: bool,
}
type Request = PlayBytes;
type Response = Sink;
pub struct NativeAudioPlayer {
_audio_thread: thread::JoinHandle<()>,
send_request: mpsc::Sender<Request>,
recv_response: mpsc::Receiver<Response>,
}
impl NativeAudioPlayer {
pub fn try_new_default_device() -> Result<Self, Error> {
let (send_request, recv_request) = mpsc::channel();
let (send_response, recv_response) = mpsc::channel();
let (send_init, recv_init) = mpsc::channel();
let _audio_thread = thread::spawn(move || {
if let Some((_output_stream, output_stream_handle)) =
crate::common::output_stream_handle()
{
send_init.send(Ok(())).unwrap();
for PlayBytes {
bytes,
loop_forever,
} in recv_request
{
let handle = if loop_forever {
crate::common::play_bytes_loop(&output_stream_handle, bytes)
} else {
crate::common::play_bytes(&output_stream_handle, bytes)
};
send_response.send(handle).expect("failed to send response");
}
log::info!("dedicated audio thread stopped");
} else {
send_init
.send(Err(Error::FailedToCreateOutputStream))
.unwrap();
}
});
let () = recv_init
.recv()
.expect("unable to get status of dedicated audio thread")?;
Ok(Self {
_audio_thread,
send_request,
recv_response,
})
}
pub fn new_default_device() -> Self {
Self::try_new_default_device().unwrap()
}
pub fn play_bytes(&self, bytes: &'static [u8]) -> Sink {
self.play_bytes_gerneral(bytes, false)
}
pub fn play_bytes_loop(&self, bytes: &'static [u8]) -> Sink {
self.play_bytes_gerneral(bytes, true)
}
fn play_bytes_gerneral(&self, bytes: &'static [u8], loop_forever: bool) -> Sink {
match self.send_request.send(PlayBytes {
bytes,
loop_forever,
}) {
Err(_) => {
log::error!("can't play audio because dedicated audio thread has stopped");
Sink::new_idle().0
}
Ok(()) => match self.recv_response.recv() {
Err(_) => {
log::error!("no response from dedicated audio thread");
Sink::new_idle().0
}
Ok(sink) => sink,
},
}
}
}