diff options
Diffstat (limited to '')
-rw-r--r-- | libmpv2/src/lib.rs | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/libmpv2/src/lib.rs b/libmpv2/src/lib.rs new file mode 100644 index 0000000..4d8d18a --- /dev/null +++ b/libmpv2/src/lib.rs @@ -0,0 +1,175 @@ +// yt - A fully featured command line YouTube client +// +// Copyright (C) 2024 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>. + +//! This crate provides abstractions for +//! [libmpv](https://github.com/mpv-player/mpv/tree/master/libmpv) of the +//! [mpv media player](https://github.com/mpv-player/mpv). +//! +//! Libmpv requires `LC_NUMERIC` to be `C`, which should be the default value. +//! +//! Most of the documentation is paraphrased or even copied from the +//! [mpv manual](https://mpv.io/manual/master/), +//! if any questions arise it will probably answer them in much more depth than this documentation. +//! +//! # Examples +//! +//! See the 'examples' directory in the crate root. + +// Procedure for updating to new libmpv: +// - make any nessecary API change (if so, bump crate version) +// - update MPV_CLIENT_API consts in lib.rs +// - run tests and examples to test whether they still work + +#![allow(non_upper_case_globals)] + +use std::fmt::Display; +use std::os::raw as ctype; + +pub const MPV_CLIENT_API_MAJOR: ctype::c_ulong = 2; +pub const MPV_CLIENT_API_MINOR: ctype::c_ulong = 2; +pub const MPV_CLIENT_API_VERSION: ctype::c_ulong = + MPV_CLIENT_API_MAJOR << 16 | MPV_CLIENT_API_MINOR; + +mod mpv; +#[cfg(test)] +mod tests; + +pub use crate::mpv::*; + +/// A format mpv can use. +pub use libmpv2_sys::mpv_format as MpvFormat; +pub mod mpv_format { + pub use libmpv2_sys::mpv_format_MPV_FORMAT_DOUBLE as Double; + pub use libmpv2_sys::mpv_format_MPV_FORMAT_FLAG as Flag; + pub use libmpv2_sys::mpv_format_MPV_FORMAT_INT64 as Int64; + pub use libmpv2_sys::mpv_format_MPV_FORMAT_NODE as Node; + pub use libmpv2_sys::mpv_format_MPV_FORMAT_NODE_ARRAY as Array; + pub use libmpv2_sys::mpv_format_MPV_FORMAT_NODE_MAP as Map; + pub use libmpv2_sys::mpv_format_MPV_FORMAT_NONE as None; + pub use libmpv2_sys::mpv_format_MPV_FORMAT_OSD_STRING as OsdString; + pub use libmpv2_sys::mpv_format_MPV_FORMAT_STRING as String; +} + +/// An libmpv2_sys mpv error. +pub use libmpv2_sys::mpv_error as MpvError; +pub mod mpv_error { + pub use libmpv2_sys::mpv_error_MPV_ERROR_AO_INIT_FAILED as AoInitFailed; + pub use libmpv2_sys::mpv_error_MPV_ERROR_COMMAND as Command; + pub use libmpv2_sys::mpv_error_MPV_ERROR_EVENT_QUEUE_FULL as EventQueueFull; + pub use libmpv2_sys::mpv_error_MPV_ERROR_GENERIC as Generic; + pub use libmpv2_sys::mpv_error_MPV_ERROR_INVALID_PARAMETER as InvalidParameter; + pub use libmpv2_sys::mpv_error_MPV_ERROR_LOADING_FAILED as LoadingFailed; + pub use libmpv2_sys::mpv_error_MPV_ERROR_NOMEM as NoMem; + pub use libmpv2_sys::mpv_error_MPV_ERROR_NOTHING_TO_PLAY as NothingToPlay; + pub use libmpv2_sys::mpv_error_MPV_ERROR_NOT_IMPLEMENTED as NotImplemented; + pub use libmpv2_sys::mpv_error_MPV_ERROR_OPTION_ERROR as OptionError; + pub use libmpv2_sys::mpv_error_MPV_ERROR_OPTION_FORMAT as OptionFormat; + pub use libmpv2_sys::mpv_error_MPV_ERROR_OPTION_NOT_FOUND as OptionNotFound; + pub use libmpv2_sys::mpv_error_MPV_ERROR_PROPERTY_ERROR as PropertyError; + pub use libmpv2_sys::mpv_error_MPV_ERROR_PROPERTY_FORMAT as PropertyFormat; + pub use libmpv2_sys::mpv_error_MPV_ERROR_PROPERTY_NOT_FOUND as PropertyNotFound; + pub use libmpv2_sys::mpv_error_MPV_ERROR_PROPERTY_UNAVAILABLE as PropertyUnavailable; + pub use libmpv2_sys::mpv_error_MPV_ERROR_SUCCESS as Success; + pub use libmpv2_sys::mpv_error_MPV_ERROR_UNINITIALIZED as Uninitialized; + pub use libmpv2_sys::mpv_error_MPV_ERROR_UNKNOWN_FORMAT as UnknownFormat; + pub use libmpv2_sys::mpv_error_MPV_ERROR_UNSUPPORTED as Unsupported; + pub use libmpv2_sys::mpv_error_MPV_ERROR_VO_INIT_FAILED as VoInitFailed; +} + +/// Log verbosity level. +pub use libmpv2_sys::mpv_log_level as LogLevel; +pub mod mpv_log_level { + pub use libmpv2_sys::mpv_log_level_MPV_LOG_LEVEL_DEBUG as Debug; + pub use libmpv2_sys::mpv_log_level_MPV_LOG_LEVEL_ERROR as Error; + pub use libmpv2_sys::mpv_log_level_MPV_LOG_LEVEL_FATAL as Fatal; + pub use libmpv2_sys::mpv_log_level_MPV_LOG_LEVEL_INFO as Info; + pub use libmpv2_sys::mpv_log_level_MPV_LOG_LEVEL_NONE as None; + pub use libmpv2_sys::mpv_log_level_MPV_LOG_LEVEL_TRACE as Trace; + pub use libmpv2_sys::mpv_log_level_MPV_LOG_LEVEL_V as V; + pub use libmpv2_sys::mpv_log_level_MPV_LOG_LEVEL_WARN as Warn; +} + +/// The reason a file stopped. +#[derive(Debug, Clone, Copy)] +pub enum EndFileReason { + /** + * The end of file was reached. Sometimes this may also happen on + * incomplete or corrupted files, or if the network connection was + * interrupted when playing a remote file. It also happens if the + * playback range was restricted with --end or --frames or similar. + */ + Eof, + + /** + * Playback was stopped by an external action (e.g. playlist controls). + */ + Stop, + + /** + * Playback was stopped by the quit command or player shutdown. + */ + Quit, + + /** + * Some kind of error happened that lead to playback abort. Does not + * necessarily happen on incomplete or broken files (in these cases, both + * MPV_END_FILE_REASON_ERROR or MPV_END_FILE_REASON_EOF are possible). + * + * mpv_event_end_file.error will be set. + */ + Error, + + /** + * The file was a playlist or similar. When the playlist is read, its + * entries will be appended to the playlist after the entry of the current + * file, the entry of the current file is removed, and a MPV_EVENT_END_FILE + * event is sent with reason set to MPV_END_FILE_REASON_REDIRECT. Then + * playback continues with the playlist contents. + * Since API version 1.18. + */ + Redirect, +} + +impl From<libmpv2_sys::mpv_end_file_reason> for EndFileReason { + fn from(value: libmpv2_sys::mpv_end_file_reason) -> Self { + match value { + 0 => Self::Eof, + 2 => Self::Stop, + 3 => Self::Quit, + 4 => Self::Error, + 5 => Self::Redirect, + _ => unreachable!("Other enum variants do not exist yet"), + } + } +} + +impl Display for EndFileReason { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + EndFileReason::Eof => f.write_str("The end of file was reached.")?, + EndFileReason::Error => { + f.write_str( + "Playback was stopped by an external action (e.g. playlist controls).", + )?; + } + EndFileReason::Quit => { + f.write_str("Playback was stopped by the quit command or player shutdown.")?; + } + EndFileReason::Redirect => { + f.write_str("Some kind of error happened that lead to playback abort.")?; + } + EndFileReason::Stop => { + f.write_str("The file was a playlist or similar.")?; + } + } + + Ok(()) + } +} |