Add basic OC page and refine stats update loop

This commit is contained in:
Ilya Zlobintsev
2021-02-07 23:58:26 +02:00
parent 11b9844f9a
commit e2cc40aa8b
8 changed files with 301 additions and 36 deletions

View File

@@ -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),
}

View File

@@ -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);
}
}

View File

@@ -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,
}
}
}

View 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);
}
}

View 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));
}
}

View File

@@ -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);
}
}
}

View 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 }
}
}

View File

@@ -40,7 +40,7 @@ fn connect_daemon() -> DaemonConnection {
);
dialog.run();
dialog.hide();
dialog.close();
DaemonConnection::new().unwrap()
}