Commit Graph

60 Commits

Author SHA1 Message Date
125bd17713 fix: entry natural width causes scrollbars in STT Engines and Wakeword (v2.03.38)
Gtk.Entry reports its placeholder text width as natural width. Without
set_width_chars(1), entries can't shrink below that, so pages with long
placeholders (URL fields, keyword rows) ended up wider than the dialog.

Added set_width_chars(1) to _entry(), _url_field(), ModelPicker,
_kw_shortcut_row, and _sound_field. Also added set_max_width_chars(50)
to the stt_result wrapping label for the same reason.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 15:28:44 +02:00
0500b24900 fix: horizontal scrollbars and empty STT Engines page in settings (v2.03.37)
- Guard _refresh_status() with hasattr checks so opening STT Engines
  before LLM Engines page is built no longer crashes the builder silently
- ww_status label: add max_width_chars(30) + ellipsize END so long model
  lists don't widen the Wakeword page
- Benchmark STT sel_sw: NEVER→AUTOMATIC horizontal policy so wide engine
  names scroll internally instead of propagating to the dialog
- _combo()/_type_combo(): set_size_request(10,-1) so ComboBoxText widgets
  (e.g. long microphone names) can shrink below natural width

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 15:16:49 +02:00
8181ad75f9 feat(2.03.36): split STT Engines / LLM Engines into separate sidebar pages
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 14:54:19 +02:00
79d6020fc6 fix(2.03.35): settings pages no longer widen the dialog
_switch_row description labels had set_line_wrap(True) but no
set_max_width_chars, so GTK computed their natural width as the full
un-wrapped text (~700px for 87-char descriptions). With NEVER horizontal
policy on the page ScrolledWindow this propagated to the dialog, making
Keyboard/Wakeword/Engines/Benchmark pages 1000–1360px wide.

Fix: add set_max_width_chars(50) to description labels, and change the
page SW horizontal policy from NEVER to AUTOMATIC as a safety net.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 14:52:28 +02:00
1f3bbf2668 fix(2.03.34): stop settings window growing wide/tall between pages
Stack.set_homogeneous(True) was requesting the max natural size of all
children (incl. wide Benchmark TreeViews) and forcing the dialog to 1000+px
wide for every page. Reverted to False so the window stays at 860×700 and
pages scroll if taller than the viewport.

Also removed the NEVER/NEVER ScrolledWindow policy on both benchmark pages —
it was propagating natural TreeView width up to the Stack, amplifying the
homogeneous bug.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 14:40:42 +02:00
5cd31c8385 fix(2.03.33): stable window size between pages, fix benchmark-ww controls clipped
- Stack.set_homogeneous(True) keeps dialog height constant when switching pages
- Benchmark WW paned position raised 260→390 so all TTS config, engine
  checkboxes, wakeword/samples/run fields are visible without scrolling
- Both benchmark pages disable their page-level ScrolledWindow so the
  Paned fills the viewport rather than growing to natural height

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 12:56:39 +02:00
af34360caa feat(2.03.32): replace Notebook with sidebar+Stack, split Input and Benchmark pages
Settings dialog navigation redesigned — Gtk.Notebook replaced with a 170px
left sidebar (section headers + flat nav buttons) + Gtk.Stack content area
(860×700 default). Lazy-loading preserved.

Input tab split into Keyboard (hotkeys, quality gate, audio cues) and
Wakeword (engine config, cancel/send words, wakeword sound cues).

Benchmark tab split into Benchmark — STT and Benchmark — Wakeword.
All field names and collect logic unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 12:46:33 +02:00
d45ab4e91d feat(2.03.32): replace Notebook with sidebar+Stack, split Input and Benchmark pages
- Replace Gtk.Notebook tab bar with a 170px left sidebar (flat buttons,
  section headers) + Gtk.Stack navigation; dialog widened to 860×700
- Split "Input" page into "Keyboard" (keys, quality gate, audio cues)
  and "Wakeword" (enable switch, mic level, test, engine CRUD, sound cues)
