Add tray controls for pause reload and diagnostics

This commit is contained in:
Thales Maciel 2026-02-26 17:42:53 -03:00
parent 77ae21d0f6
commit e262b26db7
5 changed files with 192 additions and 8 deletions

View file

@ -63,6 +63,7 @@ class Daemon:
self.verbose = verbose
self.lock = threading.Lock()
self._shutdown_requested = threading.Event()
self._paused = False
self.state = State.IDLE
self.stream = None
self.record = None
@ -108,6 +109,24 @@ class Daemon:
def request_shutdown(self):
self._shutdown_requested.set()
def is_paused(self) -> bool:
with self.lock:
return self._paused
def toggle_paused(self) -> bool:
with self.lock:
self._paused = not self._paused
paused = self._paused
logging.info("pause %s", "enabled" if paused else "disabled")
return paused
def apply_config(self, cfg: Config) -> None:
with self.lock:
self.cfg = cfg
self.vocabulary = VocabularyEngine(cfg.vocabulary)
self._stt_hint_kwargs_cache = None
logging.info("applied new runtime config")
def toggle(self):
should_stop = False
with self.lock:
@ -115,6 +134,9 @@ class Daemon:
logging.info("shutdown in progress, trigger ignored")
return
if self.state == State.IDLE:
if self._paused:
logging.info("paused, trigger ignored")
return
self._start_recording_locked()
return
if self.state == State.RECORDING:
@ -447,9 +469,10 @@ def _init_command(args: argparse.Namespace) -> int:
def _run_command(args: argparse.Namespace) -> int:
global _LOCK_HANDLE
config_path = Path(args.config) if args.config else DEFAULT_CONFIG_PATH
try:
cfg = load(args.config)
cfg = load(str(config_path))
except ConfigValidationError as exc:
logging.error("startup failed: invalid config field '%s': %s", exc.field, exc.reason)
if exc.example_fix:
@ -463,7 +486,7 @@ def _run_command(args: argparse.Namespace) -> int:
logging.info("hotkey: %s", cfg.daemon.hotkey)
logging.info(
"config (%s):\n%s",
args.config or str(Path.home() / ".config" / "aman" / "config.json"),
str(config_path),
json.dumps(redacted_dict(cfg), indent=2),
)
logging.info(
@ -491,6 +514,10 @@ def _run_command(args: argparse.Namespace) -> int:
return
shutdown_once.set()
logging.info("%s, shutting down", reason)
try:
desktop.stop_hotkey_listener()
except Exception as exc:
logging.debug("failed to stop hotkey listener: %s", exc)
if not daemon.shutdown(timeout=5.0):
logging.warning("timed out waiting for idle state during shutdown")
desktop.request_quit()
@ -501,18 +528,73 @@ def _run_command(args: argparse.Namespace) -> int:
signal.signal(signal.SIGINT, handle_signal)
signal.signal(signal.SIGTERM, handle_signal)
def hotkey_callback():
if args.dry_run:
logging.info("hotkey pressed (dry-run)")
return
daemon.toggle()
def reload_config_callback():
nonlocal cfg
try:
new_cfg = load(str(config_path))
except ConfigValidationError as exc:
logging.error("reload failed: invalid config field '%s': %s", exc.field, exc.reason)
if exc.example_fix:
logging.error("reload example fix: %s", exc.example_fix)
return
except Exception as exc:
logging.error("reload failed: %s", exc)
return
try:
desktop.start_hotkey_listener(new_cfg.daemon.hotkey, hotkey_callback)
except Exception as exc:
logging.error("reload failed: could not apply hotkey '%s': %s", new_cfg.daemon.hotkey, exc)
return
daemon.apply_config(new_cfg)
cfg = new_cfg
logging.info("config reloaded from %s", config_path)
def run_diagnostics_callback():
report = run_diagnostics(str(config_path))
if report.ok:
logging.info("diagnostics passed (%d checks)", len(report.checks))
return
failed = [check for check in report.checks if not check.ok]
logging.warning("diagnostics failed (%d/%d checks)", len(failed), len(report.checks))
for check in failed:
if check.hint:
logging.warning("%s: %s | hint: %s", check.id, check.message, check.hint)
else:
logging.warning("%s: %s", check.id, check.message)
def open_config_path_callback():
logging.info("config path: %s", config_path)
try:
desktop.start_hotkey_listener(
cfg.daemon.hotkey,
lambda: logging.info("hotkey pressed (dry-run)") if args.dry_run else daemon.toggle(),
hotkey_callback,
)
except Exception as exc:
logging.error("hotkey setup failed: %s", exc)
return 1
logging.info("ready")
try:
desktop.run_tray(daemon.get_state, lambda: shutdown("quit requested"))
desktop.run_tray(
daemon.get_state,
lambda: shutdown("quit requested"),
is_paused_getter=daemon.is_paused,
on_toggle_pause=daemon.toggle_paused,
on_reload_config=reload_config_callback,
on_run_diagnostics=run_diagnostics_callback,
on_open_config=open_config_path_callback,
)
finally:
try:
desktop.stop_hotkey_listener()
except Exception:
pass
daemon.shutdown(timeout=1.0)
return 0