Skip to main content

#
jellytau_lib/player/
native_video.rs

    1//! Whether this process renders video natively, answered once.
    2//!
    3//! Three things need this and must agree: the mpv backend (which has to be
    4//! configured for video *at construction*, before anything plays), the video
    5//! surface (which has nothing to draw otherwise), and `get_player_status`
    6//! (which tells the frontend whether to use a webview `<video>` element).
    7//!
    8//! It is a function rather than three `env::var` checks for the reason this
    9//! codebase keeps rediscovering: a capability answered in several places is a
    10//! capability whose answers drift. Four separate bugs this cycle came from
    11//! exactly that shape — a webview's decode limits applied to ExoPlayer, a
    12//! transcode target contradicting a direct-play claim, a codec list hardcoded in
    13//! a URL builder. One source, read by everyone.
    14//!
    15//! TRACES: UR-080 | DR-231, DR-235
    16
    17/// The opt-in for native desktop video.
    18///
    19/// Off by default while the render path is unproven — the webview path still
    20/// works and is what ships. This becomes the *default* (and then the only path)
    21/// when DR-235 lands; the variable is how it is exercised until then.
    22const ENV_FLAG: &str = "JELLYTAU_NATIVE_VIDEO";
    23
    24/// Whether mpv should decode and draw video in this process.
    25///
    26/// Read fresh rather than cached: it is consulted a handful of times at startup,
    27/// and a `OnceLock` here would only make it harder to test.
    28///
    29/// TRACES: UR-080 | DR-231, DR-235
    30pub fn enabled() -> bool {
    31    // Only where a native renderer exists. On Android ExoPlayer already does
    32    // this and `use_html5_element` is false for entirely separate reasons.
    33    if !cfg!(all(target_os = "linux", not(target_os = "android"))) {
    34        return false;
    35    }
    36    matches!(
    37        std::env::var(ENV_FLAG).as_deref(),
    38        Ok("1") | Ok("true") | Ok("yes")
    39    )
    40}
    41
    42#[cfg(test)]
    43mod tests {
    44    use super::*;
    45
    46    /// Absent, empty, or anything unrecognised means off. A half-set variable
    47    /// must not half-enable a renderer — the failure mode would be mpv
    48    /// configured for video with nothing drawing it, i.e. audio playing over a
    49    /// black rectangle.
    50    ///
    51    /// TRACES: UR-080 | DR-231 | UT-216
    52    #[test]
    53    fn test_only_explicit_truthy_values_enable_it() {
    54        let restore = std::env::var(ENV_FLAG).ok();
    55
    56        for value in ["", "0", "no", "false", "maybe", "2"] {
    57            std::env::set_var(ENV_FLAG, value);
    58            assert!(!enabled(), "{value:?} must not enable native video");
    59        }
    60
    61        for value in ["1", "true", "yes"] {
    62            std::env::set_var(ENV_FLAG, value);
    63            assert_eq!(
    64                enabled(),
    65                cfg!(all(target_os = "linux", not(target_os = "android"))),
    66                "{value:?} enables it exactly where a native renderer exists"
    67            );
    68        }
    69
    70        std::env::remove_var(ENV_FLAG);
    71        assert!(!enabled(), "absent means off");
    72
    73        match restore {
    74            Some(v) => std::env::set_var(ENV_FLAG, v),
    75            None => std::env::remove_var(ENV_FLAG),
    76        }
    77    }
    78}