mirror of
https://github.com/ilya-zlobintsev/LACT.git
synced 2025-02-25 18:55:26 -06:00
Add basic OC page and refine stats update loop
This commit is contained in:
@@ -8,7 +8,11 @@ use std::sync::Arc;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
use daemon::{daemon_connection::DaemonConnection, DaemonError};
|
||||
use daemon::{
|
||||
daemon_connection::DaemonConnection,
|
||||
gpu_controller::{FanControlInfo, GpuStats},
|
||||
DaemonError,
|
||||
};
|
||||
use gtk::*;
|
||||
|
||||
use header::Header;
|
||||
@@ -81,29 +85,48 @@ impl App {
|
||||
|
||||
fn start_stats_update_loop(&self, current_gpu_id: Arc<AtomicU32>) {
|
||||
let (sender, receiver) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
|
||||
{
|
||||
let daemon_connection = self.daemon_connection.clone();
|
||||
|
||||
let daemon_connection = self.daemon_connection.clone();
|
||||
thread::spawn(move || loop {
|
||||
let gpu_id = current_gpu_id.load(Ordering::SeqCst);
|
||||
|
||||
thread::spawn(move || loop {
|
||||
let gpu_id = current_gpu_id.load(Ordering::SeqCst);
|
||||
if let Ok(stats) = daemon_connection.get_gpu_stats(gpu_id) {
|
||||
sender.send(GuiUpdateMsg::GpuStats(stats)).unwrap();
|
||||
}
|
||||
|
||||
if let Ok(stats) = daemon_connection.get_gpu_stats(gpu_id) {
|
||||
sender.send(stats).unwrap();
|
||||
}
|
||||
if let Ok(fan_control) = daemon_connection.get_fan_control(gpu_id) {
|
||||
sender
|
||||
.send(GuiUpdateMsg::FanControlInfo(fan_control))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
if let Ok(fan_control) = daemon_connection.get_fan_control(gpu_id) {
|
||||
println!("{:?}", fan_control);
|
||||
}
|
||||
thread::sleep(Duration::from_millis(500));
|
||||
});
|
||||
}
|
||||
|
||||
thread::sleep(Duration::from_millis(500));
|
||||
});
|
||||
{
|
||||
let thermals_page = self.root_stack.thermals_page.clone();
|
||||
let oc_page = self.root_stack.oc_page.clone();
|
||||
|
||||
let thermals_page = self.root_stack.thermals_page.clone();
|
||||
receiver.attach(None, move |msg| {
|
||||
match msg {
|
||||
GuiUpdateMsg::GpuStats(stats) => {
|
||||
thermals_page.set_thermals_info(&stats);
|
||||
oc_page.set_stats(&stats);
|
||||
}
|
||||
GuiUpdateMsg::FanControlInfo(fan_control_info) => {
|
||||
thermals_page.set_ventilation_info(fan_control_info)
|
||||
}
|
||||
}
|
||||
|
||||
receiver.attach(None, move |stats| {
|
||||
thermals_page.set_thermals_info(&stats);
|
||||
|
||||
glib::Continue(true)
|
||||
});
|
||||
glib::Continue(true)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum GuiUpdateMsg {
|
||||
FanControlInfo(FanControlInfo),
|
||||
GpuStats(GpuStats),
|
||||
}
|
||||
|
||||
@@ -8,28 +8,36 @@ pub struct Header {
|
||||
pub container: HeaderBar,
|
||||
gpu_selector: ComboBoxText,
|
||||
switcher: StackSwitcher,
|
||||
apply_button: Button,
|
||||
}
|
||||
|
||||
impl Header {
|
||||
pub fn new() -> Self {
|
||||
let container = HeaderBar::new();
|
||||
|
||||
container.set_custom_title(Some(&Grid::new())); // Bad workaround to hide the title
|
||||
|
||||
if env::var("XDG_CURRENT_DESKTOP") == Ok("GNOME".to_string()) {
|
||||
container.set_show_close_button(true);
|
||||
}
|
||||
|
||||
let gpu_selector = ComboBoxText::new();
|
||||
|
||||
container.pack_start(&gpu_selector);
|
||||
|
||||
let switcher = StackSwitcher::new();
|
||||
|
||||
container.pack_start(&switcher);
|
||||
|
||||
let apply_button = Button::new();
|
||||
apply_button.set_label("Apply");
|
||||
apply_button.set_sensitive(false);
|
||||
|
||||
container.pack_start(&apply_button);
|
||||
|
||||
Header {
|
||||
container,
|
||||
gpu_selector,
|
||||
switcher,
|
||||
apply_button,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,4 +66,14 @@ impl Header {
|
||||
f(selected_id.parse().unwrap());
|
||||
});
|
||||
}
|
||||
|
||||
pub fn connect_apply_button_clicked<F: Fn() + 'static>(&self, f: F) {
|
||||
self.apply_button.connect_clicked(move |_| {
|
||||
f();
|
||||
});
|
||||
}
|
||||
|
||||
pub fn set_apply_button_sensitive(&self) {
|
||||
self.apply_button.set_sensitive(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
mod info_page;
|
||||
mod thermals_page;
|
||||
mod oc_page;
|
||||
|
||||
use gtk::*;
|
||||
|
||||
use info_page::InformationPage;
|
||||
use oc_page::OcPage;
|
||||
use thermals_page::ThermalsPage;
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -11,6 +13,7 @@ pub struct RootStack {
|
||||
pub container: Stack,
|
||||
pub info_page: InformationPage,
|
||||
pub thermals_page: ThermalsPage,
|
||||
pub oc_page: OcPage,
|
||||
}
|
||||
|
||||
impl RootStack {
|
||||
@@ -20,16 +23,21 @@ impl RootStack {
|
||||
let info_page = InformationPage::new();
|
||||
|
||||
container.add_titled(&info_page.container, "info_page", "Information");
|
||||
|
||||
let oc_page = OcPage::new();
|
||||
|
||||
container.add_titled(&oc_page.container, "oc_page", "OC");
|
||||
|
||||
let thermals_page = ThermalsPage::new();
|
||||
|
||||
container.add_titled(&thermals_page.container, "thermals_page", "Thermals");
|
||||
|
||||
|
||||
|
||||
Self {
|
||||
container,
|
||||
info_page,
|
||||
thermals_page,
|
||||
oc_page,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
27
gui/src/app/root_stack/oc_page.rs
Normal file
27
gui/src/app/root_stack/oc_page.rs
Normal file
@@ -0,0 +1,27 @@
|
||||
mod stats_grid;
|
||||
|
||||
use daemon::gpu_controller::GpuStats;
|
||||
use gtk::*;
|
||||
use stats_grid::StatsGrid;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct OcPage {
|
||||
pub container: Box,
|
||||
stats_grid: StatsGrid,
|
||||
}
|
||||
|
||||
impl OcPage {
|
||||
pub fn new() -> Self {
|
||||
let container = Box::new(Orientation::Vertical, 5);
|
||||
|
||||
let stats_grid = StatsGrid::new();
|
||||
|
||||
container.pack_start(&stats_grid.container, false, true, 10);
|
||||
|
||||
Self { container, stats_grid }
|
||||
}
|
||||
|
||||
pub fn set_stats(&self, stats: &GpuStats) {
|
||||
self.stats_grid.set_stats(stats);
|
||||
}
|
||||
}
|
||||
125
gui/src/app/root_stack/oc_page/stats_grid.rs
Normal file
125
gui/src/app/root_stack/oc_page/stats_grid.rs
Normal file
@@ -0,0 +1,125 @@
|
||||
use daemon::gpu_controller::GpuStats;
|
||||
use gtk::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct StatsGrid {
|
||||
pub container: Grid,
|
||||
vram_usage_bar: LevelBar,
|
||||
vram_usage_label: Label,
|
||||
gpu_clock_label: Label,
|
||||
vram_clock_label: Label,
|
||||
gpu_voltage_label: Label,
|
||||
power_usage_label: Label,
|
||||
}
|
||||
|
||||
impl StatsGrid {
|
||||
pub fn new() -> Self {
|
||||
let container = Grid::new();
|
||||
|
||||
container.set_column_homogeneous(true);
|
||||
|
||||
container.set_row_spacing(7);
|
||||
|
||||
container.attach(&Label::new(Some("VRAM Usage")), 0, 0, 1, 1);
|
||||
|
||||
let vram_usage_overlay = Overlay::new();
|
||||
|
||||
let vram_usage_bar = LevelBar::new();
|
||||
|
||||
let vram_usage_label = Label::new(None);
|
||||
|
||||
{
|
||||
vram_usage_bar.set_orientation(Orientation::Horizontal);
|
||||
vram_usage_bar.set_value(0.5);
|
||||
|
||||
vram_usage_label.set_text("512/1024 MiB");
|
||||
|
||||
vram_usage_overlay.add(&vram_usage_bar);
|
||||
vram_usage_overlay.add_overlay(&vram_usage_label);
|
||||
|
||||
container.attach(&vram_usage_overlay, 1, 0, 1, 1);
|
||||
}
|
||||
|
||||
let gpu_clock_label = Label::new(None);
|
||||
{
|
||||
let gpu_clock_box = Box::new(Orientation::Horizontal, 5);
|
||||
|
||||
gpu_clock_box.pack_start(&Label::new(Some("GPU Clock:")), false, false, 2);
|
||||
|
||||
gpu_clock_label.set_markup("<b>0000MHz</b>");
|
||||
|
||||
gpu_clock_box.pack_start(&gpu_clock_label, false, false, 2);
|
||||
|
||||
gpu_clock_box.set_halign(Align::Center);
|
||||
|
||||
container.attach(&gpu_clock_box, 0, 1, 1, 1);
|
||||
}
|
||||
|
||||
let vram_clock_label = Label::new(None);
|
||||
{
|
||||
let vram_clock_box = Box::new(Orientation::Horizontal, 5);
|
||||
|
||||
vram_clock_box.pack_start(&Label::new(Some("VRAM Clock:")), false, false, 2);
|
||||
|
||||
vram_clock_label.set_markup("<b>0000MHz</b>");
|
||||
|
||||
vram_clock_box.pack_start(&vram_clock_label, false, false, 2);
|
||||
|
||||
vram_clock_box.set_halign(Align::Center);
|
||||
|
||||
container.attach(&vram_clock_box, 1, 1, 1, 1);
|
||||
}
|
||||
let gpu_voltage_label = Label::new(None);
|
||||
{
|
||||
let gpu_voltage_box = Box::new(Orientation::Horizontal, 5);
|
||||
|
||||
gpu_voltage_box.pack_start(&Label::new(Some("GPU Voltage:")), false, false, 2);
|
||||
|
||||
gpu_voltage_label.set_markup("<b>0.000V</b>");
|
||||
|
||||
gpu_voltage_box.pack_start(&gpu_voltage_label, false, false, 2);
|
||||
|
||||
gpu_voltage_box.set_halign(Align::Center);
|
||||
|
||||
container.attach(&gpu_voltage_box, 0, 2, 1, 1);
|
||||
}
|
||||
|
||||
let power_usage_label = Label::new(None);
|
||||
{
|
||||
let power_usage_box = Box::new(Orientation::Horizontal, 5);
|
||||
|
||||
power_usage_box.pack_start(&Label::new(Some("Power Usage:")), false, false, 2);
|
||||
|
||||
power_usage_label.set_markup("<b>00/000W</b>");
|
||||
|
||||
power_usage_box.pack_start(&power_usage_label, false, false, 2);
|
||||
|
||||
power_usage_box.set_halign(Align::Center);
|
||||
|
||||
container.attach(&power_usage_box, 1, 2, 1, 1);
|
||||
}
|
||||
|
||||
Self {
|
||||
container,
|
||||
vram_usage_bar,
|
||||
vram_usage_label,
|
||||
gpu_clock_label,
|
||||
vram_clock_label,
|
||||
gpu_voltage_label,
|
||||
power_usage_label,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_stats(&self, stats: &GpuStats) {
|
||||
self.vram_usage_bar.set_value(stats.mem_used as f64 / stats.mem_total as f64);
|
||||
self.vram_usage_label.set_text(&format!("{}/{} MiB", stats.mem_used, stats.mem_total));
|
||||
|
||||
self.gpu_clock_label.set_markup(&format!("<b>{}MHz</b>", stats.gpu_freq));
|
||||
|
||||
self.vram_clock_label.set_markup(&format!("<b>{}MHz</b>", stats.mem_freq));
|
||||
|
||||
self.gpu_voltage_label.set_markup(&format!("<b>{}V</b>", stats.voltage as f64 / 1000f64));
|
||||
|
||||
self.power_usage_label.set_markup(&format!("<b>{}/{}W</b>", stats.power_avg, stats.power_cap));
|
||||
}
|
||||
}
|
||||
@@ -1,28 +1,36 @@
|
||||
use daemon::gpu_controller::GpuStats;
|
||||
mod fan_curve_frame;
|
||||
|
||||
use daemon::gpu_controller::{FanControlInfo, GpuStats};
|
||||
use gtk::*;
|
||||
|
||||
use fan_curve_frame::FanCurveFrame;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ThermalsPage {
|
||||
pub container: Grid,
|
||||
pub container: Box,
|
||||
temp_label: Label,
|
||||
fan_speed_label: Label,
|
||||
fan_control_enabled_switch: Switch,
|
||||
fan_curve_frame: FanCurveFrame,
|
||||
}
|
||||
|
||||
impl ThermalsPage {
|
||||
pub fn new() -> Self {
|
||||
let container = Grid::new();
|
||||
let container = Box::new(Orientation::Vertical, 5);
|
||||
|
||||
container.set_margin_start(5);
|
||||
container.set_margin_end(5);
|
||||
container.set_margin_bottom(5);
|
||||
container.set_margin_top(5);
|
||||
let grid = Grid::new();
|
||||
|
||||
container.set_column_homogeneous(true);
|
||||
grid.set_margin_start(5);
|
||||
grid.set_margin_end(5);
|
||||
grid.set_margin_bottom(5);
|
||||
grid.set_margin_top(5);
|
||||
|
||||
container.set_row_spacing(7);
|
||||
container.set_column_spacing(5);
|
||||
grid.set_column_homogeneous(true);
|
||||
|
||||
container.attach(
|
||||
grid.set_row_spacing(7);
|
||||
grid.set_column_spacing(5);
|
||||
|
||||
grid.attach(
|
||||
&{
|
||||
let label = Label::new(Some("Temperature:"));
|
||||
label.set_halign(Align::End);
|
||||
@@ -37,9 +45,9 @@ impl ThermalsPage {
|
||||
let temp_label = Label::new(None);
|
||||
temp_label.set_halign(Align::Start);
|
||||
|
||||
container.attach(&temp_label, 2, 0, 1, 1);
|
||||
grid.attach(&temp_label, 2, 0, 1, 1);
|
||||
|
||||
container.attach(
|
||||
grid.attach(
|
||||
&{
|
||||
let label = Label::new(Some("Fan speed:"));
|
||||
label.set_halign(Align::End);
|
||||
@@ -54,12 +62,42 @@ impl ThermalsPage {
|
||||
let fan_speed_label = Label::new(None);
|
||||
fan_speed_label.set_halign(Align::Start);
|
||||
|
||||
container.attach(&fan_speed_label, 2, 1, 1, 1);
|
||||
grid.attach(&fan_speed_label, 2, 1, 1, 1);
|
||||
|
||||
grid.attach(
|
||||
&{
|
||||
let label = Label::new(Some("Automatic fan control:"));
|
||||
label.set_halign(Align::End);
|
||||
label
|
||||
},
|
||||
0,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
);
|
||||
|
||||
|
||||
let fan_control_enabled_switch = Switch::new();
|
||||
|
||||
fan_control_enabled_switch.set_active(true);
|
||||
fan_control_enabled_switch.set_halign(Align::Start);
|
||||
|
||||
grid.attach(&fan_control_enabled_switch, 2, 2, 1, 1);
|
||||
|
||||
|
||||
container.pack_start(&grid, false, false, 5);
|
||||
|
||||
let fan_curve_frame = FanCurveFrame::new();
|
||||
|
||||
container.pack_start(&fan_curve_frame.container, true, true, 5);
|
||||
|
||||
|
||||
Self {
|
||||
container,
|
||||
temp_label,
|
||||
fan_speed_label,
|
||||
fan_control_enabled_switch,
|
||||
fan_curve_frame,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,4 +110,14 @@ impl ThermalsPage {
|
||||
(stats.fan_speed as f64 / stats.max_fan_speed as f64 * 100.0).round()
|
||||
));
|
||||
}
|
||||
|
||||
pub fn set_ventilation_info(&self, fan_control_info: FanControlInfo) {
|
||||
self.fan_control_enabled_switch.set_active(!fan_control_info.enabled);
|
||||
|
||||
if fan_control_info.enabled {
|
||||
self.fan_curve_frame.container.set_visible(true);
|
||||
} else {
|
||||
self.fan_curve_frame.container.set_visible(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
16
gui/src/app/root_stack/thermals_page/fan_curve_frame.rs
Normal file
16
gui/src/app/root_stack/thermals_page/fan_curve_frame.rs
Normal file
@@ -0,0 +1,16 @@
|
||||
use gtk::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct FanCurveFrame {
|
||||
pub container: Frame,
|
||||
}
|
||||
|
||||
impl FanCurveFrame {
|
||||
pub fn new() -> Self {
|
||||
let container = Frame::new(Some("Fan Curve"));
|
||||
|
||||
container.set_shadow_type(ShadowType::None);
|
||||
|
||||
Self { container }
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,7 @@ fn connect_daemon() -> DaemonConnection {
|
||||
);
|
||||
|
||||
dialog.run();
|
||||
dialog.hide();
|
||||
dialog.close();
|
||||
|
||||
DaemonConnection::new().unwrap()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user