diff options
Diffstat (limited to 'crates/libmpv2/src/mpv')
-rw-r--r-- | crates/libmpv2/src/mpv/errors.rs | 95 | ||||
-rw-r--r-- | crates/libmpv2/src/mpv/events.rs | 52 | ||||
-rw-r--r-- | crates/libmpv2/src/mpv/protocol.rs | 135 | ||||
-rw-r--r-- | crates/libmpv2/src/mpv/raw_error_warning.txt | 5 | ||||
-rw-r--r-- | crates/libmpv2/src/mpv/raw_error_warning.txt.license | 9 | ||||
-rw-r--r-- | crates/libmpv2/src/mpv/render.rs | 52 |
6 files changed, 218 insertions, 130 deletions
diff --git a/crates/libmpv2/src/mpv/errors.rs b/crates/libmpv2/src/mpv/errors.rs index a2baee5..a2d3dd8 100644 --- a/crates/libmpv2/src/mpv/errors.rs +++ b/crates/libmpv2/src/mpv/errors.rs @@ -8,36 +8,52 @@ // You should have received a copy of the License along with this program. // If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>. -use std::{ffi::NulError, os::raw as ctype, str::Utf8Error}; - -use thiserror::Error; +use std::{ffi::NulError, fmt::Display, os::raw as ctype, str::Utf8Error}; use super::mpv_error; #[allow(missing_docs)] pub type Result<T> = ::std::result::Result<T, Error>; -#[derive(Error, Debug)] +#[derive(Debug)] pub enum Error { - #[error("loading file failed: {error}")] - Loadfile { error: String }, + Loadfile { + error: String, + }, - #[error("version mismatch detected! Linked version ({linked}) is unequal to the loaded version ({loaded})")] VersionMismatch { linked: ctype::c_ulong, loaded: ctype::c_ulong, }, - #[error("invalid utf8 returned")] InvalidUtf8, - #[error("null pointer returned")] Null, - #[error("raw error returned: {}", to_string_mpv_error(*(.0)))] Raw(crate::MpvError), } +impl std::error::Error for Error {} + +impl Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Error::Loadfile { error } => write!(f, "loading file failed: {error}"), + Error::VersionMismatch { linked, loaded } => write!( + f, + "version mismatch detected! Linked version ({linked}) is unequal to the loaded version ({loaded})" + ), + Error::InvalidUtf8 => f.write_str("invalid utf8 returned"), + Error::Null => f.write_str("null pointer returned"), + Error::Raw(raw) => write!( + f, + include_str!("./raw_error_warning.txt"), + to_string_mpv_error(*(raw)) + ), + } + } +} + impl From<NulError> for Error { fn from(_other: NulError) -> Error { Error::Null @@ -76,35 +92,70 @@ fn to_string_mpv_error_raw(num: crate::MpvError) -> (&'static str, &'static str) mpv_error::NoMem => ("Memory allocation failed.", ""), - mpv_error::Uninitialized => ("The mpv core wasn't configured and initialized yet", " See the notes in mpv_create()."), + mpv_error::Uninitialized => ( + "The mpv core wasn't configured and initialized yet", + " See the notes in mpv_create().", + ), - mpv_error::InvalidParameter => ("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."), + mpv_error::InvalidParameter => ( + "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.", + ), mpv_error::OptionNotFound => ("Trying to set an option that doesn't exist.", ""), - mpv_error::OptionFormat => ("Trying to set an option using an unsupported MPV_FORMAT.", ""), - mpv_error::OptionError => ("Setting the option failed", " Typically this happens if the provided option value could not be parsed."), + mpv_error::OptionFormat => ( + "Trying to set an option using an unsupported MPV_FORMAT.", + "", + ), + mpv_error::OptionError => ( + "Setting the option failed", + " Typically this happens if the provided option value could not be parsed.", + ), mpv_error::PropertyNotFound => ("The accessed property doesn't exist.", ""), - mpv_error::PropertyFormat => ("Trying to set or get a property using an unsupported MPV_FORMAT.", ""), - mpv_error::PropertyUnavailable => ("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."), + mpv_error::PropertyFormat => ( + "Trying to set or get a property using an unsupported MPV_FORMAT.", + "", + ), + mpv_error::PropertyUnavailable => ( + "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.", + ), mpv_error::PropertyError => ("Error setting or getting a property.", ""), - mpv_error::Command => ("General error when running a command with mpv_command and similar.", ""), + mpv_error::Command => ( + "General error when running a command with mpv_command and similar.", + "", + ), - mpv_error::LoadingFailed => ("Generic error on loading (usually used with mpv_event_end_file.error).", ""), + mpv_error::LoadingFailed => ( + "Generic error on loading (usually used with mpv_event_end_file.error).", + "", + ), mpv_error::AoInitFailed => ("Initializing the audio output failed.", ""), mpv_error::VoInitFailed => ("Initializing the video output failed.", ""), - mpv_error::NothingToPlay => ("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."), + mpv_error::NothingToPlay => ( + "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.", + ), - mpv_error::UnknownFormat => (" * When trying to load the file, the file format could not be determined, or the file was too broken to open it.", ""), + mpv_error::UnknownFormat => ( + " * When trying to load the file, the file format could not be determined, or the file was too broken to open it.", + "", + ), - mpv_error::Generic => ("Generic error for signaling that certain system requirements are not fulfilled.", ""), + mpv_error::Generic => ( + "Generic error for signaling that certain system requirements are not fulfilled.", + "", + ), mpv_error::NotImplemented => ("The API function which was called is a stub only", ""), mpv_error::Unsupported => ("Unspecified error.", ""), - mpv_error::Success => unreachable!("This is not an error. It's just here, to ensure that the 0 case marks an success'"), + mpv_error::Success => unreachable!( + "This is not an error. It's just here, to ensure that the 0 case marks an success'" + ), _ => unreachable!("Mpv seems to have changed it's constants."), } } diff --git a/crates/libmpv2/src/mpv/events.rs b/crates/libmpv2/src/mpv/events.rs index 6fb4683..f10ff6e 100644 --- a/crates/libmpv2/src/mpv/events.rs +++ b/crates/libmpv2/src/mpv/events.rs @@ -11,7 +11,7 @@ use crate::mpv_node::sys_node::SysMpvNode; use crate::{mpv::mpv_err, *}; -use std::ffi::{c_void, CString}; +use std::ffi::{CString, c_void}; use std::os::raw as ctype; use std::ptr::NonNull; use std::slice; @@ -70,26 +70,28 @@ impl<'a> PropertyData<'a> { // SAFETY: meant to extract the data from an event property. See `mpv_event_property` in // `client.h` unsafe fn from_raw(format: MpvFormat, ptr: *mut ctype::c_void) -> Result<PropertyData<'a>> { - assert!(!ptr.is_null()); - match format { - mpv_format::Flag => Ok(PropertyData::Flag(*(ptr as *mut bool))), - mpv_format::String => { - let char_ptr = *(ptr as *mut *mut ctype::c_char); - Ok(PropertyData::Str(mpv_cstr_to_str!(char_ptr)?)) - } - mpv_format::OsdString => { - let char_ptr = *(ptr as *mut *mut ctype::c_char); - Ok(PropertyData::OsdStr(mpv_cstr_to_str!(char_ptr)?)) - } - mpv_format::Double => Ok(PropertyData::Double(*(ptr as *mut f64))), - mpv_format::Int64 => Ok(PropertyData::Int64(*(ptr as *mut i64))), - mpv_format::Node => { - let sys_node = *(ptr as *mut libmpv2_sys::mpv_node); - let node = SysMpvNode::new(sys_node, false); - return Ok(PropertyData::Node(node.value().unwrap())); + unsafe { + assert!(!ptr.is_null()); + match format { + mpv_format::Flag => Ok(PropertyData::Flag(*(ptr as *mut bool))), + mpv_format::String => { + let char_ptr = *(ptr as *mut *mut ctype::c_char); + Ok(PropertyData::Str(mpv_cstr_to_str!(char_ptr)?)) + } + mpv_format::OsdString => { + let char_ptr = *(ptr as *mut *mut ctype::c_char); + Ok(PropertyData::OsdStr(mpv_cstr_to_str!(char_ptr)?)) + } + mpv_format::Double => Ok(PropertyData::Double(*(ptr as *mut f64))), + mpv_format::Int64 => Ok(PropertyData::Int64(*(ptr as *mut i64))), + mpv_format::Node => { + let sys_node = *(ptr as *mut libmpv2_sys::mpv_node); + let node = SysMpvNode::new(sys_node, false); + Ok(PropertyData::Node(node.value().unwrap())) + } + mpv_format::None => unreachable!(), + _ => unimplemented!(), } - mpv_format::None => unreachable!(), - _ => unimplemented!(), } } } @@ -146,11 +148,13 @@ pub enum Event<'a> { } unsafe extern "C" fn wu_wrapper<F: Fn() + Send + 'static>(ctx: *mut c_void) { - if ctx.is_null() { - panic!("ctx for wakeup wrapper is NULL"); - } + unsafe { + if ctx.is_null() { + panic!("ctx for wakeup wrapper is NULL"); + } - (*(ctx as *mut F))(); + (*(ctx as *mut F))(); + } } /// Context to listen to events. diff --git a/crates/libmpv2/src/mpv/protocol.rs b/crates/libmpv2/src/mpv/protocol.rs index 31a5933..ee33411 100644 --- a/crates/libmpv2/src/mpv/protocol.rs +++ b/crates/libmpv2/src/mpv/protocol.rs @@ -17,7 +17,7 @@ use std::os::raw as ctype; use std::panic; use std::panic::RefUnwindSafe; use std::slice; -use std::sync::{atomic::Ordering, Mutex}; +use std::sync::{Mutex, atomic::Ordering}; impl Mpv { /// Create a context with which custom protocols can be registered. @@ -63,26 +63,28 @@ where T: RefUnwindSafe, U: RefUnwindSafe, { - let data = user_data as *mut ProtocolData<T, U>; + unsafe { + let data = user_data as *mut ProtocolData<T, U>; - (*info).cookie = user_data; - (*info).read_fn = Some(read_wrapper::<T, U>); - (*info).seek_fn = Some(seek_wrapper::<T, U>); - (*info).size_fn = Some(size_wrapper::<T, U>); - (*info).close_fn = Some(close_wrapper::<T, U>); + (*info).cookie = user_data; + (*info).read_fn = Some(read_wrapper::<T, U>); + (*info).seek_fn = Some(seek_wrapper::<T, U>); + (*info).size_fn = Some(size_wrapper::<T, U>); + (*info).close_fn = Some(close_wrapper::<T, U>); - let ret = panic::catch_unwind(|| { - let uri = mpv_cstr_to_str!(uri as *const _).unwrap(); - ptr::write( - (*data).cookie, - ((*data).open_fn)(&mut (*data).user_data, uri), - ); - }); + let ret = panic::catch_unwind(|| { + let uri = mpv_cstr_to_str!(uri as *const _).unwrap(); + ptr::write( + (*data).cookie, + ((*data).open_fn)(&mut (*data).user_data, uri), + ); + }); - if ret.is_ok() { - 0 - } else { - mpv_error::Generic as _ + if ret.is_ok() { + 0 + } else { + mpv_error::Generic as _ + } } } @@ -95,16 +97,14 @@ where T: RefUnwindSafe, U: RefUnwindSafe, { - let data = cookie as *mut ProtocolData<T, U>; + unsafe { + let data = cookie as *mut ProtocolData<T, U>; - let ret = panic::catch_unwind(|| { - let slice = slice::from_raw_parts_mut(buf, nbytes as _); - ((*data).read_fn)(&mut *(*data).cookie, slice) - }); - if let Ok(ret) = ret { - ret - } else { - -1 + let ret = panic::catch_unwind(|| { + let slice = slice::from_raw_parts_mut(buf, nbytes as _); + ((*data).read_fn)(&mut *(*data).cookie, slice) + }); + ret.unwrap_or(-1) } } @@ -113,18 +113,21 @@ where T: RefUnwindSafe, U: RefUnwindSafe, { - let data = cookie as *mut ProtocolData<T, U>; + unsafe { + let data = cookie as *mut ProtocolData<T, U>; - if (*data).seek_fn.is_none() { - return mpv_error::Unsupported as _; - } + if (*data).seek_fn.is_none() { + return mpv_error::Unsupported as _; + } - let ret = - panic::catch_unwind(|| (*(*data).seek_fn.as_ref().unwrap())(&mut *(*data).cookie, offset)); - if let Ok(ret) = ret { - ret - } else { - mpv_error::Generic as _ + let ret = panic::catch_unwind(|| { + (*(*data).seek_fn.as_ref().unwrap())(&mut *(*data).cookie, offset) + }); + if let Ok(ret) = ret { + ret + } else { + mpv_error::Generic as _ + } } } @@ -133,17 +136,20 @@ where T: RefUnwindSafe, U: RefUnwindSafe, { - let data = cookie as *mut ProtocolData<T, U>; + unsafe { + let data = cookie as *mut ProtocolData<T, U>; - if (*data).size_fn.is_none() { - return mpv_error::Unsupported as _; - } + if (*data).size_fn.is_none() { + return mpv_error::Unsupported as _; + } - let ret = panic::catch_unwind(|| (*(*data).size_fn.as_ref().unwrap())(&mut *(*data).cookie)); - if let Ok(ret) = ret { - ret - } else { - mpv_error::Unsupported as _ + let ret = + panic::catch_unwind(|| (*(*data).size_fn.as_ref().unwrap())(&mut *(*data).cookie)); + if let Ok(ret) = ret { + ret + } else { + mpv_error::Unsupported as _ + } } } @@ -153,9 +159,11 @@ where T: RefUnwindSafe, U: RefUnwindSafe, { - let data = Box::from_raw(cookie as *mut ProtocolData<T, U>); + unsafe { + let data = Box::from_raw(cookie as *mut ProtocolData<T, U>); - panic::catch_unwind(|| (data.close_fn)(Box::from_raw(data.cookie))); + panic::catch_unwind(|| (data.close_fn)(Box::from_raw(data.cookie))); + } } struct ProtocolData<T, U> { @@ -177,8 +185,8 @@ pub struct ProtocolContext<'parent, T: RefUnwindSafe, U: RefUnwindSafe> { _does_not_outlive: PhantomData<&'parent Mpv>, } -unsafe impl<'parent, T: RefUnwindSafe, U: RefUnwindSafe> Send for ProtocolContext<'parent, T, U> {} -unsafe impl<'parent, T: RefUnwindSafe, U: RefUnwindSafe> Sync for ProtocolContext<'parent, T, U> {} +unsafe impl<T: RefUnwindSafe, U: RefUnwindSafe> Send for ProtocolContext<'_, T, U> {} +unsafe impl<T: RefUnwindSafe, U: RefUnwindSafe> Sync for ProtocolContext<'_, T, U> {} impl<'parent, T: RefUnwindSafe, U: RefUnwindSafe> ProtocolContext<'parent, T, U> { fn new( @@ -228,20 +236,23 @@ impl<T: RefUnwindSafe, U: RefUnwindSafe> Protocol<T, U> { seek_fn: Option<StreamSeek<T>>, size_fn: Option<StreamSize<T>>, ) -> Protocol<T, U> { - let c_layout = Layout::from_size_align(mem::size_of::<T>(), mem::align_of::<T>()).unwrap(); - let cookie = alloc::alloc(c_layout) as *mut T; - let data = Box::into_raw(Box::new(ProtocolData { - cookie, - user_data, + unsafe { + let c_layout = + Layout::from_size_align(mem::size_of::<T>(), mem::align_of::<T>()).unwrap(); + let cookie = alloc::alloc(c_layout) as *mut T; + let data = Box::into_raw(Box::new(ProtocolData { + cookie, + user_data, - open_fn, - close_fn, - read_fn, - seek_fn, - size_fn, - })); + open_fn, + close_fn, + read_fn, + seek_fn, + size_fn, + })); - Protocol { name, data } + Protocol { name, data } + } } fn register(&self, ctx: *mut libmpv2_sys::mpv_handle) -> Result<()> { diff --git a/crates/libmpv2/src/mpv/raw_error_warning.txt b/crates/libmpv2/src/mpv/raw_error_warning.txt new file mode 100644 index 0000000..277500a --- /dev/null +++ b/crates/libmpv2/src/mpv/raw_error_warning.txt @@ -0,0 +1,5 @@ +Raw mpv error: {} + +This error is directly returned from `mpv`. +This is probably caused by a bug in `yt`, please open an issue about +this and try to replicate it with the `-vvvv` verbosity setting. diff --git a/crates/libmpv2/src/mpv/raw_error_warning.txt.license b/crates/libmpv2/src/mpv/raw_error_warning.txt.license new file mode 100644 index 0000000..7813eb6 --- /dev/null +++ b/crates/libmpv2/src/mpv/raw_error_warning.txt.license @@ -0,0 +1,9 @@ +yt - A fully featured command line YouTube client + +Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de> +SPDX-License-Identifier: GPL-3.0-or-later + +This file is part of Yt. + +You should have received a copy of the License along with this program. +If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>. diff --git a/crates/libmpv2/src/mpv/render.rs b/crates/libmpv2/src/mpv/render.rs index c3f2dc9..02f70bb 100644 --- a/crates/libmpv2/src/mpv/render.rs +++ b/crates/libmpv2/src/mpv/render.rs @@ -8,9 +8,9 @@ // You should have received a copy of the License along with this program. // If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>. -use crate::{mpv::mpv_err, Error, Result}; +use crate::{Error, Result, mpv::mpv_err}; use std::collections::HashMap; -use std::ffi::{c_void, CStr}; +use std::ffi::{CStr, c_void}; use std::os::raw::c_int; use std::ptr; @@ -125,26 +125,30 @@ impl<C> From<&RenderParam<C>> for u32 { } unsafe extern "C" fn gpa_wrapper<GLContext>(ctx: *mut c_void, name: *const i8) -> *mut c_void { - if ctx.is_null() { - panic!("ctx for get_proc_address wrapper is NULL"); - } + unsafe { + if ctx.is_null() { + panic!("ctx for get_proc_address wrapper is NULL"); + } - let params: *mut OpenGLInitParams<GLContext> = ctx as _; - let params = &*params; - (params.get_proc_address)( - ¶ms.ctx, - CStr::from_ptr(name) - .to_str() - .expect("Could not convert function name to str"), - ) + let params: *mut OpenGLInitParams<GLContext> = ctx as _; + let params = &*params; + (params.get_proc_address)( + ¶ms.ctx, + CStr::from_ptr(name) + .to_str() + .expect("Could not convert function name to str"), + ) + } } unsafe extern "C" fn ru_wrapper<F: Fn() + Send + 'static>(ctx: *mut c_void) { - if ctx.is_null() { - panic!("ctx for render_update wrapper is NULL"); - } + unsafe { + if ctx.is_null() { + panic!("ctx for render_update wrapper is NULL"); + } - (*(ctx as *mut F))(); + (*(ctx as *mut F))(); + } } impl<C> From<OpenGLInitParams<C>> for libmpv2_sys::mpv_opengl_init_params { @@ -197,14 +201,18 @@ impl<C> From<RenderParam<C>> for libmpv2_sys::mpv_render_param { } unsafe fn free_void_data<T>(ptr: *mut c_void) { - drop(Box::<T>::from_raw(ptr as *mut T)); + unsafe { + drop(Box::<T>::from_raw(ptr as *mut T)); + } } unsafe fn free_init_params<C>(ptr: *mut c_void) { - let params = Box::from_raw(ptr as *mut libmpv2_sys::mpv_opengl_init_params); - drop(Box::from_raw( - params.get_proc_address_ctx as *mut OpenGLInitParams<C>, - )); + unsafe { + let params = Box::from_raw(ptr as *mut libmpv2_sys::mpv_opengl_init_params); + drop(Box::from_raw( + params.get_proc_address_ctx as *mut OpenGLInitParams<C>, + )); + } } impl RenderContext { |