feat: wakeword server preset dropdown in Input tab (v2.02.03)
Adds a "Server preset" combo in the Hands-free wakeword card that lists all configured wakeword engines by name. Selecting one auto-fills the URI and model fields and re-probes the connection. Selection persists via wakeword_active in config. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
48014ae662
commit
6fb41d5a9b
@ -6,4 +6,4 @@ counterpart to the macOS Blitztext menu bar app: it runs natively on the host
|
||||
(not in a container) so it can type into any application via xdotool.
|
||||
"""
|
||||
|
||||
__version__ = "2.02.02"
|
||||
__version__ = "2.02.03"
|
||||
|
||||
@ -104,6 +104,7 @@ class Config:
|
||||
llm_active: str = ""
|
||||
# wakeword
|
||||
wakeword_enabled: bool = False
|
||||
wakeword_active: str = "" # name of selected WakewordEngine preset, "" = custom
|
||||
wakeword_uri: str = "tcp://127.0.0.1:10400"
|
||||
wakeword_model: str = "okay_computer"
|
||||
wakeword_sound_detected: str = "" # WAV played when the wakeword fires (speak now)
|
||||
@ -232,6 +233,7 @@ def load(path: Path = CONFIG_PATH) -> Config:
|
||||
sound_before=snd.get("before", ""),
|
||||
sound_after=snd.get("after", ""),
|
||||
wakeword_enabled=bool(ww.get("enabled", False)),
|
||||
wakeword_active=ww.get("active", ""),
|
||||
wakeword_uri=ww.get("uri", "tcp://127.0.0.1:10400"),
|
||||
wakeword_model=ww.get("model", "okay_computer"),
|
||||
wakeword_sound_detected=ww.get("sound_detected", ""),
|
||||
@ -368,6 +370,7 @@ def save(cfg: Config, path: Path = CONFIG_PATH) -> None:
|
||||
},
|
||||
"wakeword": {
|
||||
"enabled": cfg.wakeword_enabled,
|
||||
"active": cfg.wakeword_active,
|
||||
"uri": cfg.wakeword_uri,
|
||||
"model": cfg.wakeword_model,
|
||||
"sound_detected": cfg.wakeword_sound_detected,
|
||||
|
||||
@ -1641,6 +1641,18 @@ notebook.bt-nb tab:checked label {
|
||||
self.ww_enabled = Gtk.Switch(); self.ww_enabled.set_active(self.cfg.wakeword_enabled)
|
||||
_switch_row(ww_card, "Enable wakeword", self.ww_enabled, width=LW,
|
||||
description="Start dictation with a spoken keyword via an external openWakeWord server.")
|
||||
# ── Server preset dropdown ────────────────────────────────────────────
|
||||
self.ww_combo = Gtk.ComboBoxText()
|
||||
self.ww_combo.append_text("(custom)")
|
||||
for e in self.cfg.wakeword_engines:
|
||||
self.ww_combo.append_text(e.name)
|
||||
active_idx = next((i + 1 for i, e in enumerate(self.cfg.wakeword_engines)
|
||||
if e.name == self.cfg.wakeword_active), 0)
|
||||
self.ww_combo.set_active(active_idx)
|
||||
self.ww_combo.set_tooltip_text("Pick a saved wakeword server preset, or use (custom) to enter a URI manually.")
|
||||
_labeled(ww_card, "Server preset", self.ww_combo, width=LW,
|
||||
tooltip="Select from wakeword server presets defined in the benchmark list, or (custom) to type a URI directly.")
|
||||
|
||||
self.ww_dot = Gtk.Label(); self.ww_dot.set_markup(_dot(GREY))
|
||||
self.ww_dot.set_tooltip_text("openWakeWord server: green = reachable, red = unreachable")
|
||||
self.ww_uri = _url_field_lb(ww_card, "Wakeword server", "tcp://127.0.0.1:10400",
|
||||
@ -1651,6 +1663,7 @@ notebook.bt-nb tab:checked label {
|
||||
self.ww_model = _labeled(ww_card, "Model name", _model_combo("Search models…"), width=LW,
|
||||
tooltip="Which wake model to listen for (e.g. computer, okay_computer). Press ⟳ on the URI field to load models from the server.")
|
||||
_fill_combo(self.ww_model, [], self.cfg.wakeword_model)
|
||||
self.ww_combo.connect("changed", self._ww_preset_changed)
|
||||
|
||||
self.ww_mic_level = Gtk.LevelBar()
|
||||
self.ww_mic_level.set_min_value(0); self.ww_mic_level.set_max_value(1)
|
||||
@ -1798,6 +1811,17 @@ notebook.bt-nb tab:checked label {
|
||||
if self._meter is not None:
|
||||
self._meter.stop(); self._meter = None
|
||||
|
||||
def _ww_preset_changed(self, combo) -> None:
|
||||
idx = combo.get_active()
|
||||
if idx <= 0 or idx - 1 >= len(self.cfg.wakeword_engines):
|
||||
return # (custom) selected — leave fields as-is
|
||||
e = self.cfg.wakeword_engines[idx - 1]
|
||||
self.cfg.wakeword_active = e.name
|
||||
self.ww_uri.set_text(e.uri)
|
||||
_fill_combo(self.ww_model, [], e.model)
|
||||
self._probe_dot(self.ww_dot, e.uri, 10400)
|
||||
self._ww_load()
|
||||
|
||||
def _ww_load(self) -> None:
|
||||
self._probe_dot(self.ww_dot, self.ww_uri.get_text(), 10400)
|
||||
|
||||
@ -2466,6 +2490,10 @@ notebook.bt-nb tab:checked label {
|
||||
c.sound_before = self.snd_before.get_filename() or ""
|
||||
c.sound_after = self.snd_after.get_filename() or ""
|
||||
c.wakeword_enabled = self.ww_enabled.get_active()
|
||||
preset_idx = self.ww_combo.get_active()
|
||||
c.wakeword_active = (self.cfg.wakeword_engines[preset_idx - 1].name
|
||||
if preset_idx > 0 and preset_idx - 1 < len(self.cfg.wakeword_engines)
|
||||
else "")
|
||||
c.wakeword_uri = self.ww_uri.get_text().strip()
|
||||
c.wakeword_model = _combo_text(self.ww_model)
|
||||
c.wakeword_sound_detected = self.ww_snd_detected.get_filename() or ""
|
||||
|
||||
Loading…
Reference in New Issue
Block a user