Commit Graph
372 Commits
Author SHA1 Message Date
xavierk 1cf5423d39 fix(launcher): report leftover upstream launchers that no longer start
CI / security (pull_request) Successful in 1m14s
CI / lint (pull_request) Successful in 23s
CI / ai-review (pull_request) Successful in 7s
A previous Vocalinux install can leave ~/.local/share/applications/vocalinux.desktop
and ~/.local/bin/vocalinux(-gui) behind. When their target or venv is gone they
start nothing, yet they sit next to Voculinux in launchers.

The one-time legacy import now also checks those three paths, after the tray is
up, with stat calls and small reads only. A launcher is stale when its target is
missing, a link is dangling, or a script names a missing interpreter or venv
entry. A working install is never reported. One notice names the stale files and
a marker in the new data directory keeps it to once. No file is removed or
modified.

Fixes #52
2026-11-07 02:31:12 +05:30
xavierk 731b919865 chore(release): prepare v0.19.0 (#53)
CI / security (push) Successful in 1m11s
CI / lint (push) Successful in 21s
CI / ai-review (push) Skipped
Version 0.19.0 across version.py, the Void template and the synced docs; changelog entry; Gitea project URLs in pyproject.toml; per-backend ladder thresholds measured in #19; the xbps release workflow is manual-only, and packaging/void/publish-release.sh publishes a locally built, verified repository to the Gitea releases.
2026-11-06 20:23:14 +00:00
xavierk 85cbc37842 fix(tray): show the tray before the speech model loads (#51)
CI / security (push) Successful in 1m17s
CI / lint (push) Successful in 23s
CI / ai-review (push) Skipped
The first model load runs on a background thread after the tray is up. While it loads the tray shows the processing icon and 'Loading model…', and a dictation request gets a 'still loading' notification. A failed load leaves the tray in the error state instead of exiting.

Fixes #50
2026-11-06 20:00:50 +00:00
xavierk 0c48db5b5e fix(void): report pywhispercpp 1.5.0 and load CPU variants at runtime (#49)
CI / security (push) Successful in 1m9s
CI / lint (push) Successful in 23s
CI / ai-review (push) Skipped
Fixes #43
Fixes #44
2026-11-06 18:51:30 +00:00
xavierk b0d8afad92 fix(audio): never open the microphone for system audio, never swap a configured mic (#48)
CI / security (push) Successful in 1m18s
CI / lint (push) Successful in 23s
CI / ai-review (push) Skipped
System-audio capture sets stream.capture.sink on the spawned pw-record, so PipeWire links only the sink monitor. An explicit microphone that is missing, renamed, virtual or output-only now fails with an Audio Input Unavailable notification instead of recording from the default input.

Fixes #41
Fixes #42
2026-11-06 18:35:19 +00:00
xavierk a451e1d512 fix(niri): conflict-free example keybinds and a niri-aware inject probe (#47)
CI / security (push) Successful in 1m26s
CI / lint (push) Successful in 21s
CI / ai-review (push) Skipped
The niri example binds move to Mod+Shift+M (toggle), Mod+Shift+S (start) and Mod+Shift+X (stop), free in stock niri and in Dank Material Shell's binds. inject-probe reuses the injector's niri guard, so it no longer reports the portal on niri.

Fixes #45
Fixes #46
2026-11-06 18:29:29 +00:00
xavierk a4a831c3c6 fix(src): drop remaining upstream install and wiki references (#40)
CI / security (push) Successful in 1m11s
CI / lint (push) Successful in 22s
CI / ai-review (push) Skipped
The missing-dependency error gives the Void xbps instruction instead of piping upstream's installer, the IBus hint points at the fork's docs (niri names its own notes), and the IBus engine homepage is the fork. VocaGateway stays upstream, with the credit stated in code and docs.
2026-11-06 16:32:52 +00:00
xavierk 37cf549956 fix(void): carry python3-pysocks and constrain the audio and SOCKS floors (#39)
CI / security (push) Successful in 1m15s
CI / lint (push) Successful in 24s
CI / ai-review (push) Skipped
voculinux now depends on python3-PyAudio and python3-pysocks at the carried versions, so a stock Void package below the project floors is upgraded rather than silently kept. The container smoke installs the stock packages first and asserts the upgrade.
2026-11-06 16:17:19 +00:00
xavierk 4171567fd7 docs: publish Void xbps as the only install channel, drop upstream references (#38)
CI / security (push) Successful in 1m12s
CI / lint (push) Successful in 21s
CI / ai-review (push) Skipped
User-facing docs, About page and website now point at the fork and the Void xbps repository, with one credit line to upstream Vocalinux. Channels this fork does not publish are removed from navigation.
2026-11-06 16:17:04 +00:00
xavierk b47a65c91e fix(void): build the xbps release from the tag, not an attached sdist (#37)
CI / security (push) Successful in 1m15s
CI / lint (push) Successful in 23s
CI / ai-review (push) Skipped
Every release is built from its tag alone by packaging/void/build-release.sh, shared by the tag workflow and local dry runs. Signs in a network-less container with the key mounted read-only and publishes to the tag release and the rolling latest release.
2026-11-06 15:31:47 +00:00
xavierk 2a76793109 fix(app): detect CUDA outside PATH, warn on IBus pin on niri, query Gitea for updates, repoint migrated dictionary (#36)
CI / security (push) Successful in 1m13s
CI / lint (push) Successful in 24s
CI / ai-review (push) Skipped
CUDA toolkit detection also checks CUDA_HOME, CUDA_PATH and /usr/local/cuda*, and the backend order names only backends the installed build compiled in. An explicit IBus pin on niri is honoured with one warning. The update checker queries this fork's Gitea releases and packaged installs make no network request. The one-time legacy import repoints a migrated dictionary path at the copied file.
2026-11-06 14:38:43 +00:00
xavierk 180cd4d512 fix(spec16): close the review findings for the Void port (#34)
CI / security (push) Successful in 1m14s
CI / lint (push) Successful in 24s
CI / ai-review (push) Skipped
Model recommendation keyed to the installed build and free memory, fork-sourced Void templates, signed xbps release workflow on Gitea with the pinned repository key, niri injection guard and wtype-first order, tightened naming sweep, web copy fixes, and CI security and duplication fixes.
2026-11-06 14:13:49 +00:00
soubarnak e6c9069e0b fix(void): use concrete release-download URL for xbps client registration
Replace the self-referential <repo-url-from-release-notes> placeholder
in the root README, the release-notes template, and the Void packaging
README with the concrete per-tag download prefix the build-xbps job
attaches the signed repo to. Static docs default TAG to the current
version; release.yml renders github.ref_name at publish time.

Fixes #29
2026-11-06 09:42:12 +05:30
soubarnak 7f1e4b8ace chore(29): merge integration tip cf87331 into feature/29 2026-11-06 09:40:11 +05:30
soubarnak cf873319d4 Merge feature/31 into integration/spec16 (ticket #31: injection ladder order) 2026-11-06 09:37:14 +05:30
soubarnak 6eb8ff3d67 Merge feature/20 into integration/spec16 (ticket #20: measured ladder thresholds) 2026-11-06 09:37:13 +05:30
soubarnak e100af7bcd fix(injection): align fallback ladder to portal>wtype>ydotool>xdotool>manual
Ticket #31 review found startup and demote paths preferring ydotool
over wtype, with a KDE ydotool-first exception, contradicting the
decided order in spec #16 (portal first where a backend implements
it, then direct keysym typing, then the virtual-input tool, then
XWayland-only injection, then manual paste).

- Auto-selection is now portal, wtype, ready ydotool, daemonless
  ydotool, xdotool on every desktop including KDE; the __init__ wtype
  probe validates wtype and demotes on compositor rejection.
- Portal-deny demotion, IBus-fallback switch, XWayland recovery, and
  a new wtype runtime-failure retry all follow the same rung order
  with partial-type accounting preserved.
- Ladder suite grows to 14 tests pinning KDE portal selection,
  wtype-before-ydotool selection, and each demotion trigger.
- USER_GUIDE states the full rung order and portal-first on KDE.
2026-11-06 09:21:13 +05:30
soubarnak da450e32db fix(void): wire signed xbps repo into release, README, and release process
Add build-xbps tag job to release.yml: verifies the tag against
src/vocalinux/version.py, fails closed when XBPS_SIGNING_KEY is unset,
builds and signs via podman-only repo.sh, and attaches packages,
signatures, repodata, and client key files to the release. Fold the
xbps-repo artifact into publish-checksums (manifest + SHA256SUMS).

Document the Void install in the root README (glibc x86_64 scope,
fingerprint check, third-party repo caveat) and the post-tag template
version/checksum bump as a pull request in docs/RELEASE_PROCESS.md.

Proof: local podman run with a throwaway RSA4096 key built all four
templates, signed packages + repodata, and verified voculinux installs
from the signed repo in a clean rootdir (fingerprint
eb:29:5d:9e:5c:94:c1:63:ae:35:cd:35:db:7a:28:da).
2026-11-06 09:15:22 +05:30
soubarnak d08cacb0b4 fix(identity): share one model-download user agent definition
Both model-download call sites built the User-Agent string separately:
recognition_manager used a hardcoded literal while settings_dialog
interpolated APP_ID. Add app_identity.user_agent() and use it in both,
with a test pinning the shared definition.

Fixes #17
2026-11-06 09:01:15 +05:30
soubarnak 987d8eec29 fix(models): use ticket 19 measured peaks for ladder thresholds
q8_0 threshold becomes 1644 MiB (1132+512) and q5_0 becomes 1358 MiB
(846+512) per the recorded baseline recommendation, replacing the
on-disk-size proxies. Tests pin the measured values and the 1644/1358
boundaries.
2026-11-06 09:00:47 +05:30
soubarnak 9bc04936b6 feat(void): add signed xbps repository pipeline
Build every template in smoke-gate order, index the full repository and
sign packages plus metadata with the RSA4096 key, in the pinned Void
container via podman. Fail-closed without a key: no key file, no repo.

Ticket #29 (needs #27, #28).
2026-11-06 06:29:22 +05:30
soubarnak bd7b624f50 feat(void): add package smoke gate across all templates
Ticket xavierk/voculinux#28, needs #27. One documented command
(packaging/void/smoke.sh, just void-smoke) lints, builds, installs
and smoke-tests every template under packaging/void/srcpkgs in
dependency order in the pinned Void container via podman, failing
fast naming the package with the harness echoing each stage.

The gate caught three latent breaks in the per-package harness and
the app template, fixed here:
- container-main.sh scoped the libggml scan to python3-pywhispercpp
  and gave the leaf packages their own import smokes (pynput by
  presence: no display in the container), failing loudly for
  packages without a smoke recipe;
- voculinux template drops the deprecated wrksrc override (xbps-src
  renames the single-top-dir archive itself; xlint rejects wrksrc)
  and builds the PEP 517 wheel (the sdist ships no setup.py);
- post_install promotes the pre-rename sdist names (desktop entry
  content, icons, /usr/bin launchers) to the renamed identity, and
  the payload smoke rejects pre-rename leftovers in OS-visible paths.

Offline policy tests (tests/test_void_smoke_gate.py) pin the gate to
the template set, the app-last order, podman-only pinned inputs and
per-package failure identity; the #27 policy tests and the rename
sweep cover the harness and template contracts.
2026-11-06 05:57:37 +05:30
soubarnak f660471757 Merge feature/31 into integration/spec16 (ticket #31: injection ladder tests and first-dictation docs) 2026-11-06 03:04:14 +05:30
soubarnak d320cdae14 Merge feature/27 into integration/spec16 (ticket #27: Void xbps app template) 2026-11-06 03:04:11 +05:30
soubarnak fa14552a2a Merge feature/24 into integration/spec16 (ticket #24: web rebrand to Voculinux) 2026-11-06 03:04:09 +05:30
soubarnak d7a4b8c21e feat(void): add xbps template for the voculinux app
Ticket xavierk/voculinux#27, built on #18 (rename) plus the #25/#26
dependency templates. The template builds the app from the canonical
checksum-verified release sdist, depends on Void's interpreter, GTK,
desktop bindings and packaged Python libraries, and installs the
renamed desktop entry, icons and a packaged-install marker. No speech
models, no vendored wheels, no pip at build or install time.

Packaged installs keep background update checks as a signal, but every
update affordance presents the package-manager path
(src/vocalinux/utils/packaging.py). Also corrects the Void distro
inventory (Ayatana provider name; ydotool marked absent) and regens
the installer map.
2026-11-06 03:03:33 +05:30
soubarnak f26e0a9111 feat(web): rebrand marketing site to Voculinux
Names, wordmarks, package and install references move to voculinux;
site domain to voculinux.com with renamed public assets. Layout keeps
Carbon spacing/type/motion discipline remapped to the house palette
(teal interactive, warm paper, system stacks, red reserved). Header
and footer gain Bongbetic attribution chrome linking hosted brand
assets; no brand binaries vendored. Engine copy states whisper.cpp as
guaranteed default, others as best-effort extras, remote API as
user-configured with audio leaving the machine. Nix page carries a
fork-status note (upstream flake installs Vocalinux).

Refs #24
2026-11-06 02:30:01 +05:30
soubarnak e6f7938068 test(injection): pin fallback ladder per desktop class and niri first-run
Locks the ordered rungs without real compositors: portal first where a
backend implements it (GNOME), direct typing first on niri with IBus
excluded and no portal selected, deny demoting to direct typing with the
full dictation kept, terminal probe choosing Ctrl+Shift+V, held modifiers
delaying the XWayland paste, and clipboard manual paste as last resort.

USER_GUIDE states the niri first run (no prompt, typing goes direct,
never pin portal there) and the GNOME/KDE grant, persistence and deny
fallback under the renamed backend setting and override names.

Refs #31
2026-11-06 02:27:15 +05:30
soubarnak c27d204a00 feat(niri): add niri keybind pack and Dank Material Shell notes
Docs-only slice of ticket #22: include file, integration page, index
links. Tray-watcher observation stays open for hardware run (#32); no
probe code changed.

Refs #22
2026-11-06 02:23:40 +05:30
soubarnak 74ea855220 feat(dbus): expose dictation state signal and property
Alongside Toggle/Start/Stop, the renamed interface now publishes
dictation state (idle/listening/processing) as a StateChanged signal
and a readable State property, so status bars and scripts can follow
dictation without scraping the tray. Signals fire only on change, so
double start/stop emits no duplicates; command-line triggers behave
exactly as before.

Refs #21
2026-11-06 01:51:05 +05:30
soubarnak df771d8fb1 feat(models): memory-aware whisper.cpp ladder with conditional backend order
Free memory picks the load-time rung (large-v3-turbo-q8_0 default,
q5_0 under 1086 MiB free, small/small.en floor) for unpinned default
configs; thresholds derive from catalog sizes plus the protocol's
512 MiB headroom. A manual pin is never overridden, and a failed load
steps one rung down and retries exactly once before surfacing.

CUDA ranks before Vulkan only with a complete architecture-matching
toolkit (nvidia-smi GPU, nvcc, compute capability >= 7.0); otherwise
Vulkan, then CPU. The driver-only CUDA recommendation now demotes to
CPU logic instead of naming an unreachable VRAM ladder.

Refs #20
2026-11-06 01:48:20 +05:30
soubarnak ea7be5f111 feat(identity): rename user-visible identity to voculinux with one-time legacy import
The fork takes its own name everywhere a user can see it: binaries
(voculinux, voculinux-gui), desktop entry, autostart, tray, D-Bus
namespace (com.voculinux.Voculinux, no alias for the old name),
config/data/cache dirs, single-instance lock, IBus engine identity,
tray icons, resource prefixes, VOCULINUX_* environment names, and the
update-checker user agent. The internal Python module stays vocalinux
and the distribution metadata keeps the upstream URLs as provenance.

On first run a previous Vocalinux install's config.json, custom
dictionary, and portal restore token are copied once into the new
locations (new config always wins, no merge, no write-back); models
re-resolve through the pinned-checksum download path. An offline
naming-sweep test proves no old-name strings remain on user-visible
surfaces outside the allowlist.

Refs #18
2026-11-06 01:29:39 +05:30
soubarnak c565e6d946 Merge feature/30 into integration/spec16 (ticket #30: upstream intake policy) 2026-11-06 00:06:02 +05:30
soubarnak d4be3caf7a Merge feature/26 into integration/spec16 (ticket #26: void pywhispercpp template)
Conflict in packaging/void/tool_checksums.txt (add/add with #25):
kept #26 rows (base-image digest + void-packages pin the kept
build.sh reads) with the #25 header reference folded in. #25's
base-image digest differed; flagged for re-pin on next bump.
2026-11-06 00:06:02 +05:30
soubarnak cc9db31450 Merge feature/25 into integration/spec16 (ticket #25: void pynput/pyaudio templates) 2026-11-06 00:05:40 +05:30
soubarnak 9d09319ba1 Merge feature/23 into integration/spec16 (ticket #23: brand accent hook) 2026-11-06 00:05:37 +05:30
soubarnak c5c42fedee Merge feature/19 into integration/spec16 (ticket #19: perf baseline protocol) 2026-11-06 00:05:35 +05:30
soubarnak 203b51ab78 feat(ui): add brand accent hook to GTK colour scheme
BRAND_ACCENT single source with shade()-derived states; accent CSS
covers suggested-action buttons and the listening chip, installed at
USER priority from main().

Refs #23
2026-11-06 00:05:29 +05:30
soubarnak d7a0273da1 refactor(identity): centralise user-visible app identity
Single app_identity module owns APP_NAME/APP_ID, D-Bus names,
desktop/icon/IBus names and related surfaces; 16 consumers import
from it with zero value changes. Deliberately excludes
settings_about and dictation_pad literals pinned by existing tests.

Refs #17
2026-11-06 00:05:26 +05:30
soubarnak 1d8b07727e feat(void): add xbps template for python3-pywhispercpp
Spec #16 ticket #26: Void template for the whisper.cpp Python binding,
built from the pinned 1.5.0 sdist with the Vulkan backend (default-on
option), shared libraries, and portable CPU flags. Includes the podman
build/smoke harness, pinned base-image pins, and offline policy tests.

Refs: #26
2026-11-06 00:04:47 +05:30
soubarnak 6713722daf feat(perf): lock installed-build baseline protocol and take target-machine numbers
Ticket #19 (spec #16): fixed three-metric protocol as a runnable script
(idle memory both keep-alive states, wake latency from debug logs,
real-time factor on the fixed 30 s sample per backend) plus per-rung
load footprints, portal/direct injection probe, and threshold
derivation for the model-ladder ticket (#20). Offline unit tests for
the parsing/statistics/report helpers. Evidence recorded on the ticket.

One debug-only marker (Toggle requested in state ...) makes wake
latency derivable from logs alone.
2026-11-05 23:11:28 +05:30
soubarnak c462ffb4b2 feat(void): add xbps templates for pynput and updated PyAudio
Ticket: #25

Two in-repo void-packages-layout templates under packaging/void/srcpkgs:
python3-pynput 1.8.2 (new; Void does not ship it) and python3-PyAudio
0.2.14 (updated local template; Void ships 0.2.12, below the project's
pyaudio>=0.2.13 floor). Versions and checksums track uv.lock and
requirements/runtime.txt; pynput post_patch strips setup_requires so the
build never fetches helpers over the network (setuptools-lint and twine
are not in void-packages). No noverifypydeps/nopyprovides anywhere.

Adds tests/test_void_small_deps.py (offline policy test): template
layout and metadata shape, lock/export/floor pins, checksum pins,
no verification-disabling options, linux dep coverage, verified-only
dependency names, and the digest-pinned base image in
packaging/void/tool_checksums.txt.

Verified: xlint clean on both templates; both packages build with
xbps-src in the pinned ghcr.io/void-linux/void-glibc-full container
(podman) and install in a fresh container with pyaudio 0.2.14
importing against PortAudio V19.6.0.
2026-11-05 23:09:16 +05:30
soubarnak de548d6a56 docs(release): write upstream cherry-pick policy into release process
Intake at release-preparation sync points plus on-demand critical
fixes, freeze once the release branch opens to release-blockers only,
one upstream fix per fork pull request through the standard gates,
conflicts resolved by keeping upstream logic and re-applying fork
renames, and the qualification rule (fixes and user-instruction docs
port; features re-decided; dependency/CI churn only on a security
advisory). Names the retained internal vocalinux module as the reason
conflicts concentrate at renamed user-visible surfaces.

Tests: tests/test_upstream_intake_policy.py (7 tests)
2026-11-05 22:46:41 +05:30
Jatin K MalikandGitHub 0a4d637f5f fix(overlay): detect Wayland by GType so the fallback overlay stays compact (#1030) (#1035)
* fix(overlay): detect Wayland by GType so the fallback overlay stays compact (#1030)

_is_wayland() checked isinstance(display, Gdk.WaylandDisplay), but GTK3's
Gdk typelib has no WaylandDisplay class, so it always returned False. On
Wayland without gtk-layer-shell, _layout_bottom_strip() therefore sized the
prewarmed fallback window to the full monitor width (the X11 strip) instead
of the compact centered window meant for Wayland, which on KDE showed up as
a wide empty "Vocalinux Dictation" window listed in the taskbar.

Drop _is_wayland() and use _display_is_wayland(), which checks the GType
name and already gates prewarm, so both decisions agree.

Also list gtk-layer-shell as an optdepend of the source AUR package: with
it KWin and wlroots compositors get a layer surface that is never listed
in the taskbar and never needs the prewarmed toplevel. The AppImage (and
so vocalinux-bin) already bundles it.

* docs(overlay): describe the compact Wayland fallback in the overlay docstrings

The class docstring still said the overlay is always a full-width strip, which no longer holds on Wayland without layer shell (#1030).

* fix(overlay): keep the full-width strip on GNOME Wayland

Mutter ignores CENTER_ALWAYS for a plain Wayland toplevel, so the compact
fallback window landed in the top-left corner on GNOME (tested on GNOME
Shell 46 with the Ubuntu Dock). The full-width strip at least keeps the
orb horizontally centered there. Use the compact window only on KDE,
where KWin listed the strip in the taskbar as a wide empty window (#1030).
2026-11-02 19:17:27 -08:00
Jatin K MalikandGitHub f70357f2b8 fix(overlay): quit Vocalinux when the dock closes the overlay window (#1028) (#1036)
* fix(overlay): quit Vocalinux when the dock closes the overlay window (#1028)

On GNOME Wayland without layer shell, the prewarmed dictation overlay is a
regular toplevel that the dock lists as the app's window. Since #1017 the
overlay refuses close requests so it is never destroyed (#1010), which made
"Quit" from the dock silently do nothing.

The overlay still keeps its window, but now forwards the close request to
an optional on_close_request callback, scheduled once from an idle source.
The tray passes its _quit(), so the dock's Quit behaves like the tray's Quit.

* fix(overlay): drop a queued dock close once the app is quitting

A dock close request is forwarded through an idle source. If the tray's
Quit or SIGTERM tears the overlay down before that idle runs, the
callback would run _quit() a second time. destroy() now drops the
callback, and the pending flag is cleared when the request runs so a
later close can retry if quitting failed.

Refs #1028
2026-11-02 19:17:21 -08:00
Jatin K MalikandGitHub 61bfb1e58e fix(ui): escape device names and test errors in the audio status label (#1043)
The Settings audio status label is set with Pango markup. A microphone
named with '&' or '<' (or an audio test error carrying them) made the
markup invalid, so GTK dropped the text. Escape both with
GLib.markup_escape_text.

Also correct the v0.17.0 notes in docs/UPDATE.md: the Snap never
bundled VOSK; it installs the project without extras.
2026-11-02 18:46:31 -08:00
c461cf5147 fix(snap): build from locked python inputs and verify artifacts (#1041)
* fix(snap): build and verify payload from locked python inputs

* docs(snap): document locked inputs and artifact verification

* test(clipboard): isolate restore workers between tests

* test(packaging): tighten isolation and clarify snap audit guarantees

* fix(ci): run snap recipe tests on snap-only changes

A change to snap/snapcraft.yaml or snap/local/smoke-test.sh only matched
the snap filter, so the Python tests that guard the recipe (including the
portable whisper.cpp flags from #957) and the smoke script were skipped.
Match all of snap/ in the python filter, as scripts/ already is.

* docs(snap): use a version placeholder in the smoke-test example

---------

Co-authored-by: Jatin <jatinkrmalik@gmail.com>
2026-11-02 12:31:14 -08:00
80e3019a74 feat(parakeet): add optional Underdog Bark 3.0 models, int8 and 4-bit (#1031)
* feat(parakeet): add optional Underdog Bark 3.0 int8 model

Adds bark-3.0 to the Parakeet model picker: Underdog Bark 3.0, an
English fine-tune of Parakeet TDT 0.6B v3, as the int8 sherpa-onnx
conversion published at velddev/Underdog-Bark-3.0-sherpa-onnx. It runs
on the existing sherpa-onnx recognizer, pinned to a revision with every
file checked against model_checksums.txt, like Orukeet (#840).

The conversion writes the unknown-word token where a quote mark was, so
the Parakeet transcript drops <unk>; the other models never emit it.

* docs(parakeet): say when to pick Bark 3.0; loosen its catalog test

The README now says Bark suits English dictation of conversational
speech and v3-european stays the choice for read or multilingual
speech. The test checks that bark-3.0 is offered rather than that it is
the last catalog entry, so a later model does not break it.

* test(parakeet): add docstrings to the Bark tests

* feat(parakeet): add optional 4-bit Underdog Bark 3.0 build

Adds bark-3.0-int4: the same Bark 3.0 weights quantized to 4-bit with
onnxruntime's HQQ quantizer, for machines short on memory. It needs
about half the RAM of the int8 build (0.64 GB against 1.28 GB peak) and
a 379 MiB download, at two to four times the CPU time (about 2x on
Intel, 3.7x on AMD by the publisher's measurement). The files are
published in velddev/Underdog-Bark-3.0-sherpa-onnx (Hugging Face PR #1),
and both Bark entries now pin its revision 3ae3af1, which holds both
builds; the int8 files are unchanged there.

Catalog entries gain an optional "precision" key, so the loader opens
encoder.int4.onnx and friends instead of assuming int8; every existing
model keeps the int8 default. The README section now covers both
builds in a few lines.

* test(parakeet): type the Bark test signatures

* docs(parakeet): name the Bark sherpa-onnx source and its pins

The README now says where both Bark builds download from (a pinned revision of
velddev/Underdog-Bark-3.0-sherpa-onnx), that it is an unofficial conversion, and
that each file is checked against its bundled SHA-256 pin, as the Orukeet
section does.

---------

Co-authored-by: Jatin <jatinkrmalik@gmail.com>
2026-11-02 12:31:08 -08:00
Jatin K MalikandGitHub f3913fb6bf fix(ui): show the selected microphone's full name in the device tooltip (#1029) (#1037)
The Input Device dropdown has a fixed width and cuts labels off at about
18 characters. Raw ALSA names such as "sof-hda-dsp: - (hw:0,6)" therefore
all look like "sof-hda-dsp: - (h…", and the tooltip always showed the same
generic text, so there was no way to tell which entry was selected.

The tooltip now shows the full label of the selected device. It updates
when the list is filled and every time the selection changes, and goes
back to the generic hint for System Default.
2026-11-02 12:31:02 -08:00
e66bd218d9 fix(audio): prevent dictation hangs on stalled microphones (#974)
* fix(audio): bound capture reads and support cancellation

* fix(recognition): bound and serialize capture shutdown

* fix(recognition): cancel retries and report stalled microphones

* fix(audio): prefer pulse when the ALSA default is unavailable

* fix(recognition): guard late callbacks and finalize capture tests

* docs(audio): explain input selection and stall recovery

* fix(speech): enforce auto-pause across buffered reload timeouts

* fix(speech): recover auto-resume after reload timeout

* test(speech): fix auto-pause follow-up test regressions

* fix(speech): retain auto-resume after reconfigure timeout

* fix(tray): preserve auto-pause recovery across suspend

* test(capture-shutdown): give the bare tray the suspend path's shortcut managers

_on_system_suspend now releases the main and per-language hotkey
listeners before sleep (#1025); the fixture builds TrayIndicator without
__init__, so it needs the two attributes present.

* fix(tray): release hotkey listeners on suspend even while auto-paused

Merging #1025's suspend cleanup with this branch's auto-pause handoff
left an early return that skipped shortcut_manager.stop() whenever a
configured game was active, keeping EVIOCGRABs held through sleep. The
paused branch now only owns the model-lifecycle work; listener release
and stopping active recognition run for every suspend.

* fix(tray): hold the apply lock only around the download's verify and save

Wrapping the whole recommended-model download in _apply_settings_lock
blocked every GTK-thread settings apply (e.g. Test Dictation) for the
length of the transfer. The engine already serializes reconfigures, so
the lock only needs to cover verifying the download still owns the
receipt and saving it; an apply that lands mid-download now proceeds
instead of freezing the app.

---------

Co-authored-by: Jatin K Malik <jatinkrmalik@gmail.com>
2026-10-26 21:25:50 -07:00