From 1bdd1ed057351a5f59dd5c87aa64b1d1c25cc970 Mon Sep 17 00:00:00 2001 From: Jareth Gomes Date: Fri, 28 Nov 2025 23:02:49 +1100 Subject: [PATCH 1/3] feat: Add linear transition to device brightness change --- src/main.rs | 76 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 68 insertions(+), 8 deletions(-) diff --git a/src/main.rs b/src/main.rs index b87ddef..fbc87f7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,6 +17,9 @@ use simplelog::{ use std::env; use std::fs::{File, OpenOptions}; use std::io::prelude::*; +use std::sync::mpsc::Sender; +use std::thread::sleep; +use std::time::Duration; use syslog::Facility; mod config; @@ -105,6 +108,7 @@ fn main_loop( max_brightness: u32, mut switch_monitor: switch_monitor::SwitchMonitor, illuminance_filename: &str, + tx: Sender, ) -> Result<(), ErrorCode> { let mut kalman = Kalman::new( config.kalman_q(), @@ -118,7 +122,13 @@ fn main_loop( config.step_barrier(), ); debug!("k: s:{:?}", stepped_brightness); + let mut brightness_to_send = None; loop { + if let Some(brightness) = brightness_to_send { + if tx.send(brightness).is_ok() { + brightness_to_send = None; + } + } match read_file_to_u32(illuminance_filename) { Some(illuminance) => { let illuminance_k = kalman.process(illuminance as f32); @@ -129,7 +139,9 @@ fn main_loop( "raw {}, kalman {}, new level {} new brightness {}", illuminance, illuminance_k, brightness, new ); - set_brightness(config, new); + if tx.send(new).is_err() { + brightness_to_send = Some(new); + } } } _ => error!("Cannot read illuminance"), @@ -140,6 +152,34 @@ fn main_loop( } } +fn linear_ease_set_brightness(config: &Config, value: u32) { + let old_brightness = read_file_to_u32(config.backlight_filename()); + if let Some(old_brightness) = old_brightness { + const TRANSITION_STEPS: u32 = 20; + const TRANSITION_STEP_LENGTH_MS: u64 = 50; + if value > old_brightness { + let change = (value.saturating_sub(old_brightness)) as f32 / TRANSITION_STEPS as f32; + for i in 1..TRANSITION_STEPS { + set_brightness( + config, + old_brightness.saturating_add((change * i as f32) as u32), + ); + sleep(Duration::from_millis(TRANSITION_STEP_LENGTH_MS)); + } + } else { + let change = (old_brightness.saturating_sub(value)) as f32 / TRANSITION_STEPS as f32; + for i in 1..TRANSITION_STEPS { + set_brightness( + config, + old_brightness.saturating_sub((change * i as f32) as u32), + ); + sleep(Duration::from_millis(TRANSITION_STEP_LENGTH_MS)); + } + } + } + set_brightness(config, value); +} + fn set_brightness(config: &Config, value: u32) { if let Err(e) = write_u32_to_file(config.backlight_filename(), value) { error!("Cannot set brightness: {}", e); @@ -334,13 +374,33 @@ fn run() -> Result<(), ErrorCode> { })?; } - main_loop( - &config, - &light_convertor, - max_brightness, - switch_monitor, - &illuminance_filename, - ) + let (tx, rx) = std::sync::mpsc::channel::(); + std::thread::scope(|scope| { + scope.spawn(|| { + let rx = rx; + let config = &config; + loop { + match rx.recv() { + Ok(brightness) => { + linear_ease_set_brightness(config, brightness); + } + Err(e) => { + error!("Error on receiving channel: {}", e); + break; + } + } + } + }); + + main_loop( + &config, + &light_convertor, + max_brightness, + switch_monitor, + &illuminance_filename, + tx, + ) + }) } fn main() { From f8ab3c00987ad47b770dda5db151488aab059a66 Mon Sep 17 00:00:00 2001 From: Jareth Gomes Date: Fri, 28 Nov 2025 23:41:55 +1100 Subject: [PATCH 2/3] feat: Add config option to set backlight transition to instant or linear Adds `backlight_transition`, `backlight_transition_step_count`, and `backlight_transition_time_seconds` as options to the configuration file. --- illuminanced.toml | 5 ++++ src/brightness_transition.rs | 18 +++++++++++++ src/config.rs | 17 +++++++++++++ src/main.rs | 49 +++++++++++++++++++++--------------- 4 files changed, 69 insertions(+), 20 deletions(-) create mode 100644 src/brightness_transition.rs diff --git a/illuminanced.toml b/illuminanced.toml index 1c6759e..2f490e5 100644 --- a/illuminanced.toml +++ b/illuminanced.toml @@ -10,6 +10,11 @@ check_period_in_seconds = 1 light_steps = 10 min_backlight = 70 step_barrier = 0.1 +backlight_transition = "Linear" +# backlight_transition_step_count and backlight_transition_time_seconds are used only when backlight_transition +# is set to "linear" +backlight_transition_step_count = 20 +backlight_transition_time_seconds = 1 max_backlight_file = "/sys/class/backlight/intel_backlight/max_brightness" backlight_file = "/sys/class/backlight/intel_backlight/brightness" illuminance_file = "/sys/bus/acpi/devices/ACPI0008:00/iio:device0/in_illuminance_raw" diff --git a/src/brightness_transition.rs b/src/brightness_transition.rs new file mode 100644 index 0000000..6332bbb --- /dev/null +++ b/src/brightness_transition.rs @@ -0,0 +1,18 @@ +#[derive(Debug)] +pub enum BrightnessTransition { + Instant, + Linear, +} + +const INSTANT_STR: &str = "INSTANT"; +const LINEAR_STR: &str = "LINEAR"; + +impl BrightnessTransition { + pub fn from_str(value: &str) -> Option { + match value.to_uppercase().as_str() { + INSTANT_STR => Some(Self::Instant), + LINEAR_STR => Some(Self::Linear), + _ => None, + } + } +} diff --git a/src/config.rs b/src/config.rs index 683b25e..822f40c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,3 +1,4 @@ +use crate::brightness_transition::BrightnessTransition; use crate::ErrorCode; use crate::LightPoint; use log::LevelFilter; @@ -92,6 +93,22 @@ impl Config { .unwrap_or("/sys/bus/acpi/devices/ACPI0008:00/iio:device0/in_illuminance_raw") } + pub fn backlight_transition(&self) -> BrightnessTransition { + self.get_str("general", "backlight_transition") + .and_then(|s| BrightnessTransition::from_str(s)) + .unwrap_or(BrightnessTransition::Linear) + } + + pub fn backlight_transition_step_count(&self) -> u32 { + self.get_u32("general", "backlight_transition_step_count") + .unwrap_or(20) + } + + pub fn backlight_transition_time_seconds(&self) -> u32 { + self.get_u32("general", "backlight_transition_time_seconds") + .unwrap_or(1) + } + pub fn light_points(&self) -> Result, ErrorCode> { if self.table.is_none() { return Ok(self.default_ligth_points()); diff --git a/src/main.rs b/src/main.rs index fbc87f7..4fc6691 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,6 +22,7 @@ use std::thread::sleep; use std::time::Duration; use syslog::Facility; +mod brightness_transition; mod config; mod discrete_value; mod kalman; @@ -154,26 +155,34 @@ fn main_loop( fn linear_ease_set_brightness(config: &Config, value: u32) { let old_brightness = read_file_to_u32(config.backlight_filename()); - if let Some(old_brightness) = old_brightness { - const TRANSITION_STEPS: u32 = 20; - const TRANSITION_STEP_LENGTH_MS: u64 = 50; - if value > old_brightness { - let change = (value.saturating_sub(old_brightness)) as f32 / TRANSITION_STEPS as f32; - for i in 1..TRANSITION_STEPS { - set_brightness( - config, - old_brightness.saturating_add((change * i as f32) as u32), - ); - sleep(Duration::from_millis(TRANSITION_STEP_LENGTH_MS)); - } - } else { - let change = (old_brightness.saturating_sub(value)) as f32 / TRANSITION_STEPS as f32; - for i in 1..TRANSITION_STEPS { - set_brightness( - config, - old_brightness.saturating_sub((change * i as f32) as u32), - ); - sleep(Duration::from_millis(TRANSITION_STEP_LENGTH_MS)); + if matches!( + config.backlight_transition(), + brightness_transition::BrightnessTransition::Linear + ) { + if let Some(old_brightness) = old_brightness { + let transition_step_length_ms = (config.backlight_transition_time_seconds() as f32 + / config.backlight_transition_step_count() as f32 + * 1000_f32) as u64; + if value > old_brightness { + let change = (value.saturating_sub(old_brightness)) as f32 + / config.backlight_transition_step_count() as f32; + for i in 1..config.backlight_transition_step_count() { + set_brightness( + config, + old_brightness.saturating_add((change * i as f32) as u32), + ); + sleep(Duration::from_millis(transition_step_length_ms)); + } + } else { + let change = (old_brightness.saturating_sub(value)) as f32 + / config.backlight_transition_step_count() as f32; + for i in 1..config.backlight_transition_step_count() { + set_brightness( + config, + old_brightness.saturating_sub((change * i as f32) as u32), + ); + sleep(Duration::from_millis(transition_step_length_ms)); + } } } } From 63f1f803af19ffd0ff87aa1f0bf696598273c875 Mon Sep 17 00:00:00 2001 From: Jareth Gomes Date: Tue, 2 Dec 2025 22:42:57 +1100 Subject: [PATCH 3/3] fix: Change default of `backlight_transition` to `Instant` --- illuminanced.toml | 2 +- src/config.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/illuminanced.toml b/illuminanced.toml index 2f490e5..4e38a71 100644 --- a/illuminanced.toml +++ b/illuminanced.toml @@ -10,7 +10,7 @@ check_period_in_seconds = 1 light_steps = 10 min_backlight = 70 step_barrier = 0.1 -backlight_transition = "Linear" +backlight_transition = "Instant" # backlight_transition_step_count and backlight_transition_time_seconds are used only when backlight_transition # is set to "linear" backlight_transition_step_count = 20 diff --git a/src/config.rs b/src/config.rs index 822f40c..0ffd0bc 100644 --- a/src/config.rs +++ b/src/config.rs @@ -96,7 +96,7 @@ impl Config { pub fn backlight_transition(&self) -> BrightnessTransition { self.get_str("general", "backlight_transition") .and_then(|s| BrightnessTransition::from_str(s)) - .unwrap_or(BrightnessTransition::Linear) + .unwrap_or(BrightnessTransition::Instant) } pub fn backlight_transition_step_count(&self) -> u32 {