skua_voice/tracks/
error.rs

1use crate::input::AudioStreamError;
2use flume::RecvError;
3use std::{
4    error::Error,
5    fmt::{Display, Formatter, Result as FmtResult},
6    sync::Arc,
7};
8use symphonia_core::errors::Error as SymphoniaError;
9
10/// Errors associated with control and manipulation of tracks.
11///
12/// Unless otherwise stated, these don't invalidate an existing track,
13/// but do advise on valid operations and commands.
14#[derive(Clone, Debug)]
15#[non_exhaustive]
16pub enum ControlError {
17    /// The operation failed because the track has ended, has been removed
18    /// due to call closure, or some error within the driver.
19    Finished,
20    /// The supplied event listener can never be fired by a track, and should
21    /// be attached to the driver instead.
22    InvalidTrackEvent,
23    /// A command to seek or ready the target track failed when parsing or creating the stream.
24    ///
25    /// This is a fatal error, and the track will be removed.
26    Play(PlayError),
27    /// Another `seek`/`make_playable` request was made, and so this callback handler was dropped.
28    Dropped,
29}
30
31impl Display for ControlError {
32    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
33        write!(f, "failed to operate on track (handle): ")?;
34        match self {
35            ControlError::Finished => write!(f, "track ended"),
36            ControlError::InvalidTrackEvent => {
37                write!(f, "given event listener can't be fired on a track")
38            },
39            ControlError::Play(p) => {
40                write!(f, "i/o request on track failed: {p}")
41            },
42            ControlError::Dropped => write!(f, "request was replaced by another of same type"),
43        }
44    }
45}
46
47impl Error for ControlError {}
48
49impl From<RecvError> for ControlError {
50    fn from(_: RecvError) -> Self {
51        ControlError::Dropped
52    }
53}
54
55/// Alias for most calls to a [`TrackHandle`].
56///
57/// [`TrackHandle`]: super::TrackHandle
58pub type TrackResult<T> = Result<T, ControlError>;
59
60/// Errors reported by the mixer while attempting to play (or ready) a [`Track`].
61///
62/// [`Track`]: super::Track
63#[derive(Clone, Debug)]
64#[non_exhaustive]
65pub enum PlayError {
66    /// Failed to create a live bytestream from the lazy [`Compose`].
67    ///
68    /// [`Compose`]: crate::input::Compose
69    Create(Arc<AudioStreamError>),
70    /// Failed to read headers, codecs, or a valid stream from an [`Input`].
71    ///
72    /// [`Input`]: crate::input::Input
73    Parse(Arc<SymphoniaError>),
74    /// Failed to decode a frame received from an [`Input`].
75    ///
76    /// [`Input`]: crate::input::Input
77    Decode(Arc<SymphoniaError>),
78    /// Failed to seek to the requested location.
79    Seek(Arc<SymphoniaError>),
80}
81
82impl Display for PlayError {
83    fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
84        f.write_str("runtime error while playing track: ")?;
85        match self {
86            Self::Create(c) => {
87                f.write_str("input creation [")?;
88                f.write_fmt(format_args!("{}", &c))?;
89                f.write_str("]")
90            },
91            Self::Parse(p) => {
92                f.write_str("parsing formats/codecs [")?;
93                f.write_fmt(format_args!("{}", &p))?;
94                f.write_str("]")
95            },
96            Self::Decode(d) => {
97                f.write_str("decoding packets [")?;
98                f.write_fmt(format_args!("{}", &d))?;
99                f.write_str("]")
100            },
101            Self::Seek(s) => {
102                f.write_str("seeking along input [")?;
103                f.write_fmt(format_args!("{}", &s))?;
104                f.write_str("]")
105            },
106        }
107    }
108}
109
110impl Error for PlayError {}