feat: add separate toggle for temp/gamma

This commit is contained in:
Vladimir Rubin 2025-06-14 20:30:05 +03:00
parent 753588c6d3
commit 16b9811f00
Signed by: vavakado
GPG key ID: CAB744727F36B524
3 changed files with 147 additions and 84 deletions

View file

@ -82,14 +82,32 @@ Values in hours (023):
Unix socket at `/tmp/hinoirisetr.sock` accepts newline-terminated commands:
- **disable**
Pause automatic adjustments; keeps current settings.
Pause automatic adjustments; sets day settings.
- **disable_temp**
Pause automatic temperature adjustments; sets day settings.
- **disable_gamma**
Pause automatic gamma adjustments; sets day settings.
- **enable**
Resume automatic adjustments.
- **enable_temp**
Resume automatic temperature adjustments.
- **enable_gamma**
Resume automatic gamma adjustments.
- **toggle**
Switch between enabled/disabled states.
- **toggle_temp**
Switch between enabled/disabled temperature adjustments.
- **toggle_gamma**
Switch between enabled/disabled gamma adjustments.
- **status**
Returns current state:
`dimming is <enabled|disabled> temp: <K>K, gamma: <%>`

View file

@ -429,16 +429,14 @@ 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, config: &Config) {
trace!("apply_settings({temp}, {gamma})");
pub fn apply_temp(temp: u16, config: &Config) {
trace!("apply_temp({temp})");
let last_temp = LAST_TEMP.load(Ordering::SeqCst);
let last_gamma = LAST_GAMMA.load(Ordering::SeqCst);
if last_temp == temp && last_gamma == gamma {
if last_temp == temp {
trace!("Settings unchanged, skipping application");
return;
}
debug!("applying temperature: {temp}");
debug!("applying gamma: {gamma}");
if temp != last_temp {
match config.temp_backend {
@ -467,6 +465,16 @@ pub fn apply_settings(temp: u16, gamma: u16, config: &Config) {
}
LAST_TEMP.store(temp, Ordering::SeqCst);
}
}
pub fn apply_gamma(gamma: u16, config: &Config) {
trace!("apply_gamma({gamma})");
let last_gamma = LAST_GAMMA.load(Ordering::SeqCst);
if last_gamma == gamma {
trace!("Settings unchanged, skipping application");
return;
}
debug!("applying gamma: {gamma}");
if gamma != last_gamma {
match config.gamma_backend {

View file

@ -9,8 +9,8 @@ use std::time::{Duration, UNIX_EPOCH};
use hinoirisetr::notify::InitializedNotificationSystem;
use hinoirisetr::time::Time;
use hinoirisetr::{
Config, GammaBackend, TempBackend, apply_settings, compute_settings, debug, error, info,
reset_cache, trace, warn,
Config, GammaBackend, TempBackend, apply_gamma, apply_temp, compute_settings, debug, error,
info, reset_cache, trace, warn,
};
use tokio::io::{AsyncBufReadExt, AsyncWriteExt, BufReader};
use tokio::net::UnixListener;
@ -34,8 +34,8 @@ async fn config_reloader(notify: Arc<Notify>) {
loop {
trace!("config poll tick");
let config_path = get_config_path();
if config_path.exists() {
if let Ok(current_modified) = std::fs::metadata(&config_path)
if config_path.exists()
&& let Ok(current_modified) = std::fs::metadata(&config_path)
.and_then(|m| m.modified())
.map(|t| t.duration_since(UNIX_EPOCH).unwrap().as_secs())
{
@ -53,17 +53,24 @@ async fn config_reloader(notify: Arc<Notify>) {
reload_config(Arc::clone(&notify)).await;
}
}
}
sleep(Duration::from_secs(5)).await;
}
}
async fn socket_server(disabled: Arc<AtomicBool>, notify: Arc<Notify>) {
async fn socket_server(
disabled_temp: Arc<AtomicBool>,
disabled_gamma: Arc<AtomicBool>,
notify: Arc<Notify>,
) {
let listener = UnixListener::bind(SOCKET_PATH).expect("Failed to bind socket");
match std::fs::set_permissions(SOCKET_PATH, std::fs::Permissions::from_mode(0o600)) {
Ok(_) => {trace!("socket file permissions set");},
Err(e) => {error!("Failed to set socket file permissions: {e}");},
Ok(_) => {
trace!("socket file permissions set");
}
Err(e) => {
error!("Failed to set socket file permissions: {e}");
}
};
trace!("socket server bound");
@ -85,55 +92,64 @@ async fn socket_server(disabled: Arc<AtomicBool>, notify: Arc<Notify>) {
if let Ok(Some(line)) = lines.next_line().await {
match line.trim() {
"disable_temp" => {
trace!("disable_gamma dispatched");
disabled_temp.store(true, Ordering::SeqCst);
notify.notify_one();
debug!("temp dimming is disabled");
}
"disable_gamma" => {
trace!("disable_gamma dispatched");
disabled_gamma.store(true, Ordering::SeqCst);
notify.notify_one();
debug!("gamma dimming is disabled");
}
"disable" => {
trace!("disable dispatched");
let config = *config_guard().await;
let disabled_clone = Arc::clone(&disabled);
let notify_state = match hinoirisetr::notify::InitializedNotificationSystem::new(
"hinoirisetr",
) {
Ok(not) => NotifyState::Enabled(not),
Err(_) => NotifyState::Disabled,
};
disabled.store(true, Ordering::SeqCst);
disabled_temp.store(true, Ordering::SeqCst);
disabled_gamma.store(true, Ordering::SeqCst);
notify.notify_one();
debug!("dimming is disabled");
// Spawn a background task to remind after timeout
println!("{}", config.disable_timeout);
if config.disable_timeout != 0 {
debug!("Spawning dimming timeout task");
tokio::spawn(async move {
let timeout_secs = config.disable_timeout;
tokio::time::sleep(Duration::from_secs(timeout_secs.into())).await;
if disabled_clone.load(Ordering::SeqCst) {
warn!("You've had dimming disabled for too long!");
// Show notification
if let NotifyState::Enabled(ref not) = notify_state {
let _ = not.show_notification(
"Dimming Reminder",
"You have dimming disabled!",
"notification-icon",
(config.notification_timeout as i32) * 5,
);
}
}
});
}
}
"enable" => {
"enable_temp" => {
trace!("enable dispatched");
disabled.store(false, Ordering::SeqCst);
disabled_temp.store(false, Ordering::SeqCst);
notify.notify_one();
debug!("dimming is enabled");
}
"enable_gamma" => {
trace!("enable_gamma dispatched");
disabled_gamma.store(false, Ordering::SeqCst);
notify.notify_one();
debug!("gamma dimming is enabled");
}
"enable" => {
trace!("enable dispatched");
disabled_temp.store(false, Ordering::SeqCst);
disabled_gamma.store(false, Ordering::SeqCst);
notify.notify_one();
debug!("dimming is enabled");
}
"toggle_temp" => {
trace!("toggle dispatched");
let now = !disabled_temp.load(Ordering::SeqCst);
disabled_temp.store(now, Ordering::SeqCst);
notify.notify_one();
debug!("temp dimming is {}", if now { "enabled" } else { "disabled" });
}
"toggle_gamma" => {
trace!("toggle_gamma dispatched");
let now = !disabled_gamma.load(Ordering::SeqCst);
disabled_gamma.store(now, Ordering::SeqCst);
notify.notify_one();
debug!("gamma dimming is {}", if now { "enabled" } else { "disabled" });
}
"toggle" => {
trace!("toggle dispatched");
let now = !disabled.load(Ordering::SeqCst);
disabled.store(now, Ordering::SeqCst);
let now = !disabled_temp.load(Ordering::SeqCst);
disabled_temp.store(now, Ordering::SeqCst);
disabled_gamma.store(now, Ordering::SeqCst);
notify.notify_one();
debug!("dimming is {}", if now { "enabled" } else { "disabled" });
}
@ -143,14 +159,17 @@ async fn socket_server(disabled: Arc<AtomicBool>, notify: Arc<Notify>) {
let now = get_time();
let (cur_temp, cur_gamma) = compute_settings(now, &*config_guard().await);
let status = format!(
"dimming is {} - temp: {}K, gamma: {}%",
if disabled.load(Ordering::SeqCst) {
"disabled"
"dimming - temp: {}, gamma: {}",
if disabled_temp.load(Ordering::SeqCst) {
"disabled".to_string()
} else {
"enabled"
format!("{cur_temp}K")
},
cur_temp,
cur_gamma
if disabled_gamma.load(Ordering::SeqCst) {
"disabled".to_string()
} else {
format!("{cur_gamma}%")
}
);
if let Err(e) = writer.write(status.as_bytes()).await {
@ -170,11 +189,19 @@ async fn socket_server(disabled: Arc<AtomicBool>, notify: Arc<Notify>) {
let now = get_time();
let (cur_temp, cur_gamma) = compute_settings(now, &*config_guard().await);
let body = if disabled.load(Ordering::SeqCst) {
let status = format!(
"dimming - temp: {}, gamma: {}",
if disabled_temp.load(Ordering::SeqCst) {
"disabled".to_string()
} else {
format!("temp: {cur_temp}K, gamma: {cur_gamma}%")
};
format!("{cur_temp}K")
},
if disabled_gamma.load(Ordering::SeqCst) {
"disabled".to_string()
} else {
format!("{cur_gamma}%")
}
);
match notification {
NotifyState::Enabled(ref not) => {
@ -182,7 +209,7 @@ async fn socket_server(disabled: Arc<AtomicBool>, notify: Arc<Notify>) {
let timeout = config_guard().await.notification_timeout;
match not.show_notification(
"Sunsetting",
&body,
&status,
"notification-icon",
timeout as i32,
) {
@ -231,7 +258,8 @@ async fn main() {
std::process::exit(1);
}
let disabled = Arc::new(AtomicBool::new(false));
let disabled_temp = Arc::new(AtomicBool::new(false));
let disabled_gamma = Arc::new(AtomicBool::new(false));
let notify = Arc::new(Notify::new());
// load config
@ -305,10 +333,11 @@ async fn main() {
// Spawn control socket server
{
let disabled = Arc::clone(&disabled);
let disabled_temp = Arc::clone(&disabled_temp);
let disabled_gamma = Arc::clone(&disabled_gamma);
let notify = Arc::clone(&notify);
tokio::spawn(async move {
socket_server(disabled, notify).await;
socket_server(disabled_temp, disabled_gamma, notify).await;
});
}
@ -339,7 +368,8 @@ async fn main() {
{
let now = get_time();
let (temp, gamma) = compute_settings(now, &*config_guard().await);
apply_settings(temp, gamma, &*config_guard().await);
apply_temp(temp, &*config_guard().await);
apply_gamma(gamma, &*config_guard().await);
trace!("initial settings applied: {temp}K, {gamma}%");
}
@ -347,16 +377,23 @@ async fn main() {
tokio::select! {
_ = async {
loop {
if disabled.load(Ordering::SeqCst) {
apply_settings(
let now = get_time();
let (temp, gamma) = compute_settings(now, &*config_guard().await);
if disabled_temp.load(Ordering::SeqCst) {
apply_temp(
config_guard().await.temp_day,
&*config_guard().await,
);
} else {
apply_temp(temp, &*config_guard().await);
}
if disabled_gamma.load(Ordering::SeqCst) {
apply_gamma(
config_guard().await.gamma_day,
&*config_guard().await,
);
} else {
let now = get_time();
let (temp, gamma) = compute_settings(now, &*config_guard().await);
apply_settings(temp, gamma, &*config_guard().await);
apply_gamma(gamma, &*config_guard().await);
}
notify.notified().await;