use std::io;
#[link(name = "winmm")]
unsafe extern "system" {
fn PlaySoundW(pszSound: *const u16, hmod: isize, fdwSound: u32) -> i32;
}
unsafe extern "system" {
fn Beep(dwFreq: u32, dwDuration: u32) -> i32;
fn MessageBeep(uType: u32) -> i32;
}
pub use windows_sys::Win32::Media::Audio::{
SND_ALIAS, SND_APPLICATION, SND_ASYNC, SND_FILENAME, SND_LOOP, SND_MEMORY, SND_NODEFAULT,
SND_NOSTOP, SND_NOWAIT, SND_PURGE, SND_SENTRY, SND_SYNC, SND_SYSTEM,
};
pub use windows_sys::Win32::UI::WindowsAndMessaging::{
MB_ICONASTERISK, MB_ICONERROR, MB_ICONEXCLAMATION, MB_ICONHAND, MB_ICONINFORMATION,
MB_ICONQUESTION, MB_ICONSTOP, MB_ICONWARNING, MB_OK,
};
pub enum PlaySoundSource<'a> {
Stop,
Memory(&'a [u8]),
Name(&'a widestring::WideCStr),
}
pub fn play_sound(source: PlaySoundSource<'_>, flags: u32) -> Result<(), PlaySoundError> {
if matches!(source, PlaySoundSource::Memory(_)) && flags & SND_ASYNC != 0 {
return Err(PlaySoundError::MemoryAsyncRejected);
}
if !matches!(source, PlaySoundSource::Memory(_)) && flags & SND_MEMORY != 0 {
return Err(PlaySoundError::MemoryFlagWithoutBuffer);
}
let ptr: *const u16 = match source {
PlaySoundSource::Stop => core::ptr::null(),
PlaySoundSource::Memory(buf) => buf.as_ptr().cast(),
PlaySoundSource::Name(s) => s.as_ptr(),
};
let ok = unsafe { PlaySoundW(ptr, 0, flags) };
if ok == 0 {
Err(PlaySoundError::CallFailed)
} else {
Ok(())
}
}
#[derive(Debug, Clone, Copy)]
pub enum PlaySoundError {
CallFailed,
MemoryAsyncRejected,
MemoryFlagWithoutBuffer,
}
#[must_use]
pub fn beep(frequency: u32, duration_ms: u32) -> bool {
unsafe { Beep(frequency, duration_ms) != 0 }
}
pub fn message_beep(beep_type: u32) -> io::Result<()> {
let ok = unsafe { MessageBeep(beep_type) };
if ok == 0 {
Err(io::Error::last_os_error())
} else {
Ok(())
}
}