- 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>
- 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>
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>
_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>
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>
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>
- 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>
- 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>
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>
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>
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>
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>
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>
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>
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>
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>
String sort put "14.85" before "2.47". Now uses a custom comparator
that strips % and non-numeric markers before comparing as float.
Non-numeric values ("—", "server") sort to the bottom.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remote engines run models server-side so local RSS never changes.
Show "server" instead of "—" to make the reason clear.
Local engines show measured MB; local already-loaded shows "—".
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
300s was too long; nobody waits 5 min for a result.
30s gives slow remote servers a fair window while still failing fast.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add _api_base() to strip endpoint-specific path suffixes before probing
/models, /metadata, /info — fixes /transcribe/models 404 spam when URL
ends with a custom path like /v1/transcribe
- Increase default transcribe() timeout 60s → 300s — WhisperX with speaker
diarization (pyannote) takes 2-5 min and was always timing out
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add "WhisperX server" quickstart template pre-filled with /transcribe endpoint
- Add tooltip to STT URL field explaining that non-standard servers (WhisperX)
should use the full endpoint as the URL, not /v1
- _url_field_lb accepts optional tooltip= kwarg
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>
- Stability: remove blocking TCP socket call from _collect() — was
freezing the GTK main thread on Save when wakeword server unreachable;
now checks async in background and logs result
- Thread safety: fix _ww_load() reading GTK widget from background thread;
capture URI on main thread before spawning
- WhisperX 404: _transcribe_remote now detects non-standard paths
(anything other than /v1) and uses the URL as the full endpoint,
so http://host/transcribe works without /audio/transcriptions appended
- Log levels: logbuffer stores (ts, level, msg) tuples; log() accepts
level= (DEBUG/INFO/WARNING/ERROR); Log tab gets a Level dropdown
(Verbose/Info/Warning/Error) that filters displayed entries live
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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>
- About tab: render License with _md_panel instead of _text_panel
- Benchmark pane: set_size_request 320px min, shrink=False on both sides
so the engine list and results table are always visible
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
After running a benchmark, each engine's best result (time, accuracy)
is persisted to config and shown as a small info line in the Engines tab
when that engine is selected. Updates live as the benchmark runs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- stt.py: add ModelMeta dataclass, fmt_languages(), list_models_meta(),
detect_remote_device(); refactor list_models() to delegate
- benchmark.py: add languages field to BenchRow; fetch via _get_langs()
with URL-level caching using list_models_meta()
- gtksettings.py: show language labels per engine in checkbox list;
add language codes to search filter; add Lang column to results table
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Tab font-size 12px → 14px (matches body text)
- Inactive tabs: muted foreground color so they're clearly readable
but visually distinct from the active tab
- Active tab: bold + blue (#1a73e8), slightly more padding (8px 18px)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Schema: MAJOR.FEATURE.FIX
MAJOR — breaking changes / major redesign
FEATURE — two-digit, new user-visible features (00-99)
FIX — two-digit, bug fixes within a feature release (00-99)
Renamed 2.1.2 → 2.01.02 to start the new format.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
_stt_commit() accesses self.stt_name which only exists after the Engines
tab is lazily built. Guard with hasattr so running a benchmark directly
from the Benchmark tab no longer throws AttributeError.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Engine checklist and results table now split by a Gtk.Paned (vertical)
so the user can drag the divider to give more room to either panel
- WAV and reference .txt paths are written to disk (save()) the moment a
file is picked via the file chooser, without needing to click Save;
also saved on Run if they changed since the last disk write
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Benchmark tab: scrollable engine checklist above Run with live
reachability dots (green/red), name+model+URL filter, All/None buttons;
_run_bench respects selection and shows clear message when nothing ticked
- About tab: changelog now rendered via _md_panel (markdown headers, bold,
lists) instead of plain monospace _text_panel
- Manual tab: graceful fallback with clickable GitHub link when MANUAL.md
is not installed; build-deb.sh now copies MANUAL.md from repo root so
/opt/blitztext/MANUAL.md exists in future installs
- STT quickstart templates expanded: Speaches docker, whisper.cpp server,
NVIDIA NIM/Parakeet, five built-in local model sizes (tiny→large-v3)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Wrap ListStore in TreeModelSort and set sort_column_id on every column
so clicking any header sorts ascending/descending.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Engines tab: move Test button out of the toolbar, place it in a row
directly beside the result label so button and output are co-located;
result label is now selectable so error text can be copied
- Benchmark tab: add bench_wav/bench_ref/bench_expand_models to Config;
file pickers restore last-used paths on open; any change (file-set,
toggle, or Run) writes directly to cfg so paths survive without Save;
[benchmark] section written to config.toml on Save
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- stt.detect_remote_device(): probes /info (faster-whisper-server) then
/metadata (NVIDIA NIM) to detect CUDA vs CPU; cached per unique URL
- BenchRow gains url field; Device column now shows "CUDA" for GPU remotes
instead of the generic "remote"
- Benchmark table gains URL column (scheme stripped, max 180px wide)
- "Test all models per engine" checkbox: fetches list_models() for each
remote engine and expands to one row per model when checked
- benchmark.run() gains expand_models parameter
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- _run_bench: deduplicate STT engines by name before running; show a
warning in the summary line listing which names were skipped
- _bench_add_row: replace raw HTTP error strings with human-readable
reasons ("Wrong model name", "Server offline", "Timed out", etc.);
full raw error stored in hidden column 7 shown as row tooltip on hover
- bench_store: added 8th column (tooltip text); tree.set_tooltip_column(7)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- BenchRow gains `best_for` field: "Short clips" / "Short / medium" /
"Long / batch" / "Streaming" — derived from engine type and model name
- Device now shows "CUDA" instead of "GPU" for clarity
- Benchmark table gains a "Best for" column between Device and Time(s)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- stt._transcribe_remote: no longer falls back to "whisper-1" when
engine.model is empty — omits the field entirely so Riva/NIM uses its
default model instead of rejecting the request with HTTP 400
- gtksettings._page: switch vertical scroll policy to ALWAYS and disable
overlay scrolling so the scrollbar is permanently visible, making
it obvious when a tab has more content below the visible area
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Root cause of session freeze confirmed: a 15 000-char code block was typed
character-by-character via xdotool at 12ms/char = ~3 min, flooding the X11
per-client event buffer until the entire session froze.
- paste.py: any text >300 chars or containing newlines auto-upgrades to
clipboard paste (instant Ctrl+V) regardless of configured output mode.
xdotool type is kept only for short single-line text where it matters.
- daemon.py: replace on_token "".join(acc) accumulation (O(n²) for long
code blocks) with a sliding deque that shows only the last 400 chars in
the overlay — Pango no longer re-lays out a growing 15 KB string on each
incoming token.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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>
- 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>
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>