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
//! Audio is always muted during QA. Apps are told through `RIGHTKIT_QA_MUTE=1`
//! and Chrome gets `--mute-audio`; on macOS the system output can additionally
//! be muted for the run and restored afterwards (opt-in, restored on drop).
//! Playback is asserted from DOM/engine state, never from sound.
#[cfg(target_os = "macos")]
use std::process::{Command, Stdio};
pub struct SystemMute {
restore: Option<bool>,
}
impl SystemMute {
/// Mute system output (macOS only). A no-op elsewhere; `active()` reports it.
pub fn engage() -> Self {
#[cfg(target_os = "macos")]
{
let was = Command::new("osascript")
.args(["-e", "output muted of (get volume settings)"])
.output()
.ok()
.map(|o| String::from_utf8_lossy(&o.stdout).trim() == "true");
if let Some(was_muted) = was {
if !was_muted {
let _ = Command::new("osascript")
.args(["-e", "set volume with output muted"])
.stdout(Stdio::null())
.stderr(Stdio::null())
.status();
}
return Self {
restore: Some(was_muted),
};
}
}
Self { restore: None }
}
pub fn active(&self) -> bool {
self.restore.is_some()
}
}
impl Drop for SystemMute {
fn drop(&mut self) {
// Only the macOS path ever records a mute to restore.
#[cfg(target_os = "macos")]
if self.restore == Some(false) {
let _ = Command::new("osascript")
.args(["-e", "set volume without output muted"])
.stdout(Stdio::null())
.stderr(Stdio::null())
.status();
}
}
}