From 6ca50ac2bb426a1becfbbc43888e700248cd28df Mon Sep 17 00:00:00 2001 From: Vladimir Rubin Date: Fri, 2 May 2025 23:02:27 +0300 Subject: [PATCH] feat: add more backends --- Cargo.lock | 2 +- Cargo.toml | 2 +- flake.nix | 2 +- src/lib.rs | 92 +++++++++++++++++++++++++++++++++++++++++++++++++---- src/main.rs | 50 +++++++++++++++-------------- 5 files changed, 116 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d2a101f..b8ca81f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -244,7 +244,7 @@ checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" [[package]] name = "hinoirisetr" -version = "0.3.1" +version = "0.4.0" dependencies = [ "libloading", "smol", diff --git a/Cargo.toml b/Cargo.toml index bd0b31c..6714853 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hinoirisetr" -version = "0.3.1" +version = "0.4.0" authors = ["Vladimir Rubin "] description = "A daemon to dim the screen at night" license = "MIT" diff --git a/flake.nix b/flake.nix index 14ce1fd..a3511b6 100644 --- a/flake.nix +++ b/flake.nix @@ -42,7 +42,7 @@ packages.default = pkgs.rustPlatform.buildRustPackage { pname = "hinoirisetr"; - version = "0.3.1"; + version = "0.4.0"; src = ./.; diff --git a/src/lib.rs b/src/lib.rs index 8d78616..3d62dca 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,12 +27,26 @@ pub struct Config { pub notification_timeout: u32, pub gamma_backend: GammaBackend, + pub temp_backend: TempBackend, } #[derive(Debug, Copy, Clone)] pub enum GammaBackend { Hyprctl, Ddcutil, + Xsct, + Redshift, + Gammastep, + None, +} + +#[derive(Debug, Copy, Clone)] +pub enum TempBackend { + Hyprctl, + Redshift, + Xsct, + Gammastep, + None, } impl Default for Config { @@ -48,6 +62,7 @@ impl Default for Config { sunrise_end: 7, notification_timeout: 5000, gamma_backend: GammaBackend::Hyprctl, + temp_backend: TempBackend::Hyprctl, } } } @@ -60,6 +75,7 @@ pub enum ConfigError { InvalidTime(String), InvalidGamma(String), InvalidGammaBackend(String), + InvalidTempBackend(String), } impl From for ConfigError { @@ -108,8 +124,20 @@ impl Config { "gamma_backend" => match value.to_lowercase().as_str() { "hyprctl" => config.gamma_backend = GammaBackend::Hyprctl, "ddcutil" => config.gamma_backend = GammaBackend::Ddcutil, + "gammastep" => config.gamma_backend = GammaBackend::Gammastep, + "xsct" => config.gamma_backend = GammaBackend::Xsct, + "redshift" => config.gamma_backend = GammaBackend::Redshift, + "none" => config.gamma_backend = GammaBackend::None, _ => return Err(ConfigError::InvalidGammaBackend(value.to_string())), }, + "temp_backend" => match value.to_lowercase().as_str() { + "hyprctl" => config.temp_backend = TempBackend::Hyprctl, + "gammastep" => config.temp_backend = TempBackend::Gammastep, + "xsct" => config.temp_backend = TempBackend::Xsct, + "redshift" => config.temp_backend = TempBackend::Redshift, + "none" => config.temp_backend = TempBackend::None, + _ => return Err(ConfigError::InvalidTempBackend(value.to_string())), + }, _ => {} }, "gamma" => match key_trimmed { @@ -244,17 +272,37 @@ pub fn compute_settings(now: Time, config: &Config) -> (u16, u16) { } /// Apply given temperature (Kelvin) and gamma (%) via hyprctl commands -pub fn apply_settings(temp: u16, gamma: u16, backend: GammaBackend) { +pub fn apply_settings(temp: u16, gamma: u16, config: &Config) { trace!("apply_settings({temp}, {gamma})"); debug!("applying temperature: {temp}"); debug!("applying gamma: {gamma}"); - let _ = Command::new("hyprctl") - .args(["hyprsunset", "temperature", &temp.to_string()]) - .output(); - trace!("hyprctl hyprsunset temperature {temp}"); + match config.temp_backend { + TempBackend::Hyprctl => { + let _ = Command::new("hyprctl") + .args(["hyprsunset", "temperature", &temp.to_string()]) + .output(); + trace!("hyprctl hyprsunset temperature {temp}"); + } + TempBackend::Redshift => { + let _ = Command::new("redshift") + .args(["-o", "-t", &temp.to_string()]) + .output(); + trace!("redshift -o -t {temp}"); + } + TempBackend::Xsct => { + let _ = Command::new("xsct").args([&temp.to_string()]).output(); + trace!("xsct {temp}"); + } + TempBackend::None => {} + TempBackend::Gammastep => { + let _ = Command::new("gammastep") + .args(["-O", &temp.to_string()]) + .output(); + }, + } - match backend { + match config.gamma_backend { GammaBackend::Hyprctl => { let _ = Command::new("hyprctl") .args(["hyprsunset", "gamma", &gamma.to_string()]) @@ -267,5 +315,37 @@ pub fn apply_settings(temp: u16, gamma: u16, backend: GammaBackend) { .output(); trace!("ddcutil setvcp 10 {gamma}"); } + GammaBackend::Gammastep => { + let _ = Command::new("gammastep") + .args(["-O", "6500", "-g", &(&gamma/100).to_string()]) + .output(); + trace!("gammastep -O 6500 -g {gamma}"); + } + GammaBackend::Xsct => { + let output = Command::new("xsct").output().expect("xsct failed"); + let stdout = String::from_utf8_lossy(&output.stdout); + let mut ttemp = 6000; + for line in stdout.lines() { + if line.contains("temperature") { + // example: "Screen 0: temperature ~ 6000 0.598234" + let parts: Vec<&str> = line.split_whitespace().collect(); + if parts.len() >= 6 { + ttemp = parts[4].parse::().unwrap(); + } + } + } + + let _ = Command::new("xsct") + .args([&ttemp.to_string(), &(&gamma/100).to_string()]) + .output(); + trace!("xsct {ttemp} {gamma}"); + } + GammaBackend::Redshift => { + let _ = Command::new("redshift") + .args(["-O", "6500", "-g", &(&gamma/100).to_string()]) + .output(); + trace!("redshift -O 6500 -g {gamma}"); + }, + GammaBackend::None => {} } } diff --git a/src/main.rs b/src/main.rs index c7d7945..66275cf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,7 +7,9 @@ use std::time::{Duration, UNIX_EPOCH}; use hinoirisetr::notify::InitializedNotificationSystem; use hinoirisetr::time::Time; -use hinoirisetr::{apply_settings, compute_settings, debug, error, info, trace, warn, Config, GammaBackend}; +use hinoirisetr::{ + apply_settings, compute_settings, debug, error, info, trace, warn, Config, GammaBackend, TempBackend +}; use smol::Timer; use smol::channel::{Sender, unbounded}; use smol::io::{AsyncBufReadExt, BufReader}; @@ -211,28 +213,23 @@ fn main() { Config::default() }; - - // TODO: add more temp backends and remove this - if !is_binary_available("hyprctl") { - error!("hyprctl is not available, exiting."); - std::process::exit(1); - } - + // TODO: add a map to not check for binaries twice? match cfg.gamma_backend { - GammaBackend::Hyprctl => { - if !is_binary_available("hyprctl") { - error!("hyprctl is not available, exiting."); - std::process::exit(1); - } - } - GammaBackend::Ddcutil => { - if !is_binary_available("ddcutil") { - error!("ddcutil is not available, exiting."); - std::process::exit(1); - } - } + GammaBackend::Hyprctl => check_binary("hyprctl"), + GammaBackend::Ddcutil => check_binary("ddcutil"), + GammaBackend::Xsct => check_binary("xsct"), + GammaBackend::Redshift => check_binary("redshift"), + GammaBackend::Gammastep => check_binary("gammastep"), + GammaBackend::None => {} } + match cfg.temp_backend { + TempBackend::Hyprctl => check_binary("hyprctl"), + TempBackend::Gammastep => check_binary("gammastep"), + TempBackend::Xsct => check_binary("xsct"), + TempBackend::Redshift => check_binary("redshift"), + TempBackend::None => {} + } CONFIG.set(Arc::new(RwLock::new(cfg))).unwrap(); @@ -288,7 +285,7 @@ fn main() { { let now = get_time(); let (temp, gamma) = compute_settings(now, &*config_guard().await); - apply_settings(temp, gamma, config_guard().await.gamma_backend); + apply_settings(temp, gamma, &*config_guard().await); trace!("initial settings applied: {temp}K, {gamma}%"); } @@ -298,12 +295,12 @@ fn main() { apply_settings( config_guard().await.temp_day, config_guard().await.gamma_day, - config_guard().await.gamma_backend, + &*config_guard().await, ); } else { let now = get_time(); let (temp, gamma) = compute_settings(now, &*config_guard().await); - apply_settings(temp, gamma, config_guard().await.gamma_backend); + apply_settings(temp, gamma, &*config_guard().await); } let _ = notify_r.recv().await; @@ -404,3 +401,10 @@ fn config_handle() -> Arc> { fn get_time() -> Time { Time::now().expect("Failed to get local time") } + +fn check_binary(binary: &str) { + if !is_binary_available(binary) { + error!("{binary} is not available, exiting."); + std::process::exit(1); + } +}