- Split "Benchmark" page into "Benchmark — STT" and "Benchmark — Wakeword"
- Remove _page() helper and bt-nb CSS; add .bt-sidebar-active + .sidebar CSS
- Lazy-loading preserved via _pending_pages dict + _show_page/_build_page
- Meter start guard kept in both _build_keyboard and _build_wakeword

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 12:42:08 +02:00
ca1f408876 feat: first-run setup wizard for new users (v2.03.31)
Paged GTK dialog guides through trigger method, keyboard shortcuts,
wakeword server, STT engine, and optional LLM setup. Shows automatically
on first launch, re-openable via Settings → "Setup Wizard…". Sets
setup_complete in config so it doesn't reappear.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 12:14:06 +02:00
5aafb572ed feat: dedicated wakeword models for cancel and send actions (v2.03.30)
WakewordActionListener opens a second Wyoming connection during active
wakeword recording, listening for the configured cancel/send models. When
either fires it immediately calls cancel_dictation() or finish_dictation()
without any silence timer or Whisper pass. Settings UI adds Cancel model
and Send model pickers to the wakeword config card, populated from the
same server model list as the trigger model.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 12:07:03 +02:00
a77b15ccaf feat: real-time cancel keyword detection during wakeword recording (v2.03.29)
CancelWatcher accumulates raw PCM from the VAD LevelMeter (via new
on_chunk callback) and runs a fast beam_size=1 transcription check every
~0.6s. When a cancel keyword is detected it immediately calls
cancel_dictation() without waiting for the silence timer to expire or
a full transcription to complete.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 11:47:10 +02:00
1c276e767b fix: block scroll-wheel changes on all ComboBoxText dropdowns (v2.03.28)
Hovering over a combo and scrolling could silently change the selection.
All ComboBoxText widgets now return True from their scroll-event handler,
swallowing the event before GTK's default handler can act on it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 11:38:48 +02:00
016ffe0390 feat: overlay × cancel button + wakeword shortcut fields inline (v2.03.27)
- Overlay HUD shows a × button in the top-right corner during recording/
  streaming; clicking it cancels dictation. The button area is the only
  clickable region — rest stays fully click-through.
- Wakeword tab "Cancel words" and "Send words" rows now include an inline
  keyboard shortcut entry + Set button, so key_cancel / key_send can be
  configured right next to the spoken-word equivalents.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 04:00:23 +02:00
834cc20553 fix: cancel recording works in wakeword mode + tray Cancel item (v2.03.26)
- Cancel hotkey now fires even when wakeword triggered the recording
  (ModifierScheme state was "idle" so the key was silently ignored)
- Tray menu: "✕ Cancel recording" — always visible, enabled while recording,
  grayed out at idle; works for both wakeword and manual recordings

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 03:44:14 +02:00
599eb08c5a feat: smart Save — inline status, no restart for safe changes (v2.03.25)
Save now diffs old vs new config. Safe changes (language, sounds, LLM,
keywords, overlay) show "✓ Applied" in the header for 4s. Restart-required
changes (STT engine, hotkeys, mic, wakeword) show "⚠ restart needed for: …"
and highlight Save & Restart. No modal popup on Save.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 03:29:27 +02:00
9c812a960e fix: Input level meter works without visiting General first (v2.03.24)
_start_meter() was only called from _build_general() and referenced
self.mic_level unconditionally. Now _build_input() also starts the meter
when it's not already running, and both level bars are updated via hasattr.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 02:48:55 +02:00
8301cbb457 fix: wakeword pane actually resizable — wrap controls in ScrolledWindow (v2.03.23)
The controls pane now has shrink=True and a ScrolledWindow wrapper, so
dragging the divider upward collapses the controls and expands the table.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 02:26:32 +02:00
012a069ad0 feat: wakeword benchmark — draggable split pane for results table (v2.03.22)
Controls (TTS config, engine checkboxes, run button) are in the top pane;
the results table is in the bottom pane. Drag the divider to see more rows.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 01:57:31 +02:00
8b26bc3379 feat: wakeword results table — sortable columns + CSV export (v2.03.21)
- All columns sortable by clicking header; numeric cols sort numerically
- "Copy as CSV" → clipboard; "Save CSV…" → file chooser

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 01:47:47 +02:00
6f133771e7 fix: icon vertical centering + wakeword results table (v2.03.20)
- Section header icons were pushed down by bt-section CSS margin-top;
  now only applied to the row container, not the image widget
