diff --git a/README.md b/README.md
index ac2e6cb..744d693 100644
--- a/README.md
+++ b/README.md
@@ -21,11 +21,11 @@ If you're having a problem with auto-cpufreq, before ([submitting an issue](http
Example of auto-cpufreq GUI (available >= v2.0)
-
+
Example of `auto-cpufreq --stats` CLI output
-
+
## Looking for developers and co-maintainers
diff --git a/auto_cpufreq/bin/auto_cpufreq.py b/auto_cpufreq/bin/auto_cpufreq.py
index f37c625..fa7872c 100755
--- a/auto_cpufreq/bin/auto_cpufreq.py
+++ b/auto_cpufreq/bin/auto_cpufreq.py
@@ -12,7 +12,7 @@ from shutil import rmtree
from auto_cpufreq.battery_scripts.battery import *
from auto_cpufreq.config.config import config as conf, find_config_file
from auto_cpufreq.core import *
-from auto_cpufreq.globals import GITHUB, IS_INSTALLED_WITH_AUR, IS_INSTALLED_WITH_SNAP, SNAP_DAEMON_CHECK
+from auto_cpufreq.globals import GITHUB, IS_INSTALLED_WITH_AUR, IS_INSTALLED_WITH_SNAP
from auto_cpufreq.modules.system_monitor import ViewType, SystemMonitor
# import everything from power_helper, including bluetooth_disable and bluetooth_enable
from auto_cpufreq.power_helper import *
@@ -35,9 +35,7 @@ from threading import Thread
@click.option("--version", is_flag=True, help="Show currently installed version")
@click.option("--donate", is_flag=True, help="Support the project")
def main(monitor, live, daemon, install, update, remove, force, config, stats, get_state,
- bluetooth_boot_off,
- bluetooth_boot_on,
- debug, version, donate):
+ bluetooth_boot_off, bluetooth_boot_on, debug, version, donate):
# display info if config file is used
config_path = find_config_file(config)
conf.set_path(config_path)
@@ -45,25 +43,22 @@ def main(monitor, live, daemon, install, update, remove, force, config, stats, g
if conf.has_config():
print("\nUsing settings defined in " + config_path + " file")
- # Check for empty arguments first
- is_empty_run = len(sys.argv) == 1
-
- # set governor override unless None or invalid, but not if it's an empty run
- if not is_empty_run and force is not None:
- not_running_daemon_check()
- root_check()
- set_override(force)
-
- # Handle empty run after potential force override is processed or skipped
- if is_empty_run:
+ if len(sys.argv) == 1:
print("\n" + "-" * 32 + " auto-cpufreq " + "-" * 33 + "\n")
print("Automatic CPU speed & power optimizer for Linux")
+
print("\nExample usage:\nauto-cpufreq --monitor")
print("\n-----\n")
+
run(["auto-cpufreq", "--help"])
footer()
- # Handle other flags if it's not an empty run
else:
+ # set governor override unless None or invalid
+ if force is not None:
+ not_running_daemon_check()
+ root_check() # Calling root_check before set_override as it will require sudo access
+ set_override(force) # Calling set override, only if force has some values
+
if monitor:
root_check()
battery_setup()
@@ -74,22 +69,16 @@ def main(monitor, live, daemon, install, update, remove, force, config, stats, g
else:
gnome_power_detect()
tlp_service_detect()
-
- # Determine if confirmation is needed
- needs_confirmation = IS_INSTALLED_WITH_SNAP or tlp_stat_exists
- # Check gnome_power_status only if relevant variables exist
- if not IS_INSTALLED_WITH_SNAP and 'systemctl_exists' in globals() and systemctl_exists and 'gnome_power_status' in locals() and not bool(gnome_power_status):
- needs_confirmation = True
-
- if needs_confirmation:
+
+ if IS_INSTALLED_WITH_SNAP or tlp_stat_exists or (systemctl_exists and not bool(gnome_power_status)):
try:
input("press Enter to continue or Ctrl + c to exit...")
except KeyboardInterrupt:
conf.notifier.stop()
sys.exit(0)
-
- monitor_instance = SystemMonitor(suggestion=True, type=ViewType.MONITOR)
- monitor_instance.run(on_quit=conf.notifier.stop)
+
+ monitor = SystemMonitor(suggestion=True, type=ViewType.MONITOR)
+ monitor.run(on_quit=conf.notifier.stop)
elif live:
root_check()
battery_setup()
@@ -102,51 +91,44 @@ def main(monitor, live, daemon, install, update, remove, force, config, stats, g
gnome_power_stop_live()
tuned_stop_live()
tlp_service_detect()
-
- # Determine if confirmation is needed
- needs_confirmation = IS_INSTALLED_WITH_SNAP or tlp_stat_exists
- # Check gnome_power_status only if relevant variables exist
- if not IS_INSTALLED_WITH_SNAP and 'systemctl_exists' in globals() and systemctl_exists and 'gnome_power_status' in locals() and not bool(gnome_power_status):
- needs_confirmation = True
-
- if needs_confirmation:
+
+ if IS_INSTALLED_WITH_SNAP or tlp_stat_exists or (systemctl_exists and not bool(gnome_power_status)):
try:
input("press Enter to continue or Ctrl + c to exit...")
except KeyboardInterrupt:
conf.notifier.stop()
sys.exit(0)
-
+
cpufreqctl()
def live_daemon():
+ # Redirect stdout to suppress prints
class NullWriter:
def write(self, _): pass
def flush(self): pass
- original_stdout = sys.stdout
try:
sys.stdout = NullWriter()
+
while True:
time.sleep(1)
set_autofreq()
- except Exception as e: # Catch specific exceptions if possible
- print(f"Error in live daemon thread: {e}", file=original_stdout) # Log errors
- finally:
- sys.stdout = original_stdout # Ensure stdout is restored
-
+ except:
+ pass
+
def live_daemon_off():
gnome_power_start_live()
tuned_start_live()
cpufreqctl_restore()
conf.notifier.stop()
-
+
thread = Thread(target=live_daemon, daemon=True)
thread.start()
-
- monitor_instance = SystemMonitor(type=ViewType.LIVE)
- monitor_instance.run(on_quit=live_daemon_off)
+
+ monitor = SystemMonitor(type=ViewType.LIVE)
+ monitor.run(on_quit=live_daemon_off)
elif daemon:
config_info_dialog()
root_check()
- file_stats() # This function from core.py likely uses the stats paths internally
+ file_stats()
if IS_INSTALLED_WITH_SNAP and SNAP_DAEMON_CHECK == "enabled":
gnome_power_detect_snap()
tlp_service_detect_snap()
@@ -155,142 +137,83 @@ def main(monitor, live, daemon, install, update, remove, force, config, stats, g
tlp_service_detect()
battery_setup()
conf.notifier.start()
- print("Starting auto-cpufreq daemon...") # Add startup message
- try:
- # Initial setup before loop
- gov_check()
- cpufreqctl()
- distro_info() # Show info once on start
- sysinfo() # Show info once on start
- while True:
+ while True:
+ try:
+ footer()
+ gov_check()
+ cpufreqctl()
+ distro_info()
+ sysinfo()
set_autofreq()
- time.sleep(2) # Use simple sleep instead of countdown
- except KeyboardInterrupt:
- print("\nDaemon interrupted. Restoring settings...")
- finally: # Ensure cleanup happens
- conf.notifier.stop()
- cpufreqctl_restore() # Restore system state when daemon stops
- footer()
+ countdown(2)
+ except KeyboardInterrupt: break
+ conf.notifier.stop()
elif install:
root_check()
if IS_INSTALLED_WITH_SNAP:
running_daemon_check()
gnome_power_detect_snap()
tlp_service_detect_snap()
- bluetooth_notif_snap() # Warn about bluetooth boot setting
+ bluetooth_notif_snap()
gov_check()
- run("snapctl set daemon=enabled", shell=True, check=True)
- run("snapctl start --enable auto-cpufreq", shell=True, check=True)
+ run("snapctl set daemon=enabled", shell=True)
+ run("snapctl start --enable auto-cpufreq", shell=True)
else:
running_daemon_check()
gov_check()
- deploy_daemon() # This function from core.py likely uses stats paths
+ deploy_daemon()
deploy_complete_msg()
elif update:
root_check()
custom_dir = "/opt/auto-cpufreq/source"
- update_flag_present = False
- args_to_remove = []
- # Simplified update argument parsing
+ for arg in sys.argv:
+ if arg.startswith("--update="):
+ custom_dir = arg.split("=")[1]
+ sys.argv.remove(arg)
+
if "--update" in sys.argv:
- update_flag_present = True
- args_to_remove.append("--update")
- # Simple check if next arg exists and isn't another flag
- idx = sys.argv.index("--update")
- if idx + 1 < len(sys.argv) and not sys.argv[idx+1].startswith('--'):
- custom_dir = sys.argv[idx+1]
- args_to_remove.append(custom_dir)
+ update = True
+ sys.argv.remove("--update")
+ if len(sys.argv) == 2: custom_dir = sys.argv[1]
+
+ if IS_INSTALLED_WITH_SNAP:
+ print("Detected auto-cpufreq was installed using snap")
+ # refresh snap directly using this command
+ # path wont work in this case
+
+ print("Please update using snap package manager, i.e: `sudo snap refresh auto-cpufreq`.")
+ #check for AUR
+ elif IS_INSTALLED_WITH_AUR: print("Arch-based distribution with AUR support detected. Please refresh auto-cpufreq using your AUR helper.")
else:
- for arg in sys.argv:
- if arg.startswith("--update="):
- update_flag_present = True
- custom_dir = arg.split("=", 1)[1]
- args_to_remove.append(arg)
- break # Found it, no need to check further
-
- # Remove the parsed arguments
- # This prevents them from being misinterpreted later if code relies on sys.argv directly
- _original_argv = sys.argv[:] # Make a copy if needed elsewhere
- sys.argv = [arg for arg in sys.argv if arg not in args_to_remove]
-
-
- if update_flag_present:
- if IS_INSTALLED_WITH_SNAP:
- print("Detected auto-cpufreq was installed using snap")
- print("Please update using snap package manager, i.e: `sudo snap refresh auto-cpufreq`.")
- elif IS_INSTALLED_WITH_AUR:
- print("Arch-based distribution with AUR support detected. Please refresh auto-cpufreq using your AUR helper.")
- else:
- is_new_update = check_for_update()
- if not is_new_update: return
- ans = input(f"Update source will be placed in '{custom_dir}'.\nDo you want to update auto-cpufreq to the latest release? [Y/n]: ").strip().lower()
-
- if ans in ['', 'y', 'yes']:
- # Ensure directory exists
- os.makedirs(custom_dir, exist_ok=True)
- auto_cpufreq_subdir = os.path.join(custom_dir, "auto-cpufreq")
- if os.path.isdir(auto_cpufreq_subdir):
- print(f"Removing existing source sub-directory: {auto_cpufreq_subdir}")
- try:
- rmtree(auto_cpufreq_subdir)
- except OSError as e:
- print(f"Error removing directory {auto_cpufreq_subdir}: {e}")
- print("Update aborted.")
- return # Stop update if cleanup fails
-
- print("Removing existing installation (if any)...")
- remove_daemon() # Call remove logic first
- # remove_complete_msg() # Optional message
- print(f"Downloading new version to {custom_dir}...")
- new_update(custom_dir) # Download the update
- print("Running installer for the updated version...")
- # Use subprocess.run to call the install command of the main script
- install_result = run([_original_argv[0], "--install"], check=False) # Use original script path
- if install_result.returncode == 0:
- print("\nUpdate and installation successful.")
- run([_original_argv[0], "--version"])
- else:
- print("\nError during installation after update. Please check messages above.")
- else:
- print("Update aborted.")
- # else: # If neither --update nor --update= was found
- # Potentially show help or an error if update was expected
- # print("Update command not used correctly.")
- # run([_original_argv[0], "--help"])
-
+ is_new_update = check_for_update()
+ if not is_new_update: return
+ ans = input("Do you want to update auto-cpufreq to the latest release? [Y/n]: ").strip().lower()
+ if not os.path.exists(custom_dir): os.makedirs(custom_dir)
+ if os.path.exists(os.path.join(custom_dir, "auto-cpufreq")): rmtree(os.path.join(custom_dir, "auto-cpufreq"))
+ if ans in ['', 'y', 'yes']:
+ remove_daemon()
+ remove_complete_msg()
+ new_update(custom_dir)
+ print("enabling daemon")
+ run(["auto-cpufreq", "--install"])
+ print("auto-cpufreq is installed with the latest version")
+ run(["auto-cpufreq", "--version"])
+ else: print("Aborted")
elif remove:
root_check()
if IS_INSTALLED_WITH_SNAP:
- run("snapctl stop auto-cpufreq", shell=True, check=False)
- run("snapctl set daemon=disabled", shell=True, check=True)
- # run("snapctl disable auto-cpufreq", shell=True, check=True) # Deprecated? Use stop --disable
- run("snapctl stop --disable auto-cpufreq", shell=True, check=True) # Correct way to stop and disable
+ run("snapctl set daemon=disabled", shell=True)
+ run("snapctl stop --disable auto-cpufreq", shell=True)
+ if auto_cpufreq_stats_path.exists():
+ if auto_cpufreq_stats_file is not None:
+ auto_cpufreq_stats_file.close()
- # Check if stats path/file variables exist before using them
- # These should be available from 'from auto_cpufreq.core import *'
- if 'auto_cpufreq_stats_path' in globals() and auto_cpufreq_stats_path.exists():
- # Close file handle safely
- if 'auto_cpufreq_stats_file' in globals() and auto_cpufreq_stats_file is not None:
- if not auto_cpufreq_stats_file.closed:
- try:
- auto_cpufreq_stats_file.close()
- except Exception as e:
- print(f"Warning: Could not close stats file handle: {e}")
- # Set to None after closing or if already closed
- # auto_cpufreq_stats_file = None # Modifying imported var might be tricky
-
- # Remove the file
- try:
- auto_cpufreq_stats_path.unlink()
- print(f"Removed stats file: {auto_cpufreq_stats_path}")
- except OSError as e:
- print(f"Warning: Could not remove stats file {auto_cpufreq_stats_path}: {e}")
-
- # Reminders
+ auto_cpufreq_stats_path.unlink()
+ # ToDo:
+ # {the following snippet also used in --update, update it there too(if required)}
+ # * undo bluetooth boot disable
gnome_power_rm_reminder_snap()
- bluetooth_on_notif_snap()
- else:
- remove_daemon() # Defined in core.py, handles service removal and cleanup including stats file
+ else: remove_daemon()
remove_complete_msg()
elif stats:
not_running_daemon_check()
@@ -301,27 +224,20 @@ def main(monitor, live, daemon, install, update, remove, force, config, stats, g
else:
gnome_power_detect()
tlp_service_detect()
-
- # Determine if confirmation is needed
- needs_confirmation = IS_INSTALLED_WITH_SNAP or tlp_stat_exists
- # Check gnome_power_status only if relevant variables exist
- if not IS_INSTALLED_WITH_SNAP and 'systemctl_exists' in globals() and systemctl_exists and 'gnome_power_status' in locals() and not bool(gnome_power_status):
- needs_confirmation = True
-
- if needs_confirmation:
+
+ if IS_INSTALLED_WITH_SNAP or tlp_stat_exists or (systemctl_exists and not bool(gnome_power_status)):
try:
input("press Enter to continue or Ctrl + c to exit...")
except KeyboardInterrupt:
- # conf.notifier might not be started for stats mode
+ conf.notifier.stop()
sys.exit(0)
-
- monitor_instance = SystemMonitor(type=ViewType.STATS)
- monitor_instance.run()
+
+ monitor = SystemMonitor(type=ViewType.STATS)
+ monitor.run()
elif get_state:
not_running_daemon_check()
override = get_override()
print(override)
-
elif bluetooth_boot_off:
if IS_INSTALLED_WITH_SNAP:
footer()
@@ -343,6 +259,7 @@ def main(monitor, live, daemon, install, update, remove, force, config, stats, g
bluetooth_enable()
footer()
elif debug:
+ # ToDo: add status of GNOME Power Profile service status
config_info_dialog()
root_check()
battery_get_thresholds()
@@ -356,11 +273,7 @@ def main(monitor, live, daemon, install, update, remove, force, config, stats, g
python_info()
print()
device_info()
- # Check charging status function exists and call it
- if 'charging' in globals() and callable(charging):
- print(f"Battery is: {'' if charging() else 'dis'}charging")
- else:
- print("Battery status unavailable.")
+ print(f"Battery is: {'' if charging() else 'dis'}charging")
print()
app_res_use()
get_load()
@@ -378,16 +291,5 @@ def main(monitor, live, daemon, install, update, remove, force, config, stats, g
print("Show your appreciation by donating!")
print(GITHUB+"#donate")
footer()
- # else: # Optional: Handle unrecognized flags if not caught by click
- # print(f"Error: Unrecognized arguments.")
- # run([_original_argv[0], "--help"])
-
-
-if __name__ == "__main__":
- try:
- import click
- except ImportError:
- print("Error: Required dependency 'click' not found. Please install it (e.g., pip install click)")
- sys.exit(1)
- # Call main entry point
- main()
\ No newline at end of file
+
+if __name__ == "__main__": main()
\ No newline at end of file