diff --git a/Cargo.lock b/Cargo.lock index 36f41cfb..7f73e9cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -268,9 +268,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "az" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f771a5d1f5503f7f4279a30f3643d3421ba149848b89ecaaec0ea2acf04a5ac4" +checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" [[package]] name = "bitflags" @@ -740,7 +740,7 @@ checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" [[package]] name = "eframe" version = "0.18.0" -source = "git+https://github.com/emilk/egui#0bf9fc9428423b375ae079782c095504e85ca42c" +source = "git+https://github.com/emilk/egui#a7012cf8a628d125b211fd164ac12fbb898f316e" dependencies = [ "bytemuck", "dark-light", @@ -761,7 +761,7 @@ dependencies = [ [[package]] name = "egui" version = "0.18.1" -source = "git+https://github.com/emilk/egui#0bf9fc9428423b375ae079782c095504e85ca42c" +source = "git+https://github.com/emilk/egui#a7012cf8a628d125b211fd164ac12fbb898f316e" dependencies = [ "ahash 0.7.6", "epaint", @@ -772,7 +772,7 @@ dependencies = [ [[package]] name = "egui-winit" version = "0.18.0" -source = "git+https://github.com/emilk/egui#0bf9fc9428423b375ae079782c095504e85ca42c" +source = "git+https://github.com/emilk/egui#a7012cf8a628d125b211fd164ac12fbb898f316e" dependencies = [ "arboard", "egui", @@ -786,7 +786,7 @@ dependencies = [ [[package]] name = "egui_glow" version = "0.18.1" -source = "git+https://github.com/emilk/egui#0bf9fc9428423b375ae079782c095504e85ca42c" +source = "git+https://github.com/emilk/egui#a7012cf8a628d125b211fd164ac12fbb898f316e" dependencies = [ "bytemuck", "egui", @@ -800,7 +800,7 @@ dependencies = [ [[package]] name = "emath" version = "0.18.0" -source = "git+https://github.com/emilk/egui#0bf9fc9428423b375ae079782c095504e85ca42c" +source = "git+https://github.com/emilk/egui#a7012cf8a628d125b211fd164ac12fbb898f316e" dependencies = [ "bytemuck", ] @@ -865,7 +865,7 @@ dependencies = [ [[package]] name = "epaint" version = "0.18.1" -source = "git+https://github.com/emilk/egui#0bf9fc9428423b375ae079782c095504e85ca42c" +source = "git+https://github.com/emilk/egui#a7012cf8a628d125b211fd164ac12fbb898f316e" dependencies = [ "ab_glyph", "ahash 0.7.6", @@ -1245,9 +1245,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "js-sys" -version = "0.3.58" +version = "0.3.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27" +checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2" dependencies = [ "wasm-bindgen", ] @@ -2547,9 +2547,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.81" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994" +checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -2557,13 +2557,13 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.81" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a" +checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f" dependencies = [ "bumpalo", - "lazy_static", "log", + "once_cell", "proc-macro2", "quote", "syn", @@ -2572,9 +2572,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.31" +version = "0.4.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de9a9cec1733468a8c657e57fa2413d2ae2c0129b95e87c5b72b8ace4d13f31f" +checksum = "fa76fb221a1f8acddf5b54ace85912606980ad661ac7a503b4570ffd3a624dad" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -2584,9 +2584,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.81" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa" +checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2594,9 +2594,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.81" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048" +checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da" dependencies = [ "proc-macro2", "quote", @@ -2607,9 +2607,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.81" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be" +checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a" [[package]] name = "wayland-client" @@ -2696,9 +2696,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.58" +version = "0.3.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fed94beee57daf8dd7d51f2b15dc2bcde92d7a72304cdf662a4371008b71b90" +checksum = "ed055ab27f941423197eb86b2035720b1a3ce40504df082cac2ecc6ed73335a1" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/daemon/src/ctrl_profiles/config.rs b/daemon/src/ctrl_profiles/config.rs index 0848fdee..28ec2761 100644 --- a/daemon/src/ctrl_profiles/config.rs +++ b/daemon/src/ctrl_profiles/config.rs @@ -23,17 +23,6 @@ impl ProfileConfig { } } - pub fn set_defaults_and_save(&mut self) { - self.active_profile = Profile::get_active_profile().unwrap_or(Profile::Balanced); - if let Ok(res) = FanCurveProfiles::is_supported() { - if res { - let curves = FanCurveProfiles::default(); - self.fan_curves = Some(curves); - } - } - self.write(); - } - pub fn load(config_path: String) -> Self { let mut file = OpenOptions::new() .read(true) @@ -46,7 +35,6 @@ impl ProfileConfig { if let Ok(read_len) = file.read_to_string(&mut buf) { if read_len == 0 { config = Self::new(config_path); - config.set_defaults_and_save(); } else if let Ok(data) = toml::from_str(&buf) { config = data; config.config_path = config_path; @@ -63,11 +51,9 @@ impl ProfileConfig { ) }); config = Self::new(config_path); - config.set_defaults_and_save(); } } else { config = Self::new(config_path); - config.set_defaults_and_save(); } config } diff --git a/daemon/src/ctrl_profiles/controller.rs b/daemon/src/ctrl_profiles/controller.rs index b25fde0a..98df7308 100644 --- a/daemon/src/ctrl_profiles/controller.rs +++ b/daemon/src/ctrl_profiles/controller.rs @@ -20,12 +20,7 @@ impl GetSupported for CtrlPlatformProfile { fn get_supported() -> Self::A { if !Profile::is_platform_profile_supported() { - warn!( - r#" -platform_profile kernel interface not found, your laptop does not support this, or the interface is missing. -To enable profile support you require a kernel version 5.15.2 minimum. -"# - ); + warn!("platform_profile kernel interface not found, your laptop does not support this, or the interface is missing."); } let res = FanCurveProfiles::is_supported(); @@ -35,14 +30,7 @@ To enable profile support you require a kernel version 5.15.2 minimum. }; if !fan_curve_supported { - info!( - r#" -fan curves kernel interface not found, your laptop does not support this, or the interface is missing. -To enable fan-curve support you require a kernel with the following patch applied: -https://lkml.org/lkml/2021/10/23/250 -This patch has been accepted upstream for 5.17 kernel release. -"# - ); + info!("fan curves kernel interface not found, your laptop does not support this, or the interface is missing."); } PlatformProfileFunctions { @@ -68,12 +56,45 @@ impl crate::Reloadable for CtrlPlatformProfile { } impl CtrlPlatformProfile { - pub fn new(config: ProfileConfig) -> Result { + pub fn new(mut config: ProfileConfig) -> Result { if Profile::is_platform_profile_supported() { info!("Device has profile control available"); if FanCurveProfiles::get_device().is_ok() { info!("Device has fan curves available"); + if config.fan_curves.is_none() { + let active = Profile::get_active_profile().unwrap_or(Profile::Balanced); + let dev = FanCurveProfiles::get_device()?; + let mut curves = FanCurveProfiles::default(); + + warn!("No default fan-curves: cycling profiles to set defaults"); + Profile::set_profile(Profile::Balanced)?; + curves.read_from_dev_profile(Profile::Balanced, &dev); + info!( + "{:?}: {}", + config.active_profile, + String::from(curves.get_fan_curves_for(Profile::Balanced)) + ); + Profile::set_profile(Profile::Performance)?; + curves.read_from_dev_profile(Profile::Performance, &dev); + info!( + "{:?}: {}", + config.active_profile, + String::from(curves.get_fan_curves_for(Profile::Performance)) + ); + Profile::set_profile(Profile::Quiet)?; + curves.read_from_dev_profile(Profile::Quiet, &dev); + info!( + "{:?}: {}", + config.active_profile, + String::from(curves.get_fan_curves_for(Profile::Quiet)) + ); + + Profile::set_profile(active)?; + config.fan_curves = Some(curves); + config.write(); + info!("Set fan curve defaults"); + } } return Ok(CtrlPlatformProfile { config }); diff --git a/rog-aura/src/usb.rs b/rog-aura/src/usb.rs index 8d995995..b7948d7d 100644 --- a/rog-aura/src/usb.rs +++ b/rog-aura/src/usb.rs @@ -21,11 +21,12 @@ pub const fn aura_brightness_bytes(brightness: u8) -> [u8; 17] { } #[cfg_attr(feature = "dbus", derive(Type))] -#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)] +#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize, Default)] pub enum AuraDevice { X1854, X1869, X1866, + #[default] X19B6, Unknown, } diff --git a/rog-control-center/Cargo.toml b/rog-control-center/Cargo.toml index 034791f3..2b849c84 100644 --- a/rog-control-center/Cargo.toml +++ b/rog-control-center/Cargo.toml @@ -33,13 +33,3 @@ dirs = "3.0.1" version = "^4.3" default-features = false features = ["z"] - -[profile.release] -lto = true -debug = false -opt-level = 3 -panic = "abort" - -[profile.bench] -debug = false -opt-level = 3 diff --git a/rog-control-center/src/app.rs b/rog-control-center/src/app.rs index 4ded2cfe..8d1899f4 100644 --- a/rog-control-center/src/app.rs +++ b/rog-control-center/src/app.rs @@ -8,10 +8,12 @@ use std::{ }; use egui::{Button, RichText}; -use rog_dbus::RogDbusClientBlocking; use rog_supported::SupportedFunctions; -use crate::{config::Config, get_ipc_file, page_states::PageDataStates, Page, SHOWING_GUI}; +use crate::{ + config::Config, error::Result, get_ipc_file, page_states::PageDataStates, Page, + RogDbusClientBlocking, SHOWING_GUI, +}; pub struct RogApp<'a> { pub page: Page, @@ -34,11 +36,11 @@ impl<'a> RogApp<'a> { show_gui: Arc, states: PageDataStates, _cc: &eframe::CreationContext<'_>, - ) -> Self { - let (dbus, _) = RogDbusClientBlocking::new().unwrap(); - let supported = dbus.proxies().supported().supported_functions().unwrap(); + ) -> Result { + let (dbus, _) = RogDbusClientBlocking::new()?; + let supported = dbus.proxies().supported().supported_functions()?; - Self { + Ok(Self { supported, states, page: Page::System, @@ -46,7 +48,7 @@ impl<'a> RogApp<'a> { running_in_bg: start_closed, config, asus_dbus: dbus, - } + }) } } @@ -70,9 +72,15 @@ impl<'a> eframe::App for RogApp<'a> { states, .. } = self; - if states.refresh_if_notfied(supported, dbus) { - ctx.request_repaint(); - } + states + .refresh_if_notfied(supported, dbus) + .map(|repaint| { + if repaint { + ctx.request_repaint(); + } + }) + .map_err(|e| self.states.error = Some(e.to_string())) + .ok(); let page = self.page; diff --git a/rog-control-center/src/error.rs b/rog-control-center/src/error.rs index 98a9bef3..8664e9b9 100644 --- a/rog-control-center/src/error.rs +++ b/rog-control-center/src/error.rs @@ -1,5 +1,7 @@ use std::fmt; +pub type Result = std::result::Result; + #[derive(Debug)] pub enum Error { Io(std::io::Error), @@ -7,6 +9,7 @@ pub enum Error { ConfigLoadFail, ConfigLockFail, XdgVars, + Zbus(zbus::Error), } impl fmt::Display for Error { @@ -18,6 +21,7 @@ impl fmt::Display for Error { Error::ConfigLoadFail => write!(f, "Failed to load user config"), Error::ConfigLockFail => write!(f, "Failed to lock user config"), Error::XdgVars => write!(f, "XDG environment vars appear unset"), + Error::Zbus(err) => write!(f, "Error: {}", err), } } } @@ -30,14 +34,14 @@ impl From for Error { } } -impl From for zbus::fdo::Error { - fn from(err: Error) -> Self { - zbus::fdo::Error::Failed(format!("Anime zbus error: {}", err)) - } -} - impl From for Error { fn from(err: nix::Error) -> Self { Error::Nix(err) } } + +impl From for Error { + fn from(err: zbus::Error) -> Self { + Error::Zbus(err) + } +} diff --git a/rog-control-center/src/lib.rs b/rog-control-center/src/lib.rs index e97b287d..b7fed048 100644 --- a/rog-control-center/src/lib.rs +++ b/rog-control-center/src/lib.rs @@ -11,10 +11,17 @@ pub use app::RogApp; pub mod config; pub mod error; +#[cfg(feature = "mocking")] +pub mod mocking; pub mod notify; pub mod page_states; pub mod widgets; +#[cfg(feature = "mocking")] +pub use mocking::RogDbusClientBlocking; +#[cfg(not(feature = "mocking"))] +pub use rog_dbus::RogDbusClientBlocking; + use nix::{sys::stat, unistd}; use tempfile::TempDir; //use log::{error, info, warn}; diff --git a/rog-control-center/src/main.rs b/rog-control-center/src/main.rs index 82ef65d3..5516507e 100644 --- a/rog-control-center/src/main.rs +++ b/rog-control-center/src/main.rs @@ -1,8 +1,8 @@ use rog_control_center::{ config::Config, get_ipc_file, notify::start_notifications, on_tmp_dir_exists, - page_states::PageDataStates, RogApp, SHOW_GUI, + page_states::PageDataStates, RogApp, RogDbusClientBlocking, SHOW_GUI, }; -use rog_dbus::RogDbusClientBlocking; + use std::{ io::Read, sync::{ @@ -23,8 +23,6 @@ fn main() -> Result<(), Box> { config.save()?; } - let (dbus, _) = RogDbusClientBlocking::new().unwrap(); - let supported = dbus.proxies().supported().supported_functions().unwrap(); // Cheap method to alert to notifications rather than spinning a thread for each // This is quite different when done in a retained mode app let charge_notified = Arc::new(AtomicBool::new(false)); @@ -34,19 +32,22 @@ fn main() -> Result<(), Box> { let profiles_notified = Arc::new(AtomicBool::new(false)); let fans_notified = Arc::new(AtomicBool::new(false)); let notifs_enabled = Arc::new(AtomicBool::new(config.enable_notifications)); - // TODO: change this to an error instead of the nested unwraps, then use to - // display a bare box app with error message. - let states = PageDataStates::new( - notifs_enabled.clone(), - charge_notified.clone(), - bios_notified.clone(), - aura_notified.clone(), - anime_notified.clone(), - profiles_notified.clone(), - fans_notified.clone(), - &supported, - &dbus, - ); + + let states = { + let (dbus, _) = RogDbusClientBlocking::new()?; + let supported = dbus.proxies().supported().supported_functions().unwrap(); + PageDataStates::new( + notifs_enabled.clone(), + charge_notified.clone(), + bios_notified.clone(), + aura_notified.clone(), + anime_notified.clone(), + profiles_notified.clone(), + fans_notified.clone(), + &supported, + &dbus, + )? // TODO: if error, show alt GUI containing the error message + }; if config.enable_notifications { start_notifications( @@ -92,6 +93,8 @@ fn main() -> Result<(), Box> { eframe::run_native( "ROG Control Center", native_options, - Box::new(move |cc| Box::new(RogApp::new(start_closed, config, should, states, cc))), + Box::new(move |cc| { + Box::new(RogApp::new(start_closed, config, should, states, cc).unwrap()) + }), ); } diff --git a/rog-control-center/src/mocking.rs b/rog-control-center/src/mocking.rs new file mode 100644 index 00000000..21ebc752 --- /dev/null +++ b/rog-control-center/src/mocking.rs @@ -0,0 +1,225 @@ +use std::collections::BTreeMap; + +use rog_aura::{ + usb::{AuraDev19b6, AuraDevice, AuraPowerDev}, + AuraEffect, AuraModeNum, AuraZone, +}; +use rog_profiles::fan_curve_set::{CurveData, FanCurveSet}; +use rog_supported::{ + AnimeSupportedFunctions, ChargeSupportedFunctions, LedSupportedFunctions, + PlatformProfileFunctions, RogBiosSupportedFunctions, SupportedFunctions, +}; + +use crate::error::Result; + +const NOPE: &'static str = ""; + +pub struct RogDbusClientBlocking<'a> { + _phantom: &'a str, +} + +impl<'a> Default for RogDbusClientBlocking<'a> { + fn default() -> Self { + Self { + _phantom: Default::default(), + } + } +} + +impl<'a> RogDbusClientBlocking<'a> { + pub fn new() -> Result<(Self, bool)> { + Ok((Self { _phantom: NOPE }, true)) + } + pub fn proxies(&self) -> Proxies { + Proxies + } +} + +pub struct Proxies; +impl Proxies { + pub fn rog_bios(&self) -> Bios { + Bios + } + pub fn profile(&self) -> Profile { + Profile + } + pub fn led(&self) -> Led { + Led + } + pub fn anime(&self) -> Anime { + Anime + } + pub fn charge(&self) -> Profile { + Profile + } + pub fn supported(&self) -> Supported { + Supported + } +} + +pub struct Bios; +impl Bios { + pub fn post_boot_sound(&self) -> Result { + Ok(1) + } + pub fn dedicated_graphic_mode(&self) -> Result { + Ok(1) + } + pub fn panel_overdrive(&self) -> Result { + Ok(1) + } + pub fn set_post_boot_sound(&self, _b: bool) -> Result<()> { + Ok(()) + } + pub fn set_dedicated_graphic_mode(&self, _b: bool) -> Result<()> { + Ok(()) + } + pub fn set_panel_overdrive(&self, _b: bool) -> Result<()> { + Ok(()) + } +} + +pub struct Profile; +impl Profile { + pub fn profiles(&self) -> Result> { + Ok(vec![ + rog_profiles::Profile::Balanced, + rog_profiles::Profile::Performance, + rog_profiles::Profile::Quiet, + ]) + } + pub fn active_profile(&self) -> Result { + Ok(rog_profiles::Profile::Performance) + } + pub fn enabled_fan_profiles(&self) -> Result> { + Ok(vec![ + rog_profiles::Profile::Performance, + rog_profiles::Profile::Balanced, + ]) + } + pub fn fan_curve_data(&self, _p: rog_profiles::Profile) -> Result { + let mut curve = FanCurveSet::default(); + curve.cpu.pwm = [30, 40, 60, 100, 140, 180, 200, 250]; + curve.cpu.temp = [20, 30, 40, 50, 70, 80, 90, 100]; + curve.gpu.pwm = [40, 80, 100, 140, 170, 200, 230, 250]; + curve.gpu.temp = [20, 30, 40, 50, 70, 80, 90, 100]; + Ok(curve) + } + pub fn set_fan_curve(&self, _p: rog_profiles::Profile, _c: CurveData) -> Result<()> { + Ok(()) + } + pub fn set_fan_curve_enabled(&self, _p: rog_profiles::Profile, _b: bool) -> Result<()> { + Ok(()) + } + pub fn limit(&self) -> Result { + Ok(66) + } + pub fn set_limit(&self, _l: u8) -> Result<()> { + Ok(()) + } + pub fn set_active_profile(&self, _p: rog_profiles::Profile) -> Result<()> { + Ok(()) + } +} + +pub struct Led; +impl Led { + pub fn led_modes(&self) -> Result> { + let mut data = BTreeMap::new(); + data.insert(AuraModeNum::Static, AuraEffect::default()); + data.insert(AuraModeNum::Star, AuraEffect::default()); + data.insert(AuraModeNum::Strobe, AuraEffect::default()); + data.insert(AuraModeNum::Rain, AuraEffect::default()); + data.insert(AuraModeNum::Rainbow, AuraEffect::default()); + data.insert(AuraModeNum::Ripple, AuraEffect::default()); + data.insert(AuraModeNum::Breathe, AuraEffect::default()); + data.insert(AuraModeNum::Comet, AuraEffect::default()); + data.insert(AuraModeNum::Flash, AuraEffect::default()); + data.insert(AuraModeNum::Laser, AuraEffect::default()); + data.insert(AuraModeNum::Pulse, AuraEffect::default()); + Ok(data) + } + pub fn led_mode(&self) -> Result { + Ok(AuraModeNum::Rainbow) + } + pub fn led_brightness(&self) -> Result { + Ok(1) + } + pub fn leds_enabled(&self) -> Result { + Ok(AuraPowerDev { + x1866: vec![], + x19b6: vec![ + AuraDev19b6::BootKeyb, + AuraDev19b6::AwakeKeyb, + AuraDev19b6::SleepLogo, + AuraDev19b6::AwakeLogo, + ], + }) + } + pub fn set_leds_power(&self, _a: AuraPowerDev, _b: bool) -> Result<()> { + Ok(()) + } + pub fn set_led_mode(&self, _a: &AuraEffect) -> Result<()> { + Ok(()) + } +} + +pub struct Anime; +impl Anime { + pub fn boot_enabled(&self) -> Result { + Ok(true) + } + pub fn awake_enabled(&self) -> Result { + Ok(true) + } + pub fn set_on_off(&self, _b: bool) -> Result<()> { + Ok(()) + } + pub fn set_boot_on_off(&self, _b: bool) -> Result<()> { + Ok(()) + } +} + +pub struct Supported; +impl Supported { + pub fn supported_functions(&self) -> Result { + Ok(SupportedFunctions { + anime_ctrl: AnimeSupportedFunctions(true), + charge_ctrl: ChargeSupportedFunctions { + charge_level_set: true, + }, + platform_profile: PlatformProfileFunctions { + platform_profile: true, + fan_curves: true, + }, + keyboard_led: LedSupportedFunctions { + prod_id: AuraDevice::X19B6, + brightness_set: true, + stock_led_modes: vec![ + AuraModeNum::Rain, + AuraModeNum::Rainbow, + AuraModeNum::Star, + AuraModeNum::Static, + AuraModeNum::Strobe, + ], + multizone_led_mode: vec![ + AuraZone::Key1, + AuraZone::Key2, + AuraZone::Key3, + AuraZone::Key4, + AuraZone::BarLeft, + AuraZone::BarRight, + AuraZone::Logo, + ], + per_key_led_mode: true, + }, + rog_bios_ctrl: RogBiosSupportedFunctions { + post_sound: true, + dedicated_gfx: true, + panel_overdrive: true, + dgpu_disable: true, + egpu_enable: true, + }, + }) + } +} diff --git a/rog-control-center/src/page_states.rs b/rog-control-center/src/page_states.rs index bc5c3fa8..6690b3fd 100644 --- a/rog-control-center/src/page_states.rs +++ b/rog-control-center/src/page_states.rs @@ -8,10 +8,11 @@ use std::{ use egui::Vec2; use rog_aura::{usb::AuraPowerDev, AuraEffect, AuraModeNum}; -use rog_dbus::RogDbusClientBlocking; use rog_profiles::{fan_curve_set::FanCurveSet, FanCurvePU, Profile}; use rog_supported::SupportedFunctions; +use crate::{error::Result, RogDbusClientBlocking}; + #[derive(Clone, Debug)] pub struct BiosState { /// To be shared to a thread that checks notifications. @@ -30,28 +31,28 @@ impl BiosState { was_notified: Arc, supported: &SupportedFunctions, dbus: &RogDbusClientBlocking, - ) -> Self { - Self { + ) -> Result { + Ok(Self { was_notified, post_sound: if supported.rog_bios_ctrl.post_sound { - dbus.proxies().rog_bios().post_boot_sound().unwrap() != 0 + dbus.proxies().rog_bios().post_boot_sound()? != 0 } else { false }, dedicated_gfx: if supported.rog_bios_ctrl.dedicated_gfx { - dbus.proxies().rog_bios().dedicated_graphic_mode().unwrap() != 0 + dbus.proxies().rog_bios().dedicated_graphic_mode()? != 0 } else { false }, panel_overdrive: if supported.rog_bios_ctrl.panel_overdrive { - dbus.proxies().rog_bios().panel_overdrive().unwrap() != 0 + dbus.proxies().rog_bios().panel_overdrive()? != 0 } else { false }, // TODO: needs supergfx dgpu_disable: supported.rog_bios_ctrl.dgpu_disable, egpu_enable: supported.rog_bios_ctrl.egpu_enable, - } + }) } } @@ -67,20 +68,20 @@ impl ProfilesState { was_notified: Arc, supported: &SupportedFunctions, dbus: &RogDbusClientBlocking, - ) -> Self { - Self { + ) -> Result { + Ok(Self { was_notified, list: if supported.platform_profile.platform_profile { - dbus.proxies().profile().profiles().unwrap() + dbus.proxies().profile().profiles()? } else { vec![] }, current: if supported.platform_profile.platform_profile { - dbus.proxies().profile().active_profile().unwrap() + dbus.proxies().profile().active_profile()? } else { Profile::Balanced }, - } + }) } } @@ -99,9 +100,9 @@ impl FanCurvesState { was_notified: Arc, supported: &SupportedFunctions, dbus: &RogDbusClientBlocking, - ) -> Self { + ) -> Result { let profiles = if supported.platform_profile.platform_profile { - dbus.proxies().profile().profiles().unwrap() + dbus.proxies().profile().profiles()? } else { vec![Profile::Balanced, Profile::Quiet, Profile::Performance] }; @@ -109,8 +110,7 @@ impl FanCurvesState { HashSet::from_iter( dbus.proxies() .profile() - .enabled_fan_profiles() - .unwrap() + .enabled_fan_profiles()? .iter() .cloned(), ) @@ -121,8 +121,9 @@ impl FanCurvesState { let mut curves: HashMap = HashMap::new(); profiles.iter().for_each(|p| { if supported.platform_profile.fan_curves { - let curve = dbus.proxies().profile().fan_curve_data(*p).unwrap(); - curves.insert(*p, curve); + if let Ok(curve) = dbus.proxies().profile().fan_curve_data(*p) { + curves.insert(*p, curve); + } } else { let mut curve = FanCurveSet::default(); curve.cpu.pwm = [30, 40, 60, 100, 140, 180, 200, 250]; @@ -134,19 +135,19 @@ impl FanCurvesState { }); let show_curve = if supported.platform_profile.fan_curves { - dbus.proxies().profile().active_profile().unwrap() + dbus.proxies().profile().active_profile()? } else { Profile::Balanced }; - Self { + Ok(Self { was_notified, show_curve, show_graph: FanCurvePU::CPU, enabled, curves, drag_delta: Vec2::default(), - } + }) } } @@ -165,27 +166,27 @@ impl AuraState { was_notified: Arc, supported: &SupportedFunctions, dbus: &RogDbusClientBlocking, - ) -> Self { - Self { + ) -> Result { + Ok(Self { was_notified, current_mode: if !supported.keyboard_led.stock_led_modes.is_empty() { - dbus.proxies().led().led_mode().unwrap() + dbus.proxies().led().led_mode()? } else { AuraModeNum::Static }, modes: if !supported.keyboard_led.stock_led_modes.is_empty() { - dbus.proxies().led().led_modes().unwrap() + dbus.proxies().led().led_modes()? } else { BTreeMap::new() }, - enabled: dbus.proxies().led().leds_enabled().unwrap(), + enabled: dbus.proxies().led().leds_enabled()?, bright: if !supported.keyboard_led.brightness_set { - dbus.proxies().led().led_brightness().unwrap() + dbus.proxies().led().led_brightness()? } else { 2 }, - } + }) } } @@ -203,23 +204,23 @@ impl AnimeState { was_notified: Arc, supported: &SupportedFunctions, dbus: &RogDbusClientBlocking, - ) -> Self { - Self { + ) -> Result { + Ok(Self { was_notified, boot: if supported.anime_ctrl.0 { - dbus.proxies().anime().boot_enabled().unwrap() + dbus.proxies().anime().boot_enabled()? } else { false }, awake: if supported.anime_ctrl.0 { - dbus.proxies().anime().awake_enabled().unwrap() + dbus.proxies().anime().awake_enabled()? } else { false }, // TODO: sleep: false, bright: 200, - } + }) } } @@ -249,56 +250,106 @@ impl PageDataStates { fans_notified: Arc, supported: &SupportedFunctions, dbus: &RogDbusClientBlocking, - ) -> Self { - Self { + ) -> Result { + Ok(Self { notifs_enabled, was_notified: charge_notified, - charge_limit: dbus.proxies().charge().limit().unwrap(), - bios: BiosState::new(bios_notified, supported, dbus), - aura: AuraState::new(aura_notified, supported, dbus), - anime: AnimeState::new(anime_notified, supported, dbus), - profiles: ProfilesState::new(profiles_notified, supported, dbus), - fan_curves: FanCurvesState::new(fans_notified, supported, dbus), + charge_limit: dbus.proxies().charge().limit()?, + bios: BiosState::new(bios_notified, supported, dbus)?, + aura: AuraState::new(aura_notified, supported, dbus)?, + anime: AnimeState::new(anime_notified, supported, dbus)?, + profiles: ProfilesState::new(profiles_notified, supported, dbus)?, + fan_curves: FanCurvesState::new(fans_notified, supported, dbus)?, error: None, - } + }) } pub fn refresh_if_notfied( &mut self, supported: &SupportedFunctions, dbus: &RogDbusClientBlocking, - ) -> bool { + ) -> Result { let mut notified = false; if self.was_notified.load(Ordering::SeqCst) { - self.charge_limit = dbus.proxies().charge().limit().unwrap(); + self.charge_limit = dbus.proxies().charge().limit()?; self.was_notified.store(false, Ordering::SeqCst); notified = true; } if self.aura.was_notified.load(Ordering::SeqCst) { - self.aura = AuraState::new(self.aura.was_notified.clone(), supported, dbus); + self.aura = AuraState::new(self.aura.was_notified.clone(), supported, dbus)?; self.aura.was_notified.store(false, Ordering::SeqCst); notified = true; } if self.bios.was_notified.load(Ordering::SeqCst) { - self.bios = BiosState::new(self.bios.was_notified.clone(), supported, dbus); + self.bios = BiosState::new(self.bios.was_notified.clone(), supported, dbus)?; self.bios.was_notified.store(false, Ordering::SeqCst); notified = true; } if self.profiles.was_notified.load(Ordering::SeqCst) { - self.profiles = ProfilesState::new(self.profiles.was_notified.clone(), supported, dbus); + self.profiles = + ProfilesState::new(self.profiles.was_notified.clone(), supported, dbus)?; self.profiles.was_notified.store(false, Ordering::SeqCst); notified = true; } if self.fan_curves.was_notified.load(Ordering::SeqCst) { self.fan_curves = - FanCurvesState::new(self.fan_curves.was_notified.clone(), supported, dbus); + FanCurvesState::new(self.fan_curves.was_notified.clone(), supported, dbus)?; self.fan_curves.was_notified.store(false, Ordering::SeqCst); notified = true; } - notified + Ok(notified) + } +} + +impl Default for PageDataStates { + fn default() -> Self { + Self { + notifs_enabled: Default::default(), + was_notified: Default::default(), + bios: BiosState { + was_notified: Default::default(), + post_sound: Default::default(), + dedicated_gfx: Default::default(), + panel_overdrive: Default::default(), + dgpu_disable: Default::default(), + egpu_enable: Default::default(), + }, + aura: AuraState { + was_notified: Default::default(), + current_mode: AuraModeNum::Static, + modes: Default::default(), + enabled: AuraPowerDev { + x1866: vec![], + x19b6: vec![], + }, + bright: Default::default(), + }, + anime: AnimeState { + was_notified: Default::default(), + bright: Default::default(), + boot: Default::default(), + awake: Default::default(), + sleep: Default::default(), + }, + profiles: ProfilesState { + was_notified: Default::default(), + list: Default::default(), + current: Default::default(), + }, + fan_curves: FanCurvesState { + was_notified: Default::default(), + show_curve: Default::default(), + show_graph: Default::default(), + enabled: Default::default(), + curves: Default::default(), + drag_delta: Default::default(), + }, + charge_limit: Default::default(), + error: Default::default(), + } } } diff --git a/rog-control-center/src/widgets/aura_page.rs b/rog-control-center/src/widgets/aura_page.rs index 8a4648e7..b28a95b5 100644 --- a/rog-control-center/src/widgets/aura_page.rs +++ b/rog-control-center/src/widgets/aura_page.rs @@ -3,12 +3,11 @@ use rog_aura::{ usb::{AuraDev1866, AuraDev19b6, AuraDevice, AuraPowerDev}, AuraModeNum, AuraZone, Colour, Speed, }; -use rog_dbus::RogDbusClientBlocking; use rog_supported::SupportedFunctions; use crate::{ page_states::{AuraState, PageDataStates}, - RogApp, + RogApp, RogDbusClientBlocking, }; impl<'a> RogApp<'a> { @@ -442,7 +441,10 @@ impl<'a> RogApp<'a> { ui.with_layout(egui::Layout::right_to_left(egui::Align::TOP), |ui| { if ui.add(egui::Button::new("Cancel")).clicked() { let notif = states.aura.was_notified.clone(); - states.aura.modes = AuraState::new(notif, supported, dbus).modes; + match AuraState::new(notif, supported, dbus) { + Ok(a) => states.aura.modes = a.modes, + Err(e) => states.error = Some(e.to_string()), + } } if ui.add(egui::Button::new("Apply")).clicked() { diff --git a/rog-control-center/src/widgets/fan_curve_page.rs b/rog-control-center/src/widgets/fan_curve_page.rs index 79060725..65085e29 100644 --- a/rog-control-center/src/widgets/fan_curve_page.rs +++ b/rog-control-center/src/widgets/fan_curve_page.rs @@ -1,9 +1,8 @@ use crate::{ page_states::{FanCurvesState, ProfilesState}, - RogApp, + RogApp, RogDbusClientBlocking, }; use egui::{plot::Points, Ui}; -use rog_dbus::RogDbusClientBlocking; use rog_profiles::{FanCurvePU, Profile}; use rog_supported::SupportedFunctions; @@ -44,7 +43,7 @@ impl<'a> RogApp<'a> { let mut changed = false; ui.horizontal(|ui| { - let mut item = |p: Profile, _curves: &mut FanCurvesState, mut checked: bool| { + let mut item = |p: Profile, curves: &mut FanCurvesState, mut checked: bool| { if ui .add(egui::Checkbox::new(&mut checked, format!("{:?}", p))) .changed() @@ -57,11 +56,10 @@ impl<'a> RogApp<'a> { }) .ok(); - #[cfg(feature = "mocking")] if !checked { - _curves.enabled.remove(&p); + curves.enabled.remove(&p); } else { - _curves.enabled.insert(p); + curves.enabled.insert(p); } changed = true; } @@ -73,11 +71,10 @@ impl<'a> RogApp<'a> { }); if changed { - // Need to update app data if change made - #[cfg(not(feature = "mocking"))] - { - let notif = curves.was_notified.clone(); - *curves = FanCurvesState::new(notif, supported, dbus); + let notif = curves.was_notified.clone(); + match FanCurvesState::new(notif, supported, dbus) { + Ok(f) => *curves = f, + Err(e) => *do_error = Some(e.to_string()), } } } @@ -132,13 +129,13 @@ impl<'a> RogApp<'a> { let points = Points::new(PlotPoints::from_iter(points)).radius(3.0); Plot::new("my_plot") - .view_aspect(2.0) + .view_aspect(1.666) // .center_x_axis(true) // .center_y_axis(true) .include_x(0.0) - .include_x(110.0) + .include_x(104.0) .include_y(0.0) - .include_y(110.0) + .include_y(106.0) .allow_scroll(false) .allow_drag(false) .allow_boxed_zoom(false) @@ -183,7 +180,6 @@ impl<'a> RogApp<'a> { ui.with_layout(egui::Layout::right_to_left(egui::Align::TOP), |ui| { if ui.add(egui::Button::new("Apply Fan-curve")).clicked() { - #[cfg(not(feature = "mocking"))] dbus.proxies() .profile() .set_fan_curve(profiles.current, data.clone()) @@ -191,8 +187,6 @@ impl<'a> RogApp<'a> { *do_error = Some(err.to_string()); }) .ok(); - #[cfg(feature = "mocking")] - dbg!("Applied"); } }); } diff --git a/rog-control-center/src/widgets/side_panel.rs b/rog-control-center/src/widgets/side_panel.rs index cfaf8a89..c7db63ce 100644 --- a/rog-control-center/src/widgets/side_panel.rs +++ b/rog-control-center/src/widgets/side_panel.rs @@ -18,7 +18,7 @@ impl<'a> RogApp<'a> { *page = Page::System; } - if self.supported.platform_profile.fan_curves || cfg!(feature = "mocking") { + if self.supported.platform_profile.fan_curves { ui.separator(); if ui .selectable_value(page, Page::FanCurves, "Fan Curves") @@ -28,9 +28,7 @@ impl<'a> RogApp<'a> { } } - if !self.supported.keyboard_led.stock_led_modes.is_empty() - || cfg!(feature = "mocking") - { + if !self.supported.keyboard_led.stock_led_modes.is_empty() { ui.separator(); if ui .selectable_value(page, Page::AuraEffects, "Keyboard Aura") @@ -40,7 +38,7 @@ impl<'a> RogApp<'a> { } } - if self.supported.anime_ctrl.0 || cfg!(feature = "mocking") { + if self.supported.anime_ctrl.0 { ui.separator(); if ui .selectable_value(page, Page::AnimeMatrix, "AniMe Matrix") diff --git a/rog-control-center/src/widgets/system_page.rs b/rog-control-center/src/widgets/system_page.rs index c19c288e..1332e9a6 100644 --- a/rog-control-center/src/widgets/system_page.rs +++ b/rog-control-center/src/widgets/system_page.rs @@ -1,6 +1,5 @@ -use crate::{page_states::PageDataStates, RogApp}; +use crate::{page_states::PageDataStates, RogApp, RogDbusClientBlocking}; use egui::Ui; -use rog_dbus::RogDbusClientBlocking; use rog_profiles::Profile; impl<'a> RogApp<'a> { diff --git a/rog-profiles/src/fan_curve_set.rs b/rog-profiles/src/fan_curve_set.rs index d09a1a8e..4c4daa5e 100644 --- a/rog-profiles/src/fan_curve_set.rs +++ b/rog-profiles/src/fan_curve_set.rs @@ -34,6 +34,31 @@ pub struct CurveData { pub temp: [u8; 8], } +impl From<&CurveData> for String { + fn from(c: &CurveData) -> Self { + format!( + "{:?}: {}c:{}%,{}c:{}%,{}c:{}%,{}c:{}%,{}c:{}%,{}c:{}%,{}c:{}%,{}c:{}%", + c.fan, + c.temp[0], + (c.pwm[0] as u32) * 100 / 255, + c.temp[1], + (c.pwm[1] as u32) * 100 / 255, + c.temp[2], + (c.pwm[2] as u32) * 100 / 255, + c.temp[3], + (c.pwm[3] as u32) * 100 / 255, + c.temp[4], + (c.pwm[4] as u32) * 100 / 255, + c.temp[5], + (c.pwm[5] as u32) * 100 / 255, + c.temp[6], + (c.pwm[6] as u32) * 100 / 255, + c.temp[7], + (c.pwm[7] as u32) * 100 / 255, + ) + } +} + impl std::str::FromStr for CurveData { type Err = ProfileError; @@ -189,6 +214,17 @@ impl Default for FanCurveSet { } } +impl From<&FanCurveSet> for String { + fn from(s: &FanCurveSet) -> Self { + format!( + "Enabled: {}, {}, {}", + s.enabled, + String::from(&s.cpu), + String::from(&s.gpu), + ) + } +} + impl FanCurveSet { pub(crate) fn read_cpu_from_device(&mut self, device: &Device) { self.cpu.read_from_device(device); @@ -216,13 +252,20 @@ mod tests { use super::*; #[test] - fn curve_data_from_str() { + fn curve_data_from_str_to_str() { let curve = CurveData::from_str("30c:1%,49c:2%,59c:3%,69c:4%,79c:31%,89c:49%,99c:56%,109c:58%") .unwrap(); assert_eq!(curve.fan, FanCurvePU::CPU); assert_eq!(curve.temp, [30, 49, 59, 69, 79, 89, 99, 109]); assert_eq!(curve.pwm, [3, 5, 8, 10, 79, 125, 143, 148]); + + let string: String = (&curve).into(); + // End result is slightly different due to type conversions and rounding errors + assert_eq!( + string.as_str(), + "CPU: 30c:1%,49c:1%,59c:3%,69c:3%,79c:30%,89c:49%,99c:56%,109c:58%" + ) } #[test] @@ -257,4 +300,11 @@ mod tests { assert_eq!(temp_str('1', 4), "pwm1_auto_point5_temp"); assert_eq!(temp_str('1', 7), "pwm1_auto_point8_temp"); } + + #[test] + fn set_to_string() { + let set = FanCurveSet::default(); + let string = String::from(&set); + assert_eq!(string.as_str(), "Enabled: false, CPU: 0c:0%,0c:0%,0c:0%,0c:0%,0c:0%,0c:0%,0c:0%,0c:0%, GPU: 0c:0%,0c:0%,0c:0%,0c:0%,0c:0%,0c:0%,0c:0%,0c:0%"); + } } diff --git a/rog-profiles/src/lib.rs b/rog-profiles/src/lib.rs index 641c3003..8080afd7 100644 --- a/rog-profiles/src/lib.rs +++ b/rog-profiles/src/lib.rs @@ -163,13 +163,13 @@ impl FanCurveProfiles { enumerator.match_subsystem("hwmon")?; for device in enumerator.scan_devices()? { - if device.parent_with_subsystem("platform")?.is_some() { - if let Some(name) = device.attribute_value("name") { - if name == "asus_custom_fan_curve" { - return Ok(device); - } + // if device.parent_with_subsystem("platform")?.is_some() { + if let Some(name) = device.attribute_value("name") { + if name == "asus_custom_fan_curve" { + return Ok(device); } } + // } } Err(ProfileError::NotSupported) } diff --git a/rog-supported/src/lib.rs b/rog-supported/src/lib.rs index 3de9241e..4de3f96b 100644 --- a/rog-supported/src/lib.rs +++ b/rog-supported/src/lib.rs @@ -5,7 +5,7 @@ use serde_derive::{Deserialize, Serialize}; use std::fmt; use zvariant_derive::Type; -#[derive(Serialize, Deserialize, Type, Debug)] +#[derive(Serialize, Deserialize, Type, Debug, Default)] pub struct SupportedFunctions { pub anime_ctrl: AnimeSupportedFunctions, pub charge_ctrl: ChargeSupportedFunctions, @@ -14,21 +14,21 @@ pub struct SupportedFunctions { pub rog_bios_ctrl: RogBiosSupportedFunctions, } -#[derive(Serialize, Deserialize, Type, Debug)] +#[derive(Serialize, Deserialize, Type, Debug, Default)] pub struct AnimeSupportedFunctions(pub bool); -#[derive(Serialize, Deserialize, Type, Debug)] +#[derive(Serialize, Deserialize, Type, Debug, Default)] pub struct ChargeSupportedFunctions { pub charge_level_set: bool, } -#[derive(Serialize, Deserialize, Type, Debug)] +#[derive(Serialize, Deserialize, Type, Debug, Default)] pub struct PlatformProfileFunctions { pub platform_profile: bool, pub fan_curves: bool, } -#[derive(Serialize, Deserialize, Type, Debug)] +#[derive(Serialize, Deserialize, Type, Debug, Default)] pub struct LedSupportedFunctions { pub prod_id: AuraDevice, pub brightness_set: bool, @@ -37,7 +37,7 @@ pub struct LedSupportedFunctions { pub per_key_led_mode: bool, } -#[derive(Serialize, Deserialize, Type, Debug)] +#[derive(Serialize, Deserialize, Type, Debug, Default)] pub struct RogBiosSupportedFunctions { pub post_sound: bool, pub dedicated_gfx: bool,