thedes_tui_core/audio/
device.rs1use std::{borrow::Cow, fmt, io};
2
3use thiserror::Error;
4
5pub mod null;
6pub mod native;
7pub mod mock;
8
9#[derive(Debug, Error)]
10pub enum PlayNowError {
11 #[error("Failed to decode audio: {0}")]
12 Decode(String),
13 #[error("I/O error playing audio")]
14 Io(#[from] io::Error),
15}
16
17#[derive(Debug, Error)]
18pub enum SetVolumeError {
19 #[error("I/O error setting volume")]
20 Io(#[from] io::Error),
21}
22
23#[derive(Debug, Error)]
24pub enum ClearSinkError {
25 #[error("I/O error clearing the sink")]
26 Io(#[from] io::Error),
27}
28
29#[derive(Debug, Error)]
30pub enum PauseSinkError {
31 #[error("I/O error pausing the sink")]
32 Io(#[from] io::Error),
33}
34
35#[derive(Debug, Error)]
36pub enum ResumeSinkError {
37 #[error("I/O error resuming the sink")]
38 Io(#[from] io::Error),
39}
40
41#[derive(Debug, Error)]
42pub enum CheckPlayStatusError {
43 #[error("I/O error checking playing status")]
44 Io(#[from] io::Error),
45}
46
47#[derive(Debug, Error)]
48pub enum OpenSinkError {
49 #[error("I/O error opening sink")]
50 Io(#[from] io::Error),
51 #[error("Failed to manipulate audio stream: {0}")]
52 Stream(String),
53}
54
55pub trait AudioDevice: fmt::Debug + Send + Sync {
56 fn open_sink(&mut self) -> Result<Box<dyn AudioSinkDevice>, OpenSinkError>;
57}
58
59impl<'a, A> AudioDevice for &'a mut A
60where
61 A: AudioDevice + ?Sized,
62{
63 fn open_sink(&mut self) -> Result<Box<dyn AudioSinkDevice>, OpenSinkError> {
64 (**self).open_sink()
65 }
66}
67
68impl<A> AudioDevice for Box<A>
69where
70 A: AudioDevice + ?Sized,
71{
72 fn open_sink(&mut self) -> Result<Box<dyn AudioSinkDevice>, OpenSinkError> {
73 (**self).open_sink()
74 }
75}
76
77pub trait AudioSinkDevice: fmt::Debug + Send + Sync {
78 fn play_now(
79 &mut self,
80 bytes: Cow<'static, [u8]>,
81 ) -> Result<(), PlayNowError>;
82
83 fn set_volume(&mut self, volume: f32) -> Result<(), SetVolumeError>;
84
85 fn pause(&mut self) -> Result<(), PauseSinkError>;
86
87 fn resume(&mut self) -> Result<(), ResumeSinkError>;
88
89 fn clear(&mut self) -> Result<(), ClearSinkError>;
90
91 fn is_playing(&self) -> Result<bool, CheckPlayStatusError>;
92}
93
94impl<'a, S> AudioSinkDevice for &'a mut S
95where
96 S: AudioSinkDevice + ?Sized,
97{
98 fn play_now(
99 &mut self,
100 bytes: Cow<'static, [u8]>,
101 ) -> Result<(), PlayNowError> {
102 (**self).play_now(bytes)
103 }
104
105 fn set_volume(&mut self, volume: f32) -> Result<(), SetVolumeError> {
106 (**self).set_volume(volume)
107 }
108
109 fn pause(&mut self) -> Result<(), PauseSinkError> {
110 (**self).pause()
111 }
112
113 fn resume(&mut self) -> Result<(), ResumeSinkError> {
114 (**self).resume()
115 }
116
117 fn clear(&mut self) -> Result<(), ClearSinkError> {
118 (**self).clear()
119 }
120
121 fn is_playing(&self) -> Result<bool, CheckPlayStatusError> {
122 (**self).is_playing()
123 }
124}
125
126impl<S> AudioSinkDevice for Box<S>
127where
128 S: AudioSinkDevice + ?Sized,
129{
130 fn play_now(
131 &mut self,
132 bytes: Cow<'static, [u8]>,
133 ) -> Result<(), PlayNowError> {
134 (**self).play_now(bytes)
135 }
136
137 fn set_volume(&mut self, volume: f32) -> Result<(), SetVolumeError> {
138 (**self).set_volume(volume)
139 }
140
141 fn pause(&mut self) -> Result<(), PauseSinkError> {
142 (**self).pause()
143 }
144
145 fn resume(&mut self) -> Result<(), ResumeSinkError> {
146 (**self).resume()
147 }
148
149 fn clear(&mut self) -> Result<(), ClearSinkError> {
150 (**self).clear()
151 }
152
153 fn is_playing(&self) -> Result<bool, CheckPlayStatusError> {
154 (**self).is_playing()
155 }
156}