brightness/
lib.rs

1// Copyright (C) 2022 The brightness project authors. Distributed under the 0BSD license.
2
3//! # Overview
4//! - [📦 crates.io](https://crates.io/crates/brightness)
5//! - [📖 Documentation](https://docs.rs/brightness)
6//! - [âš– 0BSD license](https://spdx.org/licenses/0BSD.html)
7//!
8//! This crate provides definitions to get and set display brightness.
9//!
10//! Linux and Windows are supported.
11//!
12//! # Example
13//!
14//! ```rust
15//! # #[cfg(feature = "async")]
16//! # mod doctest {
17//! use brightness::Brightness;
18//! use futures::TryStreamExt;
19//!
20//! async fn show_brightness() -> Result<(), brightness::Error> {
21//!     brightness::brightness_devices().try_for_each(|dev| async move {
22//!         let name = dev.device_name().await?;
23//!         let value = dev.get().await?;
24//!         println!("Brightness of device {} is {}%", name, value);
25//!         Ok(())
26//!     }).await
27//! }
28//! # }
29//! ```
30//!
31//! # Linux
32//!
33//! This crate interacts with devices found at `/sys/class/backlight`. This means that the
34//! [ddcci-backlight](https://gitlab.com/ddcci-driver-linux/ddcci-driver-linux#ddcci-backlight-monitor-backlight-driver)
35//! kernel driver is required to control external displays (via DDC/CI).
36//!
37//! Setting brightness is attempted using D-Bus and logind, which requires
38//! [systemd 243 or newer](https://github.com/systemd/systemd/blob/877aa0bdcc2900712b02dac90856f181b93c4e40/NEWS#L262).
39//! If this fails because the method is not available, the desired brightness is written to
40//! `/sys/class/backlight/$DEVICE/brightness`, which requires permission (`udev` rules can help with
41//! that).
42//!
43//! # Contribute
44//!
45//! All contributions shall be licensed under the [0BSD license](https://spdx.org/licenses/0BSD.html).
46
47#![deny(warnings)]
48#![deny(missing_docs)]
49#![cfg_attr(doc_cfg, feature(doc_cfg))]
50
51use std::error::Error as StdError;
52use thiserror::Error;
53
54pub mod blocking;
55
56#[cfg(feature = "async")]
57#[cfg_attr(doc_cfg, doc(cfg(feature = "async")))]
58cfg_if::cfg_if! {
59    if #[cfg(target_os = "linux")] {
60        mod linux;
61        use self::linux as platform;
62    } else if #[cfg(windows)] {
63        pub mod windows;
64        use self::windows as platform;
65    } else {
66        compile_error!("unsupported platform");
67    }
68}
69
70#[cfg(feature = "async")]
71#[cfg_attr(doc_cfg, doc(cfg(feature = "async")))]
72mod r#async {
73    use super::{platform, Error};
74    use async_trait::async_trait;
75    use futures::{Stream, StreamExt};
76
77    /// Async interface to get and set brightness.
78    #[async_trait]
79    pub trait Brightness {
80        /// Returns the device name.
81        async fn device_name(&self) -> Result<String, Error>;
82
83        /// Returns the current brightness as a percentage.
84        async fn get(&self) -> Result<u32, Error>;
85
86        /// Sets the brightness as a percentage.
87        async fn set(&mut self, percentage: u32) -> Result<(), Error>;
88    }
89
90    /// Async brightness device.
91    #[derive(Debug)]
92    pub struct BrightnessDevice(pub(crate) platform::AsyncDeviceImpl);
93
94    #[async_trait]
95    impl Brightness for BrightnessDevice {
96        async fn device_name(&self) -> Result<String, Error> {
97            self.0.device_name().await
98        }
99
100        async fn get(&self) -> Result<u32, Error> {
101            self.0.get().await
102        }
103
104        async fn set(&mut self, percentage: u32) -> Result<(), Error> {
105            self.0.set(percentage).await
106        }
107    }
108
109    /// Returns all brightness devices on the running system.
110    pub fn brightness_devices() -> impl Stream<Item = Result<BrightnessDevice, Error>> {
111        platform::brightness_devices().map(|r| r.map(BrightnessDevice).map_err(Into::into))
112    }
113}
114
115#[cfg(feature = "async")]
116pub use r#async::{brightness_devices, Brightness, BrightnessDevice};
117
118/// Errors used in this API
119#[derive(Debug, Error)]
120#[non_exhaustive]
121pub enum Error {
122    /// Getting a list of brightness devices failed
123    #[error("Failed to list brightness devices")]
124    ListingDevicesFailed(#[source] Box<dyn StdError + Send + Sync>),
125
126    /// Getting device information failed
127    #[error("Failed to get brightness device {device} information")]
128    GettingDeviceInfoFailed {
129        /// Device name
130        device: String,
131        /// Cause
132        source: Box<dyn StdError + Send + Sync>,
133    },
134
135    /// Setting brightness failed
136    #[error("Setting brightness failed for device {device}")]
137    SettingBrightnessFailed {
138        /// Device name
139        device: String,
140        /// Cause
141        source: Box<dyn StdError + Send + Sync>,
142    },
143}