- Wakeword benchmark shows a full TreeView table: per-voice Detected/Total/
  Recall%/False-fires/Time with colour coding, plus aggregate row per engine

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 01:25:14 +02:00
66e431f50a feat: wakeword engine checkboxes + wakeword model selector in benchmark (v2.03.19)
- Engine checkboxes let you pick which wakeword servers to include in the run
- Wakeword combo selects which model/phrase to test; leave empty for each
  engine's own, pick a specific one (e.g. okay_computer) to override all
- Also fixes: TTS ⟳ no longer fills model combo with Kokoro voice names

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 01:13:54 +02:00
b20aa31261 feat: TTS model fix + per-engine wakeword benchmark results (v2.03.18)
- TTS ⟳ no longer floods model combo with voice names (Kokoro exposes
  voices as /models entries — detected and skipped automatically)
- Wakeword benchmark now shows per-engine Recall/False-fires/time results;
  fixes progress callback signature mismatch that crashed multi-engine runs
- Wakeword fetch feedback: ⟳ shows "Connecting…" then model count/names
- Wakeword Quickstart expanded to ports 10400–10403 + hey_jarvis/alexa
- Wakeword info box added explaining model directory setup

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 00:59:28 +02:00
7a9dc5a2f7 feat: MP3/OGG/FLAC sound support + browse dialog with auto-preview (v2.03.16)
Sound fields accept WAV/MP3/OGG/FLAC/M4A/AAC/AIFF/Opus. Browse dialog
auto-plays each file on selection so you can preview before confirming.
sound.py falls back to ffplay/gst-play-1.0 for formats not supported
by pw-play/paplay.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 00:37:07 +02:00
571dae7cc9 feat: full CRUD for wakeword engine presets (v2.03.15)
Add/Quickstart/Reload/Delete buttons + Name field mirror the STT engines UI.
Four quickstart templates for common wyoming-openwakeword setups.
Migration: existing wakeword_uri/model auto-promoted to first preset.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 00:32:17 +02:00
e831d7f1e6 fix: remove Internal engine section header in Engines tab (v2.03.14)
Device/Compute rows already only show for local engines; the titled section
break was redundant and visually separated fields that belong together.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 00:24:42 +02:00
34f75844c1 feat: Save buttons in header bar, remove Close button, center section icons (v2.03.13)
HeaderBar replaces bottom button row — Save and Save & Restart appear in the
title bar on the right, X button closes. Section header icons vertically
centered using SMALL_TOOLBAR size and valign=CENTER.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 00:22:53 +02:00
ccf3801545 feat: icons on all settings tabs and section headers (v2.03.12)
GTK symbolic icons on every tab label and every section/card header.
Also fixes the resize grip landing in the tab bar instead of the bottom-right corner.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-10 00:07:41 +02:00
efa44c8872 feat: resize grip indicator on settings window (v2.03.11)
Draws a classic dotted SE-corner grip overlaid on the bottom-right of the
notebook so users know the settings dialog is resizable.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 23:50:20 +02:00
c292ff2242 fix: probe Prometheus /metrics at server root, not under /v1 (v2.03.10)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 23:30:33 +02:00
c3cf123afe feat: server RAM via Prometheus /metrics in benchmark (v2.03.09)
Probe remote engines' /metrics for process_resident_memory_bytes or
container_memory_rss; show actual server-side MB in RAM column.
Falls back to "server" when the endpoint is not exposed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 23:24:40 +02:00
86632e1918 fix: hide Internal Engine section for remote/streaming engines (v2.03.08)
Removes whitespace gap between STT config card and device/precision card
by hiding the latter when a Server or Realtime engine type is selected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 23:06:32 +02:00
d9603c98bf feat: RAM usage column in benchmark, docs update (v2.03.01)
- benchmark.py: measure RSS delta via /proc/self/status before/after each
  transcription; add ram_mb field to BenchRow
- gtksettings.py: add RAM (MB) column to results table (index 8); tooltip
  column shifted to index 10
