use anyhow::{bail, Result};
use auto_cpufreq::battery;
use auto_cpufreq::config::{find_config_file, CONFIG};
use auto_cpufreq::core::*;
use auto_cpufreq::globals::*;
use auto_cpufreq::modules::{SystemMonitor, ViewType};
use auto_cpufreq::power_helper::*;
use std::thread;
use std::time::Duration;
use auto_cpufreq::core::footer;
struct Args {
monitor: bool,
live: bool,
daemon: bool,
install: bool,
update: Option<Option<String>>,
remove: bool,
force: Option<String>,
turbo: Option<String>,
config: Option<String>,
stats: bool,
get_state: bool,
bluetooth_boot_off: bool,
bluetooth_boot_on: bool,
debug: bool,
verbose: bool,
version: bool,
donate: bool,
}
fn parse_args() -> Result<Args> {
let mut pargs = pico_args::Arguments::from_env();
if pargs.contains(["-h", "--help"]) {
print_help();
std::process::exit(0);
}
let args = Args {
monitor: pargs.contains("--monitor"),
live: pargs.contains("--live"),
daemon: pargs.contains("--daemon"),
install: pargs.contains("--install"),
update: if pargs.contains("--update") {
Some(pargs.opt_value_from_str("--update")?)
} else {
None
},
remove: pargs.contains("--remove"),
force: pargs.opt_value_from_str("--force")?,
turbo: pargs.opt_value_from_str("--turbo")?,
config: pargs.opt_value_from_str("--config")?,
stats: pargs.contains("--stats"),
get_state: pargs.contains("--get-state"),
bluetooth_boot_off: pargs.contains("--bluetooth-boot-off"),
bluetooth_boot_on: pargs.contains("--bluetooth-boot-on"),
debug: pargs.contains("--debug"),
verbose: pargs.contains("--verbose") || pargs.contains("-v"),
version: pargs.contains("--version"),
donate: pargs.contains("--donate"),
};
let remaining = pargs.finish();
if !remaining.is_empty() {
bail!(
"Unknown arguments: {:?}",
remaining
);
}
Ok(args)
}
fn print_help() {
println!("Automatic CPU speed & power optimizer for Linux");
println!("Usage: auto-cpufreq [OPTIONS]\n");
println!("Options:");
println!(" --monitor Monitor and see suggestions for CPU optimizations");
println!(" --live Monitor and make (temp.) suggested CPU optimizations");
println!(" --install Install daemon for (permanent) automatic CPU optimizations");
println!(" --update [<PATH>] Update daemon and package");
println!(" --remove Remove daemon");
println!(" --force <GOVERNOR> Force use of either \"powersave\" or \"performance\" governors");
println!(" --turbo <MODE> Force use of CPU turbo mode");
println!(" --config <PATH> Use config file at defined path");
println!(" --stats View live stats of CPU optimizations");
println!(" --bluetooth-boot-off Turn off Bluetooth on boot");
println!(" --bluetooth-boot-on Turn on Bluetooth on boot");
println!(" --debug Show debug info");
println!(" -v, --verbose Show verbose/detailed output (use with --monitor, --live, --stats)");
println!(" --version Show currently installed version");
println!(" --donate Support the project");
println!(" -h, --help Print help");
}
fn has_any_flag(args: &Args) -> bool {
args.monitor
|| args.live
|| args.daemon
|| args.install
|| args.update.is_some()
|| args.remove
|| args.force.is_some()
|| args.turbo.is_some()
|| args.stats
|| args.get_state
|| args.bluetooth_boot_off
|| args.bluetooth_boot_on
|| args.debug
|| args.version
|| args.donate
}
fn main() -> Result<()> {
let args = parse_args()?;
let config_path = find_config_file(args.config.as_deref());
CONFIG.set_path(config_path.clone())?;
fn config_info_dialog() {
if CONFIG.has_config() {
println!(
"\nUsing settings defined in {} file",
CONFIG.get_path().display()
);
}
}
if !has_any_flag(&args) {
println!(
"\n{}\n",
"-".repeat(32) + " auto-cpufreq " + &"-".repeat(33)
);
println!("Automatic CPU speed & power optimizer for Linux");
println!("\nExample usage:\nauto-cpufreq --monitor");
println!("\n-----\n");
return Ok(());
}
if let Some(ref force_val) = args.force {
not_running_daemon_check()?;
root_check()?;
let state = AutoCpuFreqState::new();
set_override(&state, force_val)?;
}
if let Some(ref turbo_val) = args.turbo {
not_running_daemon_check()?;
root_check()?;
let state = AutoCpuFreqState::new();
set_turbo_override(&state, turbo_val)?;
}
if args.monitor {
root_check()?;
battery::battery_setup(&CONFIG)?;
gnome_power_detect().ok();
tlp_service_detect().ok();
if *TLP_STAT_EXISTS || (*SYSTEMCTL_EXISTS && gnome_power_status()?) {
println!("press Enter to continue or Ctrl + C to exit...");
let mut input = String::new();
std::io::stdin().read_line(&mut input)?;
}
let mut monitor = SystemMonitor::new_with_verbose(ViewType::Monitor, true, args.verbose);
monitor.run_blocking();
} else if args.live {
root_check()?;
battery::battery_setup(&CONFIG)?;
gnome_power_detect_install().ok();
gnome_power_stop_live().ok();
tuned_stop_live().ok();
tlp_service_detect().ok();
if *TLP_STAT_EXISTS || (*SYSTEMCTL_EXISTS && gnome_power_status()?) {
println!("press Enter to continue or Ctrl + C to exit...");
let mut input = String::new();
std::io::stdin().read_line(&mut input)?;
}
cpufreqctl()?;
let daemon_handle = thread::spawn(|| {
loop {
thread::sleep(Duration::from_secs(1));
}
});
let mut monitor = SystemMonitor::new_with_verbose(ViewType::Live, false, args.verbose);
monitor.run_blocking();
daemon_handle.join().unwrap();
} else if args.daemon {
config_info_dialog();
root_check()?;
gnome_power_detect()?;
tlp_service_detect()?;
battery::battery_setup(&CONFIG)?;
println!("\n* Starting auto-cpufreq daemon");
println!("* Monitoring system and adjusting CPU frequency...\n");
loop {
footer(79);
if let Err(e) = update_stats_file() {
eprintln!("WARNING: Failed to update stats file: {}", e);
}
cpufreqctl()?;
static FIRST_RUN: std::sync::Once = std::sync::Once::new();
FIRST_RUN.call_once(|| {
let _ = distro_info();
let _ = sysinfo();
});
if let Err(e) = set_autofreq() {
eprintln!("ERROR: Failed to set auto frequency: {}", e);
}
countdown(2);
}
} else if args.install {
root_check()?;
gnome_power_detect()?;
tlp_service_detect()?;
install_daemon()?;
println!("\nauto-cpufreq daemon installed and started");
println!("\nTo view live stats, run:\nauto-cpufreq --stats");
} else if let Some(update_path) = args.update {
root_check()?;
let _custom_dir = update_path.unwrap_or_else(|| "/opt/auto-cpufreq/source".to_string());
if *IS_INSTALLED_WITH_AUR {
println!("\n{}\n", "=".repeat(80));
println!("Arch-based distribution with AUR support detected.");
println!("Please refresh auto-cpufreq using your AUR helper.");
println!("\n{}\n", "=".repeat(80));
} else {
let is_new_update = check_for_update()?;
if !is_new_update {
return Ok(());
}
println!("\nDo you want to update auto-cpufreq to the latest release? [Y/n]: ");
let mut input = String::new();
std::io::stdin().read_line(&mut input)?;
let ans = input.trim().to_lowercase();
if ans.is_empty() || ans == "y" || ans == "yes" {
remove_daemon()?;
println!("\nRe-enabling daemon...");
install_daemon()?;
println!("\nauto-cpufreq is updated to the latest version");
app_version();
} else {
println!("Update aborted");
}
}
} else if args.remove {
root_check()?;
remove_daemon()?;
} else if args.stats {
root_check()?;
not_running_daemon_check()?;
config_info_dialog();
gnome_power_detect()?;
tlp_service_detect()?;
if *TLP_STAT_EXISTS || (*SYSTEMCTL_EXISTS && gnome_power_status()?) {
println!("press Enter to continue or Ctrl + C to exit...");
let mut input = String::new();
std::io::stdin().read_line(&mut input)?;
}
let mut monitor = SystemMonitor::new_with_verbose(ViewType::Stats, false, args.verbose);
monitor.update();
let rows = std::cmp::max(monitor.left.len(), monitor.right.len());
let width = 80usize;
let half = width / 2 - 1;
for i in 0..rows {
let left = monitor.left.get(i).cloned().unwrap_or_default();
let right = monitor.right.get(i).cloned().unwrap_or_default();
println!("{:<half$} │ {}", left, right, half = half);
}
} else if args.get_state {
not_running_daemon_check()?;
let state = AutoCpuFreqState::new();
let override_val = get_override(&state);
println!("{}", override_val.to_str());
} else if args.bluetooth_boot_off {
footer(79);
root_check()?;
bluetooth_disable()?;
footer(79);
} else if args.bluetooth_boot_on {
footer(79);
root_check()?;
bluetooth_enable()?;
footer(79);
} else if args.debug {
config_info_dialog();
root_check()?;
battery::battery_get_thresholds()?;
cpufreqctl()?;
footer(79);
distro_info()?;
sysinfo()?;
println!();
app_version();
println!();
println!(
"Battery is: {}charging",
if charging()? { "" } else { "dis" }
);
println!();
get_load();
print_current_gov();
get_turbo();
footer(79);
} else if args.version {
footer(79);
distro_info()?;
app_version();
footer(79);
} else if args.donate {
footer(79);
println!("If auto-cpufreq helped you out and you find it useful ...\n");
println!("Show your appreciation by donating!");
println!("https://codeberg.org/Zamanhuseyinli/auto-cpufreq-rust#donate");
footer(79);
}
Ok(())
}