ez_audi/
errors.rs

1//! All the toolkit to deal with errors from this library
2
3use std::{io, fmt::Display, error, sync::PoisonError};
4
5use crate::cpal_abstraction::SampleType;
6
7/// A Result<T, ez_audi::PlayError>
8pub type Error<T> = Result<T, PlayError>;
9
10#[derive(Debug)]
11/// The error type used allthrought the ez_audi crate
12pub enum PlayError {
13    /// The time specified is out of bound
14    TimeOutOfBounds,
15    /// The file is not accesible/does not exist
16    FileNotAccessible(io::Error),
17    /// The file type hints at the fact that the file type is not the right one
18    WrongFileType,
19    /// Error while trying to communicate with the device
20    DeviceIoError(String, Option<Box<dyn error::Error + 'static>>),
21    /// The device does not support specific requirements to play the samples
22    DeviceDoesNotSupportAudioSettings(Vec<AudioSettings>, Option<Box<dyn error::Error + 'static>>),
23    /// The device does not exist
24    DeviceDoesNotExist{ 
25        /// Name of the device, is "default" if failed to get the default
26        name: String 
27    },
28    /// Error while trying to comunicate with a stream
29    StreamIoError(String, Option<Box<dyn error::Error + 'static>>),
30    /// A `Mutex` got poisoned and is not accessible anymore
31    PoisonedMutex(String, Box<dyn error::Error>),
32    /// Feature is not support as of yet
33    Unsupported(String),
34}
35
36impl Display for PlayError {
37    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38        match self {
39            Self::TimeOutOfBounds => f.write_str("the time specified is out of bounds"),
40            Self::FileNotAccessible(_) => f.write_str("there was an error while trying to access the file"),
41            Self::WrongFileType => f.write_str("file was of the wrong file type"),
42            Self::DeviceDoesNotExist{ name: n } => f.write_str(&format!("the device '{n}' does not exist")),
43            Self::DeviceIoError(c, _) => f.write_str(&format!("the device had an issue with io because {c}")),
44            Self::DeviceDoesNotSupportAudioSettings(s, _) => f.write_str(&format!("the device had an issue with config because {s:?} is/are not supported")),
45            Self::StreamIoError(s, _) => f.write_str(&format!("error while communicating with stream: {s}")),
46            Self::PoisonedMutex(s, _) => f.write_str(&format!("error while trying to access mutex {s}")),
47            Self::Unsupported(e) => f.write_str(&format!("ez_audi does not support '{}'", e)),
48        }
49    }
50}
51
52impl error::Error for PlayError {
53    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
54        match self {
55            Self::TimeOutOfBounds => None,
56            Self::FileNotAccessible(e) => Some(e),
57            Self::WrongFileType => None,
58            Self::DeviceDoesNotExist{ .. } => None,
59            Self::DeviceIoError(_, s) => {
60                match s {
61                    Some(s) => Some(&**s.clone()),
62                    None => None,
63                }
64            },
65            Self::DeviceDoesNotSupportAudioSettings(_, s) => {
66                match s {
67                    Some(s) => Some(&**s.clone()),
68                    None => None,
69                }
70            },
71            Self::StreamIoError(_, s) => {
72                match s {
73                    Some(s) => Some(&**s.clone()),
74                    None => None,
75                }
76            },
77            Self::PoisonedMutex(_, s) => Some(&**s),
78            Self::Unsupported(_) => None,
79        }
80    }
81}
82
83impl From<io::Error> for PlayError {
84    fn from(value: io::Error) -> Self {
85        Self::FileNotAccessible(value)
86    }
87}
88
89impl From<cpal::PlayStreamError> for PlayError {
90    fn from(value: cpal::PlayStreamError) -> Self {
91        Self::StreamIoError("failed play stream".to_string(), Some(Box::new(value)))
92    }
93}
94
95impl From<cpal::PauseStreamError> for PlayError {
96    fn from(value: cpal::PauseStreamError) -> Self {
97        Self::StreamIoError("failed pause stream".to_string(), Some(Box::new(value)))
98    }
99}
100
101impl<T: 'static> From<PoisonError<T>> for PlayError {
102    fn from(value: PoisonError<T>) -> Self {
103        Self::PoisonedMutex("".to_string(), Box::new(value))
104    }
105}
106
107#[derive(Debug, Clone, PartialEq)]
108/// Used in PlayError::DeviceDoesNotSupportAudioSettings
109pub enum AudioSettings {
110    /// The type of the sample
111    SampleType(Option<SampleType>),
112    /// The hertz of the consuming of samples
113    SampleRate(u32),
114    /// The number of channels
115    Channels(u32),
116    /// If it is caused by the combinaison of more than one setting above,
117    /// if two independently are unsupported than it should be reported as multiple
118    /// enums
119    Combinaison,
120}
121
122impl Display for AudioSettings {
123    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
124        match self {
125            Self::SampleType(st) => f.write_str(&format!("the sample type {:?}", st)),
126            Self::SampleRate(r) => f.write_str(&format!("the sample rate of {:?}", r)),
127            Self::Channels(c) => f.write_str(&format!("the channel count of {:?}", c)),
128            Self::Combinaison => f.write_str("the combinaison of settings")
129        }
130    }
131}