mirror of
https://github.com/ilya-zlobintsev/LACT.git
synced 2025-02-25 18:55:26 -06:00
Merge branch 'oc' into master
This commit is contained in:
commit
bcbb87e74c
@ -148,6 +148,22 @@ impl DaemonConnection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_power_cap(&self, gpu_id: u32, cap: i32) -> Result<(), DaemonError> {
|
||||||
|
let mut s = UnixStream::connect(SOCK_PATH).unwrap();
|
||||||
|
s.write_all(&bincode::serialize(&Action::SetPowerCap(gpu_id, cap)).unwrap())
|
||||||
|
.unwrap();
|
||||||
|
s.shutdown(std::net::Shutdown::Write).expect("Could not shut down");
|
||||||
|
let mut buffer = Vec::<u8>::new();
|
||||||
|
s.read_to_end(&mut buffer).unwrap();
|
||||||
|
|
||||||
|
let result: Result<DaemonResponse, DaemonError> = bincode::deserialize(&buffer).unwrap();
|
||||||
|
|
||||||
|
match result {
|
||||||
|
Ok(_) => Ok(()),
|
||||||
|
Err(e) => Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_gpus(&self) -> Result<HashMap<u32, String>, DaemonError> {
|
pub fn get_gpus(&self) -> Result<HashMap<u32, String>, DaemonError> {
|
||||||
log::trace!("sending request");
|
log::trace!("sending request");
|
||||||
let mut s = UnixStream::connect(SOCK_PATH).unwrap();
|
let mut s = UnixStream::connect(SOCK_PATH).unwrap();
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::config::{Config, GpuConfig, GpuIdentifier};
|
use crate::config::{GpuConfig, GpuIdentifier};
|
||||||
use crate::hw_mon::{HWMon, HWMonError};
|
use crate::hw_mon::{HWMon, HWMonError};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
@ -13,7 +13,8 @@ pub struct GpuStats {
|
|||||||
pub gpu_freq: i32,
|
pub gpu_freq: i32,
|
||||||
pub gpu_temp: i32,
|
pub gpu_temp: i32,
|
||||||
pub power_avg: i32,
|
pub power_avg: i32,
|
||||||
pub power_max: i32,
|
pub power_cap: i32,
|
||||||
|
pub power_cap_max: i32,
|
||||||
pub fan_speed: i32,
|
pub fan_speed: i32,
|
||||||
pub max_fan_speed: i32,
|
pub max_fan_speed: i32,
|
||||||
}
|
}
|
||||||
@ -54,6 +55,8 @@ pub struct GpuInfo {
|
|||||||
pub link_width: u8,
|
pub link_width: u8,
|
||||||
pub vulkan_info: VulkanInfo,
|
pub vulkan_info: VulkanInfo,
|
||||||
pub pci_slot: String,
|
pub pci_slot: String,
|
||||||
|
pub power_cap: i32,
|
||||||
|
pub power_cap_max: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GpuController {
|
impl GpuController {
|
||||||
@ -210,6 +213,11 @@ impl GpuController {
|
|||||||
|
|
||||||
let vulkan_info = GpuController::get_vulkan_info(&model_id);
|
let vulkan_info = GpuController::get_vulkan_info(&model_id);
|
||||||
|
|
||||||
|
let (power_cap, power_cap_max) = match &self.hw_mon {
|
||||||
|
Some(hw_mon) => (hw_mon.get_power_cap(), hw_mon.get_power_cap_max()),
|
||||||
|
None => (0, 0),
|
||||||
|
};
|
||||||
|
|
||||||
GpuInfo {
|
GpuInfo {
|
||||||
gpu_vendor: vendor,
|
gpu_vendor: vendor,
|
||||||
gpu_model: model,
|
gpu_model: model,
|
||||||
@ -224,6 +232,8 @@ impl GpuController {
|
|||||||
link_width,
|
link_width,
|
||||||
vulkan_info,
|
vulkan_info,
|
||||||
pci_slot,
|
pci_slot,
|
||||||
|
power_cap,
|
||||||
|
power_cap_max,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,9 +248,9 @@ impl GpuController {
|
|||||||
Err(_) => 0,
|
Err(_) => 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
let (mem_freq, gpu_freq, gpu_temp, power_avg, power_max, fan_speed, max_fan_speed) = match &self.hw_mon {
|
let (mem_freq, gpu_freq, gpu_temp, power_avg, power_cap, power_cap_max, fan_speed, max_fan_speed) = match &self.hw_mon {
|
||||||
Some(hw_mon) => (hw_mon.get_mem_freq(), hw_mon.get_gpu_freq(), hw_mon.get_gpu_temp(), hw_mon.get_power_avg(), hw_mon.get_power_cap(), hw_mon.get_fan_speed(), hw_mon.fan_max_speed),
|
Some(hw_mon) => (hw_mon.get_mem_freq(), hw_mon.get_gpu_freq(), hw_mon.get_gpu_temp(), hw_mon.get_power_avg(), hw_mon.get_power_cap(), hw_mon.get_power_cap_max(), hw_mon.get_fan_speed(), hw_mon.fan_max_speed),
|
||||||
None => (0, 0, 0, 0, 0, 0, 0),
|
None => (0, 0, 0, 0, 0, 0, 0, 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
GpuStats {
|
GpuStats {
|
||||||
@ -250,7 +260,8 @@ impl GpuController {
|
|||||||
gpu_freq,
|
gpu_freq,
|
||||||
gpu_temp,
|
gpu_temp,
|
||||||
power_avg,
|
power_avg,
|
||||||
power_max,
|
power_cap,
|
||||||
|
power_cap_max,
|
||||||
fan_speed,
|
fan_speed,
|
||||||
max_fan_speed,
|
max_fan_speed,
|
||||||
}
|
}
|
||||||
@ -312,6 +323,17 @@ impl GpuController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_power_cap(&mut self, cap: i32) -> Result<(), HWMonError> {
|
||||||
|
match &mut self.hw_mon {
|
||||||
|
Some(hw_mon) => {
|
||||||
|
hw_mon.set_power_cap(cap).unwrap();
|
||||||
|
self.gpu_info.power_cap = cap;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
None => Err(HWMonError::NoHWMon),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn get_vulkan_info(pci_id: &str) -> VulkanInfo {
|
fn get_vulkan_info(pci_id: &str) -> VulkanInfo {
|
||||||
let mut device_name = String::from("Not supported");
|
let mut device_name = String::from("Not supported");
|
||||||
let mut api_version = String::new();
|
let mut api_version = String::new();
|
||||||
|
@ -15,6 +15,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
pub enum HWMonError {
|
pub enum HWMonError {
|
||||||
PermissionDenied,
|
PermissionDenied,
|
||||||
|
InvalidValue,
|
||||||
NoHWMon,
|
NoHWMon,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,6 +25,7 @@ pub struct HWMon {
|
|||||||
pub fan_max_speed: i32,
|
pub fan_max_speed: i32,
|
||||||
fan_control: Arc<AtomicBool>,
|
fan_control: Arc<AtomicBool>,
|
||||||
fan_curve: Arc<RwLock<BTreeMap<i32, f64>>>,
|
fan_curve: Arc<RwLock<BTreeMap<i32, f64>>>,
|
||||||
|
power_cap: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HWMon {
|
impl HWMon {
|
||||||
@ -37,16 +39,18 @@ impl HWMon {
|
|||||||
Err(_) => 0,
|
Err(_) => 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mon = HWMon {
|
let mut mon = HWMon {
|
||||||
hwmon_path: hwmon_path.clone(),
|
hwmon_path: hwmon_path.clone(),
|
||||||
fan_max_speed,
|
fan_max_speed,
|
||||||
fan_control: Arc::new(AtomicBool::new(false)),
|
fan_control: Arc::new(AtomicBool::new(false)),
|
||||||
fan_curve: Arc::new(RwLock::new(fan_curve)),
|
fan_curve: Arc::new(RwLock::new(fan_curve)),
|
||||||
|
power_cap: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
if fan_control_enabled {
|
if fan_control_enabled {
|
||||||
mon.start_fan_control().unwrap();
|
mon.start_fan_control().unwrap();
|
||||||
}
|
}
|
||||||
|
mon.power_cap = mon.get_power_cap();
|
||||||
|
|
||||||
mon
|
mon
|
||||||
}
|
}
|
||||||
@ -115,6 +119,19 @@ impl HWMon {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_power_cap_max(&self) -> i32 {
|
||||||
|
let filename = self.hwmon_path.join("power1_cap_max");
|
||||||
|
|
||||||
|
match fs::read_to_string(filename) {
|
||||||
|
Ok(a) => a
|
||||||
|
.trim()
|
||||||
|
.parse::<i32>()
|
||||||
|
.unwrap()
|
||||||
|
/ 1000000,
|
||||||
|
_ => 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_power_cap(&self) -> i32 {
|
pub fn get_power_cap(&self) -> i32 {
|
||||||
let filename = self.hwmon_path.join("power1_cap");
|
let filename = self.hwmon_path.join("power1_cap");
|
||||||
|
|
||||||
@ -128,6 +145,24 @@ impl HWMon {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_power_cap(&mut self, cap: i32) -> Result<(), HWMonError> {
|
||||||
|
|
||||||
|
if cap > self.get_power_cap_max() {
|
||||||
|
return Err(HWMonError::InvalidValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
let cap = cap * 1000000;
|
||||||
|
log::trace!("setting power cap to {}", cap);
|
||||||
|
|
||||||
|
match fs::write(self.hwmon_path.join("power1_cap"), cap.to_string()) {
|
||||||
|
Ok(_) => {
|
||||||
|
self.power_cap = cap;
|
||||||
|
Ok(())
|
||||||
|
},
|
||||||
|
Err(_) => Err(HWMonError::PermissionDenied),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_power_avg(&self) -> i32 {
|
pub fn get_power_avg(&self) -> i32 {
|
||||||
let filename = self.hwmon_path.join("power1_average");
|
let filename = self.hwmon_path.join("power1_average");
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ pub mod daemon_connection;
|
|||||||
pub mod gpu_controller;
|
pub mod gpu_controller;
|
||||||
pub mod hw_mon;
|
pub mod hw_mon;
|
||||||
|
|
||||||
use config::{Config, GpuConfig, GpuIdentifier};
|
use config::{Config, GpuConfig};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{collections::{BTreeMap, HashMap}, fs};
|
use std::{collections::{BTreeMap, HashMap}, fs};
|
||||||
use std::os::unix::net::{UnixListener, UnixStream};
|
use std::os::unix::net::{UnixListener, UnixStream};
|
||||||
@ -35,6 +35,7 @@ pub enum Action {
|
|||||||
StopFanControl(u32),
|
StopFanControl(u32),
|
||||||
GetFanControl(u32),
|
GetFanControl(u32),
|
||||||
SetFanCurve(u32, BTreeMap<i32, f64>),
|
SetFanCurve(u32, BTreeMap<i32, f64>),
|
||||||
|
SetPowerCap(u32, i32),
|
||||||
Shutdown,
|
Shutdown,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -192,9 +193,6 @@ impl Daemon {
|
|||||||
Action::SetFanCurve(i, curve) => match self.gpu_controllers.get_mut(&i) {
|
Action::SetFanCurve(i, curve) => match self.gpu_controllers.get_mut(&i) {
|
||||||
Some(controller) => {
|
Some(controller) => {
|
||||||
|
|
||||||
let mut buffer = Vec::new();
|
|
||||||
stream.read_to_end(&mut buffer).unwrap();
|
|
||||||
|
|
||||||
match controller.set_fan_curve(curve) {
|
match controller.set_fan_curve(curve) {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
self.config.gpu_configs.insert(i, (controller.get_identifier(), controller.get_config()));
|
self.config.gpu_configs.insert(i, (controller.get_identifier(), controller.get_config()));
|
||||||
@ -207,6 +205,17 @@ impl Daemon {
|
|||||||
},
|
},
|
||||||
None => Err(DaemonError::InvalidID),
|
None => Err(DaemonError::InvalidID),
|
||||||
}
|
}
|
||||||
|
Action::SetPowerCap(i, cap) => match self.gpu_controllers.get_mut(&i) {
|
||||||
|
Some(controller) => {
|
||||||
|
match controller.set_power_cap(cap) {
|
||||||
|
Ok(_) => {
|
||||||
|
Ok(DaemonResponse::OK)
|
||||||
|
},
|
||||||
|
Err(_) => Err(DaemonError::HWMonError),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => Err(DaemonError::InvalidID),
|
||||||
|
}
|
||||||
Action::Shutdown => std::process::exit(0),
|
Action::Shutdown => std::process::exit(0),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -40,6 +40,8 @@ fn build_ui(application: >k::Application) {
|
|||||||
|
|
||||||
let fan_speed_text_buffer: TextBuffer = builder.get_object("fan_speed_text_buffer").unwrap();
|
let fan_speed_text_buffer: TextBuffer = builder.get_object("fan_speed_text_buffer").unwrap();
|
||||||
|
|
||||||
|
let power_cap_label: Label = builder.get_object("power_cap_label").unwrap();
|
||||||
|
|
||||||
let automatic_fan_control_switch: Switch =
|
let automatic_fan_control_switch: Switch =
|
||||||
builder.get_object("automatic_fan_control_switch").unwrap();
|
builder.get_object("automatic_fan_control_switch").unwrap();
|
||||||
|
|
||||||
@ -47,6 +49,8 @@ fn build_ui(application: >k::Application) {
|
|||||||
|
|
||||||
let fan_curve_frame: Frame = builder.get_object("fan_curve_frame").unwrap();
|
let fan_curve_frame: Frame = builder.get_object("fan_curve_frame").unwrap();
|
||||||
|
|
||||||
|
let gpu_power_adjustment: Adjustment = builder.get_object("gpu_power_adjustment").unwrap();
|
||||||
|
|
||||||
let mut unpriviliged: bool = false;
|
let mut unpriviliged: bool = false;
|
||||||
|
|
||||||
let d = match DaemonConnection::new() {
|
let d = match DaemonConnection::new() {
|
||||||
@ -94,8 +98,15 @@ fn build_ui(application: >k::Application) {
|
|||||||
|
|
||||||
let fan_curv_frm = fan_curve_frame.clone();
|
let fan_curv_frm = fan_curve_frame.clone();
|
||||||
let auto_fan_ctrl_swtch = automatic_fan_control_switch.clone();
|
let auto_fan_ctrl_swtch = automatic_fan_control_switch.clone();
|
||||||
let b = apply_button.clone();
|
|
||||||
|
|
||||||
|
let b = apply_button.clone();
|
||||||
|
gpu_power_adjustment.connect_value_changed(move |adjustment| {
|
||||||
|
println!("changed adjustment value to {}/{}", adjustment.get_value(), adjustment.get_upper());
|
||||||
|
b.set_sensitive(true);
|
||||||
|
power_cap_label.set_text(&format!("{}/{}", adjustment.get_value().floor(), adjustment.get_upper()));
|
||||||
|
});
|
||||||
|
|
||||||
|
let b = apply_button.clone();
|
||||||
gpu_select_comboboxtext.connect_changed(move |combobox| {
|
gpu_select_comboboxtext.connect_changed(move |combobox| {
|
||||||
let mut current_gpu_id = cur_id.write().unwrap();
|
let mut current_gpu_id = cur_id.write().unwrap();
|
||||||
*current_gpu_id = combobox.get_active_id().unwrap().parse::<u32>().expect("invalid id");
|
*current_gpu_id = combobox.get_active_id().unwrap().parse::<u32>().expect("invalid id");
|
||||||
@ -166,7 +177,7 @@ fn build_ui(application: >k::Application) {
|
|||||||
gpu_temp_text_buffer.set_text(&format!("{}°C", gpu_stats.gpu_temp));
|
gpu_temp_text_buffer.set_text(&format!("{}°C", gpu_stats.gpu_temp));
|
||||||
|
|
||||||
gpu_power_text_buffer
|
gpu_power_text_buffer
|
||||||
.set_text(&format!("{}/{}W", gpu_stats.power_avg, gpu_stats.power_max));
|
.set_text(&format!("{}/{}W", gpu_stats.power_avg, gpu_stats.power_cap));
|
||||||
|
|
||||||
fan_speed_text_buffer.set_text(&format!(
|
fan_speed_text_buffer.set_text(&format!(
|
||||||
"{}RPM({}%)",
|
"{}RPM({}%)",
|
||||||
@ -174,6 +185,7 @@ fn build_ui(application: >k::Application) {
|
|||||||
(gpu_stats.fan_speed as f64 / gpu_stats.max_fan_speed as f64 * 100 as f64) as i32
|
(gpu_stats.fan_speed as f64 / gpu_stats.max_fan_speed as f64 * 100 as f64) as i32
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
||||||
glib::Continue(true)
|
glib::Continue(true)
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -268,6 +280,9 @@ fn build_ui(application: >k::Application) {
|
|||||||
d.start_fan_control(current_gpu_id).unwrap();
|
d.start_fan_control(current_gpu_id).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let power_cap = gpu_power_adjustment.get_value().floor() as i32;
|
||||||
|
d.set_power_cap(current_gpu_id, power_cap).unwrap();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
Err(_) => (),
|
Err(_) => (),
|
||||||
@ -316,6 +331,11 @@ fn set_info(builder: &Builder, gpu_info: &GpuInfo) {
|
|||||||
.get_object("vulkan_features_text_buffer")
|
.get_object("vulkan_features_text_buffer")
|
||||||
.expect("Couldn't get textbuffer");
|
.expect("Couldn't get textbuffer");
|
||||||
|
|
||||||
|
let power_cap_label: Label = builder.get_object("power_cap_label").unwrap();
|
||||||
|
|
||||||
|
let gpu_power_adjustment: Adjustment = builder.get_object("gpu_power_adjustment").unwrap();
|
||||||
|
//let power_cap_scale: Scale = builder.get_object("power_cap_scale").unwrap();
|
||||||
|
|
||||||
gpu_model_text_buffer.set_text(&gpu_info.card_model);
|
gpu_model_text_buffer.set_text(&gpu_info.card_model);
|
||||||
manufacturer_text_buffer.set_text(&gpu_info.card_vendor);
|
manufacturer_text_buffer.set_text(&gpu_info.card_vendor);
|
||||||
vbios_version_text_buffer.set_text(&gpu_info.vbios_version);
|
vbios_version_text_buffer.set_text(&gpu_info.vbios_version);
|
||||||
@ -330,6 +350,10 @@ fn set_info(builder: &Builder, gpu_info: &GpuInfo) {
|
|||||||
vulkan_version_text_buffer.set_text(&gpu_info.vulkan_info.api_version);
|
vulkan_version_text_buffer.set_text(&gpu_info.vulkan_info.api_version);
|
||||||
vulkan_features_text_buffer.set_text(&gpu_info.vulkan_info.features);
|
vulkan_features_text_buffer.set_text(&gpu_info.vulkan_info.features);
|
||||||
|
|
||||||
|
power_cap_label.set_text(&format!("{}/{}", gpu_info.power_cap, gpu_info.power_cap_max));
|
||||||
|
gpu_power_adjustment.set_upper(gpu_info.power_cap_max as f64);
|
||||||
|
gpu_power_adjustment.set_value(gpu_info.power_cap as f64);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
@ -39,6 +39,11 @@
|
|||||||
<object class="GtkTextBuffer" id="gpu_model_text_buffer">
|
<object class="GtkTextBuffer" id="gpu_model_text_buffer">
|
||||||
<property name="text">gpu_model</property>
|
<property name="text">gpu_model</property>
|
||||||
</object>
|
</object>
|
||||||
|
<object class="GtkAdjustment" id="gpu_power_adjustment">
|
||||||
|
<property name="upper">100</property>
|
||||||
|
<property name="step-increment">1</property>
|
||||||
|
<property name="page-increment">10</property>
|
||||||
|
</object>
|
||||||
<object class="GtkTextBuffer" id="gpu_power_text_buffer">
|
<object class="GtkTextBuffer" id="gpu_power_text_buffer">
|
||||||
<property name="text" translatable="yes">50W/100W</property>
|
<property name="text" translatable="yes">50W/100W</property>
|
||||||
</object>
|
</object>
|
||||||
@ -65,6 +70,9 @@
|
|||||||
<object class="GtkTextBuffer" id="manufacturer_text_buffer">
|
<object class="GtkTextBuffer" id="manufacturer_text_buffer">
|
||||||
<property name="text" translatable="yes">Manufacturer</property>
|
<property name="text" translatable="yes">Manufacturer</property>
|
||||||
</object>
|
</object>
|
||||||
|
<object class="GtkTextBuffer" id="power_cap_text_buffer">
|
||||||
|
<property name="text" translatable="yes">50/100</property>
|
||||||
|
</object>
|
||||||
<object class="GtkTextBuffer" id="vbios_version_text_buffer">
|
<object class="GtkTextBuffer" id="vbios_version_text_buffer">
|
||||||
<property name="text" translatable="yes">vbios_version</property>
|
<property name="text" translatable="yes">vbios_version</property>
|
||||||
</object>
|
</object>
|
||||||
@ -85,6 +93,7 @@
|
|||||||
</object>
|
</object>
|
||||||
<object class="GtkWindow" id="main_window">
|
<object class="GtkWindow" id="main_window">
|
||||||
<property name="can-focus">False</property>
|
<property name="can-focus">False</property>
|
||||||
|
<property name="title" translatable="yes">LACT</property>
|
||||||
<property name="default-width">350</property>
|
<property name="default-width">350</property>
|
||||||
<property name="default-height">500</property>
|
<property name="default-height">500</property>
|
||||||
<child>
|
<child>
|
||||||
@ -672,6 +681,68 @@
|
|||||||
<property name="position">1</property>
|
<property name="position">1</property>
|
||||||
</packing>
|
</packing>
|
||||||
</child>
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkFrame">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="label-xalign">0.10000000149011612</property>
|
||||||
|
<property name="shadow-type">none</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkBox">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="margin-start">10</property>
|
||||||
|
<property name="margin-end">10</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="power_cap_label">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="label" translatable="yes">50/100</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkScale" id="power_cap_scale">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
<property name="hexpand">True</property>
|
||||||
|
<property name="adjustment">gpu_power_adjustment</property>
|
||||||
|
<property name="restrict-to-fill-level">False</property>
|
||||||
|
<property name="fill-level">0</property>
|
||||||
|
<property name="round-digits">0</property>
|
||||||
|
<property name="digits">0</property>
|
||||||
|
<property name="draw-value">False</property>
|
||||||
|
<property name="value-pos">left</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child type="label">
|
||||||
|
<object class="GtkLabel">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="label" translatable="yes">Power Cap (Watts)</property>
|
||||||
|
<attributes>
|
||||||
|
<attribute name="weight" value="semibold"/>
|
||||||
|
</attributes>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">2</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
</object>
|
</object>
|
||||||
<packing>
|
<packing>
|
||||||
<property name="position">1</property>
|
<property name="position">1</property>
|
||||||
|
Loading…
Reference in New Issue
Block a user