use crate::ddc_trait::DdcControl;
use crate::ddc_types::MonitorCapabilities;
use crate::error::DdcError;
use windows::Win32::Devices::Display::*;
use windows::Win32::Foundation::HANDLE;
pub struct WindowsBackend {
pub handle: std::ptr::NonNull<core::ffi::c_void>,
}
unsafe impl Send for WindowsBackend {}
unsafe impl Sync for WindowsBackend {}
impl Drop for WindowsBackend {
fn drop(&mut self) {
unsafe {
let _ = DestroyPhysicalMonitor(HANDLE(self.handle.as_ptr()));
}
}
}
impl DdcControl for WindowsBackend {
fn get_vcp_feature(&self, code: u8) -> Result<(u32, u32), DdcError> {
let h = HANDLE(self.handle.as_ptr());
let (mut current, mut max) = (0, 0);
unsafe {
if GetVCPFeatureAndVCPFeatureReply(h, code, None, &mut current, Some(&mut max)) != 0 {
Ok((current, max))
} else {
Err(DdcError::CommunicationFailed {
reason: format!("Win32 GetVCPFeature failed for code {:#04x}", code),
})
}
}
}
fn set_vcp_feature(&self, code: u8, value: u32) -> Result<(), DdcError> {
let h = HANDLE(self.handle.as_ptr());
unsafe {
if SetVCPFeature(h, code, value) != 0 {
Ok(())
} else {
Err(DdcError::CommunicationFailed {
reason: format!("Win32 SetVCPFeature failed for code {:#04x}", code),
})
}
}
}
fn get_capabilities(&self) -> Result<MonitorCapabilities, DdcError> {
let h = HANDLE(self.handle.as_ptr());
let (mut min_b, mut cur_b, mut max_b) = (0, 0, 0);
let (mut min_c, mut cur_c, mut max_c) = (0, 0, 0);
unsafe {
if GetMonitorBrightness(h, &mut min_b, &mut cur_b, &mut max_b) == 0 {
return Err(DdcError::CommunicationFailed {
reason: "Win32 GetMonitorBrightness failed".into(),
});
}
if GetMonitorContrast(h, &mut min_c, &mut cur_c, &mut max_c) == 0 {
cur_c = 50;
max_c = 100;
}
Ok(MonitorCapabilities {
brightness: cur_b,
brightness_max: max_b,
contrast: cur_c,
contrast_max: max_c,
})
}
}
}