use thiserror::Error;
use crate::source::symph;
use cpal::{
BuildStreamError, DefaultStreamConfigError, DevicesError,
PauseStreamError, PlayStreamError, StreamError,
SupportedStreamConfigsError,
};
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Error, Debug)]
pub enum Error {
#[error("Failed to convert to timestamp")]
CannotDetermineTimestamp,
#[error("Failed to aquire lock")]
PoisonError,
#[error("Format supported by the device is not supported by the library")]
UnsupportedSampleFormat,
#[error("No available output device was found")]
NoOutDevice,
#[error("{component} doesn't support {feature}")]
Unsupported {
component: &'static str,
feature: &'static str,
},
#[error("Cannot operate on a source because there is no source playing")]
NoSourceIsPlaying,
#[error("Cannot load prefetched source. There is no prefetched source.")]
NoPrefetchedSource,
#[error(transparent)]
Cpal(#[from] CpalError),
#[error(transparent)]
Symph(#[from] symph::Error),
#[error(transparent)]
Other(anyhow::Error),
}
impl From<anyhow::Error> for Error {
fn from(value: anyhow::Error) -> Self {
if value.is::<Self>() {
value.downcast().unwrap()
} else {
Self::Other(value)
}
}
}
impl<T> From<std::sync::PoisonError<T>> for Error {
fn from(_value: std::sync::PoisonError<T>) -> Self {
Self::PoisonError
}
}
macro_rules! impl_cpal {
($($i:ident -> $t:ty),+ $(,)?) => {
$(
impl From<$t> for Error {
fn from(value: $t) -> Self {
Self::Cpal(value.into())
}
}
)+
#[derive(Error, Debug)]
pub enum CpalError {
$(
#[error(transparent)]
$i(#[from] $t),
)+
}
};
}
impl_cpal!(
DefaultStreamConfig -> DefaultStreamConfigError,
Stream -> StreamError,
BuildStream -> BuildStreamError,
PlayStream -> PlayStreamError,
SupportedConfigs -> SupportedStreamConfigsError,
PauseStreamError -> PauseStreamError,
DevicesError -> DevicesError,
);