- CHANGELOG.md: full history from v2.02.00 through v2.03.01
- README.md: benchmark description updated to mention RAM column
- MANUAL.md: benchmark result columns as table; Log tab documents
  level filter dropdown

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 22:11:38 +02:00
48be824a50 settings: emoji search, Manual tab fix, readable infobox (v1.9.5)
- Emoji picker: SearchEntry at top filters all categories via unicodedata.name()
  in real time; category view hides while searching, restores on clear
- Manual tab: add pkg_dir/MANUAL.md to _app_paths() search list so it works in
  both venv and deb installs (MANUAL.md deployed alongside the package)
- bt-infobox CSS: replace @theme_selected_bg_color (saturated blue) with a
  neutral 5% mix of fg/bg so banner text is always readable

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 13:09:42 +02:00
2fe6632269 settings: complete UI redesign — card layout, section titles, scrollable tabs (v1.9.4)
All settings tabs now use a card-based GTK3 layout:
- Related fields grouped into Gtk.ListBox cards with rounded borders (bt-card /
  boxed-list CSS) and bold all-caps section headers via _card_section helper
- CSS provider injected at init: .bt-section, .bt-card, .bt-infobox styles
- Each notebook page wraps content in a ScrolledWindow (740×700 px dialog)
- _labeled and _switch_row accept both Gtk.Box and Gtk.ListBox parents
- New helpers: _section_title, _card_section, _lb_add, _url_field_lb,
  _icon_field_lb, _key_field_lb
- Engines toolbars: creation buttons (+ Add/Stream/Quickstart) left-aligned,
  action buttons (Delete/Test/⟳) right-aligned via pack_end
- Presets: Identity / Trigger / Behaviour / Prompt cards
- Input: Input mode & keys / Quality gate / Wakeword / Sound cues cards
- General: Microphone / Output & language / Notifications / Startup cards
- Section names cleaned up (no more "WW -" prefix, cleaner device label)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 12:18:50 +02:00
dd617f625e settings: info buttons, Manual tab, engine quickstart templates, human-readable type names (v1.9.3)
- Every _labeled and _switch_row field now gets a clickable ⓘ info button
  that opens a plain-language help popover — targeted at non-technical users
- New Manual tab in Settings renders MANUAL.md directly inside the dialog
- STT and LLM toolbars each get a "Quickstart ▾" button: a menu of common
  providers (OpenAI, Groq, OpenRouter, Ollama, LM Studio, vLLM, llama-swap,
  faster-whisper-server, NVIDIA Riva) that pre-fills the engine form in one click
- Engine type combos now show human-readable labels ("Internal — faster-whisper",
  "LAN server — runs on your machine", "GPU (CUDA)", "int8 — fast, less memory")
  while storing the same internal key values (no config migration needed)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 11:48:02 +02:00
cc589f254b presets: add emoji picker to the Icon field (v1.9.2)
Adds a 😀 button next to the Icon (emoji) entry in Settings → Presets.
Clicking it opens a GTK popover with 60 common emojis in a scrollable
flow grid; selecting one writes it into the field and closes the picker.
The entry still accepts direct keyboard input as before.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-09 10:32:11 +02:00
a472ce62ba settings: lazy-build tabs (instant open); move connection dots beside the field; single-instance Settings dialog; Release 1.9.1
- gtksettings: build each notebook tab on first view instead of all up front, so
  the dialog opens instantly (was ~1.3s building Input/Benchmark file-choosers);
  _collect() force-builds unvisited tabs before saving so no field is missed.
- gtksettings: connection dot now sits left of the URL entry (like the Engines
  tab) instead of at the far right.
