use std::sync::atomic::{AtomicU64, Ordering};
use std::time::Instant;
use tracing::debug;
const COOLDOWN_SECONDS: u64 = 30;
static LAST_PLAYED_MS: AtomicU64 = AtomicU64::new(0);
static START: std::sync::OnceLock<Instant> = std::sync::OnceLock::new();
fn now_ms() -> u64 {
let start = START.get_or_init(Instant::now);
start.elapsed().as_millis() as u64
}
pub fn play_finish_sound() {
let now = now_ms();
let last = LAST_PLAYED_MS.load(Ordering::Relaxed);
if now.saturating_sub(last) < COOLDOWN_SECONDS * 1000 {
return;
}
LAST_PLAYED_MS.store(now, Ordering::Relaxed);
if let Err(e) = play_platform_sound() {
debug!("Failed to play finish sound: {e}");
}
}
fn play_platform_sound() -> Result<(), String> {
#[cfg(target_os = "macos")]
{
std::process::Command::new("afplay")
.arg("/System/Library/Sounds/Glass.aiff")
.stdout(std::process::Stdio::null())
.stderr(std::process::Stdio::null())
.spawn()
.map_err(|e| e.to_string())?;
Ok(())
}
#[cfg(target_os = "linux")]
{
let players = ["paplay", "aplay", "play", "cvlc"];
let sounds = [
"/usr/share/sounds/freedesktop/stereo/complete.oga",
"/usr/share/sounds/gnome/default/alerts/glass.ogg",
"/usr/share/sounds/alsa/Front_Center.wav",
];
for player in &players {
let which = std::process::Command::new("which").arg(player).output();
if let Ok(output) = which
&& output.status.success()
{
for sound in &sounds {
if std::path::Path::new(sound).exists() {
let mut cmd = std::process::Command::new(player);
if *player == "cvlc" {
cmd.arg("--play-and-exit");
}
cmd.arg(sound)
.stdout(std::process::Stdio::null())
.stderr(std::process::Stdio::null())
.spawn()
.map_err(|e| e.to_string())?;
return Ok(());
}
}
}
}
print!("\x07");
Ok(())
}
#[cfg(target_os = "windows")]
{
let sound_path = r"C:\Windows\Media\notify.wav";
let ps_cmd = format!("(New-Object Media.SoundPlayer '{sound_path}').PlaySync()");
std::process::Command::new("powershell")
.args(["-Command", &ps_cmd])
.stdout(std::process::Stdio::null())
.stderr(std::process::Stdio::null())
.spawn()
.map_err(|e| e.to_string())?;
Ok(())
}
#[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "windows")))]
{
print!("\x07");
Ok(())
}
}
#[cfg(test)]
#[path = "sound_tests.rs"]
mod tests;