mirror of
https://github.com/ilya-zlobintsev/LACT.git
synced 2025-02-25 18:55:26 -06:00
Implement fan curve
This commit is contained in:
@@ -67,6 +67,8 @@ impl App {
|
||||
}
|
||||
|
||||
pub fn run(&self) -> Result<(), DaemonError> {
|
||||
self.window.show_all();
|
||||
|
||||
let current_gpu_id = Arc::new(AtomicU32::new(0));
|
||||
|
||||
{
|
||||
@@ -91,14 +93,14 @@ impl App {
|
||||
self.root_stack
|
||||
.thermals_page
|
||||
.connect_settings_changed(move || {
|
||||
log::trace!("Settings changed, showing apply button");
|
||||
log::info!("Settings changed, showing apply button");
|
||||
apply_revealer.show();
|
||||
});
|
||||
|
||||
let apply_revealer = self.apply_revealer.clone();
|
||||
|
||||
self.root_stack.oc_page.connect_settings_changed(move || {
|
||||
log::trace!("Settings changed, showing apply button");
|
||||
log::info!("Settings changed, showing apply button");
|
||||
apply_revealer.show();
|
||||
});
|
||||
}
|
||||
@@ -119,12 +121,16 @@ impl App {
|
||||
if thermals_settings.automatic_fan_control_enabled {
|
||||
app.daemon_connection
|
||||
.stop_fan_control(gpu_id)
|
||||
.expect("Failed to top fan control");
|
||||
.expect("Failed to stop fan control");
|
||||
} else {
|
||||
app.daemon_connection
|
||||
.start_fan_control(gpu_id)
|
||||
.expect("Failed to start fan control");
|
||||
}
|
||||
|
||||
app.daemon_connection
|
||||
.set_fan_curve(gpu_id, thermals_settings.curve)
|
||||
.expect("Failed to set fan curve");
|
||||
}
|
||||
|
||||
{
|
||||
@@ -143,8 +149,6 @@ impl App {
|
||||
|
||||
self.start_stats_update_loop(current_gpu_id.clone());
|
||||
|
||||
self.window.show_all();
|
||||
|
||||
Ok(gtk::main())
|
||||
}
|
||||
|
||||
@@ -159,6 +163,7 @@ impl App {
|
||||
.oc_page
|
||||
.set_power_profile(&gpu_info.power_profile);
|
||||
|
||||
log::trace!("Setting fan control info");
|
||||
match self.daemon_connection.get_fan_control(gpu_id) {
|
||||
Ok(fan_control_info) => self
|
||||
.root_stack
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
mod fan_curve_frame;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use daemon::gpu_controller::{FanControlInfo, GpuStats};
|
||||
use gtk::prelude::*;
|
||||
use gtk::*;
|
||||
@@ -8,6 +10,7 @@ use fan_curve_frame::FanCurveFrame;
|
||||
|
||||
pub struct ThermalsSettings {
|
||||
pub automatic_fan_control_enabled: bool,
|
||||
pub curve: BTreeMap<i64, f64>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -94,6 +97,19 @@ impl ThermalsPage {
|
||||
|
||||
container.pack_start(&fan_curve_frame.container, true, true, 5);
|
||||
|
||||
// Show/hide fan curve when the switch is toggled
|
||||
{
|
||||
let fan_curve_frame = fan_curve_frame.clone();
|
||||
fan_control_enabled_switch.connect_changed_active(move |switch| {
|
||||
log::trace!("Fan control switch toggled");
|
||||
if switch.get_active() {
|
||||
fan_curve_frame.hide();
|
||||
} else {
|
||||
fan_curve_frame.show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Self {
|
||||
container,
|
||||
temp_label,
|
||||
@@ -120,36 +136,51 @@ impl ThermalsPage {
|
||||
}
|
||||
|
||||
pub fn set_ventilation_info(&self, fan_control_info: FanControlInfo) {
|
||||
log::info!("Setting fan control info {:?}", fan_control_info);
|
||||
|
||||
self.fan_control_enabled_switch.set_visible(true);
|
||||
self.fan_curve_frame.container.set_visible(true);
|
||||
|
||||
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);
|
||||
|
||||
if !fan_control_info.enabled {
|
||||
self.fan_curve_frame.hide();
|
||||
}
|
||||
|
||||
self.fan_curve_frame.set_curve(&fan_control_info.curve);
|
||||
}
|
||||
|
||||
pub fn connect_settings_changed<F: Fn() + 'static>(&self, f: F) {
|
||||
self.fan_control_enabled_switch
|
||||
.connect_changed_active(move |_| {
|
||||
pub fn connect_settings_changed<F: Fn() + 'static + Clone>(&self, f: F) {
|
||||
// Fan control switch toggled
|
||||
{
|
||||
let f = f.clone();
|
||||
self.fan_control_enabled_switch
|
||||
.connect_changed_active(move |_| {
|
||||
f();
|
||||
});
|
||||
}
|
||||
|
||||
// Fan curve adjusted
|
||||
{
|
||||
let f = f.clone();
|
||||
self.fan_curve_frame.connect_adjusted(move || {
|
||||
f();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_thermals_settings(&self) -> ThermalsSettings {
|
||||
let automatic_fan_control_enabled = self.fan_control_enabled_switch.get_active();
|
||||
let curve = self.fan_curve_frame.get_curve();
|
||||
|
||||
ThermalsSettings {
|
||||
automatic_fan_control_enabled,
|
||||
curve,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn hide_fan_controls(&self) {
|
||||
self.fan_control_enabled_switch.set_visible(false);
|
||||
self.fan_curve_frame.container.set_visible(false);
|
||||
self.fan_curve_frame.hide();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,216 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use gtk::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct FanCurveFrame {
|
||||
pub container: Frame,
|
||||
adjustment_1: Adjustment,
|
||||
adjustment_2: Adjustment,
|
||||
adjustment_3: Adjustment,
|
||||
adjustment_4: Adjustment,
|
||||
adjustment_5: Adjustment,
|
||||
}
|
||||
|
||||
impl FanCurveFrame {
|
||||
pub fn new() -> Self {
|
||||
let container = Frame::new(Some("Fan Curve"));
|
||||
|
||||
container.set_shadow_type(ShadowType::None);
|
||||
container.set_margin_start(10);
|
||||
container.set_margin_end(10);
|
||||
container.set_margin_bottom(10);
|
||||
container.set_margin_top(10);
|
||||
|
||||
Self { container }
|
||||
container.set_label_align(0.35, 0.5);
|
||||
|
||||
// container.set_shadow_type(ShadowType::None);
|
||||
//
|
||||
let root_grid = Grid::new();
|
||||
|
||||
// PWM Percentage Labels
|
||||
{
|
||||
root_grid.attach(
|
||||
&{
|
||||
let label = Label::new(Some("PWM %"));
|
||||
label.set_angle(90.0);
|
||||
label.set_vexpand(true); // This expands the entire top section of the grid, including the scales
|
||||
label
|
||||
},
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
5,
|
||||
);
|
||||
|
||||
root_grid.attach(
|
||||
&{
|
||||
let label = Label::new(Some("0"));
|
||||
label.set_angle(90.0);
|
||||
label
|
||||
},
|
||||
1,
|
||||
4,
|
||||
1,
|
||||
1,
|
||||
);
|
||||
root_grid.attach(
|
||||
&{
|
||||
let label = Label::new(Some("25"));
|
||||
label.set_angle(90.0);
|
||||
label
|
||||
},
|
||||
1,
|
||||
3,
|
||||
1,
|
||||
1,
|
||||
);
|
||||
root_grid.attach(
|
||||
&{
|
||||
let label = Label::new(Some("50"));
|
||||
label.set_angle(90.0);
|
||||
label
|
||||
},
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
);
|
||||
root_grid.attach(
|
||||
&{
|
||||
let label = Label::new(Some("75"));
|
||||
label.set_angle(90.0);
|
||||
label
|
||||
},
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
);
|
||||
root_grid.attach(
|
||||
&{
|
||||
let label = Label::new(Some("100"));
|
||||
label.set_angle(90.0);
|
||||
label
|
||||
},
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
);
|
||||
}
|
||||
|
||||
// Temperature threshold labels
|
||||
{
|
||||
root_grid.attach(
|
||||
&{
|
||||
let label = Label::new(Some("Temperature °C"));
|
||||
label.set_hexpand(true);
|
||||
label
|
||||
},
|
||||
2,
|
||||
7,
|
||||
5,
|
||||
1,
|
||||
);
|
||||
|
||||
root_grid.attach(&Label::new(Some("20")), 2, 6, 1, 1);
|
||||
root_grid.attach(&Label::new(Some("40")), 3, 6, 1, 1);
|
||||
root_grid.attach(&Label::new(Some("60")), 4, 6, 1, 1);
|
||||
root_grid.attach(&Label::new(Some("80")), 5, 6, 1, 1);
|
||||
root_grid.attach(&Label::new(Some("100")), 6, 6, 1, 1);
|
||||
}
|
||||
|
||||
// The actual adjustments
|
||||
let adjustment_1 = Adjustment::new(0.0, 0.0, 100.0, 1.0, 0.0, 0.0); // 20 °C
|
||||
let adjustment_2 = Adjustment::new(0.0, 0.0, 100.0, 1.0, 0.0, 0.0); // 40 °C
|
||||
let adjustment_3 = Adjustment::new(0.0, 0.0, 100.0, 1.0, 0.0, 0.0); // 60 °C
|
||||
let adjustment_4 = Adjustment::new(0.0, 0.0, 100.0, 1.0, 0.0, 0.0); // 80 °C
|
||||
let adjustment_5 = Adjustment::new(0.0, 0.0, 100.0, 1.0, 0.0, 0.0); // 100 °C
|
||||
|
||||
// Scales for the adjustments
|
||||
{
|
||||
let adjustments = [
|
||||
&adjustment_1,
|
||||
&adjustment_2,
|
||||
&adjustment_3,
|
||||
&adjustment_4,
|
||||
&adjustment_5,
|
||||
];
|
||||
|
||||
for i in 0..adjustments.len() {
|
||||
let adj = adjustments[i];
|
||||
|
||||
root_grid.attach(
|
||||
&{
|
||||
let scale = Scale::new(Orientation::Vertical, Some(adj));
|
||||
scale.set_draw_value(false);
|
||||
scale.set_inverted(true);
|
||||
scale
|
||||
},
|
||||
i as i32 + 2,
|
||||
0,
|
||||
1,
|
||||
5,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
container.add(&root_grid);
|
||||
|
||||
Self {
|
||||
container,
|
||||
adjustment_1,
|
||||
adjustment_2,
|
||||
adjustment_3,
|
||||
adjustment_4,
|
||||
adjustment_5,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_curve(&self, curve: &BTreeMap<i64, f64>) {
|
||||
self.adjustment_1.set_value(*curve.get(&20).unwrap());
|
||||
self.adjustment_2.set_value(*curve.get(&40).unwrap());
|
||||
self.adjustment_3.set_value(*curve.get(&60).unwrap());
|
||||
self.adjustment_4.set_value(*curve.get(&80).unwrap());
|
||||
self.adjustment_5.set_value(*curve.get(&100).unwrap());
|
||||
}
|
||||
|
||||
pub fn get_curve(&self) -> BTreeMap<i64, f64> {
|
||||
let mut curve = BTreeMap::new();
|
||||
|
||||
curve.insert(20, self.adjustment_1.get_value());
|
||||
curve.insert(40, self.adjustment_2.get_value());
|
||||
curve.insert(60, self.adjustment_3.get_value());
|
||||
curve.insert(80, self.adjustment_4.get_value());
|
||||
curve.insert(100, self.adjustment_5.get_value());
|
||||
|
||||
curve
|
||||
}
|
||||
|
||||
pub fn show(&self) {
|
||||
log::info!("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");
|
||||
self.container.set_visible(false);
|
||||
}
|
||||
|
||||
pub fn connect_adjusted<F: Fn() + 'static + Clone>(&self, f: F) {
|
||||
let adjustments = [
|
||||
&self.adjustment_1,
|
||||
&self.adjustment_2,
|
||||
&self.adjustment_3,
|
||||
&self.adjustment_4,
|
||||
&self.adjustment_5,
|
||||
];
|
||||
|
||||
for adj in adjustments.iter() {
|
||||
let f = f.clone();
|
||||
adj.connect_value_changed(move |_| {
|
||||
f();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user