Implement fan curve

This commit is contained in:
Ilya Zlobintsev
2021-02-10 16:55:05 +02:00
parent dbd8f5e0d3
commit 6d5555d267
3 changed files with 254 additions and 18 deletions

View File

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

View File

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

View File

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