use notify_rust::{Hint, Notification, NotificationHandle}; use rog_aura::AuraEffect; use rog_dbus::{ zbus_charge::ChargeProxy, zbus_led::LedProxy, zbus_profile::ProfileProxy, zbus_rogbios::RogBiosProxy, }; use rog_profiles::Profile; use smol::{future, Executor}; use std::{ error::Error, sync::{Arc, Mutex}, }; use zbus::export::futures_util::StreamExt; const NOTIF_HEADER: &str = "ROG Control"; macro_rules! notify { ($notifier:ident, $last_notif:ident, $data:expr) => { if let Some(notif) = $last_notif.take() { notif.close(); } if let Ok(x) = $notifier($data) { $last_notif.replace(x); } }; } macro_rules! base_notification { ($body:expr) => { Notification::new() .summary(NOTIF_HEADER) .body($body) .timeout(2000) .show() }; } type SharedHandle = Arc>>; fn main() -> Result<(), Box> { println!("asus-notify version {}", env!("CARGO_PKG_VERSION")); println!(" rog-dbus version {}", rog_dbus::VERSION); let last_notification: SharedHandle = Arc::new(Mutex::new(None)); let executor = Executor::new(); // BIOS notif let x = last_notification.clone(); executor .spawn(async move { let conn = zbus::Connection::system().await.unwrap(); let proxy = RogBiosProxy::new(&conn).await.unwrap(); if let Ok(p) = proxy.receive_notify_post_boot_sound().await { p.for_each(|e| { if let Ok(out) = e.args() { if let Ok(ref mut lock) = x.try_lock() { notify!(do_post_sound_notif, lock, &out.sound()); } } future::ready(()) }) .await; }; }) .detach(); // Charge notif let x = last_notification.clone(); executor .spawn(async move { let conn = zbus::Connection::system().await.unwrap(); let proxy = ChargeProxy::new(&conn).await.unwrap(); if let Ok(p) = proxy.receive_notify_charge().await { p.for_each(|e| { if let Ok(out) = e.args() { if let Ok(ref mut lock) = x.try_lock() { notify!(do_charge_notif, lock, &out.limit); } } future::ready(()) }) .await; }; }) .detach(); // Profile notif let x = last_notification.clone(); executor .spawn(async move { let conn = zbus::Connection::system().await.unwrap(); let proxy = ProfileProxy::new(&conn).await.unwrap(); if let Ok(p) = proxy.receive_notify_profile().await { p.for_each(|e| { if let Ok(out) = e.args() { if let Ok(ref mut lock) = x.try_lock() { notify!(do_thermal_notif, lock, &out.profile); } } future::ready(()) }) .await; }; }) .detach(); // LED notif executor .spawn(async move { let conn = zbus::Connection::system().await.unwrap(); let proxy = LedProxy::new(&conn).await.unwrap(); if let Ok(p) = proxy.receive_notify_led().await { p.for_each(|e| { if let Ok(out) = e.args() { if let Ok(ref mut lock) = last_notification.try_lock() { notify!(do_led_notif, lock, &out.data); } } future::ready(()) }) .await; }; }) .detach(); loop { smol::block_on(executor.tick()); } } fn do_thermal_notif(profile: &Profile) -> Result> { let icon = match profile { Profile::Balanced => "asus_notif_yellow", Profile::Performance => "asus_notif_red", Profile::Quiet => "asus_notif_green", }; let profile: &str = (*profile).into(); let x = Notification::new() .summary("ASUS ROG") .body(&format!( "Thermal profile changed to {}", profile.to_uppercase(), )) .hint(Hint::Resident(true)) .timeout(2000) .hint(Hint::Category("device".into())) //.hint(Hint::Transient(true)) .icon(icon) .show()?; Ok(x) } fn do_led_notif(ledmode: &AuraEffect) -> Result { base_notification!(&format!( "Keyboard LED mode changed to {}", ledmode.mode_name() )) } fn do_charge_notif(limit: &u8) -> Result { base_notification!(&format!("Battery charge limit changed to {}", limit)) } fn do_post_sound_notif(on: &bool) -> Result { base_notification!(&format!("BIOS Post sound {}", on)) }