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, PartialEq, Eq, Hash)]
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, PartialEq, Eq, Hash)]
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, PartialEq, Eq, Hash)]
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, PartialEq, Eq, Hash)]
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(Clone, Debug, PartialEq, Eq, Hash)]
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(Clone, Debug, PartialEq, Eq, Hash)]
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            Self::DeviceNotAvailable => f.write_str(
138                "The requested device is no longer available. For example, it has been unplugged.",
139            ),
140            Self::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(Clone, Debug, PartialEq, Eq, Hash)]
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            Self::DeviceNotAvailable => f.write_str(
178                "The requested device is no longer available. For example, it has been unplugged.",
179            ),
180            Self::StreamConfigNotSupported => {
181                f.write_str("The requested stream configuration is not supported by the device.")
182            }
183            Self::InvalidArgument => f.write_str(
184                "The requested device does not support this capability (invalid argument)",
185            ),
186            Self::StreamIdOverflow => f.write_str("Adding a new stream ID would cause an overflow"),
187        }
188    }
189}
190
191impl Error for BuildStreamError {}
192
193impl From<BackendSpecificError> for BuildStreamError {
194    fn from(err: BackendSpecificError) -> Self {
195        Self::BackendSpecific { err }
196    }
197}
198
199/// Errors that might occur when calling [`Stream::play()`](crate::traits::StreamTrait::play).
200///
201/// As of writing this, only macOS may immediately return an error while calling this method. This
202/// is because both the alsa and wasapi backends only enqueue these commands and do not process
203/// them immediately.
204#[derive(Clone, Debug, PartialEq, Eq, Hash)]
205pub enum PlayStreamError {
206    /// The device associated with the stream is no longer available.
207    DeviceNotAvailable,
208    /// See the [`BackendSpecificError`] docs for more information about this error variant.
209    BackendSpecific { err: BackendSpecificError },
210}
211
212impl Display for PlayStreamError {
213    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
214        match self {
215            Self::BackendSpecific { err } => err.fmt(f),
216            Self::DeviceNotAvailable => {
217                f.write_str("the device associated with the stream is no longer available")
218            }
219        }
220    }
221}
222
223impl Error for PlayStreamError {}
224
225impl From<BackendSpecificError> for PlayStreamError {
226    fn from(err: BackendSpecificError) -> Self {
227        Self::BackendSpecific { err }
228    }
229}
230
231/// Errors that might occur when calling [`Stream::pause()`](crate::traits::StreamTrait::pause).
232///
233/// As of writing this, only macOS may immediately return an error while calling this method. This
234/// is because both the alsa and wasapi backends only enqueue these commands and do not process
235/// them immediately.
236#[derive(Clone, Debug, PartialEq, Eq, Hash)]
237pub enum PauseStreamError {
238    /// The device associated with the stream is no longer available.
239    DeviceNotAvailable,
240    /// See the [`BackendSpecificError`] docs for more information about this error variant.
241    BackendSpecific { err: BackendSpecificError },
242}
243
244impl Display for PauseStreamError {
245    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
246        match self {
247            Self::BackendSpecific { err } => err.fmt(f),
248            Self::DeviceNotAvailable => {
249                f.write_str("the device associated with the stream is no longer available")
250            }
251        }
252    }
253}
254
255impl Error for PauseStreamError {}
256
257impl From<BackendSpecificError> for PauseStreamError {
258    fn from(err: BackendSpecificError) -> Self {
259        Self::BackendSpecific { err }
260    }
261}
262
263/// Errors that might occur while a stream is running.
264#[derive(Clone, Debug, PartialEq, Eq, Hash)]
265pub enum StreamError {
266    /// The device no longer exists. This can happen if the device is disconnected while the
267    /// program is running.
268    DeviceNotAvailable,
269    /// See the [`BackendSpecificError`] docs for more information about this error variant.
270    BackendSpecific { err: BackendSpecificError },
271}
272
273impl Display for StreamError {
274    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
275        match self {
276            Self::BackendSpecific { err } => err.fmt(f),
277            Self::DeviceNotAvailable => f.write_str(
278                "The requested device is no longer available. For example, it has been unplugged.",
279            ),
280        }
281    }
282}
283
284impl Error for StreamError {}
285
286impl From<BackendSpecificError> for StreamError {
287    fn from(err: BackendSpecificError) -> Self {
288        Self::BackendSpecific { err }
289    }
290}