libmpv_client/
error.rs

1//! The various errors that can be raised by this crate's functions.
2//!
3//! The primary return type of this crate is [`Result<T>`], which may return an [`Error`].
4
5use std::ffi::{NulError, c_int};
6use std::str::Utf8Error;
7
8/// [`std::result::Result`] wrapper around [`Error`] for mpv functions.
9///
10/// Many mpv API functions returning error codes can also return positive values, which also indicate success.
11/// Where relevant, these are exposed as [`Result<i32>`].
12pub type Result<T> = std::result::Result<T, Error>;
13
14/// Interpret an error code from an mpv API function into a `Result`, discarding the success code.
15pub(crate) fn error_to_result_code(value: c_int) -> Result<i32> {
16    if value >= 0 {
17        Ok(value)
18    } else {
19        Err(Error::from(value))
20    }
21}
22
23/// Interpret an error code from an mpv API function into a `Result`, retaining the success code.
24pub(crate) fn error_to_result(value: c_int) -> Result<()> {
25    if value >= 0 {
26        Ok(())
27    } else {
28        Err(Error::from(value))
29    }
30}
31
32/// A structure representing a mismatch between an expected and actual version number.
33#[derive(Debug, Clone)]
34pub struct VersionError {
35    /// The version number that was expected.
36    pub expected: u64,
37    /// The actual version number that was found.
38    pub found: u64,
39}
40
41/// A debug struct for marking specific locations in code.
42#[derive(Debug)]
43pub struct DebugLoc {
44    /// The referenced file.
45    pub file: &'static str,
46    /// The referenced line.
47    pub line: u32,
48    /// Name of the referenced function.
49    pub function: &'static str,
50    /// Name of the referenced variable.
51    pub variable: Option<&'static str>,
52}
53
54/// Enum containing the possible errors in the Rust wrapper over mpv, which may be caused by data passed from mpv or by the user.
55#[derive(Debug)]
56pub enum RustError {
57    /// Invalid UTF-8 data was encountered while parsing a C string into a Rust string.
58    InvalidUtf8(Utf8Error),
59    /// An unexpected NULL byte was found while parsing a Rust string into a C string.
60    InteriorNull(NulError),
61    /// The version of the mpv header or client does not match the version this crate was built for.
62    VersionMismatch(VersionError),
63    /// mpv provided us with a null or otherwise malformed pointer.
64    ///
65    /// This can happen occasionally, especially during init, and is not fatal.
66    Pointer(Option<DebugLoc>),
67}
68
69/// List of error codes than can be returned by API functions.
70#[derive(Debug)]
71pub enum Error {
72    /// No error happened (used to signal successful operation).
73    ///
74    /// Keep in mind that many API functions returning error codes can also return positive values, which also indicate success.
75    Success(i32),
76    /// The event ringbuffer is full. This means the client is choked, and can't receive any events. This can happen when too many asynchronous requests have been made, but not answered. Probably never happens in practice, unless the mpv core is frozen for some reason, and the client keeps making asynchronous requests. (Bugs in the client API implementation could also trigger this, e.g. if events become "lost".)
77    EventQueueFull,
78    /// Memory allocation failed.
79    NoMemory,
80    /// The mpv core wasn't configured and initialized yet.
81    Uninitialized,
82    /// Generic catch-all error if a parameter is set to an invalid or unsupported value. This is used if there is no better error code.
83    InvalidParameter,
84    /// Trying to set an option that doesn't exist.
85    OptionNotFound,
86    /// Trying to set an option using an unsupported [`Format`](crate::Format).
87    OptionFormat,
88    /// Setting the option failed. Typically this happens if the provided option value could not be parsed.
89    OptionError,
90    /// The accessed property doesn't exist.
91    PropertyNotFound,
92    /// Trying to set or get a property using an unsupported [`Format`](crate::Format).
93    PropertyFormat,
94    /// The property exists, but is not available. This usually happens when the associated subsystem is not active, e.g. querying audio parameters while audio is disabled.
95    PropertyUnavailable,
96    /// Error setting or getting a property.
97    PropertyError,
98    /// General error when running a command with [`Handle::command()`](crate::Handle::command()) and similar.
99    Command,
100    /// Generic error on loading (usually used with [`EndFileReason::Error(e)`](crate::event::EndFileReason::Error)).
101    LoadingFailed,
102    /// Initializing the audio output failed.
103    AoInitFailed,
104    /// Initializing the video output failed.
105    VoInitFailed,
106    /// There was no audio or video data to play. This also happens if the file was recognized, but did not contain any audio or video streams, or no streams were selected.
107    NothingToPlay,
108    /// When trying to load the file, the file format could not be determined, or the file was too broken to open it.
109    UnknownFormat,
110    /// Generic error for signaling that certain system requirements are not fulfilled.
111    Unsupported,
112    /// The API function which was called is a stub only.
113    NotImplemented,
114    /// Unspecified error.
115    Generic,
116    /// Rust implementation specific error.
117    Rust(RustError),
118}
119
120impl From<Utf8Error> for Error {
121    fn from(value: Utf8Error) -> Self {
122        Self::Rust(RustError::InvalidUtf8(value))
123    }
124}
125
126impl From<NulError> for Error {
127    fn from(value: NulError) -> Self {
128        Self::Rust(RustError::InteriorNull(value))
129    }
130}
131
132impl From<c_int> for Error {
133    fn from(value: c_int) -> Self {
134        match value {
135            value @ 0.. => Error::Success(value),
136            libmpv_client_sys::mpv_error_MPV_ERROR_EVENT_QUEUE_FULL => Error::EventQueueFull,
137            libmpv_client_sys::mpv_error_MPV_ERROR_NOMEM => Error::NoMemory,
138            libmpv_client_sys::mpv_error_MPV_ERROR_UNINITIALIZED => Error::Uninitialized,
139            libmpv_client_sys::mpv_error_MPV_ERROR_INVALID_PARAMETER => Error::InvalidParameter,
140            libmpv_client_sys::mpv_error_MPV_ERROR_OPTION_NOT_FOUND => Error::OptionNotFound,
141            libmpv_client_sys::mpv_error_MPV_ERROR_OPTION_FORMAT => Error::OptionFormat,
142            libmpv_client_sys::mpv_error_MPV_ERROR_OPTION_ERROR => Error::OptionError,
143            libmpv_client_sys::mpv_error_MPV_ERROR_PROPERTY_NOT_FOUND => Error::PropertyNotFound,
144            libmpv_client_sys::mpv_error_MPV_ERROR_PROPERTY_FORMAT => Error::PropertyFormat,
145            libmpv_client_sys::mpv_error_MPV_ERROR_PROPERTY_UNAVAILABLE => Error::PropertyUnavailable,
146            libmpv_client_sys::mpv_error_MPV_ERROR_PROPERTY_ERROR => Error::PropertyError,
147            libmpv_client_sys::mpv_error_MPV_ERROR_COMMAND => Error::Command,
148            libmpv_client_sys::mpv_error_MPV_ERROR_LOADING_FAILED => Error::LoadingFailed,
149            libmpv_client_sys::mpv_error_MPV_ERROR_AO_INIT_FAILED => Error::AoInitFailed,
150            libmpv_client_sys::mpv_error_MPV_ERROR_VO_INIT_FAILED => Error::VoInitFailed,
151            libmpv_client_sys::mpv_error_MPV_ERROR_NOTHING_TO_PLAY => Error::NothingToPlay,
152            libmpv_client_sys::mpv_error_MPV_ERROR_UNKNOWN_FORMAT => Error::UnknownFormat,
153            libmpv_client_sys::mpv_error_MPV_ERROR_UNSUPPORTED => Error::Unsupported,
154            libmpv_client_sys::mpv_error_MPV_ERROR_NOT_IMPLEMENTED => Error::NotImplemented,
155            libmpv_client_sys::mpv_error_MPV_ERROR_GENERIC => Error::Generic,
156            _ => unimplemented!(),
157        }
158    }
159}
160
161impl From<&Error> for c_int {
162    fn from(value: &Error) -> Self {
163        match value {
164            Error::EventQueueFull => libmpv_client_sys::mpv_error_MPV_ERROR_EVENT_QUEUE_FULL,
165            Error::NoMemory => libmpv_client_sys::mpv_error_MPV_ERROR_NOMEM,
166            Error::Uninitialized => libmpv_client_sys::mpv_error_MPV_ERROR_UNINITIALIZED,
167            Error::InvalidParameter => libmpv_client_sys::mpv_error_MPV_ERROR_INVALID_PARAMETER,
168            Error::OptionNotFound => libmpv_client_sys::mpv_error_MPV_ERROR_OPTION_NOT_FOUND,
169            Error::OptionFormat => libmpv_client_sys::mpv_error_MPV_ERROR_OPTION_FORMAT,
170            Error::OptionError => libmpv_client_sys::mpv_error_MPV_ERROR_OPTION_ERROR,
171            Error::PropertyNotFound => libmpv_client_sys::mpv_error_MPV_ERROR_PROPERTY_NOT_FOUND,
172            Error::PropertyFormat => libmpv_client_sys::mpv_error_MPV_ERROR_PROPERTY_FORMAT,
173            Error::PropertyUnavailable => libmpv_client_sys::mpv_error_MPV_ERROR_PROPERTY_UNAVAILABLE,
174            Error::PropertyError => libmpv_client_sys::mpv_error_MPV_ERROR_PROPERTY_ERROR,
175            Error::Command => libmpv_client_sys::mpv_error_MPV_ERROR_COMMAND,
176            Error::LoadingFailed => libmpv_client_sys::mpv_error_MPV_ERROR_LOADING_FAILED,
177            Error::AoInitFailed => libmpv_client_sys::mpv_error_MPV_ERROR_AO_INIT_FAILED,
178            Error::VoInitFailed => libmpv_client_sys::mpv_error_MPV_ERROR_VO_INIT_FAILED,
179            Error::NothingToPlay => libmpv_client_sys::mpv_error_MPV_ERROR_NOTHING_TO_PLAY,
180            Error::UnknownFormat => libmpv_client_sys::mpv_error_MPV_ERROR_UNKNOWN_FORMAT,
181            Error::Unsupported => libmpv_client_sys::mpv_error_MPV_ERROR_UNSUPPORTED,
182            Error::NotImplemented => libmpv_client_sys::mpv_error_MPV_ERROR_NOT_IMPLEMENTED,
183            Error::Generic => libmpv_client_sys::mpv_error_MPV_ERROR_GENERIC,
184            Error::Rust(_) => libmpv_client_sys::mpv_error_MPV_ERROR_GENERIC,
185            Error::Success(x) => *x as c_int,
186        }
187    }
188}