hinoirisetr/src/lib.rs

121 lines
3.7 KiB
Rust

//! hinoirisetr library
//! Contains core logic for computing temperature and gamma and applying settings.
use std::fs;
use std::path::Path;
use std::process::Command;
use chrono::{DateTime, Local, Timelike};
use serde::Deserialize;
pub mod log;
#[derive(Debug, Deserialize, Copy, Clone)]
#[serde(default)]
pub struct Config {
pub temp_day: u16,
pub temp_night: u16,
pub gamma_day: u16,
pub gamma_night: u16,
pub sunset_start: u8,
pub sunset_end: u8,
pub sunrise_start: u8,
pub sunrise_end: u8,
pub notification_timeout: u32,
}
impl Default for Config {
fn default() -> Self {
Self {
temp_day: 6500,
temp_night: 2700,
gamma_day: 100,
gamma_night: 95,
sunset_start: 19,
sunset_end: 22,
sunrise_start: 4,
sunrise_end: 7,
notification_timeout: 5000,
}
}
}
impl Config {
pub fn load<P: AsRef<Path> + std::fmt::Debug>(
path: P,
) -> Result<Self, Box<dyn std::error::Error>> {
trace!("Config::load({path:?})");
let content = fs::read_to_string(path)?;
let config = toml::from_str(&content)?;
Ok(config)
}
}
/// Linearly interpolate between start and end by factor [0.0, 1.0]
pub fn interpolate(start: u16, end: u16, factor: f64) -> u16 {
trace!("interpolate({start}, {end}, {factor})");
if end < start {
(end as f64 + (start - end) as f64 * (1.0 - factor)).round() as u16
} else {
(start as f64 + (end - start) as f64 * factor).round() as u16
}
}
/// Compute current temperature and gamma based on provided time
pub fn compute_settings(now: DateTime<Local>, config: &Config) -> (u16, u16) {
trace!("compute_settings({now:?})");
let time_in_hours = now.hour() as f64 + now.minute() as f64 / 60.0;
trace!("time_in_hours: {time_in_hours}");
if (time_in_hours >= config.sunset_start as f64) && (time_in_hours <= config.sunset_end as f64)
{
trace!("time_in_hours is within sunset");
let factor = ((time_in_hours - config.sunset_start as f64)
/ (config.sunset_end - config.sunset_start) as f64)
.clamp(0.0, 1.0);
(
interpolate(config.temp_day, config.temp_night, factor),
interpolate(config.gamma_day, config.gamma_night, factor),
)
} else if (time_in_hours >= config.sunrise_start as f64)
&& (time_in_hours <= config.sunrise_end as f64)
{
trace!("time_in_hours is within sunrise");
let factor = 1.0
- ((time_in_hours - config.sunrise_start as f64)
/ (config.sunrise_end - config.sunrise_start) as f64)
.clamp(0.0, 1.0);
(
interpolate(config.temp_day, config.temp_night, factor),
interpolate(config.gamma_day, config.gamma_night, factor),
)
} else if time_in_hours > config.sunset_end as f64
|| time_in_hours < config.sunrise_start as f64
{
trace!("time_in_hours is within night");
(config.temp_night, config.gamma_night)
} else {
trace!("time_in_hours is within day");
(config.temp_day, config.gamma_day)
}
}
/// Apply given temperature (Kelvin) and gamma (%) via hyprctl commands
pub fn apply_settings(temp: u16, gamma: u16) {
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}");
let _ = Command::new("hyprctl")
.args(["hyprsunset", "gamma", &gamma.to_string()])
.output();
trace!("hyprctl hyprsunset gamma {gamma}");
}