about summary refs log tree commit diff stats
path: root/crates/libmpv2/src/lib.rs
blob: 4d8d18a88932b62481dc19f58ae8da6c392bc6b5 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
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(())
    }
}