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}