- gtkui: open_settings raises the existing dialog instead of opening a second.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 19:30:08 +02:00
27cf81de46 gtksettings: connection dots for the Wakeword (Wyoming) + TTS URLs; rename "Wyoming URI" to "Wakeword engine"; Release 1.9.0
Green/red/grey reachability dot next to the wakeword and TTS endpoint fields,
matching the existing STT/LLM engine dots. Lightweight background TCP probe,
refreshed on open, on reload (⟳), and on focus-out — never blocks dialog build.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 19:15:29 +02:00
0d4ad0920d gtkui: force GIO unix volume monitor so file choosers don't hang on dbus; Settings + panel open again; Release 1.8.1
On headless/minimal desktops the gvfs org.gtk.vfs.UDisks2VolumeMonitor dbus
service often fails to activate; each Gtk.FileChooserButton then blocked ~25s on
a StartServiceByName timeout while realizing, so the Settings dialog never
appeared and the stalled main loop froze the control panel too. Set
GIO_USE_VOLUME_MONITOR=unix in run_gui() before any window is realized.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 14:30:48 +02:00
28020fdeda routing: send-by-voice keyword (types + presses Enter); wakeword benchmark via TTS; Release 1.8.0
- Send by voice: a configured edge-anchored phrase (e.g. "computer send") is
  stripped and the rest is delivered AND submitted with Enter. Off by default;
  [routing] send_keywords + Settings → Input.
- Wakeword benchmark (Settings → Benchmark): synthesize the wake phrase in
  random voices via any OpenAI-compatible TTS server, stream to
  wyoming-openwakeword, report recall / false-fires / per-voice breakdown.
  New [tts] config block.
- Tests: test_voice_send.py, test_wakeword_bench.py.
- Ignore agent workspace folder jules/.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 13:17:33 +02:00
1c64f19bce overlay: drive waveform + silence countdown via pw-record (fix PipeWire); app reports as "Blitztext" not __main__.py; Release 1.7.1
The live waveform and silence auto-stop countdown were driven by a level
meter that was the last user of sounddevice/PortAudio, which hangs opening
the default input on PipeWire systems — so both stayed blank on the hotkey
and wakeword paths alike. Rewrite LevelMeter to stream raw PCM from the same
recorder as the WAV path (pw-record/parecord/arecord) and RMS it; identical
API, scaling, and ~10 Hz cadence. Also fixes the Settings mic-level preview.

Set GLib prgname/application name to "Blitztext" before any window is
realized (and add StartupWMClass to the .desktop) so the taskbar and GNOME's
"… is not responding" dialog show the app name instead of "__main__.py",
without touching the `python -m blitztext` entry point.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-08 08:39:37 +02:00
1567202e1a routing: spoken cancel keyword to discard a clip; Release 1.7.0
Add a configurable voice cancel: saying "abbrechen" (or "cancel") at the start
or end of a clip discards the whole dictation — it is never routed onward,
rewritten, or typed. The rescue for accidentally triggered (e.g. wakeword)
recordings. Matched the same edge-anchored, ASR-tolerant way as routing keywords
via routing.is_cancel(), so the word buried mid-sentence won't trip it; checked
in Daemon._process right after transcription, before routing/rewrite/delivery.
Configurable via [routing] cancel_keywords (default ["abbrechen", "cancel"];
empty disables) and Settings -> Mic/Cues -> "Cancel words". The overlay briefly
shows "Abgebrochen". Docs (both READMEs) and CHANGELOG updated; tests cover the
matcher, the config round-trip, and the discard/deliver pipeline branches.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 22:09:07 +02:00
ae01472b77 overlay: fix AT-SPI caret freeze; fuse routing match + live LLM into HUD; Release 1.6.0
Fix a desktop-session freeze (forced logout/reboot) caused by the overlay's
AT-SPI caret tracker: it subscribed to the high-frequency object:text-caret-moved
signal and made synchronous, blocking AT-SPI reads from inside the event handler,
re-entering the a11y dispatcher and getting stormed by the app's own xdotool
typing until GNOME stopped responding. Now track focus changes only and read the
caret rectangle lazily, once, when the overlay shows — never on the hot path.

