skua_voice/input/
error.rs

1use std::{error::Error, fmt::Display, time::Duration};
2use symphonia_core::errors::Error as SymphError;
3
4/// Errors encountered when creating an [`AudioStream`] or requesting metadata
5/// from a [`Compose`].
6///
7/// [`AudioStream`]: super::AudioStream
8/// [`Compose`]: super::Compose
9#[non_exhaustive]
10#[derive(Debug)]
11pub enum AudioStreamError {
12    /// The operation failed, and should be retried after a given time.
13    ///
14    /// Create operations invoked by the driver will retry on the first tick
15    /// after this time has passed.
16    RetryIn(Duration),
17    /// The operation failed, and should not be retried.
18    Fail(Box<dyn Error + Send + Sync>),
19    /// The operation was not supported, and will never succeed.
20    Unsupported,
21}
22
23impl Display for AudioStreamError {
24    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25        f.write_str("failed to create audio: ")?;
26        match self {
27            Self::RetryIn(t) => f.write_fmt(format_args!("retry in {:.2}s", t.as_secs_f32())),
28            Self::Fail(why) => f.write_fmt(format_args!("{why}")),
29            Self::Unsupported => f.write_str("operation was not supported"),
30        }
31    }
32}
33
34impl Error for AudioStreamError {
35    fn source(&self) -> Option<&(dyn Error + 'static)> {
36        None
37    }
38}
39
40/// Errors encountered when readying or pre-processing an [`Input`].
41///
42/// [`Input`]: super::Input
43#[non_exhaustive]
44#[derive(Debug)]
45pub enum MakePlayableError {
46    /// Failed to create a [`LiveInput`] from the lazy [`Compose`].
47    ///
48    /// [`LiveInput`]: super::LiveInput
49    /// [`Compose`]: super::Compose
50    Create(AudioStreamError),
51    /// Failed to read headers, codecs, or a valid stream from a [`LiveInput`].
52    ///
53    /// [`LiveInput`]: super::LiveInput
54    Parse(SymphError),
55    /// A blocking thread panicked or failed to return a parsed input.
56    Panicked,
57}
58
59impl Display for MakePlayableError {
60    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61        f.write_str("failed to make track playable: ")?;
62        match self {
63            Self::Create(c) => {
64                f.write_str("input creation [")?;
65                f.write_fmt(format_args!("{}", &c))?;
66                f.write_str("]")
67            },
68            Self::Parse(p) => {
69                f.write_str("parsing formats/codecs [")?;
70                f.write_fmt(format_args!("{}", &p))?;
71                f.write_str("]")
72            },
73            Self::Panicked => f.write_str("panic during blocking I/O in parse"),
74        }
75    }
76}
77
78impl Error for MakePlayableError {
79    fn source(&self) -> Option<&(dyn Error + 'static)> {
80        None
81    }
82}
83
84impl From<AudioStreamError> for MakePlayableError {
85    fn from(val: AudioStreamError) -> Self {
86        Self::Create(val)
87    }
88}
89
90impl From<SymphError> for MakePlayableError {
91    fn from(val: SymphError) -> Self {
92        Self::Parse(val)
93    }
94}
95
96/// Errors encountered when trying to access in-stream [`Metadata`] for an [`Input`].
97///
98/// Both cases can be solved by using [`Input::make_playable`] or [`LiveInput::promote`].
99///
100/// [`Input`]: super::Input
101/// [`Metadata`]: super::Metadata
102/// [`Input::make_playable`]: super::Input::make_playable
103/// [`LiveInput::promote`]: super::LiveInput::promote
104#[non_exhaustive]
105#[derive(Debug)]
106pub enum MetadataError {
107    /// This input is currently lazily initialised, and must be made live.
108    NotLive,
109    /// This input is ready, but has not had its headers parsed.
110    NotParsed,
111}
112
113impl Display for MetadataError {
114    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
115        f.write_str("failed to get metadata: ")?;
116        match self {
117            Self::NotLive => f.write_str("the input is not live, and hasn't been parsed"),
118            Self::NotParsed => f.write_str("the input is live but hasn't been parsed"),
119        }
120    }
121}
122
123impl Error for MetadataError {
124    fn source(&self) -> Option<&(dyn Error + 'static)> {
125        None
126    }
127}
128
129/// Errors encountered when trying to access out-of-band [`AuxMetadata`] for an [`Input`]
130/// or [`Compose`].
131///
132/// [`Input`]: super::Input
133/// [`AuxMetadata`]: super::AuxMetadata
134/// [`Compose`]: super::Compose
135#[non_exhaustive]
136#[derive(Debug)]
137pub enum AuxMetadataError {
138    /// This input has no lazy [`Compose`] initialiser, which is needed to
139    /// retrieve [`AuxMetadata`].
140    ///
141    /// [`Compose`]: super::Compose
142    /// [`AuxMetadata`]: super::AuxMetadata
143    NoCompose,
144    /// There was an error when trying to access auxiliary metadata.
145    Retrieve(AudioStreamError),
146}
147
148impl Display for AuxMetadataError {
149    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
150        f.write_str("failed to get aux_metadata: ")?;
151        match self {
152            Self::NoCompose => f.write_str("the input has no Compose object"),
153            Self::Retrieve(e) => f.write_fmt(format_args!("aux_metadata error from Compose: {e}")),
154        }
155    }
156}
157
158impl Error for AuxMetadataError {
159    fn source(&self) -> Option<&(dyn Error + 'static)> {
160        None
161    }
162}
163
164impl From<AudioStreamError> for AuxMetadataError {
165    fn from(val: AudioStreamError) -> Self {
166        Self::Retrieve(val)
167    }
168}