cpal/
error.rs

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("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 } => 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 } => 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 } => err.fmt(f),
107            Self::DeviceNotAvailable => f.write_str("The requested device is no longer available. For example, it has been unplugged."),
108            Self::InvalidArgument => f.write_str("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 } => err.fmt(f),
137            DefaultStreamConfigError::DeviceNotAvailable => f.write_str(
138                "The requested device is no longer available. For example, it has been unplugged.",
139            ),
140            DefaultStreamConfigError::StreamTypeNotSupported => {
141                f.write_str("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 } => err.fmt(f),
177            BuildStreamError::DeviceNotAvailable => f.write_str(
178                "The requested device is no longer available. For example, it has been unplugged.",
179            ),
180            BuildStreamError::StreamConfigNotSupported => {
181                f.write_str("The requested stream configuration is not supported by the device.")
182            }
183            BuildStreamError::InvalidArgument => f.write_str(
184                "The requested device does not support this capability (invalid argument)",
185            ),
186            BuildStreamError::StreamIdOverflow => {
187                f.write_str("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 } => err.fmt(f),
218            PlayStreamError::DeviceNotAvailable => {
219                f.write_str("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 } => err.fmt(f),
250            PauseStreamError::DeviceNotAvailable => {
251                f.write_str("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 } => err.fmt(f),
279            StreamError::DeviceNotAvailable => f.write_str(
280                "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}