use anyhow::Result;
use clap::Parser;
use auto_cpufreq::config::{CONFIG, find_config_file};
use auto_cpufreq::core::*;
use auto_cpufreq::globals::*;
use auto_cpufreq::power_helper::*;
use auto_cpufreq::battery;
use auto_cpufreq::modules::{SystemMonitor, ViewType};
use std::thread;
use std::time::Duration;
use auto_cpufreq::core::footer;
#[derive(Parser, Debug)]
#[command(name = "auto-cpufreq")]
#[command(about = "Automatic CPU speed & power optimizer for Linux", long_about = None)]
struct Args {
#[arg(long)]
monitor: bool,
#[arg(long)]
live: bool,
#[arg(long, hide = true)]
daemon: bool,
#[arg(long)]
install: bool,
#[arg(long, value_name = "PATH")]
update: Option<Option<String>>,
#[arg(long)]
remove: bool,
#[arg(long, value_name = "GOVERNOR")]
force: Option<String>,
#[arg(long, value_name = "MODE")]
turbo: Option<String>,
#[arg(long, value_name = "PATH")]
config: Option<String>,
#[arg(long)]
stats: bool,
#[arg(long, hide = true)]
get_state: bool,
#[arg(long)]
bluetooth_boot_off: bool,
#[arg(long)]
bluetooth_boot_on: bool,
#[arg(long)]
debug: bool,
#[arg(long, short)]
verbose: bool,
#[arg(long)]
version: bool,
#[arg(long)]
donate: bool,
}
fn main() -> Result<()> {
let args = Args::parse();
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://github.com/Zamanhuseyinli/auto-cpufreq#donate");
footer(79);
}
Ok(())
}
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
}