Fuse voice-routing feedback into the overlay instead of a desktop notification:
show the matched preset's emoji, name, and spoken keyword on a banner, narrate
the phase (Transcribing -> Rewriting), and stream the LLM rewrite into the bubble
token-by-token. Redundant per-dictation notifications are suppressed when the
overlay is present (errors still notify); headless/overlay-off is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 16:58:47 +02:00
6a9c1fc95a overlay: silence auto-stop countdown ring around the mic; Release 1.5.1
A full circle wraps the mic glyph and drains clockwise as the trailing-
silence timer runs out, recolouring cyan→amber→red and emptying exactly
as auto-stop fires. The daemon emits the countdown from the same VAD loop
that decides auto-stop, so the ring stays in sync; the overlay drains it
against its own clock for smooth motion and fades it in/out so word gaps
don't flicker it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 15:41:17 +02:00
d55cdafcc1 on-screen dictation overlay at the cursor; Release 1.5.0
Show a translucent, click-through bubble the moment recording starts (by
hotkey or wakeword): a pulsing microphone, a live waveform of the mic
level, and the recognised text (word-by-word when streaming, otherwise a
brief final-result confirmation). The tail points at the text caret via
AT-SPI accessibility, falling back to the mouse pointer, then a screen
corner. Also gives hands-free wakeword sessions visible feedback, whose
notifications are suppressed by design. X11 only.

- overlay.py: GTK override-redirect HUD (mic + waveform + bubble), drawn
  with Cairo; thread-safe, marshalled onto the GTK loop.
- caret.py: best-effort anchor (AT-SPI caret -> pointer -> window/corner).
- daemon: optional level_cb/text_cb hooks; reuses the VAD level meter for
  non-streaming, a dedicated meter for streaming. Stays UI-agnostic.
- gtkui: instantiate the overlay, drive show/update/hide from status.
- General settings: "Visual overlay" toggle; config overlay_enabled /
  overlay_anchor (default on, "caret").
- Docs: CHANGELOG 1.5.0, version bump, README + MANUAL.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 13:13:41 +02:00
d00064b6cd routing by preset name; right-aligned General switches; About copyright
- Spoken presets: route() now also matches a preset's name as an implicit
  keyword, so presets with no configured keywords (Nicer email, Calm down,
  Add emojis) are triggerable by voice — say the name. Explicit keywords still
  win; names are added to STT hotwords too. Tests added.
- General tab: switches moved to the far right of each row with an inline
  grey description (new _switch_row helper) so each toggle is self-explanatory.
- About tab: add "Copyright: 2026 mARTin Bierschenk - Design".
- MANUAL + CHANGELOG updated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 11:48:22 +02:00
8cfc006296 Release 1.4.0
Bump version to 1.4.0 and cut the [1.4.0] - 2026-06-07 changelog section:
- "Announce matched preset" notification (shown even hands-free) + per-preset
  emoji icons.
- Voice-routing no-keyword default now prefers a transcribe preset instead of
  the first preset.

Refresh the README status line.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 11:37:51 +02:00
227e4407c4 routing: announce which preset/keyword you triggered (incl. hands-free)
The matched-preset feedback used _dnotify, which is suppressed for hands-free
sessions — so wakeword users never saw which keyword/preset fired.

- Add a dedicated "Announce matched preset" notification (_rnotify), gated by
  a new [general] notify_routing flag (default on) and independent of the
  hands-free silence, so it shows for wakeword commands too. It only fires on a
  real routing match, so it never spams when nothing is said.
- Show each preset's emoji in that notification; add a per-preset "Icon (emoji)"
  field to the Presets editor so matches are visually distinct.
- General-tab toggle; MANUAL + CHANGELOG updated. Adds a test that the match is
  announced even when _session_silent is set.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 10:43:08 +02:00
ae12eea861 routing: default to transcribe, not the first preset
When no [routing] default is configured, default_preset fell back to
workflows[0]. If that was an LLM rewrite (e.g. "Improve text"), every
wakeword/voice command without a matching keyword was sent to the language
model — repeatedly failing with HTTP 502 when the LLM backend was down.

default_preset now prefers a transcribe-mode preset for the no-keyword
fallback, so the default action is plain transcription. Adds tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 09:53:37 +02:00
11e469b444 Release 1.3.0
Bump version to 1.3.0 and cut the [1.3.0] - 2026-06-07 changelog section
(wakeword pause toggle, independent hands-free audio cues, configurable
auto-stop silence, notification hygiene, PortAudio noise suppression, and the
new MANUAL.md). Refresh the README status line.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 09:39:00 +02:00