Add tray controls for pause reload and diagnostics
This commit is contained in:
parent
77ae21d0f6
commit
e262b26db7
5 changed files with 192 additions and 8 deletions
90
src/aman.py
90
src/aman.py
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue