use std::io::BufReader;
use std::path::PathBuf;
use crate::app::window_state::WindowState;
impl WindowState {
pub(super) fn play_sound_file(sound_id: &str, volume: u8) {
let candidate = std::path::Path::new(sound_id);
let path = if candidate.is_absolute() {
candidate.to_path_buf()
} else {
Self::sounds_dir().join(sound_id)
};
if !path.exists() {
log::warn!("Sound file not found: {}", path.display());
return;
}
let volume_f32 = (volume as f32 / 100.0).clamp(0.0, 1.0);
std::thread::spawn(move || {
let file = match std::fs::File::open(&path) {
Ok(f) => f,
Err(e) => {
log::error!("Failed to open sound file '{}': {}", path.display(), e);
return;
}
};
let stream = match rodio::DeviceSinkBuilder::open_default_sink() {
Ok(s) => s,
Err(e) => {
log::error!("Failed to open audio output: {}", e);
return;
}
};
let sink = rodio::Player::connect_new(stream.mixer());
let source = match rodio::Decoder::new(BufReader::new(file)) {
Ok(s) => s,
Err(e) => {
log::error!("Failed to decode sound file '{}': {}", path.display(), e);
return;
}
};
sink.set_volume(volume_f32);
sink.append(source);
sink.sleep_until_end();
});
}
pub(super) fn sounds_dir() -> PathBuf {
if let Some(config_dir) = dirs::config_dir() {
config_dir.join("par-term").join("sounds")
} else {
PathBuf::from("sounds")
}
}
}