mqttdpms/src/dpms.rs

162 lines
4.7 KiB
Rust

#![allow(dead_code)]
use std::ffi::CStr;
use x11::dpms::{
DPMSCapable, DPMSDisable, DPMSEnable, DPMSForceLevel, DPMSGetTimeouts,
DPMSInfo, DPMSQueryExtension,
};
use x11::dpms::{DPMSModeOff, DPMSModeOn, DPMSModeStandby, DPMSModeSuspend};
use x11::xlib::{XCloseDisplay, XDisplayName, XOpenDisplay, _XDisplay};
use x11::xmd::{BOOL, CARD16};
/// Error returned if connecting to the X server fails
#[derive(Debug)]
pub struct OpenDisplayError;
/// Wrapper for an X display pointer
pub struct Display {
display: *mut _XDisplay,
}
impl Display {
/// Open a connection to the X server
///
/// If the connection succeeds, a [`Display`] is returned. Otherwise, an
/// [`OpenDisplayError`] is returned.
pub fn open() -> Result<Self, OpenDisplayError> {
let display = unsafe { XOpenDisplay(std::ptr::null()) };
if display.is_null() {
Err(OpenDisplayError)
} else {
Ok(Self { display })
}
}
/// Return the name of the X server display
///
/// If the display name cannot be determined, an empty string is returned.
pub fn name() -> String {
let name = unsafe { CStr::from_ptr(XDisplayName(std::ptr::null())) };
let name = name.to_str().unwrap_or("");
String::from(name)
}
}
impl Drop for Display {
fn drop(&mut self) {
unsafe { XCloseDisplay(self.display) };
}
}
/// DPMS Power Level
///
/// There are four power levels specified by the Video Electronics Standards
/// Association (VESA) Display Power Management Signaling (DPMS) standard.
/// These are mapped onto the X DPMS Extension
#[derive(PartialEq)]
pub enum DpmsPowerLevel {
/// In use
On = DPMSModeOn as isize,
/// Blanked, low power
Standby = DPMSModeStandby as isize,
/// Blanked, lower power
Suspend = DPMSModeSuspend as isize,
/// Shut off, awaiting activity
Off = DPMSModeOff as isize,
Unknown = -1,
}
impl From<u16> for DpmsPowerLevel {
fn from(v: u16) -> Self {
#[allow(non_snake_case)]
match v {
x if x == DpmsPowerLevel::On as u16 => Self::On,
x if x == DpmsPowerLevel::Standby as u16 => Self::Standby,
x if x == DpmsPowerLevel::Suspend as u16 => Self::Suspend,
x if x == DpmsPowerLevel::Off as u16 => Self::Off,
_ => Self::Unknown,
}
}
}
/// Result from [`get_info`] function (`DPMSInfo`)
pub struct DpmsInfo {
/// Current power level
pub power_level: DpmsPowerLevel,
/// DPMS enabled/disabled state
pub state: bool,
}
/// Result from [`get_timeouts`] function (`DPMSGetTimeouts`)
pub struct DpmsTimeouts {
/// Amount of time of inactivity in seconds before standby mode is invoked
pub standby: u16,
/// Amount of time of inactivity in seconds before the second level of power
/// savings is invoked
pub suspend: u16,
/// Amount of time of inactivity in seconds before the third and final level
/// of power savings is invoked
pub off: u16,
}
/// Queries the X server to determine the availability of the DPMS Extension
pub fn query_extension(display: &Display) -> bool {
let mut event_base = 0;
let mut error_base = 0;
let r = unsafe {
DPMSQueryExtension(display.display, &mut event_base, &mut error_base)
};
r != 0
}
/// Returns the DPMS capability of the X server, either TRUE (capable of DPMS)
/// or FALSE (incapable of DPMS)
pub fn dpms_capable(display: &Display) -> bool {
let r = unsafe { DPMSCapable(display.display) };
r != 0
}
/// Returns information about the current DPMS state
pub fn get_info(display: &Display) -> DpmsInfo {
let mut power_level: CARD16 = 0;
let mut state: BOOL = 0;
unsafe { DPMSInfo(display.display, &mut power_level, &mut state) };
DpmsInfo {
power_level: power_level.into(),
state: state != 0,
}
}
/// Retrieves the timeout values used by the X server for DPMS timings
pub fn get_timeouts(display: &Display) -> DpmsTimeouts {
let mut standby: CARD16 = 0;
let mut suspend: CARD16 = 0;
let mut off: CARD16 = 0;
unsafe {
DPMSGetTimeouts(display.display, &mut standby, &mut suspend, &mut off)
};
DpmsTimeouts {
standby,
suspend,
off,
}
}
/// Forces a DPMS capable display into the specified power level
pub fn force_level(display: &Display, level: DpmsPowerLevel) -> bool {
let r = unsafe { DPMSForceLevel(display.display, level as u16) };
r != 0
}
/// Enables DPMS on the specified display
pub fn enable(display: &Display) -> bool {
let r = unsafe { DPMSEnable(display.display) };
r != 0
}
/// Disables DPMS on the specified display
pub fn disable(display: &Display) -> bool {
let r = unsafe { DPMSDisable(display.display) };
r != 0
}