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}