diff --git a/Cargo.lock b/Cargo.lock index 9785308..a940e31 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,7 +26,7 @@ dependencies = [ [[package]] name = "amdgpu-sysfs" version = "0.5.0" -source = "git+https://github.com/ilya-zlobintsev/amdgpu-sysfs-rs?branch=blocking#55ddcc95cddde27e5c5147d9b5ee4831b5d7aaf8" +source = "git+https://github.com/ilya-zlobintsev/amdgpu-sysfs-rs?branch=blocking#0308d4c475f5091f7e8bc4b7b5d8c101f8dd40d7" dependencies = [ "serde", ] diff --git a/lact-gui/src/app.rs b/lact-gui/src/app.rs index c295b01..8701e73 100644 --- a/lact-gui/src/app.rs +++ b/lact-gui/src/app.rs @@ -80,7 +80,8 @@ impl App { }); } - let devices = self.daemon_client.list_devices()?; + let devices_buf = self.daemon_client.list_devices()?; + let devices = devices_buf.inner()?; self.header.set_devices(&devices); // Show apply button on setting changes @@ -96,10 +97,10 @@ impl App { let apply_revealer = self.apply_revealer.clone(); - self.root_stack.oc_page.connect_settings_changed(move || { - debug!("Settings changed, showing apply button"); - apply_revealer.show(); - }); + // self.root_stack.oc_page.connect_settings_changed(move || { + // debug!("Settings changed, showing apply button"); + // apply_revealer.show(); + // }); } { @@ -185,13 +186,17 @@ impl App { } fn set_info(&self, gpu_id: &str) { - let info = self.daemon_client.get_device_info(gpu_id).unwrap(); + let info_buf = self + .daemon_client + .get_device_info(gpu_id) + .expect("Could not fetch info"); + let info = info_buf.inner().unwrap(); trace!("Setting info {info:?}"); self.root_stack.info_page.set_info(&info); - trace!("Setting clocks"); - self.root_stack.oc_page.set_info(&info); + // trace!("Setting clocks"); + // self.root_stack.oc_page.set_info(&info); // TODO: this should be stats /*trace!("Setting performance level {:?}", info.power_profile); @@ -221,15 +226,15 @@ impl App { let ppfeaturemask: u64 = u64::from_str_radix(ppfeaturemask, 16).expect("Invalid ppfeaturemask"); - if (ppfeaturemask & PP_OVERDRIVE_MASK as u64) > 0 { + /*if (ppfeaturemask & PP_OVERDRIVE_MASK as u64) > 0 { self.root_stack.oc_page.warning_frame.hide(); } else { self.root_stack.oc_page.warning_frame.show(); - } + }*/ } Err(_) => { info!("Failed to read feature mask! This is expected if your system doesn't have an AMD GPU."); - self.root_stack.oc_page.warning_frame.hide(); + // self.root_stack.oc_page.warning_frame.hide(); } } } @@ -249,7 +254,10 @@ impl App { thread::spawn(move || loop { let gpu_id = current_gpu_id.read().unwrap(); - match daemon_connection.get_device_stats(&gpu_id) { + match daemon_connection + .get_device_stats(&gpu_id) + .and_then(|stats| stats.inner()) + { Ok(stats) => { sender.send(GuiUpdateMsg::GpuStats(stats)).unwrap(); } @@ -264,14 +272,14 @@ impl App { // Receiving stats into the gui event loop { let thermals_page = self.root_stack.thermals_page.clone(); - let oc_page = self.root_stack.oc_page.clone(); + // let oc_page = self.root_stack.oc_page.clone(); receiver.attach(None, move |msg| { match msg { GuiUpdateMsg::GpuStats(stats) => { trace!("New stats received, updating {stats:?}"); thermals_page.set_stats(&stats); - oc_page.set_stats(&stats); + // oc_page.set_stats(&stats); } /*GuiUpdateMsg::FanControlInfo(fan_control_info) => { thermals_page.set_ventilation_info(fan_control_info) }*/ diff --git a/lact-gui/src/app/root_stack.rs b/lact-gui/src/app/root_stack.rs index 60bd65f..0b232c2 100644 --- a/lact-gui/src/app/root_stack.rs +++ b/lact-gui/src/app/root_stack.rs @@ -1,5 +1,5 @@ mod info_page; -mod oc_page; +// mod oc_page; mod software_page; mod thermals_page; @@ -7,7 +7,7 @@ use gtk::prelude::*; use gtk::*; use info_page::InformationPage; -use oc_page::OcPage; +// use oc_page::OcPage; use software_page::SoftwarePage; use thermals_page::ThermalsPage; @@ -17,7 +17,7 @@ pub struct RootStack { pub info_page: InformationPage, pub thermals_page: ThermalsPage, pub software_page: SoftwarePage, - pub oc_page: OcPage, + // pub oc_page: OcPage, } impl RootStack { @@ -28,9 +28,9 @@ impl RootStack { container.add_titled(&info_page.container, "info_page", "Information"); - let oc_page = OcPage::new(); + // let oc_page = OcPage::new(); - container.add_titled(&oc_page.container, "oc_page", "OC"); + // container.add_titled(&oc_page.container, "oc_page", "OC"); let thermals_page = ThermalsPage::new(); @@ -44,7 +44,7 @@ impl RootStack { container, info_page, thermals_page, - oc_page, + // oc_page, software_page, } } diff --git a/lact-gui/src/app/root_stack/info_page.rs b/lact-gui/src/app/root_stack/info_page.rs index 0c0b597..86819ce 100644 --- a/lact-gui/src/app/root_stack/info_page.rs +++ b/lact-gui/src/app/root_stack/info_page.rs @@ -151,11 +151,13 @@ impl InformationPage { pub fn set_info(&self, gpu_info: &DeviceInfo) { let gpu_name = gpu_info .pci_info + .as_ref() .and_then(|pci_info| { pci_info .subsystem_pci_info .model - .or_else(|| pci_info.device_pci_info.model) + .as_deref() + .or_else(|| pci_info.device_pci_info.model.as_deref()) }) .unwrap_or_default(); self.gpu_name_label @@ -163,43 +165,48 @@ impl InformationPage { let gpu_manufacturer = gpu_info .pci_info + .as_ref() .and_then(|pci_info| { pci_info .subsystem_pci_info .vendor - .or_else(|| pci_info.device_pci_info.model) + .as_deref() + .or_else(|| pci_info.device_pci_info.model.as_deref()) }) .unwrap_or_default(); self.gpu_manufacturer_label .set_markup(&format!("{gpu_manufacturer}",)); - let vbios_version = gpu_info.vbios_version.as_deref().unwrap_or(""); + let vbios_version = gpu_info.vbios_version.as_deref().unwrap_or("unknown"); self.vbios_version_label .set_markup(&format!("{vbios_version}",)); self.driver_label .set_markup(&format!("{}", gpu_info.driver)); - let vram_size = gpu_info - .vram_size - .map_or_else(|| "".to_owned(), |size| size.to_string()); - self.vram_size_label - .set_markup(&format!("{vram_size}")); + // TODO + // let vram_size = gpu_info + // .vram_size + // .map_or_else(|| "unknown".to_owned(), |size| size.to_string()); + // self.vram_size_label + // .set_markup(&format!("{vram_size}")); let link_speed = gpu_info .link_info .current_speed .as_deref() - .unwrap_or(""); + .unwrap_or("unknown"); let link_width = gpu_info .link_info .current_width .as_deref() - .unwrap_or(""); + .unwrap_or("unknown"); self.link_speed_label .set_markup(&format!("{link_speed} x{link_width}",)); - self.vulkan_info_frame.set_info(&gpu_info.vulkan_info); + if let Some(vulkan_info) = &gpu_info.vulkan_info { + self.vulkan_info_frame.set_info(vulkan_info); + } self.container.show_all(); } diff --git a/lact-gui/src/app/root_stack/oc_page.rs b/lact-gui/src/app/root_stack/oc_page.rs index 1adcea5..c792cb3 100644 --- a/lact-gui/src/app/root_stack/oc_page.rs +++ b/lact-gui/src/app/root_stack/oc_page.rs @@ -1,12 +1,10 @@ -mod clocks_frame; +// mod clocks_frame; mod performance_level_frame; mod power_cap_frame; mod stats_grid; mod warning_frame; use amdgpu_sysfs::gpu_handle::PerformanceLevel; -use clocks_frame::ClocksFrame; -use clocks_frame::ClocksSettings; use gtk::prelude::*; use gtk::*; use lact_schema::{DeviceInfo, DeviceStats}; @@ -21,7 +19,7 @@ pub struct OcPage { stats_grid: StatsGrid, performance_level_frame: PowerProfileFrame, power_cap_frame: PowerCapFrame, - clocks_frame: ClocksFrame, + // clocks_frame: ClocksFrame, pub warning_frame: WarningFrame, } @@ -45,15 +43,15 @@ impl OcPage { container.pack_start(&power_profile_frame.container, false, true, 0); - let clocks_frame = ClocksFrame::new(); + // let clocks_frame = ClocksFrame::new(); - container.pack_start(&clocks_frame.container, false, true, 0); + // container.pack_start(&clocks_frame.container, false, true, 0); Self { container, stats_grid, performance_level_frame: power_profile_frame, - clocks_frame, + // clocks_frame, warning_frame, power_cap_frame, } @@ -100,9 +98,12 @@ impl OcPage { } } - pub fn get_power_profile(&self) -> Option { + pub fn get_performance_level(&self) -> Option { match self.performance_level_frame.get_visibility() { - true => Some(self.performance_level_frame.get_selected_power_profile()), + true => Some( + self.performance_level_frame + .get_selected_performance_level(), + ), false => None, } } diff --git a/lact-gui/src/app/root_stack/oc_page/clocks_frame.rs b/lact-gui/src/app/root_stack/oc_page/clocks_frame.rs index 6605b12..8c249c8 100644 --- a/lact-gui/src/app/root_stack/oc_page/clocks_frame.rs +++ b/lact-gui/src/app/root_stack/oc_page/clocks_frame.rs @@ -1,4 +1,3 @@ -use daemon::gpu_controller::ClocksTable; use gtk::prelude::*; use gtk::*; diff --git a/lact-gui/src/app/root_stack/oc_page/performance_level_frame.rs b/lact-gui/src/app/root_stack/oc_page/performance_level_frame.rs index 43a054f..f7445ba 100644 --- a/lact-gui/src/app/root_stack/oc_page/performance_level_frame.rs +++ b/lact-gui/src/app/root_stack/oc_page/performance_level_frame.rs @@ -1,4 +1,4 @@ -use daemon::gpu_controller::PowerProfile; +use amdgpu_sysfs::gpu_handle::PerformanceLevel; use gtk::prelude::*; use gtk::*; @@ -57,11 +57,12 @@ impl PowerProfileFrame { } } - pub fn set_active_profile(&self, profile: &PowerProfile) { - match profile { - PowerProfile::Auto => self.combo_box.set_active_id(Some("0")), - PowerProfile::High => self.combo_box.set_active_id(Some("1")), - PowerProfile::Low => self.combo_box.set_active_id(Some("2")), + pub fn set_active_profile(&self, level: PerformanceLevel) { + match level { + PerformanceLevel::Auto => self.combo_box.set_active_id(Some("0")), + PerformanceLevel::High => self.combo_box.set_active_id(Some("1")), + PerformanceLevel::Low => self.combo_box.set_active_id(Some("2")), + PerformanceLevel::Manual => todo!(), }; } @@ -71,11 +72,11 @@ impl PowerProfileFrame { }); } - pub fn get_selected_power_profile(&self) -> PowerProfile { + pub fn get_selected_performance_level(&self) -> PerformanceLevel { match self.combo_box.active().unwrap() { - 0 => PowerProfile::Auto, - 1 => PowerProfile::High, - 2 => PowerProfile::Low, + 0 => PerformanceLevel::Auto, + 1 => PerformanceLevel::High, + 2 => PerformanceLevel::Low, _ => unreachable!(), } } diff --git a/lact-gui/src/app/root_stack/thermals_page/fan_curve_frame.rs b/lact-gui/src/app/root_stack/thermals_page/fan_curve_frame.rs index 60f0fda..1395ef8 100644 --- a/lact-gui/src/app/root_stack/thermals_page/fan_curve_frame.rs +++ b/lact-gui/src/app/root_stack/thermals_page/fan_curve_frame.rs @@ -1,7 +1,7 @@ -use std::collections::BTreeMap; - use gtk::prelude::*; use gtk::*; +use std::collections::BTreeMap; +use tracing::debug; #[derive(Clone)] pub struct FanCurveFrame { @@ -189,12 +189,12 @@ impl FanCurveFrame { } pub fn show(&self) { - log::info!("Manual fan control enaged, showing fan curve"); + debug!("Manual fan control enaged, showing fan curve"); self.container.set_visible(true); } pub fn hide(&self) { - log::info!("Manual fan control disenaged, hiding fan curve"); + debug!("Manual fan control disenaged, hiding fan curve"); self.container.set_visible(false); } diff --git a/lact-gui/src/client.rs b/lact-gui/src/client.rs index 72b34a0..071148b 100644 --- a/lact-gui/src/client.rs +++ b/lact-gui/src/client.rs @@ -1,9 +1,11 @@ use anyhow::{anyhow, Context}; use lact_schema::{request::Request, response::Response, DeviceInfo, DeviceListEntry, DeviceStats}; use nix::unistd::getuid; -use serde::de::DeserializeOwned; +use serde::{de::DeserializeOwned, Deserialize}; use std::{ io::{BufRead, BufReader, Write}, + marker::PhantomData, + ops::DerefMut, os::unix::net::UnixStream, path::PathBuf, sync::{Arc, Mutex}, @@ -26,8 +28,12 @@ impl DaemonClient { }) } - fn make_request(&self, request: Request) -> anyhow::Result { - let (reader, writer) = *self.stream.lock().map_err(|err| anyhow!("{err}"))?; + fn make_request<'a, T: Deserialize<'a>>( + &self, + request: Request, + ) -> anyhow::Result> { + let mut stream_guard = self.stream.lock().map_err(|err| anyhow!("{err}"))?; + let (reader, writer) = stream_guard.deref_mut(); if !reader.buffer().is_empty() { return Err(anyhow!("Another request was not processed properly")); @@ -38,30 +44,29 @@ impl DaemonClient { writer.write_all(b"\n")?; let mut response_payload = String::new(); - reader.read_line(&mut response_payload); + reader.read_line(&mut response_payload)?; - let response: Response = serde_json::from_str(&response_payload) - .context("Could not deserialize response from daemon")?; - - match response { - Response::Ok(data) => Ok(data), - Response::Error(error) => Err(anyhow!("Error from daemon: {error}")), - } + Ok(ResponseBuffer { + buf: response_payload, + _phantom: PhantomData, + }) } - pub fn list_devices<'a>(&self) -> anyhow::Result>> { + pub fn list_devices<'a>(&self) -> anyhow::Result>>> { self.make_request(Request::ListDevices) } pub fn set_fan_control(&self, id: &str, enabled: bool) -> anyhow::Result<()> { - self.make_request(Request::SetFanControl { id, enabled }) + self.make_request::<()>(Request::SetFanControl { id, enabled })? + .inner()?; + Ok(()) } - pub fn get_device_info(&self, id: &str) -> anyhow::Result { + pub fn get_device_info(&self, id: &str) -> anyhow::Result> { self.make_request(Request::DeviceInfo { id }) } - pub fn get_device_stats(&self, id: &str) -> anyhow::Result { + pub fn get_device_stats(&self, id: &str) -> anyhow::Result> { self.make_request(Request::DeviceStats { id }) } } @@ -82,3 +87,19 @@ fn get_socket_path() -> Option { None } } + +pub struct ResponseBuffer { + buf: String, + _phantom: PhantomData, +} + +impl<'a, T: Deserialize<'a>> ResponseBuffer { + pub fn inner(&'a self) -> anyhow::Result { + let response: Response = serde_json::from_str(&self.buf) + .context("Could not deserialize response from daemon")?; + match response { + Response::Ok(data) => Ok(data), + Response::Error(err) => Err(anyhow!("Got error from daemon: {err}")), + } + } +}