121 lines
3.7 KiB
Rust
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}");
|
|
}
|