coreaudio/
error.rs

1//! This module is an attempt at rustifying the OSStatus result.
2
3pub use self::audio::Error as AudioError;
4pub use self::audio_codec::Error as AudioCodecError;
5pub use self::audio_format::Error as AudioFormatError;
6pub use self::audio_unit::Error as AudioUnitError;
7use crate::OSStatus;
8
9use objc2_audio_toolbox::{
10    kAudioServicesSystemSoundClientTimedOutError, kAudioServicesSystemSoundUnspecifiedError,
11};
12
13pub mod audio {
14    use crate::OSStatus;
15    use objc2_core_audio_types::{
16        kAudio_BadFilePathError, kAudio_FileNotFoundError, kAudio_FilePermissionError,
17        kAudio_MemFullError, kAudio_ParamError, kAudio_TooManyFilesOpenError,
18        kAudio_UnimplementedError,
19    };
20
21    #[derive(Copy, Clone, Debug)]
22    pub enum Error {
23        Unimplemented = kAudio_UnimplementedError as isize,
24        FileNotFound = kAudio_FileNotFoundError as isize,
25        FilePermission = kAudio_FilePermissionError as isize,
26        TooManyFilesOpen = kAudio_TooManyFilesOpenError as isize,
27        BadFilePath = kAudio_BadFilePathError as isize,
28        Param = kAudio_ParamError as isize,
29        MemFull = kAudio_MemFullError as isize,
30        Unknown,
31    }
32
33    impl Error {
34        pub fn from_os_status(os_status: OSStatus) -> Result<(), Error> {
35            match os_status {
36                0 => Ok(()),
37                _ if os_status == kAudio_UnimplementedError => Err(Error::Unimplemented),
38                _ if os_status == kAudio_FileNotFoundError => Err(Error::FileNotFound),
39                _ if os_status == kAudio_FilePermissionError => Err(Error::FilePermission),
40                _ if os_status == kAudio_TooManyFilesOpenError => Err(Error::TooManyFilesOpen),
41                _ if os_status == kAudio_BadFilePathError => Err(Error::BadFilePath),
42                _ if os_status == kAudio_ParamError => Err(Error::Param),
43                _ if os_status == kAudio_MemFullError => Err(Error::MemFull),
44                _ => Err(Error::Unknown),
45            }
46        }
47
48        pub fn as_os_status(&self) -> OSStatus {
49            *self as OSStatus
50        }
51    }
52
53    impl std::error::Error for Error {}
54
55    impl ::std::fmt::Display for Error {
56        fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
57            let description = match *self {
58                Error::Unimplemented => "Unimplemented",
59                Error::FileNotFound => "File not found",
60                Error::FilePermission => "File permission",
61                Error::TooManyFilesOpen => "Too many files open",
62                Error::BadFilePath => "Bad file path",
63                Error::Param => "Param",
64                Error::MemFull => "Memory full",
65                Error::Unknown => "An unknown error occurred",
66            };
67            write!(f, "{description}")
68        }
69    }
70}
71
72pub mod audio_codec {
73    use crate::OSStatus;
74    use objc2_audio_toolbox::{
75        kAudioCodecBadDataError, kAudioCodecBadPropertySizeError, kAudioCodecIllegalOperationError,
76        kAudioCodecNotEnoughBufferSpaceError, kAudioCodecStateError,
77        kAudioCodecUnknownPropertyError, kAudioCodecUnspecifiedError,
78        kAudioCodecUnsupportedFormatError,
79    };
80
81    #[derive(Copy, Clone, Debug)]
82    pub enum Error {
83        Unspecified = kAudioCodecUnspecifiedError as isize,
84        UnknownProperty = kAudioCodecUnknownPropertyError as isize,
85        BadPropertySize = kAudioCodecBadPropertySizeError as isize,
86        IllegalOperation = kAudioCodecIllegalOperationError as isize,
87        UnsupportedFormat = kAudioCodecUnsupportedFormatError as isize,
88        State = kAudioCodecStateError as isize,
89        NotEnoughBufferSpace = kAudioCodecNotEnoughBufferSpaceError as isize,
90        BadData = kAudioCodecBadDataError as isize,
91        Unknown,
92    }
93
94    impl Error {
95        pub fn from_os_status(os_status: OSStatus) -> Result<(), Error> {
96            match os_status {
97                0 => Ok(()),
98                _ if os_status == kAudioCodecUnspecifiedError => Err(Error::Unspecified),
99                _ if os_status == kAudioCodecUnknownPropertyError => Err(Error::UnknownProperty),
100                _ if os_status == kAudioCodecBadPropertySizeError => Err(Error::BadPropertySize),
101                _ if os_status == kAudioCodecIllegalOperationError => Err(Error::IllegalOperation),
102                _ if os_status == kAudioCodecUnsupportedFormatError => {
103                    Err(Error::UnsupportedFormat)
104                }
105                _ if os_status == kAudioCodecStateError => Err(Error::State),
106                _ if os_status == kAudioCodecNotEnoughBufferSpaceError => {
107                    Err(Error::NotEnoughBufferSpace)
108                }
109                _ if os_status == kAudioCodecBadDataError => Err(Error::BadData),
110                _ => Err(Error::Unknown),
111            }
112        }
113
114        pub fn as_os_status(&self) -> OSStatus {
115            *self as OSStatus
116        }
117    }
118
119    impl std::error::Error for Error {}
120
121    impl ::std::fmt::Display for Error {
122        fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
123            let description = match *self {
124                Error::Unspecified => "Unspecified",
125                Error::UnknownProperty => "Unknown property",
126                Error::BadPropertySize => "Bad property size",
127                Error::IllegalOperation => "Illegal operation",
128                Error::UnsupportedFormat => "Unsupported format",
129                Error::State => "State",
130                Error::NotEnoughBufferSpace => "Not enough buffer space",
131                Error::BadData => "Bad data",
132                Error::Unknown => "Unknown error occurred",
133            };
134            write!(f, "{description}")
135        }
136    }
137}
138
139pub mod audio_format {
140    use crate::OSStatus;
141    use objc2_audio_toolbox::{
142        kAudioFormatBadPropertySizeError, kAudioFormatBadSpecifierSizeError,
143        kAudioFormatUnknownFormatError, kAudioFormatUnspecifiedError,
144        kAudioFormatUnsupportedDataFormatError, kAudioFormatUnsupportedPropertyError,
145    };
146
147    // TODO: Finish implementing these values.
148    #[derive(Copy, Clone, Debug)]
149    pub enum Error {
150        Unspecified = kAudioFormatUnspecifiedError as isize,
151        UnsupportedProperty = kAudioFormatUnsupportedPropertyError as isize,
152        BadPropertySize = kAudioFormatBadPropertySizeError as isize,
153        BadSpecifierSize = kAudioFormatBadSpecifierSizeError as isize,
154        UnsupportedDataFormat = kAudioFormatUnsupportedDataFormatError as isize,
155        UnknownFormat = kAudioFormatUnknownFormatError as isize,
156        Unknown,
157    }
158
159    impl Error {
160        pub fn from_os_status(os_status: OSStatus) -> Result<(), Error> {
161            match os_status {
162                0 => Ok(()),
163                _ if os_status == kAudioFormatUnspecifiedError => Err(Error::Unspecified),
164                _ if os_status == kAudioFormatUnsupportedPropertyError => {
165                    Err(Error::UnsupportedProperty)
166                }
167                _ if os_status == kAudioFormatBadPropertySizeError => Err(Error::BadPropertySize),
168                _ if os_status == kAudioFormatBadSpecifierSizeError => Err(Error::BadSpecifierSize),
169                _ if os_status == kAudioFormatUnsupportedDataFormatError => {
170                    Err(Error::UnsupportedDataFormat)
171                }
172                _ if os_status == kAudioFormatUnknownFormatError => Err(Error::UnknownFormat),
173                _ => Err(Error::Unknown),
174            }
175        }
176
177        pub fn as_os_status(&self) -> OSStatus {
178            *self as OSStatus
179        }
180    }
181
182    impl std::error::Error for Error {}
183
184    impl ::std::fmt::Display for Error {
185        fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
186            let description = match *self {
187                Error::Unspecified => "An unspecified error",
188                Error::UnsupportedProperty => "The specified property is not supported",
189                Error::BadPropertySize => "Bad property size",
190                Error::BadSpecifierSize => "Bad specifier size",
191                Error::UnsupportedDataFormat => "The specified data format is not supported",
192                Error::UnknownFormat => "The specified data format is not a known format",
193                Error::Unknown => "Unknown error occurred",
194            };
195            write!(f, "{description}")
196        }
197    }
198}
199
200pub mod audio_unit {
201    use crate::OSStatus;
202    use objc2_audio_toolbox::{
203        kAudioUnitErr_CannotDoInCurrentContext, kAudioUnitErr_FailedInitialization,
204        kAudioUnitErr_FormatNotSupported, kAudioUnitErr_Initialized, kAudioUnitErr_InvalidElement,
205        kAudioUnitErr_InvalidFile, kAudioUnitErr_InvalidOfflineRender,
206        kAudioUnitErr_InvalidParameter, kAudioUnitErr_InvalidProperty,
207        kAudioUnitErr_InvalidPropertyValue, kAudioUnitErr_InvalidScope, kAudioUnitErr_NoConnection,
208        kAudioUnitErr_PropertyNotInUse, kAudioUnitErr_PropertyNotWritable,
209        kAudioUnitErr_TooManyFramesToProcess, kAudioUnitErr_Unauthorized,
210        kAudioUnitErr_Uninitialized,
211    };
212
213    #[derive(Copy, Clone, Debug)]
214    pub enum Error {
215        InvalidProperty = kAudioUnitErr_InvalidProperty as isize,
216        InvalidParameter = kAudioUnitErr_InvalidParameter as isize,
217        InvalidElement = kAudioUnitErr_InvalidElement as isize,
218        NoConnection = kAudioUnitErr_NoConnection as isize,
219        FailedInitialization = kAudioUnitErr_FailedInitialization as isize,
220        TooManyFramesToProcess = kAudioUnitErr_TooManyFramesToProcess as isize,
221        InvalidFile = kAudioUnitErr_InvalidFile as isize,
222        FormatNotSupported = kAudioUnitErr_FormatNotSupported as isize,
223        Uninitialized = kAudioUnitErr_Uninitialized as isize,
224        InvalidScope = kAudioUnitErr_InvalidScope as isize,
225        PropertyNotWritable = kAudioUnitErr_PropertyNotWritable as isize,
226        CannotDoInCurrentContext = kAudioUnitErr_CannotDoInCurrentContext as isize,
227        InvalidPropertyValue = kAudioUnitErr_InvalidPropertyValue as isize,
228        PropertyNotInUse = kAudioUnitErr_PropertyNotInUse as isize,
229        Initialized = kAudioUnitErr_Initialized as isize,
230        InvalidOfflineRender = kAudioUnitErr_InvalidOfflineRender as isize,
231        Unauthorized = kAudioUnitErr_Unauthorized as isize,
232        Unknown,
233    }
234
235    impl Error {
236        pub fn from_os_status(os_status: OSStatus) -> Result<(), Error> {
237            match os_status {
238                _ if os_status == kAudioUnitErr_InvalidProperty => Err(Error::InvalidProperty),
239                _ if os_status == kAudioUnitErr_InvalidParameter => Err(Error::InvalidParameter),
240                _ if os_status == kAudioUnitErr_InvalidElement => Err(Error::InvalidElement),
241                _ if os_status == kAudioUnitErr_NoConnection => Err(Error::NoConnection),
242                _ if os_status == kAudioUnitErr_FailedInitialization => {
243                    Err(Error::FailedInitialization)
244                }
245                _ if os_status == kAudioUnitErr_TooManyFramesToProcess => {
246                    Err(Error::TooManyFramesToProcess)
247                }
248                _ if os_status == kAudioUnitErr_InvalidFile => Err(Error::InvalidFile),
249                _ if os_status == kAudioUnitErr_FormatNotSupported => {
250                    Err(Error::FormatNotSupported)
251                }
252                _ if os_status == kAudioUnitErr_Uninitialized => Err(Error::Uninitialized),
253                _ if os_status == kAudioUnitErr_InvalidScope => Err(Error::InvalidScope),
254                _ if os_status == kAudioUnitErr_PropertyNotWritable => {
255                    Err(Error::PropertyNotWritable)
256                }
257                _ if os_status == kAudioUnitErr_CannotDoInCurrentContext => {
258                    Err(Error::CannotDoInCurrentContext)
259                }
260                _ if os_status == kAudioUnitErr_InvalidPropertyValue => {
261                    Err(Error::InvalidPropertyValue)
262                }
263                _ if os_status == kAudioUnitErr_PropertyNotInUse => Err(Error::PropertyNotInUse),
264                _ if os_status == kAudioUnitErr_Initialized => Err(Error::Initialized),
265                _ if os_status == kAudioUnitErr_InvalidOfflineRender => {
266                    Err(Error::InvalidOfflineRender)
267                }
268                _ if os_status == kAudioUnitErr_Unauthorized => Err(Error::Unauthorized),
269                _ => Err(Error::Unknown),
270            }
271        }
272
273        pub fn as_os_status(&self) -> OSStatus {
274            *self as OSStatus
275        }
276    }
277
278    impl std::error::Error for Error {}
279
280    impl ::std::fmt::Display for Error {
281        fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
282            let description = match *self {
283                Error::InvalidProperty => "Invalid property",
284                Error::InvalidParameter => "Invalid parameter",
285                Error::InvalidElement => "Invalid element",
286                Error::NoConnection => "No connection",
287                Error::FailedInitialization => "Failed initialization",
288                Error::TooManyFramesToProcess => "Too many frames to process",
289                Error::InvalidFile => "Invalid file",
290                Error::FormatNotSupported => "Format not supported",
291                Error::Uninitialized => "Uninitialized",
292                Error::InvalidScope => "Invalid scope",
293                Error::PropertyNotWritable => "Property not writable",
294                Error::CannotDoInCurrentContext => "Cannot do in current context",
295                Error::InvalidPropertyValue => "Invalid property value",
296                Error::PropertyNotInUse => "Property not in use",
297                Error::Initialized => "Initialized",
298                Error::InvalidOfflineRender => "Invalid offline render",
299                Error::Unauthorized => "Unauthorized",
300                Error::Unknown => "Unknown error occurred",
301            };
302            write!(f, "{description}")
303        }
304    }
305}
306
307/// A wrapper around all possible Core Audio errors.
308#[derive(Copy, Clone, Debug)]
309pub enum Error {
310    Unspecified,
311    SystemSoundClientMessageTimedOut,
312    NoMatchingDefaultAudioUnitFound,
313    RenderCallbackBufferFormatDoesNotMatchAudioUnitStreamFormat,
314    NoKnownSubtype,
315    NonInterleavedInputOnlySupportsMono,
316    UnsupportedSampleRate,
317    UnsupportedStreamFormat,
318    Audio(AudioError),
319    AudioCodec(AudioCodecError),
320    AudioFormat(AudioFormatError),
321    AudioUnit(AudioUnitError),
322    Unknown(OSStatus),
323}
324
325impl Error {
326    /// Convert an OSStatus to a std Rust Result.
327    pub fn from_os_status(os_status: OSStatus) -> Result<(), Error> {
328        match os_status {
329            0 => Ok(()),
330            _ if os_status == kAudioServicesSystemSoundUnspecifiedError => Err(Error::Unspecified),
331            _ if os_status == kAudioServicesSystemSoundClientTimedOutError => {
332                Err(Error::SystemSoundClientMessageTimedOut)
333            }
334            _ => {
335                match AudioError::from_os_status(os_status) {
336                    Ok(()) => return Ok(()),
337                    Err(AudioError::Unknown) => (),
338                    Err(err) => return Err(Error::Audio(err)),
339                }
340                match AudioCodecError::from_os_status(os_status) {
341                    Ok(()) => return Ok(()),
342                    Err(AudioCodecError::Unknown) => (),
343                    Err(err) => return Err(Error::AudioCodec(err)),
344                }
345                match AudioFormatError::from_os_status(os_status) {
346                    Ok(()) => return Ok(()),
347                    Err(AudioFormatError::Unknown) => (),
348                    Err(err) => return Err(Error::AudioFormat(err)),
349                }
350                match AudioUnitError::from_os_status(os_status) {
351                    Ok(()) => return Ok(()),
352                    Err(AudioUnitError::Unknown) => (),
353                    Err(err) => return Err(Error::AudioUnit(err)),
354                }
355                Err(Error::Unknown(os_status))
356            }
357        }
358    }
359
360    /// Convert an Error to an OSStatus.
361    pub fn as_os_status(&self) -> OSStatus {
362        match *self {
363            Error::Unspecified => kAudioServicesSystemSoundUnspecifiedError,
364            Error::NoMatchingDefaultAudioUnitFound => kAudioServicesSystemSoundUnspecifiedError,
365            Error::RenderCallbackBufferFormatDoesNotMatchAudioUnitStreamFormat => {
366                kAudioServicesSystemSoundUnspecifiedError
367            }
368            Error::SystemSoundClientMessageTimedOut => kAudioServicesSystemSoundClientTimedOutError,
369            Error::Audio(err) => err as OSStatus,
370            Error::AudioCodec(err) => err as OSStatus,
371            Error::AudioUnit(err) => err as OSStatus,
372            _ => kAudioServicesSystemSoundUnspecifiedError,
373        }
374    }
375}
376
377impl std::error::Error for Error {}
378
379impl ::std::fmt::Display for Error {
380    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
381        match *self {
382            Error::Unspecified => write!(f, "An unspecified error has occurred"),
383            Error::NoMatchingDefaultAudioUnitFound => write!(f, "No matching default audio unit found"),
384            Error::RenderCallbackBufferFormatDoesNotMatchAudioUnitStreamFormat =>
385                write!(f, "The given render callback buffer format does not match the `AudioUnit` `StreamFormat`"),
386            Error::SystemSoundClientMessageTimedOut => write!(f, "The system sound client message timed out"),
387            Error::NoKnownSubtype => write!(f, "The type has no known subtypes"),
388            Error::NonInterleavedInputOnlySupportsMono => write!(f, "In non-interleaved mode input only supports one channel"),
389            Error::UnsupportedSampleRate => write!(f, "The requested sample rate is not available"),
390            Error::UnsupportedStreamFormat => write!(f, "The requested stream format is not available"),
391            Error::Audio(ref err) => write!(f, "{err}"),
392            Error::AudioCodec(ref err) => write!(f, "{err}"),
393            Error::AudioFormat(ref err) => write!(f, "{err}"),
394            Error::AudioUnit(ref err) => write!(f, "{err}"),
395            Error::Unknown(os_status) => write!(f, "An error unknown to the coreaudio-rs API occurred, OSStatus: {os_status}"),
396
397        }
398    }
399}