Commit Graph
3 Commits
Author SHA1 Message Date
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
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
047b379bd2 feat(audio): add PipeWire capture path with system-audio sources (#889)
* feat(audio): add PipeWire capture path with system-audio sources

Enumerate PipeWire sinks via pw-dump and expose their monitors as
"System audio: <name>" capture devices at negative device indices
(-2..), alongside the existing PortAudio microphones. Recording,
device test, and stream-reconnection paths route to a
pw-record-backed stream shaped like a PyAudio stream, so the VAD and
silence-detection loop is unchanged.

Playback ducking is skipped when the selected source is a monitor,
since ducking the default sink would also duck the captured audio.

Closes #751

* test(audio): restore stashed numpy instead of re-importing it

test_audio_input imports numpy lazily; deleting the MagicMock that
earlier test modules leave in sys.modules re-imported a second numpy
module object whose lazy submodule attributes (linalg, testing) were
unpopulated while sys.modules kept the first object's entries. The
next test file to reach for numpy.testing hit a __getattr__ import
loop (RecursionError in TestDownmixToMono on CI).

Restore the conftest-stashed _vocalinux_real_numpy instead, matching
the pattern tests/test_recognition_manager_device_config.py already
uses.

* fix(pipewire): drop PyAudio requirement for PipeWire sources, rebind source after reconnect

* docs(pipewire): restore PipeWireCaptureSource class docstring

* fix(audio): initialize PyAudio for mic reconnection after PipeWire session

A session started on a PipeWire sink never creates a PyAudio instance;
when capture later reconnects onto a PortAudio device the source needs
one to reopen, and a failed open dereferenced None calling terminate.

* fix(audio): harden PipeWire source resolution, reads, and cleanup

- resolve stored names by node.name/description; a stored name that no
  longer resolves never falls back to a positional index
- require pw-record before listing system-audio sources in the picker
- bound pw-record chunk reads with a stall watchdog so stopping cannot
  block on a wedged stream
- close the reconnection probe stream when its verification read fails
- log cleanup failures instead of swallowing them; narrow exception
  handlers in enumeration and PyAudio reconnection init
- annotate test helpers and signatures per repo style

---------

Co-authored-by: Jatin K Malik <jatinkrmalik@gmail.com>
2026-09-30 02:07:41 -07:00