1use std::error::Error;
2use std::fmt::{Display, Formatter};
3
4/// The requested host, although supported on this platform, is unavailable.
5#[derive(Copy, Clone, Debug)]
6pub struct HostUnavailable;
7
8impl Display for HostUnavailable {
9 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
10 f.write_str(data:"the requested host is unavailable")
11 }
12}
13
14impl Error for HostUnavailable {}
15
16/// Some error has occurred that is specific to the backend from which it was produced.
17///
18/// This error is often used as a catch-all in cases where:
19///
20/// - It is unclear exactly what error might be produced by the backend API.
21/// - It does not make sense to add a variant to the enclosing error type.
22/// - No error was expected to occur at all, but we return an error to avoid the possibility of a
23/// `panic!` caused by some unforeseen or unknown reason.
24///
25/// **Note:** If you notice a `BackendSpecificError` that you believe could be better handled in a
26/// cross-platform manner, please create an issue or submit a pull request with a patch that adds
27/// the necessary error variant to the appropriate error enum.
28#[derive(Clone, Debug)]
29pub struct BackendSpecificError {
30 pub description: String,
31}
32
33impl Display for BackendSpecificError {
34 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
35 write!(
36 f,
37 "A backend-specific error has occurred: {}",
38 self.description
39 )
40 }
41}
42
43impl Error for BackendSpecificError {}
44
45/// An error that might occur while attempting to enumerate the available devices on a system.
46#[derive(Clone, Debug)]
47pub enum DevicesError {
48 /// See the [`BackendSpecificError`] docs for more information about this error variant.
49 BackendSpecific { err: BackendSpecificError },
50}
51
52impl Display for DevicesError {
53 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
54 match self {
55 Self::BackendSpecific { err: &BackendSpecificError } => err.fmt(f),
56 }
57 }
58}
59
60impl Error for DevicesError {}
61
62impl From<BackendSpecificError> for DevicesError {
63 fn from(err: BackendSpecificError) -> Self {
64 Self::BackendSpecific { err }
65 }
66}
67
68/// An error that may occur while attempting to retrieve a device name.
69#[derive(Clone, Debug)]
70pub enum DeviceNameError {
71 /// See the [`BackendSpecificError`] docs for more information about this error variant.
72 BackendSpecific { err: BackendSpecificError },
73}
74
75impl Display for DeviceNameError {
76 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
77 match self {
78 Self::BackendSpecific { err: &BackendSpecificError } => err.fmt(f),
79 }
80 }
81}
82
83impl Error for DeviceNameError {}
84
85impl From<BackendSpecificError> for DeviceNameError {
86 fn from(err: BackendSpecificError) -> Self {
87 Self::BackendSpecific { err }
88 }
89}
90
91/// Error that can happen when enumerating the list of supported formats.
92#[derive(Debug)]
93pub enum SupportedStreamConfigsError {
94 /// The device no longer exists. This can happen if the device is disconnected while the
95 /// program is running.
96 DeviceNotAvailable,
97 /// We called something the C-Layer did not understand
98 InvalidArgument,
99 /// See the [`BackendSpecificError`] docs for more information about this error variant.
100 BackendSpecific { err: BackendSpecificError },
101}
102
103impl Display for SupportedStreamConfigsError {
104 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
105 match self {
106 Self::BackendSpecific { err: &BackendSpecificError } => err.fmt(f),
107 Self::DeviceNotAvailable => f.write_str(data:"The requested device is no longer available. For example, it has been unplugged."),
108 Self::InvalidArgument => f.write_str(data:"Invalid argument passed to the backend. For example, this happens when trying to read capture capabilities when the device does not support it.")
109 }
110 }
111}
112
113impl Error for SupportedStreamConfigsError {}
114
115impl From<BackendSpecificError> for SupportedStreamConfigsError {
116 fn from(err: BackendSpecificError) -> Self {
117 Self::BackendSpecific { err }
118 }
119}
120
121/// May occur when attempting to request the default input or output stream format from a [`Device`](crate::Device).
122#[derive(Debug)]
123pub enum DefaultStreamConfigError {
124 /// The device no longer exists. This can happen if the device is disconnected while the
125 /// program is running.
126 DeviceNotAvailable,
127 /// Returned if e.g. the default input format was requested on an output-only audio device.
128 StreamTypeNotSupported,
129 /// See the [`BackendSpecificError`] docs for more information about this error variant.
130 BackendSpecific { err: BackendSpecificError },
131}
132
133impl Display for DefaultStreamConfigError {
134 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
135 match self {
136 Self::BackendSpecific { err: &BackendSpecificError } => err.fmt(f),
137 DefaultStreamConfigError::DeviceNotAvailable => f.write_str(
138 data:"The requested device is no longer available. For example, it has been unplugged.",
139 ),
140 DefaultStreamConfigError::StreamTypeNotSupported => {
141 f.write_str(data:"The requested stream type is not supported by the device.")
142 }
143 }
144 }
145}
146
147impl Error for DefaultStreamConfigError {}
148
149impl From<BackendSpecificError> for DefaultStreamConfigError {
150 fn from(err: BackendSpecificError) -> Self {
151 Self::BackendSpecific { err }
152 }
153}
154/// Error that can happen when creating a [`Stream`](crate::Stream).
155#[derive(Debug)]
156pub enum BuildStreamError {
157 /// The device no longer exists. This can happen if the device is disconnected while the
158 /// program is running.
159 DeviceNotAvailable,
160 /// The specified stream configuration is not supported.
161 StreamConfigNotSupported,
162 /// We called something the C-Layer did not understand
163 ///
164 /// On ALSA device functions called with a feature they do not support will yield this. E.g.
165 /// Trying to use capture capabilities on an output only format yields this.
166 InvalidArgument,
167 /// Occurs if adding a new Stream ID would cause an integer overflow.
168 StreamIdOverflow,
169 /// See the [`BackendSpecificError`] docs for more information about this error variant.
170 BackendSpecific { err: BackendSpecificError },
171}
172
173impl Display for BuildStreamError {
174 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
175 match self {
176 Self::BackendSpecific { err: &BackendSpecificError } => err.fmt(f),
177 BuildStreamError::DeviceNotAvailable => f.write_str(
178 data:"The requested device is no longer available. For example, it has been unplugged.",
179 ),
180 BuildStreamError::StreamConfigNotSupported => {
181 f.write_str(data:"The requested stream configuration is not supported by the device.")
182 }
183 BuildStreamError::InvalidArgument => f.write_str(
184 data:"The requested device does not support this capability (invalid argument)",
185 ),
186 BuildStreamError::StreamIdOverflow => {
187 f.write_str(data:"Adding a new stream ID would cause an overflow")
188 }
189 }
190 }
191}
192
193impl Error for BuildStreamError {}
194
195impl From<BackendSpecificError> for BuildStreamError {
196 fn from(err: BackendSpecificError) -> Self {
197 Self::BackendSpecific { err }
198 }
199}
200
201/// Errors that might occur when calling [`Stream::play()`](crate::traits::StreamTrait::play).
202///
203/// As of writing this, only macOS may immediately return an error while calling this method. This
204/// is because both the alsa and wasapi backends only enqueue these commands and do not process
205/// them immediately.
206#[derive(Debug)]
207pub enum PlayStreamError {
208 /// The device associated with the stream is no longer available.
209 DeviceNotAvailable,
210 /// See the [`BackendSpecificError`] docs for more information about this error variant.
211 BackendSpecific { err: BackendSpecificError },
212}
213
214impl Display for PlayStreamError {
215 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
216 match self {
217 Self::BackendSpecific { err: &BackendSpecificError } => err.fmt(f),
218 PlayStreamError::DeviceNotAvailable => {
219 f.write_str(data:"the device associated with the stream is no longer available")
220 }
221 }
222 }
223}
224
225impl Error for PlayStreamError {}
226
227impl From<BackendSpecificError> for PlayStreamError {
228 fn from(err: BackendSpecificError) -> Self {
229 Self::BackendSpecific { err }
230 }
231}
232
233/// Errors that might occur when calling [`Stream::pause()`](crate::traits::StreamTrait::pause).
234///
235/// As of writing this, only macOS may immediately return an error while calling this method. This
236/// is because both the alsa and wasapi backends only enqueue these commands and do not process
237/// them immediately.
238#[derive(Debug)]
239pub enum PauseStreamError {
240 /// The device associated with the stream is no longer available.
241 DeviceNotAvailable,
242 /// See the [`BackendSpecificError`] docs for more information about this error variant.
243 BackendSpecific { err: BackendSpecificError },
244}
245
246impl Display for PauseStreamError {
247 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
248 match self {
249 Self::BackendSpecific { err: &BackendSpecificError } => err.fmt(f),
250 PauseStreamError::DeviceNotAvailable => {
251 f.write_str(data:"the device associated with the stream is no longer available")
252 }
253 }
254 }
255}
256
257impl Error for PauseStreamError {}
258
259impl From<BackendSpecificError> for PauseStreamError {
260 fn from(err: BackendSpecificError) -> Self {
261 Self::BackendSpecific { err }
262 }
263}
264
265/// Errors that might occur while a stream is running.
266#[derive(Debug)]
267pub enum StreamError {
268 /// The device no longer exists. This can happen if the device is disconnected while the
269 /// program is running.
270 DeviceNotAvailable,
271 /// See the [`BackendSpecificError`] docs for more information about this error variant.
272 BackendSpecific { err: BackendSpecificError },
273}
274
275impl Display for StreamError {
276 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
277 match self {
278 Self::BackendSpecific { err: &BackendSpecificError } => err.fmt(f),
279 StreamError::DeviceNotAvailable => f.write_str(
280 data:"The requested device is no longer available. For example, it has been unplugged.",
281 ),
282 }
283 }
284}
285
286impl Error for StreamError {}
287
288impl From<BackendSpecificError> for StreamError {
289 fn from(err: BackendSpecificError) -> Self {
290 Self::BackendSpecific { err }
291 }
292}
293