use std::os::windows::raw::HANDLE;
use log::warn;
use winapi::shared::minwindef::FALSE;
use winapi::um::avrt::AvRevertMmThreadCharacteristics;
use winapi::um::avrt::AvSetMmThreadCharacteristicsA;
use winapi::um::errhandlingapi::GetLastError;
use winapi::um::processthreadsapi::GetCurrentThread;
use winapi::um::processthreadsapi::SetThreadPriority;
use super::errno_result;
use super::Result;
pub fn set_audio_thread_priority() -> Result<SafeMultimediaHandle> {
let multimedia_handle = unsafe {
let mut task_index: u32 = 0;
let pro_audio = std::ffi::CString::new("Pro Audio").unwrap();
AvSetMmThreadCharacteristicsA(pro_audio.as_ptr(), &mut task_index)
};
if multimedia_handle.is_null() {
warn!(
"Failed to set audio thread to Pro Audio. Error: {}",
unsafe { GetLastError() }
);
errno_result()
} else {
Ok(SafeMultimediaHandle { multimedia_handle })
}
}
pub fn set_thread_priority(thread_priority: i32) -> Result<()> {
let res =
unsafe { SetThreadPriority(GetCurrentThread(), thread_priority) };
if res == 0 {
errno_result()
} else {
Ok(())
}
}
pub struct SafeMultimediaHandle {
multimedia_handle: HANDLE,
}
impl Drop for SafeMultimediaHandle {
fn drop(&mut self) {
if unsafe { AvRevertMmThreadCharacteristics(self.multimedia_handle) } == FALSE {
warn!(
"Failed to revert audio thread. Error: {}",
unsafe { GetLastError() }
);
}
}
}
#[cfg(test)]
mod test {
use winapi::um::processthreadsapi::GetCurrentThread;
use winapi::um::processthreadsapi::GetThreadPriority;
use winapi::um::winbase::THREAD_PRIORITY_NORMAL;
use winapi::um::winbase::THREAD_PRIORITY_TIME_CRITICAL;
use super::*;
#[test]
#[ignore]
fn test_mm_handle_is_dropped() {
unsafe {
let thread_priority = GetThreadPriority(GetCurrentThread());
assert_eq!(thread_priority, THREAD_PRIORITY_NORMAL as i32);
{
let _handle = set_audio_thread_priority();
let thread_priority = GetThreadPriority(GetCurrentThread());
assert_eq!(thread_priority, THREAD_PRIORITY_TIME_CRITICAL as i32);
}
let thread_priority = GetThreadPriority(GetCurrentThread());
assert_eq!(thread_priority, THREAD_PRIORITY_NORMAL as i32);
}
}
}