diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 33e988e..958d467 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -1,6 +1,6 @@
---
name: Bug Report
-about: Report a bug to help improve Vocalinux
+about: Report a bug to help improve Voculinux
title: "[BUG] "
labels: bug
assignees: ''
@@ -32,7 +32,7 @@ If applicable, attach screenshots.
- **OS / distro**: (e.g. Ubuntu 24.04)
- **Python version**: (e.g. 3.12; 3.11+ required)
-- **Vocalinux version**: (`vocalinux --version`)
+- **Voculinux version**: (`voculinux --version`)
- **Install method**: (installer / AppImage / AUR / Flatpak / Snap / source / PyPI)
- **Display server**: (X11 / Wayland)
- **Desktop environment**: (e.g. GNOME, KDE Plasma)
@@ -41,7 +41,7 @@ If applicable, attach screenshots.
## Debug logs
-Run `vocalinux --debug` and paste the relevant output:
+Run `voculinux --debug` and paste the relevant output:
```
[paste logs here]
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
index 14580fa..cffd071 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -1,6 +1,6 @@
---
name: Feature Request
-about: Suggest an idea for Vocalinux
+about: Suggest an idea for Voculinux
title: "[FEATURE] "
labels: enhancement
assignees: ''
@@ -8,7 +8,7 @@ assignees: ''
## Feature description
-What you would like Vocalinux to do.
+What you would like Voculinux to do.
## Problem
diff --git a/.github/labeler.yml b/.github/labeler.yml
index da0f44d..3ce9e4c 100644
--- a/.github/labeler.yml
+++ b/.github/labeler.yml
@@ -8,7 +8,7 @@ app:
- "src/**/*"
- "pyproject.toml"
- "MANIFEST.in"
- - "vocalinux.desktop"
+ - "voculinux.desktop"
# Next.js website
web:
diff --git a/.github/workflows/codeberg-mirror.yml b/.github/workflows/codeberg-mirror.yml
index 500c260..d8d1c1f 100644
--- a/.github/workflows/codeberg-mirror.yml
+++ b/.github/workflows/codeberg-mirror.yml
@@ -41,7 +41,7 @@ jobs:
export GIT_SSH_COMMAND="ssh -i ~/.ssh/codeberg_mirror -o IdentitiesOnly=yes"
- git remote add codeberg git@codeberg.org:jatinkrmalik/vocalinux.git
+ git remote add codeberg git@codeberg.org:jatinkrmalik/voculinux.git
git push codeberg --all
# Force tags so the mirror stays aligned with GitHub when a tag
# already exists on Codeberg (retagged release or prior partial sync).
diff --git a/.github/workflows/distro-test-matrix.yml b/.github/workflows/distro-test-matrix.yml
index efa8ff1..cc92fcf 100644
--- a/.github/workflows/distro-test-matrix.yml
+++ b/.github/workflows/distro-test-matrix.yml
@@ -11,7 +11,7 @@ on:
- 'uv.lock'
- 'requirements/**'
- 'src/vocalinux/version.py'
- - 'vocalinux.desktop'
+ - 'voculinux.desktop'
- '.github/workflows/distro-test-matrix.yml'
pull_request:
branches: [ main, master ]
@@ -23,7 +23,7 @@ on:
- 'uv.lock'
- 'requirements/**'
- 'src/vocalinux/version.py'
- - 'vocalinux.desktop'
+ - 'voculinux.desktop'
- '.github/workflows/distro-test-matrix.yml'
workflow_dispatch:
diff --git a/.github/workflows/flatpak.yml b/.github/workflows/flatpak.yml
index 188ffa3..18e809b 100644
--- a/.github/workflows/flatpak.yml
+++ b/.github/workflows/flatpak.yml
@@ -71,8 +71,8 @@ jobs:
- name: Build and bundle
uses: flatpak/flatpak-github-actions/flatpak-builder@79327416609af08178ad73b352877e51450790b3 # v6
with:
- bundle: vocalinux-${{ matrix.arch }}.flatpak
- manifest-path: packaging/flatpak/com.vocalinux.Vocalinux.yml
+ bundle: voculinux-${{ matrix.arch }}.flatpak
+ manifest-path: packaging/flatpak/com.voculinux.Voculinux.yml
# The action appends -${arch} and restore-keys is
# `flatpak-builder-${arch}`, so the key has to start with that
# prefix. Putting the packaging hash first made every lock
@@ -80,7 +80,7 @@ jobs:
# github.sha in the key forced a full rebuild every run.
cache-key: flatpak-builder-${{ matrix.arch }}-${{ hashFiles('packaging/flatpak/**') }}
arch: ${{ matrix.arch }}
- artifact-name: vocalinux-flatpak-${{ matrix.arch }}
+ artifact-name: voculinux-flatpak-${{ matrix.arch }}
# Flathub mirrors screenshots at submission time; mirror locally so the
# builddir linter does not flag the external screenshot URL.
mirror-screenshots-url: https://dl.flathub.org/media
diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml
index eaf5678..2facd27 100644
--- a/.github/workflows/nightly.yml
+++ b/.github/workflows/nightly.yml
@@ -77,12 +77,12 @@ jobs:
- name: Cache AppImage build tools
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
- path: ~/.cache/vocalinux-appimage
+ path: ~/.cache/voculinux-appimage
key: appimage-native-${{ runner.arch }}-${{ steps.native-cache.outputs.id }}
- name: Build AppImage (x86_64)
env:
- VOCALINUX_APPIMAGE_REQUIRE_VULKAN: "1"
+ VOCULINUX_APPIMAGE_REQUIRE_VULKAN: "1"
run: |
bash packaging/appimage/docker-build.sh dist/*.whl "${{ steps.version.outputs.version }}" dist
ls -la dist/*.AppImage
@@ -159,13 +159,13 @@ jobs:
#### Quick Install (Recommended)
Download the wheel file below and install:
\`\`\`bash
- pip install vocalinux-${{ steps.version.outputs.version }}-py3-none-any.whl
+ pip install voculinux-${{ steps.version.outputs.version }}-py3-none-any.whl
\`\`\`
#### From PyPI (Stable)
For the latest stable release:
\`\`\`bash
- pip install vocalinux
+ pip install voculinux
\`\`\`
#### Using Install Script
@@ -176,8 +176,8 @@ jobs:
#### AppImage (no install, no root)
Download the \`.AppImage\` matching your CPU (\`x86_64\` or \`aarch64\`) below:
\`\`\`bash
- chmod +x Vocalinux-${{ steps.version.outputs.version }}-x86_64.AppImage
- ./Vocalinux-${{ steps.version.outputs.version }}-x86_64.AppImage
+ chmod +x Voculinux-${{ steps.version.outputs.version }}-x86_64.AppImage
+ ./Voculinux-${{ steps.version.outputs.version }}-x86_64.AppImage
\`\`\`
Requires \`xdotool\`/\`wtype\`/\`ydotool\` on the host for text injection, same as the PyPI install path.
@@ -197,16 +197,16 @@ jobs:
### Files
- - **\`vocalinux-${{ steps.version.outputs.version }}-py3-none-any.whl\`** - Python wheel (recommended)
- - **\`vocalinux-${{ steps.version.outputs.version }}.tar.gz\`** - Source distribution
- - **\`Vocalinux-${{ steps.version.outputs.version }}-x86_64.AppImage\`** - Self-contained, no install (Intel/AMD)
- - **\`Vocalinux-${{ steps.version.outputs.version }}-aarch64.AppImage\`** - Self-contained, no install (ARM64, added shortly after this release is published)
+ - **\`voculinux-${{ steps.version.outputs.version }}-py3-none-any.whl\`** - Python wheel (recommended)
+ - **\`voculinux-${{ steps.version.outputs.version }}.tar.gz\`** - Source distribution
+ - **\`Voculinux-${{ steps.version.outputs.version }}-x86_64.AppImage\`** - Self-contained, no install (Intel/AMD)
+ - **\`Voculinux-${{ steps.version.outputs.version }}-aarch64.AppImage\`** - Self-contained, no install (ARM64, added shortly after this release is published)
---
### Links
- - [Documentation](https://vocalinux.com)
+ - [Documentation](https://voculinux.com)
- [Report Issues](https://github.com/VocaHQ/vocalinux/issues)
- [Other Releases](https://github.com/VocaHQ/vocalinux/releases)
@@ -242,7 +242,7 @@ jobs:
- name: Upload artifacts (backup)
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
- name: vocalinux-nightly-${{ steps.version.outputs.version }}
+ name: voculinux-nightly-${{ steps.version.outputs.version }}
path: dist/
retention-days: 7
@@ -296,12 +296,12 @@ jobs:
- name: Cache AppImage build tools
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
- path: ~/.cache/vocalinux-appimage
+ path: ~/.cache/voculinux-appimage
key: appimage-native-${{ runner.arch }}-${{ steps.native-cache.outputs.id }}
- name: Build AppImage (aarch64)
env:
- VOCALINUX_APPIMAGE_REQUIRE_VULKAN: "1"
+ VOCULINUX_APPIMAGE_REQUIRE_VULKAN: "1"
run: |
bash packaging/appimage/docker-build.sh dist/*.whl "${{ needs.nightly.outputs.version }}" dist
ls -la dist/*.AppImage
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 6f1d327..b647efd 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -15,11 +15,11 @@ env:
# Build against the supported floor (requires-python in pyproject.toml).
PYTHON_VERSION: '3.11'
# The dedicated "tap" repo and the URL Pages serves it at. A custom
- # domain (e.g. flatpak.vocalinux.com) overrides both via the vars.
+ # domain (e.g. flatpak.voculinux.com) overrides both via the vars.
FLATPAK_REMOTE_REPO: ${{ vars.FLATPAK_REMOTE_REPO || 'VocaHQ/vocalinux-flatpak' }}
- FLATPAK_REMOTE_URL: ${{ vars.FLATPAK_REMOTE_URL || 'https://vocahq.github.io/vocalinux-flatpak/repo' }}
- FLATPAKREPO_URL: ${{ vars.FLATPAKREPO_URL || 'https://vocahq.github.io/vocalinux-flatpak/vocahq.flatpakrepo' }}
- FLATPAKREF_URL: ${{ vars.FLATPAKREF_URL || 'https://vocahq.github.io/vocalinux-flatpak/com.vocalinux.Vocalinux.flatpakref' }}
+ FLATPAK_REMOTE_URL: ${{ vars.FLATPAK_REMOTE_URL || 'https://vocahq.github.io/voculinux-flatpak/repo' }}
+ FLATPAKREPO_URL: ${{ vars.FLATPAKREPO_URL || 'https://vocahq.github.io/voculinux-flatpak/vocahq.flatpakrepo' }}
+ FLATPAKREF_URL: ${{ vars.FLATPAKREF_URL || 'https://vocahq.github.io/voculinux-flatpak/com.voculinux.Voculinux.flatpakref' }}
jobs:
build-and-release:
@@ -101,12 +101,12 @@ jobs:
- name: Cache AppImage build tools
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
- path: ~/.cache/vocalinux-appimage
+ path: ~/.cache/voculinux-appimage
key: appimage-native-${{ runner.arch }}-${{ steps.native-cache.outputs.id }}
- name: Build AppImage (x86_64)
env:
- VOCALINUX_APPIMAGE_REQUIRE_VULKAN: "1"
+ VOCULINUX_APPIMAGE_REQUIRE_VULKAN: "1"
run: |
bash packaging/appimage/docker-build.sh dist/*.whl "${{ steps.get_version.outputs.VERSION }}" dist
ls -la dist/*.AppImage
@@ -151,7 +151,7 @@ jobs:
```bash
flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
flatpak remote-add --if-not-exists vocahq __FLATPAKREPO_URL__
- flatpak install vocahq com.vocalinux.Vocalinux
+ flatpak install vocahq com.voculinux.Voculinux
```
Or download the `.flatpak` matching your CPU (`x86_64` or `aarch64`, attached
@@ -161,8 +161,8 @@ jobs:
flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
flatpak install flathub org.gnome.Platform//50
- flatpak install --user ./Vocalinux-__VERSION__-x86_64.flatpak
- flatpak run com.vocalinux.Vocalinux
+ flatpak install --user ./Voculinux-__VERSION__-x86_64.flatpak
+ flatpak run com.voculinux.Voculinux
```
EOF
else
@@ -175,8 +175,8 @@ jobs:
flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
flatpak install flathub org.gnome.Platform//50
- flatpak install --user ./Vocalinux-__VERSION__-x86_64.flatpak
- flatpak run com.vocalinux.Vocalinux
+ flatpak install --user ./Voculinux-__VERSION__-x86_64.flatpak
+ flatpak run com.voculinux.Voculinux
```
EOF
if [ "$prerelease" = true ]; then
@@ -223,7 +223,7 @@ jobs:
### From Source
```bash
git clone https://github.com/VocaHQ/vocalinux.git
- cd vocalinux
+ cd voculinux
./install.sh
```
@@ -231,10 +231,10 @@ jobs:
```bash
# Install the Linux system packages first:
# GTK/AppIndicator, PortAudio, and xdotool/wtype are required.
- python3 -m venv ~/.local/share/vocalinux-pypi/venv --system-site-packages
- source ~/.local/share/vocalinux-pypi/venv/bin/activate
- pip install vocalinux
- vocalinux
+ python3 -m venv ~/.local/share/voculinux-pypi/venv --system-site-packages
+ source ~/.local/share/voculinux-pypi/venv/bin/activate
+ pip install voculinux
+ voculinux
```
PyPI installs the Python package only. For automatic system dependency,
@@ -243,15 +243,15 @@ jobs:
### Arch Linux (AUR)
```bash
- yay -S vocalinux
+ yay -S voculinux
```
### AppImage (no install, no root)
Download the `.AppImage` matching your CPU (`x86_64` or `aarch64`, the latter attached
shortly after this release is published) below:
```bash
- chmod +x Vocalinux-${{ steps.get_version.outputs.VERSION }}-x86_64.AppImage
- ./Vocalinux-${{ steps.get_version.outputs.VERSION }}-x86_64.AppImage
+ chmod +x Voculinux-${{ steps.get_version.outputs.VERSION }}-x86_64.AppImage
+ ./Voculinux-${{ steps.get_version.outputs.VERSION }}-x86_64.AppImage
```
Still requires `xdotool`/`wtype`/`ydotool` on the host for text injection, same as the PyPI path.
@@ -260,10 +260,10 @@ jobs:
attached shortly after this release is published):
```bash
# Debian / Ubuntu
- sudo apt install ./vocalinux_*_amd64.deb
+ sudo apt install ./voculinux_*_amd64.deb
# Fedora
- sudo dnf install ./vocalinux-*.x86_64.rpm
+ sudo dnf install ./voculinux-*.x86_64.rpm
```
Thin packages: Python, GTK, PyGObject and the AppIndicator typelib come from the
distro, and `apt`/`dnf` resolves them. Only `pywhispercpp` and `pynput` are
@@ -278,13 +278,13 @@ jobs:
${{ steps.flatpak_notes.outputs.flatpak }}
### Snap
- Tagged releases also attach `vocalinux_${{ steps.get_version.outputs.VERSION }}_amd64.snap`
+ Tagged releases also attach `voculinux_${{ steps.get_version.outputs.VERSION }}_amd64.snap`
and try the Snap Store (`edge` and `candidate`). `stable` is promoted
from candidate after QA by the `snap-promote.yml` dispatch workflow.
Wayland typing runs through the RemoteDesktop portal; the snap ships no `uinput` plug.
The GitHub `.snap` is also the sideload while a Store revision lags:
```bash
- sudo snap install --dangerous ./vocalinux_${{ steps.get_version.outputs.VERSION }}_amd64.snap
+ sudo snap install --dangerous ./voculinux_${{ steps.get_version.outputs.VERSION }}_amd64.snap
```
`--dangerous` is required because this file is not a Store revision. It will not
refresh from the Store. amd64 only.
@@ -298,7 +298,7 @@ jobs:
```
Each artifact also carries GitHub build provenance, which ties it to this workflow run:
```bash
- gh attestation verify Vocalinux-${{ steps.get_version.outputs.VERSION }}-x86_64.AppImage \
+ gh attestation verify Voculinux-${{ steps.get_version.outputs.VERSION }}-x86_64.AppImage \
--repo ${{ github.repository }}
```
@@ -343,12 +343,12 @@ jobs:
- name: Cache AppImage build tools
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
- path: ~/.cache/vocalinux-appimage
+ path: ~/.cache/voculinux-appimage
key: appimage-native-${{ runner.arch }}-${{ steps.native-cache.outputs.id }}
- name: Build AppImage (aarch64)
env:
- VOCALINUX_APPIMAGE_REQUIRE_VULKAN: "1"
+ VOCULINUX_APPIMAGE_REQUIRE_VULKAN: "1"
run: |
bash packaging/appimage/docker-build.sh dist/*.whl "${{ steps.get_version.outputs.VERSION }}" dist
ls -la dist/*.AppImage
@@ -492,8 +492,8 @@ jobs:
- name: Build and bundle
uses: flatpak/flatpak-github-actions/flatpak-builder@79327416609af08178ad73b352877e51450790b3 # v6
with:
- bundle: Vocalinux-${{ steps.get_version.outputs.VERSION }}-x86_64.flatpak
- manifest-path: packaging/flatpak/com.vocalinux.Vocalinux.yml
+ bundle: Voculinux-${{ steps.get_version.outputs.VERSION }}-x86_64.flatpak
+ manifest-path: packaging/flatpak/com.voculinux.Voculinux.yml
# Same prefix rule as flatpak.yml: restore-keys is
# `flatpak-builder-${arch}`. The action appends -${arch} again.
cache-key: flatpak-builder-x86_64-${{ hashFiles('packaging/flatpak/**') }}
@@ -506,7 +506,7 @@ jobs:
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: flatpak-x86_64
- path: Vocalinux-${{ steps.get_version.outputs.VERSION }}-x86_64.flatpak
+ path: Voculinux-${{ steps.get_version.outputs.VERSION }}-x86_64.flatpak
if-no-files-found: error
retention-days: 7
@@ -529,8 +529,8 @@ jobs:
- name: Build and bundle
uses: flatpak/flatpak-github-actions/flatpak-builder@79327416609af08178ad73b352877e51450790b3 # v6
with:
- bundle: Vocalinux-${{ steps.get_version.outputs.VERSION }}-aarch64.flatpak
- manifest-path: packaging/flatpak/com.vocalinux.Vocalinux.yml
+ bundle: Voculinux-${{ steps.get_version.outputs.VERSION }}-aarch64.flatpak
+ manifest-path: packaging/flatpak/com.voculinux.Voculinux.yml
cache-key: flatpak-builder-aarch64-${{ hashFiles('packaging/flatpak/**') }}
arch: aarch64
upload-artifact: false
@@ -540,7 +540,7 @@ jobs:
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: flatpak-aarch64
- path: Vocalinux-${{ steps.get_version.outputs.VERSION }}-aarch64.flatpak
+ path: Voculinux-${{ steps.get_version.outputs.VERSION }}-aarch64.flatpak
if-no-files-found: error
retention-days: 7
@@ -715,27 +715,27 @@ jobs:
echo '[Flatpak Repo]'
echo 'Title=VocaHQ'
echo "Url=${FLATPAK_REMOTE_URL}"
- echo 'Homepage=https://vocalinux.com'
- echo 'Comment=Official Vocalinux Flatpak remote'
- echo 'Description=Self-hosted Vocalinux Flatpak repository'
- echo 'Icon=https://vocalinux.com/icon-512x512.png'
+ echo 'Homepage=https://voculinux.com'
+ echo 'Comment=Official Voculinux Flatpak remote'
+ echo 'Description=Self-hosted Voculinux Flatpak repository'
+ echo 'Icon=https://voculinux.com/icon-512x512.png'
echo 'DefaultBranch=stable'
echo "GPGKey=$(base64 -w0 "$RUNNER_TEMP/pubkey.gpg")"
} > publish/vocahq.flatpakrepo
{
echo '[Flatpak Ref]'
echo 'Version=1'
- echo 'Title=Vocalinux'
- echo 'Name=com.vocalinux.Vocalinux'
+ echo 'Title=Voculinux'
+ echo 'Name=com.voculinux.Voculinux'
echo 'Branch=stable'
echo "Url=${FLATPAK_REMOTE_URL}"
echo 'SuggestRemoteName=vocahq'
echo 'RuntimeRepo=https://dl.flathub.org/repo/flathub.flatpakrepo'
echo 'IsRuntime=false'
- echo 'Homepage=https://vocalinux.com'
- echo 'Icon=https://vocalinux.com/icon-512x512.png'
+ echo 'Homepage=https://voculinux.com'
+ echo 'Icon=https://voculinux.com/icon-512x512.png'
echo "GPGKey=$(base64 -w0 "$RUNNER_TEMP/pubkey.gpg")"
- } > publish/com.vocalinux.Vocalinux.flatpakref
+ } > publish/com.voculinux.Voculinux.flatpakref
cp "$RUNNER_TEMP/pubkey.gpg" publish/vocahq.gpg
grep -v GPGKey publish/vocahq.flatpakrepo
sed -e "s|__FLATPAKREPO_URL__|${FLATPAKREPO_URL}|g" \
@@ -751,7 +751,7 @@ jobs:
external_repository: ${{ env.FLATPAK_REMOTE_REPO }}
publish_dir: ./publish
publish_branch: gh-pages
- commit_message: 'Vocalinux ${{ github.ref_name }}'
+ commit_message: 'Voculinux ${{ github.ref_name }}'
attach-flatpak:
name: Attach Flatpak bundles
@@ -854,7 +854,7 @@ jobs:
id-token: write # PyPI trusted publishing; there is no API token to leak
environment:
name: pypi
- url: https://pypi.org/project/vocalinux/
+ url: https://pypi.org/project/voculinux/
steps:
# Not a rebuild: the artifact attached to the GitHub release, so one
# checksum describes both.
@@ -892,14 +892,14 @@ jobs:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh release download "$GITHUB_REF_NAME" --repo "$GITHUB_REPOSITORY" \
- --pattern 'vocalinux-*.tar.gz' --pattern SHA256SUMS --dir release-source
+ --pattern 'voculinux-*.tar.gz' --pattern SHA256SUMS --dir release-source
- name: Verify provenance and prepare the exact source PKGBUILD
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
uv run --python "$(command -v python)" --locked --only-group release-build \
python scripts/prepare_aur_source.py \
- --sdist release-source/vocalinux-*.tar.gz --manifest release-source/SHA256SUMS \
+ --sdist release-source/voculinux-*.tar.gz --manifest release-source/SHA256SUMS \
--tag "$GITHUB_REF_NAME" --source-commit "$GITHUB_SHA" --output build/aur-source
- name: Build and install the exact source PKGBUILD on Arch
run: |
@@ -944,7 +944,7 @@ jobs:
if: steps.aur.outputs.configured == 'true'
uses: KSXGitHub/github-actions-deploy-aur@084b0d9b15415bf9cdb65d44dad1efe37a354050 # v4.2.0
with:
- pkgname: vocalinux
+ pkgname: voculinux
pkgbuild: aur-source/PKGBUILD
updpkgsums: 'false'
commit_username: ${{ secrets.AUR_USERNAME }}
@@ -985,7 +985,7 @@ jobs:
run: |
set -euo pipefail
TAG="${GITHUB_REF#refs/tags/v}"
- PKGBUILD=packaging/aur/vocalinux-bin/PKGBUILD
+ PKGBUILD=packaging/aur/voculinux-bin/PKGBUILD
sed -i "s/^pkgver=.*/pkgver=${TAG//-/}/; s/^_tag=.*/_tag=${TAG}/; s/^pkgrel=.*/pkgrel=1/" "$PKGBUILD"
grep -E '^(pkgver|_tag|pkgrel)=' "$PKGBUILD"
@@ -998,21 +998,21 @@ jobs:
set -euo pipefail
tag="${GITHUB_REF_NAME#v}"
for arch in x86_64 aarch64; do
- url="https://github.com/VocaHQ/vocalinux/releases/download/${GITHUB_REF_NAME}/Vocalinux-${tag}-${arch}.AppImage"
+ url="https://github.com/VocaHQ/vocalinux/releases/download/${GITHUB_REF_NAME}/Voculinux-${tag}-${arch}.AppImage"
sum="$(curl -fsSL "$url" | sha256sum | cut -d' ' -f1)"
sed -i "s/^sha256sums_${arch}=('[0-9a-f]*')/sha256sums_${arch}=('${sum}')/" \
- packaging/aur/vocalinux-bin/PKGBUILD
+ packaging/aur/voculinux-bin/PKGBUILD
done
- name: Publish AUR -bin package
if: steps.aur.outputs.configured == 'true'
uses: KSXGitHub/github-actions-deploy-aur@084b0d9b15415bf9cdb65d44dad1efe37a354050 # v4.2.0
with:
- pkgname: vocalinux-bin
- # The -bin PKGBUILD names local sources (vocalinux.desktop,
- # vocalinux.svg, LICENSE); publishing the whole directory mirrors
+ pkgname: voculinux-bin
+ # The -bin PKGBUILD names local sources (voculinux.desktop,
+ # voculinux.svg, LICENSE); publishing the whole directory mirrors
# them into the AUR repo instead of shipping a lone PKGBUILD.
- asset_dir: packaging/aur/vocalinux-bin
+ asset_dir: packaging/aur/voculinux-bin
# Sums are pinned in the step above for BOTH arches; regenerating
# here would only refresh the x86_64 array.
updpkgsums: 'false'
@@ -1195,5 +1195,5 @@ jobs:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./web/out
publish_branch: gh-pages
- cname: vocalinux.com
+ cname: voculinux.com
force_orphan: true
diff --git a/.github/workflows/snap-promote.yml b/.github/workflows/snap-promote.yml
index 45b2eff..16a0b89 100644
--- a/.github/workflows/snap-promote.yml
+++ b/.github/workflows/snap-promote.yml
@@ -77,7 +77,7 @@ jobs:
run: |
set -euo pipefail
VERSION="${TAG#v}"
- /snap/bin/snapcraft status vocalinux | tee /tmp/snap-status.txt
+ /snap/bin/snapcraft status voculinux | tee /tmp/snap-status.txt
# POSIX: mawk has no \S — use a literal non-space class.
row=$(awk '/^[^ \t]/ { track = $1 }
track == "latest" && $1 == "candidate" { print $2, $3; exit }
@@ -110,7 +110,7 @@ jobs:
row=$(awk '/^[^ \t]/ { track = $1 }
track == "latest" && $1 == "candidate" { print $2, $3; exit }
track == "latest" && $3 == "candidate" { print $4, $5; exit }' \
- <(/snap/bin/snapcraft status vocalinux))
+ <(/snap/bin/snapcraft status voculinux))
read -r seen_version revision <<<"$row"
if [ "${revision:-}" != "$REVISION" ] || [ "$seen_version" != "$VERSION" ]; then
echo "latest/candidate moved on (now version=${seen_version:-none} revision=${revision:-none}); aborting instead of promoting the stale revision" >&2
@@ -123,5 +123,5 @@ jobs:
REVISION: ${{ steps.candidate.outputs.revision }}
run: |
set -euo pipefail
- /snap/bin/snapcraft release vocalinux "$REVISION" latest/stable
- /snap/bin/snapcraft status vocalinux
+ /snap/bin/snapcraft release voculinux "$REVISION" latest/stable
+ /snap/bin/snapcraft status voculinux
diff --git a/.github/workflows/unified-pipeline.yml b/.github/workflows/unified-pipeline.yml
index 8329b14..3a5ef40 100644
--- a/.github/workflows/unified-pipeline.yml
+++ b/.github/workflows/unified-pipeline.yml
@@ -1,4 +1,4 @@
-name: Vocalinux CI
+name: Voculinux CI
on:
push:
@@ -51,7 +51,7 @@ jobs:
# entry and the icon into the AppDir.
- 'install.sh'
- 'install.d/**'
- - 'vocalinux.desktop'
+ - 'voculinux.desktop'
- 'resources/**'
- 'justfile'
# scripts/ is guarded by tests/ and one of them is executed by the
@@ -65,7 +65,7 @@ jobs:
- '.pre-commit-config.yaml'
- '.github/workflows/unified-pipeline.yml'
- '.github/workflows/release.yml'
- # The AUR gate builds packaging/aur/vocalinux/PKGBUILD from this
+ # The AUR gate builds packaging/aur/voculinux/PKGBUILD from this
# tree. Its depends= mirror pyproject.toml, so every python change
# reaches the gate through the python filter above; this filter
# exists so a PKGBUILD-only change runs the gate without dragging
@@ -350,12 +350,12 @@ jobs:
- name: Cache AppImage build tools
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
- path: ~/.cache/vocalinux-appimage
+ path: ~/.cache/voculinux-appimage
key: appimage-native-${{ runner.arch }}-${{ steps.native-cache.outputs.id }}
- name: Build AppImage
env:
- VOCALINUX_APPIMAGE_REQUIRE_VULKAN: "1"
+ VOCULINUX_APPIMAGE_REQUIRE_VULKAN: "1"
run: |
VERSION=$(grep -oP '__version__\s*=\s*"\K[^"]+' src/vocalinux/version.py)
WHEEL=$(ls dist/*.whl)
@@ -365,7 +365,7 @@ jobs:
- name: Upload AppImage artifact
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
- name: vocalinux-appimage-${{ matrix.arch }}
+ name: voculinux-appimage-${{ matrix.arch }}
path: dist/*.AppImage
retention-days: 7
@@ -394,7 +394,7 @@ jobs:
- name: Download the AppImage built above
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
- name: vocalinux-appimage-x86_64
+ name: voculinux-appimage-x86_64
path: dist
- name: Boot it on ${{ matrix.distro }}
@@ -434,7 +434,7 @@ jobs:
run: |
uv run --python "$(command -v python)" --locked --only-group release-build \
python scripts/prepare_aur_source.py \
- --local-unattested --sdist dist/vocalinux-*.tar.gz --output build/aur-source
+ --local-unattested --sdist dist/voculinux-*.tar.gz --output build/aur-source
- name: Build the PKGBUILD on Arch
run: |
@@ -445,7 +445,7 @@ jobs:
# The .deb and .rpm exist to be installed and run, so the gate does exactly
# that: build both in the pinned Debian 12 image release.yml uses, then
- # install them in distro containers and run vocalinux --version plus an
+ # install them in distro containers and run voculinux --version plus an
# import smoke. debian:12 and ubuntu:24.04 exercise the .deb's dependency
# list (and the vendored cp311/cp312 wheels), fedora:42 the .rpm's.
native-build:
@@ -535,7 +535,7 @@ jobs:
- name: Upload the verified snap
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
- name: vocalinux-snap-amd64
+ name: voculinux-snap-amd64
path: ${{ steps.build.outputs.snap }}
if-no-files-found: error
retention-days: 7
@@ -628,5 +628,5 @@ jobs:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./web/out
publish_branch: gh-pages
- cname: vocalinux.com
+ cname: voculinux.com
force_orphan: true
diff --git a/.gitignore b/.gitignore
index d042f3a..145844c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,7 +24,7 @@ env/
ENV/
.env
.venv/
-activate-vocalinux.sh
+activate-voculinux.sh
# Local development settings
.vscode/
diff --git a/.oss-scanner/Dockerfile b/.oss-scanner/Dockerfile
index 5d9181f..a768bd4 100644
--- a/.oss-scanner/Dockerfile
+++ b/.oss-scanner/Dockerfile
@@ -23,7 +23,7 @@ ENV UV_PYTHON_INSTALL_DIR=/opt/uv-python \
UV_LINK_MODE=copy
RUN uv sync --locked --extra dev --extra vad
-# Make the project venv the default interpreter, so `python`, `pytest` and `vocalinux` work offline.
+# Make the project venv the default interpreter, so `python`, `pytest` and `voculinux` work offline.
ENV VIRTUAL_ENV=/src/.venv \
PATH=/src/.venv/bin:$PATH \
PYTHONPATH=/src \
diff --git a/.oss-scanner/threat_model.md b/.oss-scanner/threat_model.md
index fdac3a0..64511ae 100644
--- a/.oss-scanner/threat_model.md
+++ b/.oss-scanner/threat_model.md
@@ -1,6 +1,6 @@
# Threat model
-Vocalinux is a desktop voice-dictation app for Linux (X11 and Wayland). It records the
+Voculinux is a desktop voice-dictation app for Linux (X11 and Wayland). It records the
microphone, runs speech recognition, and types the result into whichever window has focus.
It runs as the logged-in user, never as root, and has no server of its own. Python
sources are under `src/vocalinux/`; the tests are under `tests/`.
@@ -26,9 +26,9 @@ has the user's privileges. Input from these places is untrusted:
(`docs/HTTP_REMOTE.md`), audio goes to a user-configured OpenAI-compatible or
whisper.cpp HTTP endpoint, and the JSON response is parsed and *typed into the
focused window*. Treat the server as hostile. It may return oversized, malformed,
- or control-character-laden responses, try to make Vocalinux type key sequences,
+ or control-character-laden responses, try to make Voculinux type key sequences,
shell commands or terminal escapes, or redirect requests elsewhere.
-4. **Local VocaGateway embed** (`gateway_embed/`). Vocalinux can start a
+4. **Local VocaGateway embed** (`gateway_embed/`). Voculinux can start a
[VocaGateway](https://github.com/VocaHQ/vocagateway) container via podman or docker
compose. It writes the compose `.env` (`runner.py`, with `_IMAGE_RE` guarding image
refs) and fetches pairing JSON and QR SVG from the gateway over HTTP (`pairing.py`,
@@ -66,7 +66,7 @@ has the user's privileges. Input from these places is untrusted:
- Out of scope: `web/` (the marketing website), `docs/`, `packaging/` (AppImage,
Flatpak, AUR, Snap recipes), `snap/`, `.github/` workflows, and bugs that live
in third-party engines (whisper.cpp, VOSK, sherpa-onnx, onnxruntime, torch)
- themselves. Report those upstream, unless Vocalinux calls them unsafely.
+ themselves. Report those upstream, unless Voculinux calls them unsafely.
## How to exercise it
- `python -m pytest -q tests/` runs the full suite offline. Hardware and display tests
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 0b7058b..c11b5e1 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,4 +1,4 @@
-# Pre-commit hooks for Vocalinux
+# Pre-commit hooks for Voculinux
# Run: pre-commit run --all-files
repos:
diff --git a/AGENTS.md b/AGENTS.md
index 84f6de3..1c9fcc6 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -1,4 +1,4 @@
-# AGENTS.md — Vocalinux
+# AGENTS.md — Voculinux
Voice dictation for Linux: GTK 3 tray app (Python) plus a Next.js marketing site in `web/`. Default speech engine is **whisper.cpp** (`pywhispercpp`); OpenAI Whisper, Vosk, and a user-configured remote API are optional. Do not invent features, user counts, or privacy claims.
@@ -13,18 +13,18 @@ Never create a branch, commit, or open a pull request in the primary checkout. A
```bash
git fetch origin
-git worktree add /tmp/vocalinux- -b / origin/main
+git worktree add /tmp/voculinux- -b / origin/main
# All edits, commits, and `gh pr create` happen inside that worktree.
-git worktree remove /tmp/vocalinux-
+git worktree remove /tmp/voculinux-
git worktree prune
```
Rules:
- One worktree per branch, one branch per PR
-- Place worktrees **outside** the primary working tree (`/tmp/vocalinux-` or a sibling directory such as `../.worktrees/vocalinux-`)
+- Place worktrees **outside** the primary working tree (`/tmp/voculinux-` or a sibling directory such as `../.worktrees/voculinux-`)
- Never run two tasks in the same worktree
- Never commit directly to `main`
- Clean up the worktree after the PR is pushed
@@ -97,7 +97,7 @@ just remote-install-gate debian:12 # remote curl|bash path end to end against H
just verify-release # check a published release as published (needs gh)
just reproducible-wheel # independent locked wheel builds; stages verified dist/ (needs uv)
just pre-commit # pre-commit run --all-files
-just run-debug # vocalinux --debug
+just run-debug # voculinux --debug
just run-source-debug
```
@@ -127,7 +127,7 @@ Use **uv 0.13.3** for `just lock` and `just export-check`, matching CI. Other ve
| pywhispercpp | Pinned in `install.sh` as `PYWHISPERCPP_VERSION` (keep in sync with `uv.lock`) |
| Installer build tools | `[dependency-groups].installer-build` exports to `requirements/installer-build.txt`. Bootstrap uses hashed wheels on new and reused venvs; source builds use these tools without build isolation. Its setuptools `>=83` floor keeps the pinned installer tools patched; do not add it to `[build-system]` (Arch). Backend rebuilds select pywhispercpp's complete hash block from `runtime.txt` via `scripts/installer_requirements.py`, with `--no-deps` so they cannot replace the runtime |
| Release build tools | `[dependency-groups].release-build` exports to `requirements/release-build.txt`. `scripts/build_reproducible_wheel.py` builds in two fresh source trees/venvs with hashed tools and `--no-isolation`, compares wheel bytes, and stages only canonical distributions in `dist/`. These build-only venvs exclude system site-packages: host setuptools plugins must not influence locked builds, and packaging does not import GTK. Repeat runs clean recognized diagnostics and staged archives matching retained canonical digests; staged copies are deleted first so interrupted cleanup remains retryable. Unrelated/modified files are preserved and block cleanup. Never wipe all of `build/`. PR and release CI use Python 3.11 and pinned uv. Failed build outputs/logs stay under `build/reproducible-wheel/`, excluded from release artifacts |
-| AUR source publication | Use the canonical release sdist, not a GitHub tag archive. `scripts/prepare_aur_source.py` (run with the locked `release-build` group) requires its published checksum and provenance from the exact release workflow/tag/commit before preparing a pinned PKGBUILD. Release CI builds/installs that unchanged recipe on current Arch; publication consumes only the gated artifact with `updpkgsums: false`. PR/local fixtures must explicitly use `--local-unattested` and are never publication inputs. `just aur-gate` keeps distributions, diagnostics and tooling in its own temporary directory, leaving shared packaging outputs and dev environments untouched; failures retain that directory and print its path. `vocalinux-bin` publication depends only on release creation and both AppImages, not the source gate or global checksums. Existing AUR provider stubs/pinned import smoke remain limited as documented in `docs/AUR.md` |
+| AUR source publication | Use the canonical release sdist, not a GitHub tag archive. `scripts/prepare_aur_source.py` (run with the locked `release-build` group) requires its published checksum and provenance from the exact release workflow/tag/commit before preparing a pinned PKGBUILD. Release CI builds/installs that unchanged recipe on current Arch; publication consumes only the gated artifact with `updpkgsums: false`. PR/local fixtures must explicitly use `--local-unattested` and are never publication inputs. `just aur-gate` keeps distributions, diagnostics and tooling in its own temporary directory, leaving shared packaging outputs and dev environments untouched; failures retain that directory and print its path. `voculinux-bin` publication depends only on release creation and both AppImages, not the source gate or global checksums. Existing AUR provider stubs/pinned import smoke remain limited as documented in `docs/AUR.md` |
| Installer Whisper export | Compiled universally from Python 3.11, constrained by `runtime.txt` and `installer-build.txt` to keep shared pins consistent. Uses a `+cpu` torch pin and best-match index resolution so the CPU index's older copies of shared packages do not downgrade the runtime |
| Remote installer | After cloning, hand off to the tagged `install.sh` with the original arguments and remote venv path. The installer and its exports must come from the same revision, including when the tag predates the pinned installer |
| `[vad]` extra | `onnxruntime` for Silero VAD |
@@ -136,7 +136,7 @@ Use **uv 0.13.3** for `just lock` and `just export-check`, matching CI. Other ve
| AppImage PyGObject | Pinned separately in `requirements/appimage.in`, and below 3.52: the AppImage bundles its own interpreter and builds PyGObject against the base image's girepository-1.0, while uv.lock's 3.56 needs girepository-2.0 (glib 2.80+) |
| AppImage build inputs | Base image, tooling, interpreter, shaderc and the Vulkan headers are pinned in `packaging/appimage/tool_checksums.txt`. Build with `just appimage` (docker) — building on the host ships the host's glibc, which is what kept the AppImage off Debian 12 |
| AppImage boot matrix | `packaging/appimage/boot-test.sh` runs the finished AppImage in distro containers, and the matrix in `unified-pipeline.yml` must keep distros both older and newer than the build image: the old ones prove the glibc floor, the new ones catch a bundle that breaks the host binaries it spawns. A distro added there needs its package recipe in the script — `tests/test_appimage_packaging.py` checks both |
-| Native packages (.deb / .rpm) | Thin packages built by nfpm in the pinned Debian 12 image (`packaging/native/tool_checksums.txt` pins the image and the nfpm releases). Python, GTK and PyGObject come from the distro; only `pywhispercpp` and `pynput` are vendored under `/usr/lib/vocalinux/vendor` (unpackaged on Debian/Fedora). `packaging/native/smoke-test.sh` installs the package per-distro and runs `vocalinux --version` plus an import smoke — `tests/test_native_packaging.py` keeps the deps lists, vendored set and CI matrix consistent offline |
+| Native packages (.deb / .rpm) | Thin packages built by nfpm in the pinned Debian 12 image (`packaging/native/tool_checksums.txt` pins the image and the nfpm releases). Python, GTK and PyGObject come from the distro; only `pywhispercpp` and `pynput` are vendored under `/usr/lib/voculinux/vendor` (unpackaged on Debian/Fedora). `packaging/native/smoke-test.sh` installs the package per-distro and runs `voculinux --version` plus an import smoke — `tests/test_native_packaging.py` keeps the deps lists, vendored set and CI matrix consistent offline |
| Snap Python inputs | `snap/local/build.py` uses `requirements/installer-build.txt` in an isolated, build-only venv and installs `requirements/runtime.txt` with hashes, no dependency resolution or build isolation. The project installs without dependencies or index access; never strip PyGObject from `pyproject.toml`. GI comes from the GNOME extension. Keep portable CPU flags and force the pinned pywhispercpp sdist without a wheel cache. PR/release CI installs the real artifact via `snap/local/smoke-test.sh` before publication. Native Ubuntu/GNOME/Snapcraft inputs remain channel-controlled, not byte-for-byte reproducible — see `docs/SNAP.md` |
| Flatpak deps | `packaging/flatpak/python3-dependencies.yaml` is generated from `requirements/vad.txt` (runtime dependencies plus the `[vad]` extra) by `scripts/sync_flatpak_deps.py` (`just flatpak-deps`, which `just lock` runs itself). It resolves each artifact by the digest uv already recorded, so the Flatpak downloads the bytes in `uv.lock`; `onnxruntime` is pinned to CPython wheels for each Flatpak architecture and the GNOME 50 Python version. The project installs there with `pip3 install --no-deps`, so nothing inside the build evaluates `pyproject.toml` — `tests/test_flatpak_packaging.py` checks the invariant offline |
| Speech models | Verified against digests pinned in `src/vocalinux/utils/model_checksums.txt` before install, by both `install.sh` and the runtime downloaders. **Fails closed** — an unpinned model is refused. Regenerate with `just model-checksums` (never by hand); `tests/test_model_checksums.py` fails if it falls behind. whisper.cpp URLs use a pinned Hugging Face commit, never `main` |
@@ -152,7 +152,7 @@ src/vocalinux/
│ ├── capture.py # PortAudio capture sources and device handling
│ ├── pipewire.py # PipeWire system-audio capture
│ └── playback_ducker.py # lower default sink while dictating
-├── single_instance.py # $XDG_DATA_HOME/vocalinux/instance.lock
+├── single_instance.py # $XDG_DATA_HOME/voculinux/instance.lock
├── auto_pause_monitor.py # unload model while configured apps run
├── model_keepalive.py # idle unload
├── suspend_handler.py # logind PrepareForSleep
@@ -243,9 +243,9 @@ Site-only work: `web/AGENTS.md` (commands, layout map). Product claims: `web/PRO
## Runtime (any Linux dev machine)
- Create runtime/dev venvs with `--system-site-packages`. Build-only venvs for `scripts/build_reproducible_wheel.py`, `just aur-gate` preparation and `snap/local/build.py` are the exception: exclude host packages to keep the locked tools isolated; the Snap runtime gets GI from its GNOME command chain. Never prune the developer environment to run a packaging gate
-- Kill the app by PID, never `pkill -f vocalinux` (matches editors, shells, and cwd paths)
-- Stale instance: `$XDG_DATA_HOME/vocalinux/instance.lock` (default `~/.local/share/vocalinux/instance.lock`)
-- Default dictation shortcut: hold Right Alt (push-to-talk). Existing `~/.config/vocalinux/config.json` wins
+- Kill the app by PID, never `pkill -f voculinux` (matches editors, shells, and cwd paths)
+- Stale instance: `$XDG_DATA_HOME/voculinux/instance.lock` (default `~/.local/share/voculinux/instance.lock`)
+- Default dictation shortcut: hold Right Alt (push-to-talk). Existing `~/.config/voculinux/config.json` wins
- Headless speech smoke: `pywhispercpp.model.Model` + `CommandProcessor` (first run may download the tiny model)
Update this file when commands, layout, or agent rules change.
diff --git a/CNAME b/CNAME
index 25761b0..461f008 100644
--- a/CNAME
+++ b/CNAME
@@ -1 +1 @@
-vocalinux.com
\ No newline at end of file
+voculinux.com
\ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index cf71026..64f195c 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,4 +1,4 @@
-# Contributing to Vocalinux
+# Contributing to Voculinux
Thanks for your interest in contributing. This guide covers setup, style, testing, and pull requests.
@@ -18,8 +18,8 @@ Participation is covered by our [Code of Conduct](CODE_OF_CONDUCT.md). Be respec
### Automated (recommended)
```bash
-git clone https://github.com/YOUR-USERNAME/vocalinux.git
-cd vocalinux
+git clone https://github.com/YOUR-USERNAME/voculinux.git
+cd voculinux
./install.sh --dev
```
@@ -152,7 +152,7 @@ just typecheck # mypy src/
### Project structure
```
-vocalinux/
+voculinux/
├── src/vocalinux/ # Application
│ ├── main.py
│ ├── speech_recognition/ # Engines + command processor
diff --git a/MANIFEST.in b/MANIFEST.in
index 88fc4f3..3000916 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,4 +1,4 @@
-include vocalinux.desktop
+include voculinux.desktop
include resources/icons/scalable/*.svg
include resources/sounds/*.wav
recursive-include src/vocalinux/resources *
diff --git a/README.md b/README.md
index acc93f6..112783d 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,8 @@
-Vocalinux turns speech into typed text in whatever app has focus. It is a free, AGPL-3.0-licensed desktop app for X11 and Wayland. After you download a model, local engines (whisper.cpp by default, plus OpenAI Whisper, Faster Whisper, VOSK, and Parakeet) run speech-to-text on your machine. An optional remote HTTP API is off unless you configure it.
+Voculinux turns speech into typed text in whatever app has focus. It is a free, AGPL-3.0-licensed desktop app for X11 and Wayland. After you download a model, local engines (whisper.cpp by default, plus OpenAI Whisper, Faster Whisper, VOSK, and Parakeet) run speech-to-text on your machine. An optional remote HTTP API is off unless you configure it.
No Voca account is required. Models download once. After that, speech-to-text stays on your machine.
@@ -54,7 +54,7 @@ No Voca account is required. Models download once. After that, speech-to-text st
## Screenshots
-Vocalinux in action. Full gallery on the [website screenshots page](https://vocalinux.com/screenshots/).
+Voculinux in action. Full gallery on the [website screenshots page](https://voculinux.com/screenshots/).
### Product
@@ -161,7 +161,7 @@ For a specific release tag, see [GitHub Releases](https://github.com/VocaHQ/voca
### Arch Linux (AUR)
```bash
-yay -S vocalinux
+yay -S voculinux
```
See [docs/AUR.md](docs/AUR.md).
@@ -172,28 +172,28 @@ Download the `x86_64` or `aarch64` AppImage from [Releases](https://github.com/V
### Distro packages (.deb / .rpm)
-Download the `.deb` (Debian 12+, Ubuntu 24.04+) or `.rpm` (Fedora) matching your CPU from [Releases](https://github.com/VocaHQ/vocalinux/releases) and install with `sudo apt install ./vocalinux_*.deb` or `sudo dnf install ./vocalinux-*.rpm`. Thin packages: Python and GTK come from the distro. No auto-update; CPU whisper.cpp. Details in [docs/INSTALL.md](docs/INSTALL.md).
+Download the `.deb` (Debian 12+, Ubuntu 24.04+) or `.rpm` (Fedora) matching your CPU from [Releases](https://github.com/VocaHQ/vocalinux/releases) and install with `sudo apt install ./voculinux_*.deb` or `sudo dnf install ./voculinux-*.rpm`. Thin packages: Python and GTK come from the distro. No auto-update; CPU whisper.cpp. Details in [docs/INSTALL.md](docs/INSTALL.md).
### Flatpak (any distro)
Install and auto-update via the self-hosted VocaHQ remote (`flatpak update` picks up each release):
```bash
-flatpak install https://vocahq.github.io/vocalinux-flatpak/com.vocalinux.Vocalinux.flatpakref
+flatpak install https://vocahq.github.io/voculinux-flatpak/com.voculinux.Voculinux.flatpakref
```
The `.flatpakref` adds the `vocahq` remote and resolves the GNOME runtime through Flathub. Manually instead:
```bash
flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
-flatpak remote-add --if-not-exists vocahq https://vocahq.github.io/vocalinux-flatpak/vocahq.flatpakrepo
-flatpak install vocahq com.vocalinux.Vocalinux
+flatpak remote-add --if-not-exists vocahq https://vocahq.github.io/voculinux-flatpak/vocahq.flatpakrepo
+flatpak install vocahq com.voculinux.Voculinux
```
-Or sideload a GitHub Release bundle (`Vocalinux--x86_64.flatpak` or `-aarch64.flatpak`) after the Flathub GNOME runtime is present — bundles do not auto-update:
+Or sideload a GitHub Release bundle (`Voculinux--x86_64.flatpak` or `-aarch64.flatpak`) after the Flathub GNOME runtime is present — bundles do not auto-update:
```bash
-flatpak install --user ./Vocalinux--x86_64.flatpak
+flatpak install --user ./Voculinux--x86_64.flatpak
```
Local build:
@@ -201,21 +201,21 @@ Local build:
```bash
flatpak install flathub org.gnome.Platform//50 org.gnome.Sdk//50
flatpak-builder --user --install --force-clean build-dir \
- packaging/flatpak/com.vocalinux.Vocalinux.yml
-flatpak run com.vocalinux.Vocalinux
+ packaging/flatpak/com.voculinux.Voculinux.yml
+flatpak run com.voculinux.Voculinux
```
Ships whisper.cpp with Vulkan. It is **not on Flathub** (submission [flathub#9368](https://github.com/flathub/flathub/pull/9368) closed 2026-07-23 on policy grounds). Details: [packaging/flatpak/README.md](packaging/flatpak/README.md).
### Snap (Ubuntu Snap Store)
-Listing: [snapcraft.io/vocalinux](https://snapcraft.io/vocalinux). `stable` is promoted from `candidate` after QA. Tagged releases also attach `vocalinux__amd64.snap` on GitHub.
+Listing: [snapcraft.io/voculinux](https://snapcraft.io/voculinux). `stable` is promoted from `candidate` after QA. Tagged releases also attach `voculinux__amd64.snap` on GitHub.
```bash
-sudo snap install vocalinux --edge
-sudo snap connect vocalinux:audio-record # if mic is not auto-connected
-sudo snap connect vocalinux:raw-input # global keyboard shortcuts (evdev)
-sudo snap connect vocalinux:hardware-observe # list keyboards (/proc/bus/input/devices)
+sudo snap install voculinux --edge
+sudo snap connect voculinux:audio-record # if mic is not auto-connected
+sudo snap connect voculinux:raw-input # global keyboard shortcuts (evdev)
+sudo snap connect voculinux:hardware-observe # list keyboards (/proc/bus/input/devices)
```
Native Wayland typing uses the RemoteDesktop portal: the compositor asks once on first dictation, nothing to connect. The recipe ships **no `uinput` plug** and no ydotool; the Store denied the super-privileged grant, which held the 0.17.0+ revisions and left **v0.16.2 (rev 7)** on edge. On KDE Plasma, KWin's portal can mistype letter case ([KDE bug 489021](https://bugs.kde.org/show_bug.cgi?id=489021)); set Virtual Keyboard to "IBus Wayland" so dictation types correctly.
@@ -223,8 +223,8 @@ Native Wayland typing uses the RemoteDesktop portal: the compositor asks once on
GitHub `.snap` files through v0.18.2 declare `uinput`, so KDE users who want ydotool can sideload that build and connect the plug manually:
```bash
-sudo snap install --dangerous ./vocalinux_0.18.2_amd64.snap
-sudo snap connect vocalinux:uinput # only in the v0.18.x sideload; the recipe no longer ships it
+sudo snap install --dangerous ./voculinux_0.18.2_amd64.snap
+sudo snap connect voculinux:uinput # only in the v0.18.x sideload; the recipe no longer ships it
```
### Nix / NixOS (flake)
@@ -234,13 +234,13 @@ nix run github:VocaHQ/vocalinux # try it
nix profile install github:VocaHQ/vocalinux
```
-The flake also ships `nixosModules.vocalinux` and `homeManagerModules.vocalinux` for declarative installs (`programs.vocalinux.enable = true`). The bundled pywhispercpp builds with Vulkan GPU inference. Details: [packaging/nix/README.md](packaging/nix/README.md).
+The flake also ships `nixosModules.voculinux` and `homeManagerModules.voculinux` for declarative installs (`programs.voculinux.enable = true`). The bundled pywhispercpp builds with Vulkan GPU inference. Details: [packaging/nix/README.md](packaging/nix/README.md).
### From source
```bash
git clone https://github.com/VocaHQ/vocalinux.git
-cd vocalinux
+cd voculinux
./install.sh
# or pick the engine up front
./install.sh --engine=whisper_cpp
@@ -251,12 +251,12 @@ cd vocalinux
### After installation
```bash
-vocalinux # if ~/.local/bin is on PATH
+voculinux # if ~/.local/bin is on PATH
# or
-~/.local/share/vocalinux/venv/bin/vocalinux
+~/.local/share/voculinux/venv/bin/voculinux
```
-You can also launch Vocalinux from your application menu.
+You can also launch Voculinux from your application menu.
### Nightly builds
@@ -271,7 +271,7 @@ Daily builds from `main` appear on [Releases](https://github.com/VocaHQ/vocalinu
| **Display** | X11 or Wayland |
| **Hardware** | Microphone; GPU optional (Vulkan) |
-The distro must ship Python 3.11+ because Vocalinux uses distro PyGObject (`python3-gi`). Ubuntu 22.04 (Python 3.10) and Debian 11 (3.9) are below that floor. Distribution notes: [docs/DISTRO_COMPATIBILITY.md](docs/DISTRO_COMPATIBILITY.md).
+The distro must ship Python 3.11+ because Voculinux uses distro PyGObject (`python3-gi`). Ubuntu 22.04 (Python 3.10) and Debian 11 (3.9) are below that floor. Distribution notes: [docs/DISTRO_COMPATIBILITY.md](docs/DISTRO_COMPATIBILITY.md).
## Usage
@@ -302,20 +302,20 @@ punctuation / line-break phrases in that language are also recognized
### CLI
```bash
-vocalinux --help
-vocalinux --version
-vocalinux --debug
-vocalinux --engine whisper_cpp # default
-vocalinux --engine whisper
-vocalinux --engine faster_whisper
-vocalinux --engine vosk
-vocalinux --engine parakeet
-vocalinux --engine remote_api
-vocalinux --model medium
-vocalinux --model medium.en-q5_0 # exact whisper.cpp variant
-vocalinux --model large-v3-turbo
-vocalinux --wayland
-vocalinux --start-minimized
+voculinux --help
+voculinux --version
+voculinux --debug
+voculinux --engine whisper_cpp # default
+voculinux --engine whisper
+voculinux --engine faster_whisper
+voculinux --engine vosk
+voculinux --engine parakeet
+voculinux --engine remote_api
+voculinux --model medium
+voculinux --model medium.en-q5_0 # exact whisper.cpp variant
+voculinux --model large-v3-turbo
+voculinux --wayland
+voculinux --start-minimized
```
### Autostart
@@ -324,9 +324,9 @@ vocalinux --start-minimized
### Configuration
-Stored at `~/.config/vocalinux/config.json`. Prefer the Settings dialog for day-to-day changes. **Settings → Speech Model** starts with a simple setup; expand **Advanced** for engine, size, and specialization. Set `post_processing.script_path` to an executable to transform each transcription result (stdin → stdout) before it is injected; leave empty to disable.
+Stored at `~/.config/voculinux/config.json`. Prefer the Settings dialog for day-to-day changes. **Settings → Speech Model** starts with a simple setup; expand **Advanced** for engine, size, and specialization. Set `post_processing.script_path` to an executable to transform each transcription result (stdin → stdout) before it is injected; leave empty to disable.
-Neural VAD (Silero) is used when `onnxruntime` is available; install via `pip install "vocalinux[vad]"` for manual/PyPI installs. The installer attempts this automatically.
+Neural VAD (Silero) is used when `onnxruntime` is available; install via `pip install "voculinux[vad]"` for manual/PyPI installs. The installer attempts this automatically.
## Documentation
@@ -358,7 +358,7 @@ Report vulnerabilities privately per [SECURITY.md](SECURITY.md).
```bash
git clone https://github.com/VocaHQ/vocalinux.git
-cd vocalinux
+cd voculinux
./install.sh --dev
source venv/bin/activate
pytest
@@ -379,11 +379,11 @@ Planned:
## Voca ecosystem
-Vocalinux is part of [VocaHQ](https://vocahq.com). On-device speech-to-text first, one app per platform. Optional [VocaGateway](https://vocagateway.vocahq.com) is self-hosted and not on-device.
+Voculinux is part of [VocaHQ](https://vocahq.com). On-device speech-to-text first, one app per platform. Optional [VocaGateway](https://vocagateway.vocahq.com) is self-hosted and not on-device.
| Platform | Project | Website | GitHub |
|----------|---------|---------|--------|
-| Linux | **VocaLinux** | [vocalinux.com](https://vocalinux.com) | [VocaHQ/vocalinux](https://github.com/VocaHQ/vocalinux) |
+| Linux | **Voculinux** | [voculinux.com](https://voculinux.com) | [VocaHQ/vocalinux](https://github.com/VocaHQ/vocalinux) |
| macOS | **VocaMac** | [vocamac.com](https://vocamac.com) | [VocaHQ/vocamac](https://github.com/VocaHQ/vocamac) |
| Windows | **VocaWin** | [vocawin.com](https://vocawin.com) | [VocaHQ/vocawin](https://github.com/VocaHQ/vocawin) |
| Phone | **VocaPhone** | [vocaphone.vocahq.com](https://vocaphone.vocahq.com) | [VocaHQ/vocaphone](https://github.com/VocaHQ/vocaphone) |
@@ -404,7 +404,7 @@ Bug reports, docs, and code are welcome. Start with [CONTRIBUTING.md](CONTRIBUTI
Thanks to everyone who has contributed code, docs, or fixes:
-
+
## Repository mirrors
@@ -414,7 +414,7 @@ GitHub is the primary forge for issues, PRs, CI, and releases.
| Role | URL |
|------|-----|
| Primary | https://github.com/VocaHQ/vocalinux |
-| Read-only mirror (Codeberg) | https://codeberg.org/jatinkrmalik/vocalinux |
+| Read-only mirror (Codeberg) | https://codeberg.org/jatinkrmalik/voculinux |
Open issues and pull requests on GitHub only.
@@ -440,7 +440,7 @@ offers `orukeet-v0.1.0`. It uses the existing local sherpa-onnx recognizer for
engine stay unchanged.
The download comes from a pinned revision of
-[oruk/orukeet on Hugging Face](https://huggingface.co/oruk/orukeet). Vocalinux
+[oruk/orukeet on Hugging Face](https://huggingface.co/oruk/orukeet). Voculinux
checks every file against its bundled SHA-256 pins and checks the publisher's
release manifest against those same pins. The manifest download participates
in Hugging Face's normal model-download accounting. Cached recognition works
diff --git a/SECURITY.md b/SECURITY.md
index 32ede63..74e4ba1 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -20,7 +20,7 @@ Do not open a public GitHub issue for security vulnerabilities.
**Preferred:** email the maintainer at **jatinkrmalik@gmail.com** with subject:
-`Vocalinux Security Vulnerability Report`
+`Voculinux Security Vulnerability Report`
Include:
@@ -35,7 +35,7 @@ If email is unavailable, use [GitHub private vulnerability reporting](https://gi
## Privacy design
-Vocalinux is built for local-first dictation:
+Voculinux is built for local-first dictation:
- Local engines process audio on-device after you download a model
- No Voca account is required for local engines
@@ -62,8 +62,8 @@ When the user enables **Remote API**, audio is uploaded to the configured server
| Path | Purpose | Permissions (typical) |
|------|---------|------------------------|
-| `~/.config/vocalinux/` | Configuration | User-only (mode 700) |
-| `~/.local/share/vocalinux/` | Data and models | User-only (mode 700) |
+| `~/.config/voculinux/` | Configuration | User-only (mode 700) |
+| `~/.local/share/voculinux/` | Data and models | User-only (mode 700) |
### Known limitations
diff --git a/SUPPORT.md b/SUPPORT.md
index fce6c01..dd37969 100644
--- a/SUPPORT.md
+++ b/SUPPORT.md
@@ -1,6 +1,6 @@
# Support
-Where to get help with Vocalinux.
+Where to get help with Voculinux.
## Documentation
@@ -14,7 +14,7 @@ Where to get help with Vocalinux.
| Distros and sessions | [docs/DISTRO_COMPATIBILITY.md](docs/DISTRO_COMPATIBILITY.md) |
| Remote transcription API | [docs/HTTP_REMOTE.md](docs/HTTP_REMOTE.md) |
| Full index | [docs/README.md](docs/README.md) |
-| Website | [vocalinux.com](https://vocalinux.com) |
+| Website | [voculinux.com](https://voculinux.com) |
## Community
@@ -25,7 +25,7 @@ Where to get help with Vocalinux.
| [Bug report](https://github.com/VocaHQ/vocalinux/issues/new?template=bug_report.md) | Something is broken |
| [Feature request](https://github.com/VocaHQ/vocalinux/issues/new?template=feature_request.md) | New capability proposals |
-When filing a bug, include OS/distro, `vocalinux --version`, install method, display server (X11/Wayland), engine, and a `vocalinux --debug` snippet.
+When filing a bug, include OS/distro, `voculinux --version`, install method, display server (X11/Wayland), engine, and a `voculinux --debug` snippet.
## Security
diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md
index 6587f8b..460bcbb 100644
--- a/docs/ARCHITECTURE.md
+++ b/docs/ARCHITECTURE.md
@@ -1,6 +1,6 @@
# Architecture
-Vocalinux is a GTK 3 desktop application. `main.py` wires together the
+Voculinux is a GTK 3 desktop application. `main.py` wires together the
configuration manager, recognition manager, tray UI, D-Bus service, and text
injector. Audio capture and recognition run outside the GTK event loop.
@@ -104,7 +104,7 @@ as `tray_indicator.py`, `dictation_overlay.py`, `transcription_history.py`,
## Services and optional integrations
-`dbus_service.py` owns the `com.vocalinux.Vocalinux` session-bus name and
+`dbus_service.py` owns the `com.voculinux.Voculinux` session-bus name and
provides Toggle, Start, and Stop methods for external controls.
`gateway_embed/` manages the optional local VocaGateway container lifecycle,
status, pairing, and configuration. It is separate from the default
diff --git a/docs/AUR.md b/docs/AUR.md
index cd9ee3b..f9ecc2c 100644
--- a/docs/AUR.md
+++ b/docs/AUR.md
@@ -3,13 +3,13 @@
## Users
```bash
-yay -S vocalinux # canonical release sdist, built against Arch dependencies
-yay -S vocalinux-git # community package; tracks main
+yay -S voculinux # canonical release sdist, built against Arch dependencies
+yay -S voculinux-git # community package; tracks main
```
-`vocalinux`, `vocalinux-bin` and `vocalinux-git` conflict; install only one.
+`voculinux`, `voculinux-bin` and `voculinux-git` conflict; install only one.
-`packaging/aur/vocalinux-bin/` builds a `-bin` variant that installs the
+`packaging/aur/voculinux-bin/` builds a `-bin` variant that installs the
prebuilt AppImage from the release — no Python, engine, or GPU dependency
builds, since the bundle carries them (#817). Its publication waits only for
release creation and both AppImages, not the source-package gate or other
@@ -19,7 +19,7 @@ then pushes to AUR in the `Publish AUR -bin package` step.
## Maintainers (one-time setup)
Release tags prepare and test the source PKGBUILD from
-`packaging/aur/vocalinux/PKGBUILD`, then auto-push the verified file when these
+`packaging/aur/voculinux/PKGBUILD`, then auto-push the verified file when these
secrets exist:
| Secret | Value |
@@ -30,16 +30,16 @@ secrets exist:
```bash
# 1. AUR account + SSH pubkey: https://aur.archlinux.org/register
-ssh-keygen -t ed25519 -C "vocalinux-aur" -f ./aur_ed25519 -N ""
+ssh-keygen -t ed25519 -C "voculinux-aur" -f ./aur_ed25519 -N ""
# upload aur_ed25519.pub on AUR; put aur_ed25519 in AUR_SSH_PRIVATE_KEY
# 2. Create empty package once
-git clone ssh://aur@aur.archlinux.org/vocalinux.git
+git clone ssh://aur@aur.archlinux.org/voculinux.git
# 3. Next v* tag runs Publish to AUR (skipped if secret missing)
```
-Sources: `packaging/aur/vocalinux/PKGBUILD`. Community git package: https://aur.archlinux.org/packages/vocalinux-git
+Sources: `packaging/aur/voculinux/PKGBUILD`. Community git package: https://aur.archlinux.org/packages/voculinux-git
## Source archive and trust model
@@ -91,7 +91,7 @@ Only after this succeeds is `aur-source-pkgbuild` uploaded for `publish-aur`.
Publication downloads that exact file; there is no version rewrite or
`updpkgsums` afterwards. The gate runs even without AUR credentials; only the
final push is secret-gated. This intentionally makes source publication wait
-for the release's checksums and attestations. `vocalinux-bin` uses a separate
+for the release's checksums and attestations. `voculinux-bin` uses a separate
AppImage publication path independent of this source gate and the global
checksum job; its PR smoke still uses a stub AppImage.
@@ -107,7 +107,7 @@ What those providers actually ship remains a separate monitoring question.
**`ERROR Missing dependencies: setuptools<82`**
-The AUR package builds with `python -m build --wheel --no-isolation`, so it uses Arch extra `python-setuptools` (currently 84). Vocalinux 0.16.1 drops the `<82` cap in `pyproject.toml`. Rebuild 0.16.1 or later.
+The AUR package builds with `python -m build --wheel --no-isolation`, so it uses Arch extra `python-setuptools` (currently 84). Voculinux 0.16.1 drops the `<82` cap in `pyproject.toml`. Rebuild 0.16.1 or later.
**`'_pywhispercpp.whisper_full_params' object has no attribute 'context_params'`**
diff --git a/docs/CUSTOM_DICTIONARY_DESIGN.md b/docs/CUSTOM_DICTIONARY_DESIGN.md
index 1a421b3..7eda4a0 100644
--- a/docs/CUSTOM_DICTIONARY_DESIGN.md
+++ b/docs/CUSTOM_DICTIONARY_DESIGN.md
@@ -16,13 +16,13 @@ would make the external terms contract surprising.
## File contracts
-Both files live in VocaLinux's XDG-aware configuration directory:
-`$XDG_CONFIG_HOME/vocalinux` (or `~/.config/vocalinux` when unset).
+Both files live in Voculinux's XDG-aware configuration directory:
+`$XDG_CONFIG_HOME/voculinux` (or `~/.config/voculinux` when unset).
| File | Contract | Consumer |
| --- | --- | --- |
-| `dictionary.txt` | UTF-8 (BOM accepted), one term per line. Blank lines and lines beginning with `#` are ignored. Terms are de-duplicated case-insensitively while retaining the first spelling. | VocaLinux and an external accessibility scanner. |
-| `custom-dictionary-corrections.json` | UTF-8 JSON object: `{"version": 1, "corrections": [{"heard": "super base", "replacement": "Supabase"}]}`. | VocaLinux only. |
+| `dictionary.txt` | UTF-8 (BOM accepted), one term per line. Blank lines and lines beginning with `#` are ignored. Terms are de-duplicated case-insensitively while retaining the first spelling. | Voculinux and an external accessibility scanner. |
+| `custom-dictionary-corrections.json` | UTF-8 JSON object: `{"version": 1, "corrections": [{"heard": "super base", "replacement": "Supabase"}]}`. | Voculinux only. |
The terms file remains deliberately simple and scanner-friendly. Corrections
need two unambiguous fields, a version, and exact replacement casing, so JSON is
@@ -35,7 +35,7 @@ edited file therefore takes effect on the next dictation segment without an app
restart. Missing, unreadable, malformed, or unsupported correction files are
ignored safely; dictation continues without their entries.
-The terms file may contain any number of lines, but VocaLinux limits a single
+The terms file may contain any number of lines, but Voculinux limits a single
prompt to the first 200 valid terms and 2,000 characters. This bounds decoding
work while leaving the scanner's complete line-file contract intact. The Custom
Dictionary page keeps both an add/remove editor and a validated file chooser
@@ -43,7 +43,7 @@ for the terms file.
## Processing and engine behavior
-For every completed audio segment, VocaLinux applies this order:
+For every completed audio segment, Voculinux applies this order:
1. The selected engine transcribes audio.
2. Live phrase corrections run against the raw transcript.
@@ -78,7 +78,7 @@ the JSON corrections file exists; it is never silently deleted or migrated.
The #767 persisted configuration keys are retained unchanged:
`dictionary.enabled`, `dictionary.file_path` (default
-`~/.config/vocalinux/dictionary.txt`), and `dictionary.max_words`. Existing
+`~/.config/voculinux/dictionary.txt`), and `dictionary.max_words`. Existing
Peony settings therefore continue to select the scanner's `dictionary.txt`
file. New configured paths are accepted only when they can be expanded and are
either absent (so the UI can create them) or readable regular files; a failed
@@ -99,7 +99,7 @@ paths are safely ignored and shown as unavailable rather than raising.
## Human test checklist
-1. Add `VocaLinux`, `PyGObject`, and a non-ASCII term in **Custom terms**;
+1. Add `Voculinux`, `PyGObject`, and a non-ASCII term in **Custom terms**;
confirm `dictionary.txt` is UTF-8, one line per term, and an external
edit changes the next Whisper, whisper.cpp, and Faster Whisper dictation segment.
2. Add `super base` → `Supabase`; test lowercase, uppercase, punctuation, an
@@ -108,7 +108,7 @@ paths are safely ignored and shown as unavailable rather than raising.
3. With voice commands enabled, add a correction that changes a command-like
misrecognition into ordinary text. Confirm it is injected rather than acted
on. Also verify an intentionally command-like replacement is avoided.
-4. Edit each file externally while VocaLinux is running. Test an invalid JSON
+4. Edit each file externally while Voculinux is running. Test an invalid JSON
correction file and invalid UTF-8 terms file; confirm dictation continues and
the Settings status/save feedback is clear.
5. Test the UI with keyboard only: Add buttons via Enter, empty validation,
diff --git a/docs/DISTRO_COMPATIBILITY.md b/docs/DISTRO_COMPATIBILITY.md
index 1d25ce6..5a1c8a0 100644
--- a/docs/DISTRO_COMPATIBILITY.md
+++ b/docs/DISTRO_COMPATIBILITY.md
@@ -1,8 +1,8 @@
# Linux distribution compatibility
-How Vocalinux behaves across distributions, what is tested, and what to install manually when needed.
+How Voculinux behaves across distributions, what is tested, and what to install manually when needed.
-For install steps, prefer [INSTALL.md](INSTALL.md). Flatpak packaging (useful on immutable or non-standard layouts): [packaging/flatpak/README.md](../packaging/flatpak/README.md). Snap Store listing: [snapcraft.io/vocalinux](https://snapcraft.io/vocalinux) (`--edge`; pack/upload steps in [INSTALL.md](INSTALL.md)). Flatpak is not on Flathub: submission [flathub#9368](https://github.com/flathub/flathub/pull/9368) closed 2026-07-23 on policy grounds; channel tracked in [#167](https://github.com/VocaHQ/vocalinux/issues/167).
+For install steps, prefer [INSTALL.md](INSTALL.md). Flatpak packaging (useful on immutable or non-standard layouts): [packaging/flatpak/README.md](../packaging/flatpak/README.md). Snap Store listing: [snapcraft.io/voculinux](https://snapcraft.io/voculinux) (`--edge`; pack/upload steps in [INSTALL.md](INSTALL.md)). Flatpak is not on Flathub: submission [flathub#9368](https://github.com/flathub/flathub/pull/9368) closed 2026-07-23 on policy grounds; channel tracked in [#167](https://github.com/VocaHQ/vocalinux/issues/167).
## Cross-distro behavior
@@ -24,7 +24,7 @@ The installer uses a multi-step approach to detect the correct GI_TYPELIB_PATH:
### Wrapper Scripts
-The installer creates wrapper scripts (`~/.local/bin/vocalinux` and `~/.local/bin/vocalinux-gui`) that:
+The installer creates wrapper scripts (`~/.local/bin/voculinux` and `~/.local/bin/voculinux-gui`) that:
- Set the correct `GI_TYPELIB_PATH` environment variable
- Handle input group permissions for Wayland keyboard shortcuts
- Provide seamless cross-distro compatibility
@@ -35,7 +35,7 @@ The `.desktop` entry is automatically configured with the detected `GI_TYPELIB_P
## Officially Supported Distributions
-These distributions are tested and known to work well with Vocalinux. A
+These distributions are tested and known to work well with Voculinux. A
derivative is judged by the Python and package repositories it ships rather
than by its own version number, which rarely tracks the base release. In
particular, `install.sh` does not interpret a Debian-based derivative's product
@@ -94,7 +94,7 @@ sudo apt install -y python3-gi gir1.2-gtk-3.0 gir1.2-ibus-1.0 gir1.2-gdkpixbuf-2
### Debian-specific notes
-Debian's standard repositories differ from Ubuntu in a few ways that matter for Vocalinux:
+Debian's standard repositories differ from Ubuntu in a few ways that matter for Voculinux:
**pywhispercpp build prerequisites.** On a clean Debian install the following packages are not
pulled in transitively (unlike Ubuntu) but are required when `pywhispercpp` must be compiled
@@ -125,16 +125,16 @@ package-scoped flag to avoid compiling unrelated deps like NumPy from source (wh
long time and can fail):
```bash
-source ~/.local/share/vocalinux/venv/bin/activate
+source ~/.local/share/voculinux/venv/bin/activate
PYWHISPERCPP_CLEAN=1 pip install --force-reinstall --no-binary=pywhispercpp pywhispercpp
deactivate
```
-**Verifying libwhisper.so resolution.** If Vocalinux starts with
+**Verifying libwhisper.so resolution.** If Voculinux starts with
`libwhisper.so.1: cannot open shared object file`, check for unresolved symbols:
```bash
-ldd $(find ~/.local/share/vocalinux/venv -name '*.so' -path '*/pywhispercpp*' 2>/dev/null | head -1) | grep 'not found'
+ldd $(find ~/.local/share/voculinux/venv -name '*.so' -path '*/pywhispercpp*' 2>/dev/null | head -1) | grep 'not found'
```
If any libraries are listed, re-run the installer with `--rebuild-whispercpp` or switch to
@@ -215,11 +215,11 @@ sudo urpmi -y python3-gobject gtk3-devel gobject-introspection-devel \
## PyPI, pip, and pipx Installation
The PyPI package is useful when you want a standard Python package install, or
-when you want to manage Vocalinux with `pipx`. However, **Vocalinux requires
+when you want to manage Voculinux with `pipx`. However, **Voculinux requires
system desktop packages** that cannot be installed by pip or pipx.
Use the official installer when possible. It installs the required system
-packages, creates the virtual environment, installs Vocalinux, sets up desktop
+packages, creates the virtual environment, installs Voculinux, sets up desktop
integration, and downloads the default speech model:
```bash
@@ -229,8 +229,8 @@ bash /tmp/vl.sh
### Important: Install System Packages First
-Before running `pip install vocalinux`, `pip install "vocalinux[vosk]"`, or
-`pipx install vocalinux`, you **must** install the required system packages:
+Before running `pip install voculinux`, `pip install "voculinux[vosk]"`, or
+`pipx install voculinux`, you **must** install the required system packages:
#### Ubuntu/Debian
```bash
@@ -272,8 +272,8 @@ sudo zypper install "${PYVER}-gobject" "${PYVER}-gobject-cairo" gtk3 ibus typeli
2. **Create a virtual environment with system site-packages enabled**:
```bash
- python3 -m venv ~/.local/share/vocalinux-pypi/venv --system-site-packages
- source ~/.local/share/vocalinux-pypi/venv/bin/activate
+ python3 -m venv ~/.local/share/voculinux-pypi/venv --system-site-packages
+ source ~/.local/share/voculinux-pypi/venv/bin/activate
pip install --upgrade pip setuptools wheel
```
@@ -281,15 +281,15 @@ sudo zypper install "${PYVER}-gobject" "${PYVER}-gobject-cairo" gtk3 ibus typeli
as `python3-gi`, which are often more reliable than building PyGObject from
source in a venv.
-3. **Install Vocalinux from PyPI**:
+3. **Install Voculinux from PyPI**:
```bash
- pip install vocalinux
- # vosk engine: pip install "vocalinux[vosk]"
+ pip install voculinux
+ # vosk engine: pip install "voculinux[vosk]"
```
-4. **Run Vocalinux**:
+4. **Run Voculinux**:
```bash
- vocalinux
+ voculinux
```
### pipx Installation Steps
@@ -311,20 +311,20 @@ sudo zypper install "${PYVER}-gobject" "${PYVER}-gobject-cairo" gtk3 ibus typeli
pipx ensurepath
```
-3. **Install Vocalinux**:
+3. **Install Voculinux**:
```bash
- pipx install vocalinux
- # vosk engine: pipx install "vocalinux[vosk]"
+ pipx install voculinux
+ # vosk engine: pipx install "voculinux[vosk]"
```
-4. **Run Vocalinux**:
+4. **Run Voculinux**:
```bash
- vocalinux
+ voculinux
```
### Why System Packages Are Required
-Vocalinux uses GTK3 for its GUI, AppIndicator/Ayatana for the system tray icon,
+Voculinux uses GTK3 for its GUI, AppIndicator/Ayatana for the system tray icon,
PortAudio for microphone capture, and tools such as `xdotool`, `wtype`, and clipboard utilities (`wl-clipboard`, `xclip`, `xsel`) for
text injection and layout-independent Wayland paste fallback. These are system libraries and desktop tools that must be
installed with your distribution's package manager. Python packages from PyPI
@@ -333,20 +333,20 @@ typelibs, tray support, audio development libraries, or text injection binaries.
### Troubleshooting pip/pipx Installation
-If `vocalinux` fails to start:
+If `voculinux` fails to start:
1. **Check for missing system packages** - The error message will indicate which packages are missing
2. **Verify GI_TYPELIB_PATH** - In rare cases, you may need to set this environment variable:
```bash
export GI_TYPELIB_PATH=/usr/lib/x86_64-linux-gnu/girepository-1.0
- vocalinux
+ voculinux
```
-3. **Check package metadata** - Run `pip show vocalinux` or
- `pipx runpip vocalinux show vocalinux` to confirm which version was installed.
+3. **Check package metadata** - Run `pip show voculinux` or
+ `pipx runpip voculinux show voculinux` to confirm which version was installed.
4. **Check Python dependencies** - Run `pip check` inside the venv, or
- `pipx runpip vocalinux check` for pipx.
+ `pipx runpip voculinux check` for pipx.
-If Vocalinux reports that a speech recognition model is missing, open Settings
+If Voculinux reports that a speech recognition model is missing, open Settings
and download a model, or use the official installer to download the default model
during setup.
@@ -362,7 +362,7 @@ This installer automatically detects your distribution and installs all required
## Text Injection Tools
-Vocalinux requires text injection tools to work with X11 or Wayland:
+Voculinux requires text injection tools to work with X11 or Wayland:
### For X11
- **xdotool**: Required for X11 sessions
@@ -370,7 +370,7 @@ Vocalinux requires text injection tools to work with X11 or Wayland:
### For Wayland
- **IBus**: Recommended for KDE Plasma Wayland and generally the most reliable direct text input path
- **wtype**: Recommended for wlroots-style Wayland compositors such as sway
-- **ydotool**: Universal alternative that works with both X11 and Wayland. Current distro packages use the per-user `ydotool.service`; source builds can install the system-level `ydotoold.service`. Vocalinux uses clipboard paste with `wl-clipboard`, `xclip`, or `xsel` to avoid non-US layout scrambling.
+- **ydotool**: Universal alternative that works with both X11 and Wayland. Current distro packages use the per-user `ydotool.service`; source builds can install the system-level `ydotoold.service`. Voculinux uses clipboard paste with `wl-clipboard`, `xclip`, or `xsel` to avoid non-US layout scrambling.
- **xdotool**: May work via XWayland fallback
### Installation by Distribution
@@ -383,7 +383,7 @@ sudo zypper install xdotool wtype wl-clipboard xclip xsel # openSUSE
```
Ubuntu releases which package `ydotool` install a **user** unit named
-`ydotool.service`. Enable it only for the account running Vocalinux:
+`ydotool.service`. Enable it only for the account running Voculinux:
```bash
sudo apt install ydotool
@@ -443,13 +443,13 @@ For unsupported or experimental distributions:
### Autostart Compatibility
-Vocalinux uses **XDG autostart desktop entries** for "Start on Login".
+Voculinux uses **XDG autostart desktop entries** for "Start on Login".
- Desktop-session autostart file location:
- - `$XDG_CONFIG_HOME/autostart/vocalinux.desktop`, or
- - `~/.config/autostart/vocalinux.desktop` (fallback)
-- This launches Vocalinux as a user GUI app after login.
-- Vocalinux does **not** create a `systemd` service/unit for this feature.
+ - `$XDG_CONFIG_HOME/autostart/voculinux.desktop`, or
+ - `~/.config/autostart/voculinux.desktop` (fallback)
+- This launches Voculinux as a user GUI app after login.
+- Voculinux does **not** create a `systemd` service/unit for this feature.
Practical caveat:
@@ -500,7 +500,7 @@ When reporting issues, please include:
5. **Error messages or logs:**
- Any error messages from the installer
- - Output from running `vocalinux-gui` from terminal
+ - Output from running `voculinux-gui` from terminal
- Relevant journal logs if applicable
6. **Steps to reproduce:**
@@ -525,7 +525,7 @@ Use this checklist when testing on a new distribution:
- [ ] Check wrapper scripts exist
### Post-Install
-- [ ] Launch from terminal: `~/.local/bin/vocalinux-gui`
+- [ ] Launch from terminal: `~/.local/bin/voculinux-gui`
- [ ] Launch from application menu
- [ ] Verify tray icon appears
- [ ] Test keyboard shortcuts (Hold Right Alt by default)
@@ -543,7 +543,7 @@ Use this checklist when testing on a new distribution:
## Contributing Compatibility Fixes
-If you successfully get Vocalinux working on an unsupported or experimental distribution:
+If you successfully get Voculinux working on an unsupported or experimental distribution:
1. Test thoroughly using the checklist above
2. Document any distribution-specific requirements
diff --git a/docs/FLATPAK_REMOTE.md b/docs/FLATPAK_REMOTE.md
index 5e3833d..6c53752 100644
--- a/docs/FLATPAK_REMOTE.md
+++ b/docs/FLATPAK_REMOTE.md
@@ -1,13 +1,13 @@
# Self-hosted Flatpak remote
-Vocalinux publishes a signed OSTree Flatpak remote on every stable `v*` tag —
+Voculinux publishes a signed OSTree Flatpak remote on every stable `v*` tag —
the Homebrew-tap analogue to `VocaHQ/homebrew-vocamac`
([issue #785](https://github.com/VocaHQ/vocalinux/issues/785)). The remote
lives in the dedicated repo `VocaHQ/vocalinux-flatpak`, served by GitHub
Pages:
```bash
-flatpak install https://vocahq.github.io/vocalinux-flatpak/com.vocalinux.Vocalinux.flatpakref
+flatpak install https://vocahq.github.io/voculinux-flatpak/com.voculinux.Voculinux.flatpakref
flatpak update # picks up each new release
```
@@ -18,8 +18,8 @@ steps:
```bash
flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
-flatpak remote-add --if-not-exists vocahq https://vocahq.github.io/vocalinux-flatpak/vocahq.flatpakrepo
-flatpak install vocahq com.vocalinux.Vocalinux
+flatpak remote-add --if-not-exists vocahq https://vocahq.github.io/voculinux-flatpak/vocahq.flatpakrepo
+flatpak install vocahq com.voculinux.Voculinux
```
Only the app is ours; the GNOME runtime still comes from Flathub —
@@ -38,7 +38,7 @@ prerelease tags, which never reach the remote.
3. **Signing key** — OSTree remotes sign the summary and commits with GPG:
```bash
- gpg --quick-gen-key "Vocalinux Flatpak " ed25519 sign never
+ gpg --quick-gen-key "Voculinux Flatpak " ed25519 sign never
gpg --list-secret-keys # note the KEYID
gpg --export-secret-keys --armor KEYID # -> FLATPAK_GPG_PRIVATE_KEY
gpg --gen-revoke KEYID > flatpak-remote-revoke.asc # store it somewhere safe
@@ -59,12 +59,12 @@ prerelease tags, which never reach the remote.
- `FLATPAK_REMOTE_REPO` — publish target (default
`VocaHQ/vocalinux-flatpak`)
- `FLATPAK_REMOTE_URL` — remote URL baked into the `.flatpakrepo`
- (default `https://vocahq.github.io/vocalinux-flatpak/repo`; set
- e.g. `https://flatpak.vocalinux.com/repo` for a custom domain)
+ (default `https://vocahq.github.io/voculinux-flatpak/repo`; set
+ e.g. `https://flatpak.voculinux.com/repo` for a custom domain)
- `FLATPAKREPO_URL` — where users fetch `vocahq.flatpakrepo` (default
- `https://vocahq.github.io/vocalinux-flatpak/vocahq.flatpakrepo`)
+ `https://vocahq.github.io/voculinux-flatpak/vocahq.flatpakrepo`)
- `FLATPAKREF_URL` — where users fetch the app `.flatpakref` (default
- `https://vocahq.github.io/vocalinux-flatpak/com.vocalinux.Vocalinux.flatpakref`)
+ `https://vocahq.github.io/voculinux-flatpak/com.voculinux.Voculinux.flatpakref`)
6. **Trigger** — push a stable `v*` tag (alpha/beta/rc tags do not publish to
the remote), or re-run `publish-flatpak-remote` on an existing release run
after configuring the secrets.
@@ -77,7 +77,7 @@ an unconfigured remote never fails a release.
`release.yml → publish-flatpak-remote` runs on stable tags only, after the
GitHub Release exists and the two arch builds finish:
-1. Downloads `Vocalinux--{x86_64,aarch64}.flatpak` from the build
+1. Downloads `Voculinux--{x86_64,aarch64}.flatpak` from the build
jobs.
2. Probes the remote repo for an existing `gh-pages` branch; only a confirmed
first publish may skip the history checkout — a transient failure aborts
@@ -90,7 +90,7 @@ GitHub Release exists and the two arch builds finish:
4. `flatpak build-update-repo --generate-static-deltas --gpg-sign
--gpg-import` rebuilds the summary, signs it, and generates static deltas.
5. Regenerates `vocahq.flatpakrepo` (URL + base64 public key),
- `com.vocalinux.Vocalinux.flatpakref` (the one-command app ref carrying the
+ `com.voculinux.Voculinux.flatpakref` (the one-command app ref carrying the
`RuntimeRepo=` pointer to Flathub), `vocahq.gpg` (the bare public key, for
the key-rotation path below), and the index page from
`packaging/flatpak/index.html`.
@@ -101,10 +101,10 @@ GitHub Release exists and the two arch builds finish:
```bash
flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
-flatpak remote-add --if-not-exists vocahq https://vocahq.github.io/vocalinux-flatpak/vocahq.flatpakrepo
-flatpak remote-info vocahq com.vocalinux.Vocalinux # signed commit, both arches
-flatpak install vocahq com.vocalinux.Vocalinux
-flatpak run com.vocalinux.Vocalinux
+flatpak remote-add --if-not-exists vocahq https://vocahq.github.io/voculinux-flatpak/vocahq.flatpakrepo
+flatpak remote-info vocahq com.voculinux.Voculinux # signed commit, both arches
+flatpak install vocahq com.voculinux.Voculinux
+flatpak run com.voculinux.Voculinux
# after the next tag: flatpak update pulls the delta
```
@@ -121,7 +121,7 @@ does nothing at all), and `flatpak update` fails verification until the key
is updated. Point users at the public key published beside the repo:
```bash
-curl -fsSL https://vocahq.github.io/vocalinux-flatpak/vocahq.gpg -o /tmp/vocahq.gpg
+curl -fsSL https://vocahq.github.io/voculinux-flatpak/vocahq.gpg -o /tmp/vocahq.gpg
flatpak remote-modify --gpg-import=/tmp/vocahq.gpg vocahq
flatpak update
```
@@ -133,7 +133,7 @@ their `vocahq` origin and update normally afterwards):
```bash
flatpak remote-delete --force vocahq # --force: the remote is still in use
-flatpak remote-add vocahq https://vocahq.github.io/vocalinux-flatpak/vocahq.flatpakrepo
+flatpak remote-add vocahq https://vocahq.github.io/voculinux-flatpak/vocahq.flatpakrepo
flatpak update
```
diff --git a/docs/GATEWAY_EMBED.md b/docs/GATEWAY_EMBED.md
index 81c4af1..177b897 100644
--- a/docs/GATEWAY_EMBED.md
+++ b/docs/GATEWAY_EMBED.md
@@ -1,6 +1,6 @@
-# Local VocaGateway from Vocalinux (optional)
+# Local VocaGateway from Voculinux (optional)
-Vocalinux can start a **local** [VocaGateway](https://github.com/VocaHQ/vocagateway)
+Voculinux can start a **local** [VocaGateway](https://github.com/VocaHQ/vocagateway)
container from **Settings → Speech Model → Advanced**, next to Remote Server. This is an
optional power-user path. It is **not** on-device processing: microphone audio
still leaves the desktop client and is transcribed by the gateway process on
@@ -8,23 +8,23 @@ your machine (or LAN).
The default speech engine remains **whisper.cpp** on-device. Enabling a local
gateway never changes that default by itself. Use **Use this Gateway** only when
-you want Vocalinux to talk to the gateway over the existing Remote API settings
+you want Voculinux to talk to the gateway over the existing Remote API settings
(`remote_api_*`, endpoint `/v1/audio/transcriptions`). See [HTTP_REMOTE.md](HTTP_REMOTE.md).
## Requirements (Linux MVP)
- **podman** (preferred) or **docker**, with a working `compose` plugin (or
`podman-compose` / `docker-compose`).
-- Vocalinux does **not** bundle a container engine inside the AppImage.
+- Voculinux does **not** bundle a container engine inside the AppImage.
- **Flatpak**: the sandbox cannot reach the host container socket. Run the
native package or AppImage, or start VocaGateway on the host yourself and
point Remote Server at it.
-## What Vocalinux does
+## What Voculinux does
1. Pins upstream **VocaGateway `v0.1.0`** (git tag) under your XDG cache and uses
that checkout's `compose.yaml` with Compose project name `vocagateway`.
-2. Writes a private bootstrap token under `~/.config/vocalinux/gateway_embed/`
+2. Writes a private bootstrap token under `~/.config/voculinux/gateway_embed/`
(mode `600`) and a matching Compose `.env`.
3. Runs `compose -f compose.yaml --profile cpu up -d` for the `gateway` service.
The v0.1.0 GitHub release has no published container image assets, so the first
@@ -55,18 +55,18 @@ By default the published host is `127.0.0.1` (desktop-only). Turn on **Allow LAN
access for Phone** to set `VOCAGATEWAY_PUBLISH_HOST=0.0.0.0` and to advertise a
LAN URL in pairing. Open port `8765` in your firewall only on trusted networks.
Never put `127.0.0.1` / `localhost` in the phone QR. If a LAN toggle fails,
-compose keeps the previous bind, Vocalinux restores the embed `.env`, and the
+compose keeps the previous bind, Voculinux restores the embed `.env`, and the
switch snaps back with an error (Stop and Run again, or retry).
## Tray and Quit
The tray menu offers **Stop local Gateway** whenever compose is actually running
(Starting, Live, Pairable, Ready, or Error), including a leftover from a previous
-Vocalinux session. Vocalinux does not auto-start the gateway on login in v1.
+Voculinux session. Voculinux does not auto-start the gateway on login in v1.
**Quit does not stop compose.** The pinned compose file uses `restart:
unless-stopped`, so a LAN-published gateway on `0.0.0.0:8765` keeps running after
-you quit Vocalinux. The next launch restores the Allow LAN switch from the running
+you quit Voculinux. The next launch restores the Allow LAN switch from the running
compose publish host. Use **Stop local Gateway** in Settings or the tray when you
want it gone. Do not assume Quit tears it down.
diff --git a/docs/HTTP_REMOTE.md b/docs/HTTP_REMOTE.md
index ab3d65e..9de7b7e 100644
--- a/docs/HTTP_REMOTE.md
+++ b/docs/HTTP_REMOTE.md
@@ -1,8 +1,8 @@
# Remote HTTP transcription
-Vocalinux can offload speech recognition to a remote HTTP server instead of running a local model. Use this when you want faster transcription on a more powerful machine, to share one model across clients, or to keep a laptop free of GPU/model overhead.
+Voculinux can offload speech recognition to a remote HTTP server instead of running a local model. Use this when you want faster transcription on a more powerful machine, to share one model across clients, or to keep a laptop free of GPU/model overhead.
-Vocalinux speaks two wire formats out of the box:
+Voculinux speaks two wire formats out of the box:
- **OpenAI-compatible**: `POST /v1/audio/transcriptions` (e.g. OpenAI, [Speaches](https://github.com/speaches-ai/speaches), LocalAI, FunASR/SenseVoice)
- **whisper.cpp server**: `POST /inference` (the binary shipped with [whisper.cpp](https://github.com/ggerganov/whisper.cpp))
@@ -17,7 +17,7 @@ On Linux you can start an optional local [VocaGateway](https://github.com/VocaHQ
## How it works
-When the **Remote API** engine is active, Vocalinux:
+When the **Remote API** engine is active, Voculinux:
1. Captures microphone audio locally (16 kHz, mono, 16-bit PCM).
2. On end-of-utterance, packages the buffer as a WAV file in memory.
@@ -61,7 +61,7 @@ The endpoint is `/v1/audio/transcriptions`.
[FunASR](https://github.com/modelscope/FunASR) can run a local
OpenAI-compatible transcription service, which keeps audio on your own machine
-or LAN while letting Vocalinux use SenseVoice or Paraformer-family models:
+or LAN while letting Voculinux use SenseVoice or Paraformer-family models:
```bash
pip install 'torch>=2.13.0' torchaudio
@@ -70,7 +70,7 @@ funasr-server --device cuda
```
The server listens on `http://localhost:8000` by default and exposes
-`POST /v1/audio/transcriptions`. In Vocalinux, set:
+`POST /v1/audio/transcriptions`. In Voculinux, set:
- **Server URL**: `http://localhost:8000`
- **API Endpoint**: `OpenAI/FunASR (/v1/audio/transcriptions)`
@@ -78,7 +78,7 @@ The server listens on `http://localhost:8000` by default and exposes
Use `--device cpu` for CPU-only testing if your FunASR install supports it. A
remote GPU host works too: bind the server to the LAN interface, open the port,
-and point Vocalinux at that host.
+and point Voculinux at that host.
### Network checklist
@@ -87,26 +87,26 @@ and point Vocalinux at that host.
- For anything outside a trusted LAN, terminate TLS in front of the server (Caddy, nginx, Traefik) and require an API key. The audio you upload is private speech.
- If you also use the server from a mobile dictation app, terminate TLS even on a LAN. Most Android and iOS apps refuse cleartext HTTP.
-## Client-side setup (Vocalinux)
+## Client-side setup (Voculinux)
### Via the Settings dialog
The remote engine is a power-user option in the **Speech Engine** settings.
-1. Launch Vocalinux and open **Settings → Speech Engine → Remote Server**.
+1. Launch Voculinux and open **Settings → Speech Engine → Remote Server**.
2. Toggle **Use remote server** on. This overrides whatever local engine is selected above it.
3. Fill in the fields:
- **Server URL**: base URL of the server, e.g. `http://192.168.1.100:8080` (no trailing slash needed; one is stripped automatically).
- **API Key** (optional): sent as `Authorization: Bearer `. Leave blank if your server doesn't require auth.
- **API Endpoint**: pick **Whisper.cpp (`/inference`)** or **OpenAI/FunASR (`/v1/audio/transcriptions`)** to match your server.
- **Model**: model identifier sent to OpenAI-compatible servers. Use `whisper-1` for classic Whisper servers, or `sensevoice` for FunASR/SenseVoice.
-4. Click **Test Connection**. Success means the URL is reachable and credentials (if any) are accepted. A failure here is only a warning; Vocalinux will try again on the first transcription.
+4. Click **Test Connection**. Success means the URL is reachable and credentials (if any) are accepted. A failure here is only a warning; Voculinux will try again on the first transcription.
Settings auto-save and re-initialise the engine immediately, so you can start dictating as soon as the test passes. Toggling the switch off restores the local engine selected on the Speech Engine page in Settings.
### Via the config file
-The same options live in `~/.config/vocalinux/config.json`:
+The same options live in `~/.config/voculinux/config.json`:
```json
{
@@ -120,7 +120,7 @@ The same options live in `~/.config/vocalinux/config.json`:
}
```
-Restart Vocalinux after editing the file by hand.
+Restart Voculinux after editing the file by hand.
FunASR/SenseVoice example:
@@ -201,7 +201,7 @@ en
```
For OpenAI-compatible FunASR/SenseVoice wrappers, extra metadata is allowed and
-ignored by Vocalinux:
+ignored by Voculinux:
```json
{
@@ -214,16 +214,16 @@ ignored by Vocalinux:
}
```
-If `text` is not present, Vocalinux also accepts `transcript`, `transcription`,
+If `text` is not present, Voculinux also accepts `transcript`, `transcription`,
or a `segments` list with per-segment `text` fields. If a SenseVoice wrapper
returns rich labels inline, for example `<|en|><|NEUTRAL|><|Speech|>hello`,
-Vocalinux strips the leading labels before text injection.
+Voculinux strips the leading labels before text injection.
-Empty utterances should return `{"text": ""}`. HTTP 4xx/5xx responses are surfaced as transcription errors in the Vocalinux log.
+Empty utterances should return `{"text": ""}`. HTTP 4xx/5xx responses are surfaced as transcription errors in the Voculinux log.
### Language handling
-- Vocalinux's UI language `auto` is sent as **no `language` field** (server auto-detects).
+- Voculinux's UI language `auto` is sent as **no `language` field** (server auto-detects).
- `en-us` is normalised to `en`.
- Anything else is forwarded verbatim.
@@ -273,10 +273,10 @@ compatible response shapes above.
| First transcription is slow | Cold model load on the server | Warm the server before dictating, or increase the client timeout server-side |
| Garbled text in foreign language | Wrong `language` setting | Set the language explicitly in Settings instead of `auto` |
-Logs live at `~/.local/share/vocalinux/vocalinux.log` (or wherever your `XDG_DATA_HOME` points). Look for lines tagged `Remote API` for client-side detail.
+Logs live at `~/.local/share/voculinux/voculinux.log` (or wherever your `XDG_DATA_HOME` points). Look for lines tagged `Remote API` for client-side detail.
## Security notes
-- The API key is stored in plain JSON in `~/.config/vocalinux/config.json`. Treat that file the same way you treat any other secret on disk.
+- The API key is stored in plain JSON in `~/.config/voculinux/config.json`. Treat that file the same way you treat any other secret on disk.
- Audio is sent as raw WAV. Anyone on the wire can hear it, so use HTTPS outside a fully trusted network.
-- Vocalinux does **not** validate TLS certificate pins; standard system trust is used. Self-signed certs require importing the CA into your system trust store.
+- Voculinux does **not** validate TLS certificate pins; standard system trust is used. Self-signed certs require importing the CA into your system trust store.
diff --git a/docs/INSTALL.md b/docs/INSTALL.md
index 03bac2b..2ce4ded 100644
--- a/docs/INSTALL.md
+++ b/docs/INSTALL.md
@@ -1,6 +1,6 @@
# Installation guide
-How to install Vocalinux on Linux. Short overview: [project README](../README.md).
+How to install Voculinux on Linux. Short overview: [project README](../README.md).
| Path | When to use |
|------|-------------|
@@ -75,7 +75,7 @@ Useful flags: `--tag=TAG`, `--skip-models`, `--rebuild-whispercpp`, `--no-rebuil
1. Detects the distribution and installs system packages
2. Creates a Python venv from the system interpreter with `--system-site-packages` (for distro GTK / PyGObject)
-3. Installs Vocalinux and the chosen speech engine
+3. Installs Voculinux and the chosen speech engine
4. Optionally installs neural VAD (`onnxruntime`)
5. Downloads a default speech model (checksum-verified)
6. Installs icons, desktop entry, and `~/.local/bin` wrappers
@@ -85,8 +85,8 @@ Useful flags: `--tag=TAG`, `--skip-models`, `--rebuild-whispercpp`, `--no-rebuil
From [GitHub Releases](https://github.com/VocaHQ/vocalinux/releases):
```bash
-chmod +x Vocalinux-*-x86_64.AppImage # or aarch64
-./Vocalinux-*-x86_64.AppImage
+chmod +x Voculinux-*-x86_64.AppImage # or aarch64
+./Voculinux-*-x86_64.AppImage
```
Built against glibc 2.35, so it starts on Debian 12+, Ubuntu 22.04+, Fedora 36+, Arch, and Tumbleweed. Older bases (RHEL 9, Debian 11, Ubuntu 20.04) are below that AppImage floor. The installer and PyPI package still require a distro that ships Python 3.11+, so they are not a workaround for Debian 11 or Ubuntu 20.04.
@@ -99,13 +99,13 @@ From [GitHub Releases](https://github.com/VocaHQ/vocalinux/releases), pick the f
```bash
# Debian / Ubuntu (amd64; arm64 files are attached too)
-sudo apt install ./vocalinux_*_amd64.deb
+sudo apt install ./voculinux_*_amd64.deb
# Fedora (x86_64; aarch64 files are attached too)
-sudo dnf install ./vocalinux-*.x86_64.rpm
+sudo dnf install ./voculinux-*.x86_64.rpm
```
-These are thin packages: Python, GTK, PyGObject and the AppIndicator typelib come from the distribution, and `apt`/`dnf` resolves them. `xdotool`, `wtype`, `ydotool`, the clipboard tools and IBus are `Recommends`, matching the optional feature set of the other paths. Only `pywhispercpp` and `pynput` are vendored inside the package — `pywhispercpp` is packaged by neither distro and `pynput` is missing on Fedora. They land under `/usr/lib/vocalinux/vendor`, on `sys.path` via the `vocalinux` launcher.
+These are thin packages: Python, GTK, PyGObject and the AppIndicator typelib come from the distribution, and `apt`/`dnf` resolves them. `xdotool`, `wtype`, `ydotool`, the clipboard tools and IBus are `Recommends`, matching the optional feature set of the other paths. Only `pywhispercpp` and `pynput` are vendored inside the package — `pywhispercpp` is packaged by neither distro and `pynput` is missing on Fedora. They land under `/usr/lib/voculinux/vendor`, on `sys.path` via the `voculinux` launcher.
The `.deb` needs a distro that ships Python 3.11+: Debian 12+ and Ubuntu 24.04+ (Ubuntu 22.04 ships 3.10). whisper.cpp runs on CPU in these packages — the PyPI wheel, not the Vulkan build the AppImage carries. There is no auto-update: a new release is a new package install. A PPA and a COPR are not published yet.
@@ -120,7 +120,7 @@ Joining `input` grants read access to every keyboard and pointer device — X11
## Arch Linux (AUR)
```bash
-yay -S vocalinux
+yay -S voculinux
```
See [AUR.md](AUR.md).
@@ -130,21 +130,21 @@ See [AUR.md](AUR.md).
Install and auto-update via the self-hosted VocaHQ remote (`flatpak update` picks up each release):
```bash
-flatpak install https://vocahq.github.io/vocalinux-flatpak/com.vocalinux.Vocalinux.flatpakref
+flatpak install https://vocahq.github.io/voculinux-flatpak/com.voculinux.Voculinux.flatpakref
```
The `.flatpakref` adds the `vocahq` remote and resolves the GNOME runtime through Flathub. Manually instead:
```bash
flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo
-flatpak remote-add --if-not-exists vocahq https://vocahq.github.io/vocalinux-flatpak/vocahq.flatpakrepo
-flatpak install vocahq com.vocalinux.Vocalinux
+flatpak remote-add --if-not-exists vocahq https://vocahq.github.io/voculinux-flatpak/vocahq.flatpakrepo
+flatpak install vocahq com.voculinux.Voculinux
```
-Or sideload a GitHub Release bundle (`Vocalinux--x86_64.flatpak` or `-aarch64.flatpak`) after the Flathub GNOME runtime is present — bundles do not auto-update:
+Or sideload a GitHub Release bundle (`Voculinux--x86_64.flatpak` or `-aarch64.flatpak`) after the Flathub GNOME runtime is present — bundles do not auto-update:
```bash
-flatpak install --user ./Vocalinux--x86_64.flatpak
+flatpak install --user ./Voculinux--x86_64.flatpak
```
Local build (contributors):
@@ -152,8 +152,8 @@ Local build (contributors):
```bash
flatpak install flathub org.gnome.Platform//50 org.gnome.Sdk//50
flatpak-builder --user --install --force-clean build-dir \
- packaging/flatpak/com.vocalinux.Vocalinux.yml
-flatpak run com.vocalinux.Vocalinux
+ packaging/flatpak/com.voculinux.Voculinux.yml
+flatpak run com.voculinux.Voculinux
```
Whisper.cpp + Vulkan. It is **not on Flathub** (submission [flathub#9368](https://github.com/flathub/flathub/pull/9368) closed 2026-07-23 on policy grounds). Details: [packaging/flatpak/README.md](../packaging/flatpak/README.md).
@@ -168,7 +168,7 @@ Desktop shortcuts only toggle dictation, so they cannot support push-to-talk.
## Snap (Ubuntu Snap Store)
-Listing: [snapcraft.io/vocalinux](https://snapcraft.io/vocalinux) (issue [#48](https://github.com/VocaHQ/vocalinux/issues/48)). Recipe: `snap/snapcraft.yaml`. Tagged `v*` releases attach `vocalinux__amd64.snap` to the GitHub Release and try Snap Store `edge` and `candidate` when credentials are set. `stable` is promoted from `candidate` after QA.
+Listing: [snapcraft.io/voculinux](https://snapcraft.io/voculinux) (issue [#48](https://github.com/VocaHQ/vocalinux/issues/48)). Recipe: `snap/snapcraft.yaml`. Tagged `v*` releases attach `voculinux__amd64.snap` to the GitHub Release and try Snap Store `edge` and `candidate` when credentials are set. `stable` is promoted from `candidate` after QA.
Build inputs, the PR/release artifact gate, and its verification limits are
documented in [SNAP.md](SNAP.md).
@@ -176,10 +176,10 @@ documented in [SNAP.md](SNAP.md).
Store install, once Canonical lists the revision:
```bash
-sudo snap install vocalinux --edge
-sudo snap connect vocalinux:audio-record # if mic is not auto-connected
-sudo snap connect vocalinux:raw-input # global keyboard shortcuts (evdev)
-sudo snap connect vocalinux:hardware-observe # list keyboards (/proc/bus/input/devices)
+sudo snap install voculinux --edge
+sudo snap connect voculinux:audio-record # if mic is not auto-connected
+sudo snap connect voculinux:raw-input # global keyboard shortcuts (evdev)
+sudo snap connect voculinux:hardware-observe # list keyboards (/proc/bus/input/devices)
```
Native Wayland typing uses the RemoteDesktop portal: the compositor asks once on first dictation, nothing to connect. The recipe ships **no `uinput` plug** and no ydotool; the Store denied the super-privileged grant ([the request thread](https://forum.snapcraft.io/t/53528)), which held the 0.17.0+ revisions and left **v0.16.2 (rev 7)** on edge. On KDE Plasma, KWin's portal can mistype letter case ([KDE bug 489021](https://bugs.kde.org/show_bug.cgi?id=489021)); set Virtual Keyboard to "IBus Wayland" so dictation types correctly.
@@ -189,14 +189,14 @@ Under strict confinement the snap reaches audio through the PulseAudio/PipeWire
GitHub `.snap` files through v0.18.2 declare `uinput`, so KDE users who want ydotool can sideload that build and connect the plug manually:
```bash
-sudo snap install --dangerous ./vocalinux_0.18.2_amd64.snap
-sudo snap connect vocalinux:audio-record
-sudo snap connect vocalinux:raw-input
-sudo snap connect vocalinux:hardware-observe
-sudo snap connect vocalinux:uinput # only in the v0.18.x sideload; the recipe no longer ships it
+sudo snap install --dangerous ./voculinux_0.18.2_amd64.snap
+sudo snap connect voculinux:audio-record
+sudo snap connect voculinux:raw-input
+sudo snap connect voculinux:hardware-observe
+sudo snap connect voculinux:uinput # only in the v0.18.x sideload; the recipe no longer ships it
```
-`--dangerous` is required because this file is not a Store revision and will not refresh from the Store; once the Store carries a newer revision, `sudo snap install vocalinux --edge` (or `snap refresh`) replaces it.
+`--dangerous` is required because this file is not a Store revision and will not refresh from the Store; once the Store carries a newer revision, `sudo snap install voculinux --edge` (or `snap refresh`) replaces it.
## Nix / NixOS
@@ -207,13 +207,13 @@ nix run github:VocaHQ/vocalinux # try it
nix profile install github:VocaHQ/vocalinux
```
-On NixOS, `vocalinux.nixosModules.vocalinux` provides `programs.vocalinux.enable`, which installs the package and enables `hardware.uinput`. Add each dictating user to `input` and `uinput` for Wayland shortcuts and ydotool typing. Home Manager users get `vocalinux.homeManagerModules.vocalinux` with the same `programs.vocalinux` options — device permissions stay on the system side. Usage snippets and scope notes: [packaging/nix/README.md](../packaging/nix/README.md).
+On NixOS, `voculinux.nixosModules.voculinux` provides `programs.voculinux.enable`, which installs the package and enables `hardware.uinput`. Add each dictating user to `input` and `uinput` for Wayland shortcuts and ydotool typing. Home Manager users get `voculinux.homeManagerModules.voculinux` with the same `programs.voculinux` options — device permissions stay on the system side. Usage snippets and scope notes: [packaging/nix/README.md](../packaging/nix/README.md).
## From source
```bash
git clone https://github.com/VocaHQ/vocalinux.git
-cd vocalinux
+cd voculinux
./install.sh
```
@@ -228,18 +228,18 @@ cd vocalinux
| **Disk** | ~200MB with default whisper.cpp model |
| **RAM** | 4GB minimum; 8GB comfortable |
-The distro must ship Python 3.11+ because Vocalinux uses distro PyGObject (`python3-gi`). Ubuntu 22.04 (Python 3.10) and Debian 11 (3.9) are below that floor. Distro matrix: [DISTRO_COMPATIBILITY.md](DISTRO_COMPATIBILITY.md).
+The distro must ship Python 3.11+ because Voculinux uses distro PyGObject (`python3-gi`). Ubuntu 22.04 (Python 3.10) and Debian 11 (3.9) are below that floor. Distro matrix: [DISTRO_COMPATIBILITY.md](DISTRO_COMPATIBILITY.md).
### GPU (optional)
whisper.cpp uses Vulkan when available (AMD, Intel, NVIDIA). Check with `vulkaninfo --summary`.
-## Running Vocalinux
+## Running Voculinux
```bash
-vocalinux # if ~/.local/bin is on PATH
-~/.local/share/vocalinux/venv/bin/vocalinux # direct
-source venv/bin/activate && vocalinux # source checkout
+voculinux # if ~/.local/bin is on PATH
+~/.local/share/voculinux/venv/bin/voculinux # direct
+source venv/bin/activate && voculinux # source checkout
```
Or launch from the application menu.
@@ -247,19 +247,19 @@ Or launch from the application menu.
### CLI
```bash
-vocalinux --help
-vocalinux --version
-vocalinux --debug
-vocalinux --engine whisper_cpp
-vocalinux --engine whisper
-vocalinux --engine vosk
-vocalinux --engine parakeet
-vocalinux --engine remote_api
-vocalinux --model tiny
-vocalinux --model medium.en-q5_0
-vocalinux --model large-v3-turbo
-vocalinux --wayland
-vocalinux --start-minimized
+voculinux --help
+voculinux --version
+voculinux --debug
+voculinux --engine whisper_cpp
+voculinux --engine whisper
+voculinux --engine vosk
+voculinux --engine parakeet
+voculinux --engine remote_api
+voculinux --model tiny
+voculinux --model medium.en-q5_0
+voculinux --model large-v3-turbo
+voculinux --wayland
+voculinux --start-minimized
```
## Autostart
@@ -270,8 +270,8 @@ vocalinux --start-minimized
| Directory | Purpose |
|-----------|---------|
-| `~/.config/vocalinux/` | Configuration |
-| `~/.local/share/vocalinux/` | Data and speech models |
+| `~/.config/voculinux/` | Configuration |
+| `~/.local/share/voculinux/` | Data and speech models |
| `~/.local/share/applications/` | Desktop entry |
| `~/.local/share/icons/hicolor/scalable/apps/` | Icons |
@@ -296,11 +296,11 @@ Reuse an existing `pywhispercpp` build:
./install.sh --auto --rebuild-whispercpp # force rebuild
```
-Switch engines in Settings → Speech Model (Advanced), or edit `~/.config/vocalinux/config.json` (`engine`: `whisper_cpp` | `whisper` | `vosk` | `parakeet` | `remote_api`).
+Switch engines in Settings → Speech Model (Advanced), or edit `~/.config/voculinux/config.json` (`engine`: `whisper_cpp` | `whisper` | `vosk` | `parakeet` | `remote_api`).
## Uninstall
-From a source checkout, `./uninstall.sh` removes the install and that checkout's `venv/`, `build/`, `dist/`, and Python bytecode. `--keep-config` and `--keep-data` leave `~/.config/vocalinux` and `~/.local/share/vocalinux` in place.
+From a source checkout, `./uninstall.sh` removes the install and that checkout's `venv/`, `build/`, `dist/`, and Python bytecode. `--keep-config` and `--keep-data` leave `~/.config/voculinux` and `~/.local/share/voculinux` in place.
```bash
./uninstall.sh
@@ -315,15 +315,15 @@ curl -fsSL https://raw.githubusercontent.com/VocaHQ/vocalinux/main/uninstall.sh
bash /tmp/vul.sh
```
-That removes Vocalinux from your home directory (config, data, launchers, desktop entry, icons). It does not delete `venv/`, `build/`, `dist/`, or `.pyc` files in the directory where you ran it.
+That removes Voculinux from your home directory (config, data, launchers, desktop entry, icons). It does not delete `venv/`, `build/`, `dist/`, or `.pyc` files in the directory where you ran it.
From the source checkout, the equivalent by hand:
```bash
-rm -rf venv ~/.config/vocalinux ~/.local/share/vocalinux
-rm -f activate-vocalinux.sh
-rm -f ~/.local/share/applications/vocalinux.desktop
-rm -f ~/.local/share/icons/hicolor/scalable/apps/vocalinux*.svg
+rm -rf venv ~/.config/voculinux ~/.local/share/voculinux
+rm -f activate-voculinux.sh
+rm -f ~/.local/share/applications/voculinux.desktop
+rm -f ~/.local/share/icons/hicolor/scalable/apps/voculinux*.svg
gtk-update-icon-cache -f -t ~/.local/share/icons/hicolor
```
diff --git a/docs/INSTALL_MANUAL.md b/docs/INSTALL_MANUAL.md
index 1c09688..6e866cf 100644
--- a/docs/INSTALL_MANUAL.md
+++ b/docs/INSTALL_MANUAL.md
@@ -12,7 +12,7 @@ Related: [DISTRO_COMPATIBILITY.md](DISTRO_COMPATIBILITY.md), [TROUBLESHOOTING.md
## System packages by distribution
-Install desktop/system dependencies **before** creating a venv or running `pip install vocalinux`. Pip cannot install GTK typelibs, AppIndicator, PortAudio, or text-injection tools.
+Install desktop/system dependencies **before** creating a venv or running `pip install voculinux`. Pip cannot install GTK typelibs, AppIndicator, PortAudio, or text-injection tools.
Debian 11 and earlier are unsupported; the Debian instructions start at Debian
12, which is the oldest release with the required Python 3.11.
@@ -84,7 +84,7 @@ sudo dnf install -y \
### Arch Linux
-Prefer the AUR package (`yay -S vocalinux`). Manual packages:
+Prefer the AUR package (`yay -S voculinux`). Manual packages:
```bash
sudo pacman -S --needed \
@@ -125,7 +125,7 @@ Gentoo, Alpine, Void, Solus, Mageia: [DISTRO_COMPATIBILITY.md](DISTRO_COMPATIBIL
Use the **system** Python (`/usr/bin/python3`). Distro PyGObject (`gi`) is compiled for that interpreter only, so a venv from pyenv/conda/uv cannot import it even with `--system-site-packages`.
```bash
-cd vocalinux
+cd voculinux
/usr/bin/python3 -m venv venv --system-site-packages
source venv/bin/activate
pip install --upgrade pip setuptools wheel
@@ -141,14 +141,14 @@ pip install -e ".[dev,vad]" # development
### Desktop integration
```bash
-mkdir -p ~/.config/vocalinux \
- ~/.local/share/vocalinux/models \
+mkdir -p ~/.config/voculinux \
+ ~/.local/share/voculinux/models \
~/.local/share/applications \
~/.local/share/icons/hicolor/scalable/apps
-cp vocalinux.desktop ~/.local/share/applications/
-VENV_PATH=$(realpath venv/bin/vocalinux)
-sed -i "s|^Exec=vocalinux|Exec=$VENV_PATH|" ~/.local/share/applications/vocalinux.desktop
+cp voculinux.desktop ~/.local/share/applications/
+VENV_PATH=$(realpath venv/bin/voculinux)
+sed -i "s|^Exec=voculinux|Exec=$VENV_PATH|" ~/.local/share/applications/voculinux.desktop
cp resources/icons/scalable/*.svg ~/.local/share/icons/hicolor/scalable/apps/
gtk-update-icon-cache -f -t ~/.local/share/icons/hicolor
@@ -159,14 +159,14 @@ gtk-update-icon-cache -f -t ~/.local/share/icons/hicolor
Same system packages as above, then:
```bash
-python3 -m venv ~/.local/share/vocalinux-pypi/venv --system-site-packages
-source ~/.local/share/vocalinux-pypi/venv/bin/activate
+python3 -m venv ~/.local/share/voculinux-pypi/venv --system-site-packages
+source ~/.local/share/voculinux-pypi/venv/bin/activate
pip install --upgrade pip setuptools wheel
-pip install vocalinux
-# vosk engine: pip install "vocalinux[vosk]"
-# faster-whisper: pip install "vocalinux[faster_whisper]"
-# parakeet engine: pip install "vocalinux[parakeet]"
-vocalinux
+pip install voculinux
+# vosk engine: pip install "voculinux[vosk]"
+# faster-whisper: pip install "voculinux[faster_whisper]"
+# parakeet engine: pip install "voculinux[parakeet]"
+voculinux
```
`--system-site-packages` lets the venv use distro GTK bindings (`python3-gi`). Building PyGObject from pip is often painful on Ubuntu/Debian.
@@ -177,18 +177,18 @@ If the app starts but no speech model is present, open Settings and download a m
```bash
# After system packages are installed:
-pipx install vocalinux
-vocalinux
+pipx install voculinux
+voculinux
```
pipx still cannot install system desktop libraries. Install those first with your package manager.
## Why system packages are required
-Vocalinux uses GTK3, AppIndicator/Ayatana, PortAudio, and tools such as `xdotool`, `wtype`, and clipboard utilities. Those come from the distro. PyPI only supplies Python packages and wheels.
+Voculinux uses GTK3, AppIndicator/Ayatana, PortAudio, and tools such as `xdotool`, `wtype`, and clipboard utilities. Those come from the distro. PyPI only supplies Python packages and wheels.
## After install
-- Run: [INSTALL.md](INSTALL.md#running-vocalinux)
+- Run: [INSTALL.md](INSTALL.md#running-voculinux)
- Engines and models: [USER_GUIDE.md](USER_GUIDE.md)
- Failures: [TROUBLESHOOTING.md](TROUBLESHOOTING.md)
diff --git a/docs/MODEL_SELECTION.md b/docs/MODEL_SELECTION.md
index 944c21f..e705031 100644
--- a/docs/MODEL_SELECTION.md
+++ b/docs/MODEL_SELECTION.md
@@ -1,6 +1,6 @@
# Choosing a speech model
-Vocalinux never downloads a speech model on its own. Changing the model pickers in
+Voculinux never downloads a speech model on its own. Changing the model pickers in
Settings → Speech Model only selects a model. If that model is not on disk yet, the
info card shows its download size and a **Download** button, and the transfer starts
only after you confirm it. Cancelling the download, or declining the confirmation,
@@ -43,7 +43,7 @@ more accurate for English.
| Large v3 Turbo | 1.6 GB | 874 MB | 574 MB (q5_0) | 809M |
| Large (v3) | 2.9 GB | | 1.1 GB (q5_0) | 1550M |
-Sizes are the catalog values Vocalinux shows before a download; the file on disk can
+Sizes are the catalog values Voculinux shows before a download; the file on disk can
differ slightly.
If you already have a quantized model of the size you want (for example Small Q8_0),
@@ -57,5 +57,5 @@ there is no reason to download the full model of the same size.
- **Parakeet**: one model of about 640 MB.
- **Remote API**: transcription runs on your server, nothing is downloaded locally.
-Models are stored under `~/.local/share/vocalinux/models/` by default. Deleting a file there
-removes the model; Vocalinux will show it as not downloaded again.
+Models are stored under `~/.local/share/voculinux/models/` by default. Deleting a file there
+removes the model; Voculinux will show it as not downloaded again.
diff --git a/docs/PERF_BASELINE_PROTOCOL.md b/docs/PERF_BASELINE_PROTOCOL.md
index f88a121..b526b50 100644
--- a/docs/PERF_BASELINE_PROTOCOL.md
+++ b/docs/PERF_BASELINE_PROTOCOL.md
@@ -19,7 +19,7 @@ no CUDA toolkit installed (Vulkan then CPU backend order).
`small.en` (floor, by language).
- Isolated XDG directories so the pass never touches a live install:
point `XDG_CONFIG_HOME`, `XDG_DATA_HOME`, `XDG_STATE_HOME` at scratch
- roots and link the verified models under `/vocalinux/models/`.
+ roots and link the verified models under `/voculinux/models/`.
- Seed `config.json` from the app's own `DEFAULT_CONFIG`: engine
`whisper_cpp`, the rung under test, keep-alive enabled with the
minimum 60 s timeout, `first_run` false, update checks off.
@@ -36,8 +36,8 @@ with the installed build's interpreter.
`reason=idle_keepalive`). RSS does not reflect the unload (freed
native pages stay mapped); VRAM-used is the state signal.
2. **Wake latency, toggle to capture start.** Drive starts over D-Bus
- (`busctl --user call com.vocalinux.Vocalinux
- /com/vocalinux/Vocalinux com.vocalinux.Vocalinux Toggle`; the
+ (`busctl --user call com.voculinux.Voculinux
+ /com/voculinux/Voculinux com.voculinux.Voculinux Toggle`; the
`--toggle` client also works but spawns the full app stack).
Parse repeated runs with `parse-log --log`: each `Toggle requested
in state IDLE` pairs with the next `Opened capture stream`. Report
diff --git a/docs/README.md b/docs/README.md
index 0062c05..b576c87 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -1,6 +1,6 @@
# Documentation
-User and maintainer documentation for Vocalinux.
+User and maintainer documentation for Voculinux.
| Document | Audience | Description |
|----------|----------|-------------|
@@ -32,4 +32,4 @@ Project root:
Website product and design notes live under [`web/`](../web/) (`PRODUCT.md`, `DESIGN.md`, `README.md`). Flatpak packaging: [`packaging/flatpak/README.md`](../packaging/flatpak/README.md).
-Website: [vocalinux.com](https://vocalinux.com)
+Website: [voculinux.com](https://voculinux.com)
diff --git a/docs/RELEASE_PROCESS.md b/docs/RELEASE_PROCESS.md
index 86438c7..533fe1b 100644
--- a/docs/RELEASE_PROCESS.md
+++ b/docs/RELEASE_PROCESS.md
@@ -1,10 +1,10 @@
-# Vocalinux Release Process
+# Voculinux Release Process
-This document outlines the step-by-step process for creating a new release of Vocalinux.
+This document outlines the step-by-step process for creating a new release of Voculinux.
## Overview
-Vocalinux uses [Semantic Versioning](https://semver.org/) with pre-release suffixes:
+Voculinux uses [Semantic Versioning](https://semver.org/) with pre-release suffixes:
- **Alpha**: Early testing phase (e.g., `0.4.1-alpha`)
- **Beta**: Feature-complete, testing phase (e.g., `0.5.0-beta`)
- **RC** (Release Candidate): Final testing before stable (e.g., `0.5.0-rc1`)
@@ -19,13 +19,13 @@ in the corresponding job.
`publish-pypi` authenticates with a short-lived OIDC token instead of a stored API
token, so there is no `PYPI_API_TOKEN` secret to leak or rotate. It only works once
-PyPI knows about this workflow. On https://pypi.org/manage/project/vocalinux/settings/publishing/
+PyPI knows about this workflow. On https://pypi.org/manage/project/voculinux/settings/publishing/
add a GitHub publisher:
| field | value |
|---|---|
| Owner | `VocaHQ` |
-| Repository | `vocalinux` |
+| Repository | `voculinux` |
| Workflow name | `release.yml` |
| Environment | `pypi` |
@@ -144,7 +144,7 @@ AUR push, but does not unpublish GitHub/PyPI artifacts already released. It is
separate from PR/local `--local-unattested` fixtures, which exercise the same
preparation/build path but are never used for publication. See [AUR.md](AUR.md)
for the trust model and the existing AUR-provider smoke-test limitations.
-`vocalinux-bin` publication waits only for release creation and both AppImages;
+`voculinux-bin` publication waits only for release creation and both AppImages;
source-gate failures or unrelated checksum producers do not block it.
## Detailed Release Steps
@@ -199,9 +199,9 @@ When shipping bug fixes only (PATCH bump, same MINOR):
- **README / `docs/UPDATE.md` "What's New"** keeps the **minor-series feature list** (everything introduced in that 0.Y line) and adds a short **Bug fixes in this patch** subsection for the delta only. Do not make the marketing highlight table look featureless because this tag only contains fixes.
- **Website changelog** (`web/src/app/changelog/page.tsx`) may list only the delta for the new entry; older entries stay historical.
-- **AppStream** (`packaging/flatpak/com.vocalinux.Vocalinux.metainfo.xml`): add a short `` note for the patch delta only; leave the long product feature `
` as series/product-level.
+- **AppStream** (`packaging/flatpak/com.voculinux.Voculinux.metainfo.xml`): add a short `` note for the patch delta only; leave the long product feature `
` as series/product-level.
- **SECURITY.md** supported versions table usually stays on the minor line (`0.14.x`) without a row per patch.
-- **AUR source PKGBUILD**: the release gate prepares `pkgver`, `_tag`, the normalized `_version`, and the canonical sdist digest, then tests that exact file. Do not introduce `SKIP` or rehash it during publication. The separate `vocalinux-bin` path still pins both AppImage digests before its own publication.
+- **AUR source PKGBUILD**: the release gate prepares `pkgver`, `_tag`, the normalized `_version`, and the canonical sdist digest, then tests that exact file. Do not introduce `SKIP` or rehash it during publication. The separate `voculinux-bin` path still pins both AppImage digests before its own publication.
- **Dates**: patch release dates must not predate the previous release in changelog / AppStream / version history.
### GitHub Release Notes Writing Rules
@@ -216,7 +216,7 @@ Use these rules for every GitHub Release body (and for the draft pasted into the
#### Required structure
-1. `# Vocalinux vX.Y.Z` title
+1. `# Voculinux vX.Y.Z` title
2. One to three plain sentences: what this release is for (no hype)
3. `## Highlights` - markdown table, about 4-8 rows
4. `## New Features` - bullets with PR + author; include issue closes when real
@@ -334,7 +334,7 @@ Add new release entry to the `releases` array at the top of the file.
```json
{
- "name": "vocalinux-website",
+ "name": "voculinux-website",
"version": "0.5.0"
}
```
@@ -369,7 +369,7 @@ bash -n install.sh
### Upstream Fix Intake (Cherry-Pick Policy)
-Upstream Vocalinux fixes enter this fork only as hand cherry-picks: taken at
+Upstream Voculinux fixes enter this fork only as hand cherry-picks: taken at
defined sync points, never as continuous tracking and never as wholesale
merges. Like every other change, each port goes through the pull request flow
with the standard test, lint, and type gates. Never land one as a direct or
@@ -390,7 +390,7 @@ worktree per branch, every change via a pull request, never commit on `main`
renames on top. Conflicts concentrate at the renamed user-visible surfaces
(application name, entry points, desktop and D-Bus identity, configuration
and data directories, package, website) precisely because the internal
- Python module name stays `vocalinux` as a retained internal name — that
+ Python module name stays `voculinux` as a retained internal name — that
split is what keeps hand cherry-picks nearly conflict-free everywhere else.
Upstream URLs and changelog history stay untouched for provenance.
- **What qualifies.** Fixes and documentation that changes user instructions
@@ -448,7 +448,7 @@ git checkout main
git pull origin main
# Create annotated tag
-git tag -a v0.5.0-beta -m "Vocalinux Beta Release 0.5.0
+git tag -a v0.5.0-beta -m "Voculinux Beta Release 0.5.0
Key changes since 0.4.1-alpha:
- Feature 1
@@ -481,7 +481,7 @@ After pushing the tag, the GitHub Actions workflow will automatically:
(stable tags only, once the GitHub Release exists, when
`FLATPAK_GPG_PRIVATE_KEY` + `FLATPAK_REPO_TOKEN` are configured — see
docs/FLATPAK_REMOTE.md)
-8. Deploy the website to vocalinux.com
+8. Deploy the website to voculinux.com
9. Build the amd64 snap from locked Python exports and run the installed-artifact
gate described in [SNAP.md](SNAP.md), then attach it to the GitHub Release and
try Snap Store
@@ -511,9 +511,9 @@ Monitor at: https://github.com/VocaHQ/vocalinux/actions
- [ ] Verify provenance: `gh attestation verify --repo VocaHQ/vocalinux`
- [ ] Verify PyPI package was published (if applicable), and that its wheel sha256
matches the line for that wheel in `SHA256SUMS`
-- [ ] Verify website was deployed (check vocalinux.com)
+- [ ] Verify website was deployed (check voculinux.com)
- [ ] If the Flatpak remote is configured, verify it picked up the tag:
- `flatpak remote-info vocahq com.vocalinux.Vocalinux` (docs/FLATPAK_REMOTE.md)
+ `flatpak remote-info vocahq com.voculinux.Voculinux` (docs/FLATPAK_REMOTE.md)
- [ ] Announce on social media/communities
- [ ] Update any pinned issues or discussions
@@ -562,7 +562,7 @@ git push origin v0.5.1-beta
| 0.14.1 | 2026-07-17 | Stable | Flatpak packaging, AUR package, layout-aware hotkeys, installer/text-injection fixes |
| 0.14.2 | 2026-07-17 | Stable | IBus engine launch + FocusIn gate; settings tabs scroll to fit monitor |
| 0.15.0 | 2026-07-28 | Stable | Searchable settings + sidebar dictation footer, AppImage, expanded languages, dictation polish, auto-pause/keepalive, Vulkan device selection, ibus-wayland, Bluetooth mic + shortcut UI fixes |
-| 0.16.0 | 2026-08-23 | Stable | Update checker + tray notify, Right Alt PTT default (new installs), searchable language list, delete unused models, Voca tone picker (family preview WAVs), About page, AGPL-3.0, family mic icons, installer/just/uv pinning, Test Dictation missing-model message, IBus/audio/clipboard/GPU/AppImage reliability, vocalinux.com family workbench restyle |
+| 0.16.0 | 2026-08-23 | Stable | Update checker + tray notify, Right Alt PTT default (new installs), searchable language list, delete unused models, Voca tone picker (family preview WAVs), About page, AGPL-3.0, family mic icons, installer/just/uv pinning, Test Dictation missing-model message, IBus/audio/clipboard/GPU/AppImage reliability, voculinux.com family workbench restyle |
| 0.17.0 | 2026-09-16 | Stable | Faster Whisper + Parakeet engines, Speech Model simple setup, first-run system language, Snap with ydotool/uinput, Flatpak bundles on the GitHub Release, XWayland/layout paste and settings/audio fixes |
| 0.18.0 | 2026-10-02 | Stable | Dictation Pad, evdev hotkey suppression, PipeWire capture + system audio, RemoteDesktop portal injection, per-language shortcuts + tray history, TinyDiarize file transcription, D-Bus activation, custom dictionary, postprocessing hook, floating overlay, audio ducking, AUR -bin + self-hosted Flatpak remote + snap-promote |
| 0.18.1 | 2026-10-08 | Stable | Settings Proxy page, opt-in JSONL transcript persistence, .deb/.rpm release packages, slimmer tray menu, dictation-pad Wayland ghost fix, evdev keyboard-discovery tightening, KWin 6 case fix, staged model picker |
diff --git a/docs/SNAP.md b/docs/SNAP.md
index ba1a002..9e812f9 100644
--- a/docs/SNAP.md
+++ b/docs/SNAP.md
@@ -30,7 +30,7 @@ packages over incidental copies in the GNOME platform.
The build audits build-tool and installed runtime versions against the active
export pins and records expected runtime versions and both export digests in
-`usr/share/vocalinux/python-inputs.json` inside the snap. Missing or wrong-version
+`usr/share/voculinux/python-inputs.json` inside the snap. Missing or wrong-version
build tools fail the build. For the packaged runtime, extra and duplicate
Python distributions are rejected as well.
@@ -49,15 +49,15 @@ snapcraft pack
On a **disposable Ubuntu host with snapd**, inspect the resulting artifact:
```bash
-bash snap/local/smoke-test.sh ./vocalinux__amd64.snap
+bash snap/local/smoke-test.sh ./voculinux__amd64.snap
```
Replace `` with the version that was built. The script refuses to overwrite an
-existing Vocalinux snap. It installs the supplied file with `--dangerous`,
+existing Voculinux snap. It installs the supplied file with `--dangerous`,
runs the actual application launcher with `--version`, then enters the GNOME
command-chain environment to audit Python versions and import the native,
GTK, recognition and text-injection modules. It leaves the installation in
-place for inspection; use a disposable host, not your normal Vocalinux install.
+place for inspection; use a disposable host, not your normal Voculinux install.
`unified-pipeline.yml` builds and runs this gate on relevant Python/Snap PRs and
main pushes, including recipe-only changes. `release.yml` runs it before the
diff --git a/docs/TROUBLESHOOTING.md b/docs/TROUBLESHOOTING.md
index 01d72e0..5b336c3 100644
--- a/docs/TROUBLESHOOTING.md
+++ b/docs/TROUBLESHOOTING.md
@@ -5,36 +5,36 @@ Common install and runtime problems. Install overview: [INSTALL.md](INSTALL.md).
Always try once with debug logs:
```bash
-vocalinux --debug
+voculinux --debug
```
-## Command not found: `vocalinux`
+## Command not found: `voculinux`
```bash
# Official install wrappers
export PATH="$HOME/.local/bin:$PATH"
-vocalinux
+voculinux
# Or run the venv binary
-~/.local/share/vocalinux/venv/bin/vocalinux
+~/.local/share/voculinux/venv/bin/voculinux
# Source checkout
source venv/bin/activate
-vocalinux
+voculinux
```
## No audio / microphone not working
1. Check system sound settings and mute state
2. List capture devices: `arecord -l`
-3. Run `vocalinux --debug` and confirm the selected device
-4. Reset a bad device index: set `audio.device_index` to `null` in `~/.config/vocalinux/config.json`
+3. Run `voculinux --debug` and confirm the selected device
+4. Reset a bad device index: set `audio.device_index` to `null` in `~/.config/voculinux/config.json`
5. Bluetooth mics: try a wired device to isolate SCO capture issues
### Microphone Stalled
A **Microphone Stalled** notification means the selected input stopped delivering
-audio. Vocalinux stops the failed dictation attempt.
+audio. Voculinux stops the failed dictation attempt.
Open **Settings → Audio**. Use **Microphone Test → Test** to record two seconds and
check the audio level, or select a different **Input Device**, then retry
@@ -75,7 +75,7 @@ Refresh icons:
```bash
gtk-update-icon-cache -f -t ~/.local/share/icons/hicolor
-vocalinux --debug
+voculinux --debug
```
## Text not injected into apps
@@ -95,7 +95,7 @@ wtype "hello"
printf "bonjour" | xsel --clipboard --input
```
-**KDE Plasma Wayland:** `wtype` may fail if the compositor does not expose a virtual keyboard to normal clients. Prefer **System Settings → Keyboard → Virtual Keyboard → IBus Wayland**, then restart Vocalinux (or log out/in).
+**KDE Plasma Wayland:** `wtype` may fail if the compositor does not expose a virtual keyboard to normal clients. Prefer **System Settings → Keyboard → Virtual Keyboard → IBus Wayland**, then restart Voculinux (or log out/in).
Install IBus if needed:
@@ -115,8 +115,8 @@ Compositor-specific notes: [DISTRO_COMPATIBILITY.md](DISTRO_COMPATIBILITY.md).
Models download on first use. Manual VOSK example:
```bash
-mkdir -p ~/.local/share/vocalinux/models
-cd ~/.local/share/vocalinux/models
+mkdir -p ~/.local/share/voculinux/models
+cd ~/.local/share/voculinux/models
wget https://alphacephei.com/vosk/models/vosk-model-small-en-us-0.15.zip
unzip vosk-model-small-en-us-0.15.zip
```
@@ -128,23 +128,23 @@ whisper.cpp models are managed from Settings or first-run download.
```bash
# Unresolved libs
-ldd $(find ~/.local/share/vocalinux/venv -name '*.so' -path '*/pywhispercpp*' 2>/dev/null | head -1) | grep 'not found'
+ldd $(find ~/.local/share/voculinux/venv -name '*.so' -path '*/pywhispercpp*' 2>/dev/null | head -1) | grep 'not found'
# Rebuild whisper.cpp bindings via installer
./install.sh --auto --rebuild-whispercpp
# Or switch to VOSK temporarily
-vocalinux --engine vosk
+voculinux --engine vosk
```
## Old process still running after update
-Stop via the tray, or use the lock-file PID (do **not** use `pkill -f vocalinux`; it can kill editors and shells):
+Stop via the tray, or use the lock-file PID (do **not** use `pkill -f voculinux`; it can kill editors and shells):
```bash
-kill "$(tr -d '[:space:]' < "${XDG_DATA_HOME:-$HOME/.local/share}/vocalinux/instance.lock")"
-kill "$(tr -d '[:space:]' < "${XDG_DATA_HOME:-$HOME/.local/share}/vocalinux-ibus/engine.pid")"
-vocalinux
+kill "$(tr -d '[:space:]' < "${XDG_DATA_HOME:-$HOME/.local/share}/voculinux/instance.lock")"
+kill "$(tr -d '[:space:]' < "${XDG_DATA_HOME:-$HOME/.local/share}/voculinux-ibus/engine.pid")"
+voculinux
```
## Clean reinstall
diff --git a/docs/UPDATE.md b/docs/UPDATE.md
index 0109824..13d2b0a 100644
--- a/docs/UPDATE.md
+++ b/docs/UPDATE.md
@@ -1,10 +1,10 @@
-# Updating Vocalinux
+# Updating Voculinux
How to upgrade an existing install, plus release notes for the current series.
## Quick update
-Vocalinux checks GitHub Releases in the background about every six hours (and shortly after startup). When a newer build is on your selected channel, the tray menu gains an **Update Available...** entry and Settings -> About shows a green **New** badge; open that page for release notes and download links. Updates are not installed automatically. Re-run the installer (or your package manager) as below.
+Voculinux checks GitHub Releases in the background about every six hours (and shortly after startup). When a newer build is on your selected channel, the tray menu gains an **Update Available...** entry and Settings -> About shows a green **New** badge; open that page for release notes and download links. Updates are not installed automatically. Re-run the installer (or your package manager) as below.
### Official installer
@@ -15,7 +15,7 @@ bash /tmp/vl.sh
The installer detects a running instance, updates in place, preserves configuration and models, and pulls new dependencies (including neural VAD when available).
-On an existing install (a virtual environment plus `~/.config/vocalinux/config.json`), the installer reports the saved configuration and defaults to **Upgrade (keep current settings)**: the configured engine stays selected, `config.json` is never rewritten, the virtual environment is reused, downloaded models are kept, and pywhispercpp is rebuilt only when this release pins a new version or GPU support is missing. Pick the interactive or automatic modes instead if you want to reconfigure the install.
+On an existing install (a virtual environment plus `~/.config/voculinux/config.json`), the installer reports the saved configuration and defaults to **Upgrade (keep current settings)**: the configured engine stays selected, `config.json` is never rewritten, the virtual environment is reused, downloaded models are kept, and pywhispercpp is rebuilt only when this release pins a new version or GPU support is missing. Pick the interactive or automatic modes instead if you want to reconfigure the install.
For a scripted, non-interactive upgrade:
@@ -28,7 +28,7 @@ bash /tmp/vl.sh --upgrade
### Installed from source
```bash
-cd vocalinux
+cd voculinux
git fetch origin
git checkout v0.18.5
./install.sh
@@ -37,7 +37,7 @@ git checkout v0.18.5
Latest development tree:
```bash
-cd vocalinux
+cd voculinux
git pull origin main
./install.sh
```
@@ -46,16 +46,16 @@ git pull origin main
| Method | Upgrade |
|--------|---------|
-| AUR | `yay -S vocalinux` (or your AUR helper) |
+| AUR | `yay -S voculinux` (or your AUR helper) |
| AppImage | Download the new file from [Releases](https://github.com/VocaHQ/vocalinux/releases) |
-| Snap | Store: `sudo snap refresh vocalinux` (`--edge` until stable is promoted). The recipe ships no `uinput` plug (the Store denied the grant); Wayland typing uses the RemoteDesktop portal. The GitHub `vocalinux_0.18.2_amd64.snap` still declares `uinput` for KDE users who want ydotool (`sudo snap install --dangerous`, then `sudo snap connect vocalinux:uinput`). |
+| Snap | Store: `sudo snap refresh voculinux` (`--edge` until stable is promoted). The recipe ships no `uinput` plug (the Store denied the grant); Wayland typing uses the RemoteDesktop portal. The GitHub `voculinux_0.18.2_amd64.snap` still declares `uinput` for KDE users who want ydotool (`sudo snap install --dangerous`, then `sudo snap connect voculinux:uinput`). |
| Flatpak (release bundle) | Install the new `.flatpak` from Releases; bundles do not auto-update |
| PyPI | Reinstall in the same venv after system packages are current |
### Check your version
```bash
-vocalinux --version
+voculinux --version
# or
python3 -c "import vocalinux; print(vocalinux.version.__version__)"
```
@@ -76,13 +76,13 @@ curl -fsSL https://raw.githubusercontent.com/VocaHQ/vocalinux/main/install.sh -o
bash /tmp/vl.sh
```
-If an old process is stuck, stop via the tray or the PID in the instance lock file (do not use `pkill -f vocalinux`; it can kill unrelated processes):
+If an old process is stuck, stop via the tray or the PID in the instance lock file (do not use `pkill -f voculinux`; it can kill unrelated processes):
```bash
-kill "$(tr -d '[:space:]' < "${XDG_DATA_HOME:-$HOME/.local/share}/vocalinux/instance.lock")"
+kill "$(tr -d '[:space:]' < "${XDG_DATA_HOME:-$HOME/.local/share}/voculinux/instance.lock")"
# If you use IBus injection:
-kill "$(tr -d '[:space:]' < "${XDG_DATA_HOME:-$HOME/.local/share}/vocalinux-ibus/engine.pid")"
-vocalinux
+kill "$(tr -d '[:space:]' < "${XDG_DATA_HOME:-$HOME/.local/share}/voculinux-ibus/engine.pid")"
+voculinux
```
Missing system packages: see [INSTALL.md](INSTALL.md) or [DISTRO_COMPATIBILITY.md](DISTRO_COMPATIBILITY.md).
@@ -196,7 +196,7 @@ See the [full changelog](https://github.com/VocaHQ/vocalinux/releases/tag/v0.18.
- Installer package map covers cairo headers on openSUSE, Void, Solus and Alpine (#937)
- evdev monitors remapper virtual keyboards ungrabbed so remappers like keyd keep working (#932)
-- The install section on vocalinux.com showcases the .deb, .rpm, Snap, Flatpak and AUR packages (#929)
+- The install section on voculinux.com showcases the .deb, .rpm, Snap, Flatpak and AUR packages (#929)
- The remote `curl | bash` install path is gated end to end in CI (#898)
AppImage, Flatpak, and Snap still ship whisper.cpp only.
@@ -273,7 +273,7 @@ See the [full changelog](https://github.com/VocaHQ/vocalinux/releases/tag/v0.18.
- Audio: stop passing an explicit index when zero devices enumerate; View Logs closes via the titlebar X (#891, #892)
- Snap gains `hardware-observe` so hotkeys can read input devices (#858, fixes #857 reported by @RhysU)
- Installer installs hash-pinned dependencies and build tools, and is split into sourced modules with a generated distro package map (#856, #862, #872 by @sesav)
-- AUR `vocalinux-bin` ships the AppImage with per-arch digests; releases publish a signed self-hosted Flatpak OSTree remote; a snap-promote workflow gates stable promotion (#879, #875, #881, fixes #817, #785, #783)
+- AUR `voculinux-bin` ships the AppImage with per-arch digests; releases publish a signed self-hosted Flatpak OSTree remote; a snap-promote workflow gates stable promotion (#879, #875, #881, fixes #817, #785, #783)
- VocaGateway can run locally from Settings → Advanced (podman-first) (#774)
- Dependency advisories cleared and workflow tokens scoped to repository reads (#869, #865, #866 by @Mr-Sunglasses, #870)
- Settings dialog consolidated: guard flags and widget construction in one place each (#878, fixes #793)
@@ -359,7 +359,7 @@ See the [full changelog](https://github.com/VocaHQ/vocalinux/releases/tag/v0.17.
- **CI**: gate AUR PKGBUILD builds on every PR (#772 by @sesav)
- **CI / docs**: test the distros the docs promise and fix docs drift (#773 by @sesav)
- **Site**: VocaGateway family card is Beta; README logo, badges, and privacy copy (#765 by @jatinkrmalik, #764)
-- **Snap**: v0.16.2 `latest/edge` (rev 7) has no `uinput` plug. `sudo snap connect vocalinux:uinput` errors with `snap "vocalinux" has no plug named "uinput"`. Dictation only reaches XWayland apps. (v0.17.0+ added the plug, but the Store denied it, so later revisions drop it again and type via the RemoteDesktop portal.) (#823)
+- **Snap**: v0.16.2 `latest/edge` (rev 7) has no `uinput` plug. `sudo snap connect voculinux:uinput` errors with `snap "voculinux" has no plug named "uinput"`. Dictation only reaches XWayland apps. (v0.17.0+ added the plug, but the Store denied it, so later revisions drop it again and type via the RemoteDesktop portal.) (#823)
See the [full changelog](https://github.com/VocaHQ/vocalinux/releases/tag/v0.16.2).
@@ -453,7 +453,7 @@ See the [full changelog](https://github.com/VocaHQ/vocalinux/releases/tag/v0.16.
- CUDA device 0 note for dual NVIDIA (#644)
- Discord and VocaHQ README shields; VocaHQ URL migration; VocaGateway rename (#695, #696, #697)
- Discord invite and X handle point at VocaHQ (#722)
-- vocalinux.com restyled to the Voca family workbench; Open Graph card uses the flat Tux (#728, #729)
+- voculinux.com restyled to the Voca family workbench; Open Graph card uses the flat Tux (#728, #729)
- Website copy drops the stale 100% offline claim and marks VocaWin as alpha on the site (#717)
- Codeberg mirror tag force-push (#633)
- Installer hardening, Justfile in place of Makefile, and uv lockfiles with pinned build inputs. Epic #701 remains open (#700, #705 by @sesav)
diff --git a/docs/USER_GUIDE.md b/docs/USER_GUIDE.md
index f8dfb0c..7a38029 100644
--- a/docs/USER_GUIDE.md
+++ b/docs/USER_GUIDE.md
@@ -1,10 +1,10 @@
# User guide
-How to use Vocalinux day to day. Install first: [INSTALL.md](INSTALL.md).
+How to use Voculinux day to day. Install first: [INSTALL.md](INSTALL.md).
## Getting started
-1. Launch Vocalinux (`vocalinux` or the application menu)
+1. Launch Voculinux (`voculinux` or the application menu)
2. Find the microphone icon in the system tray
3. Start dictation with the tray menu or your keyboard shortcut
4. Speak into the focused application; text is injected when an utterance completes
@@ -12,7 +12,7 @@ How to use Vocalinux day to day. Install first: [INSTALL.md](INSTALL.md).
### Start on login
-Enable **Start on Login** from the first-run dialog, tray menu, or Settings. Vocalinux writes an XDG autostart entry (`~/.config/autostart/vocalinux.desktop`) and starts as a normal user app (`--start-minimized`). It does not create a systemd service.
+Enable **Start on Login** from the first-run dialog, tray menu, or Settings. Voculinux writes an XDG autostart entry (`~/.config/autostart/voculinux.desktop`) and starts as a normal user app (`--start-minimized`). It does not create a systemd service.
Works on common desktop environments (GNOME, KDE, Xfce, Cinnamon, MATE, LXQt). Minimal window-manager sessions may need their own autostart helper.
@@ -26,15 +26,15 @@ Works on common desktop environments (GNOME, KDE, Xfce, Cinnamon, MATE, LXQt). M
### Dictation formatting
-Vocalinux capitalizes the start of dictation and letters after `.`, `!`, or `?`. Each completed utterance leaves a trailing space so the next session does not glue onto the previous sentence.
+Voculinux capitalizes the start of dictation and letters after `.`, `!`, or `?`. Each completed utterance leaves a trailing space so the next session does not glue onto the previous sentence.
### Dictating into terminals
-When Vocalinux injects through the clipboard (the usual Wayland / ydotool path), it sends **Ctrl+V** in ordinary text fields and **Ctrl+Shift+V** in terminal emulator windows. Auto-detect works on X11 and on Hyprland, Sway, and niri. On GNOME or KDE Wayland, set **Settings → Dictation → Clipboard Paste Shortcut** to **Ctrl+Shift+V**.
+When Voculinux injects through the clipboard (the usual Wayland / ydotool path), it sends **Ctrl+V** in ordinary text fields and **Ctrl+Shift+V** in terminal emulator windows. Auto-detect works on X11 and on Hyprland, Sway, and niri. On GNOME or KDE Wayland, set **Settings → Dictation → Clipboard Paste Shortcut** to **Ctrl+Shift+V**.
On non-US layouts such as German Neo, that chord uses the key that types **v** on the active layout (not physical KEY_V). Nested terminal panels inside an IDE are often invisible to window-class detection. If paste lands as a literal `^V` or does nothing, open **Settings → Dictation → Clipboard Paste Shortcut** and choose **Ctrl+Shift+V**.
-On X11, **Paste long dictations** opts in to clipboard-pasting dictations of 30 or more characters instead of typing them key by key. It is off by default. Vocalinux restores the previous clipboard contents after pasting unless **Copy to Clipboard** is enabled. If the clipboard contains an image or other non-text content, Vocalinux types the dictation and leaves that content alone.
+On X11, **Paste long dictations** opts in to clipboard-pasting dictations of 30 or more characters instead of typing them key by key. It is off by default. Voculinux restores the previous clipboard contents after pasting unless **Copy to Clipboard** is enabled. If the clipboard contains an image or other non-text content, Voculinux types the dictation and leaves that content alone.
The clipboard copy behind these pastes is temporary: your previous clipboard comes back right after. When the copy goes through `wl-copy` 2.2 or newer, it is also marked sensitive (`wl-copy --sensitive`), and clipboard managers that honor that hint, such as Klipper or cliphist, keep it out of their history. Older `wl-copy` builds and X11 or XWayland pastes (`xclip`/`xsel`) have no such hint, so there the dictated text can still show up in history. With **Settings → Dictation → Copy to Clipboard** on, the dictated text is an ordinary copy and stays in history.
@@ -46,11 +46,11 @@ Open **Settings → Audio → Input Device** to select a specific microphone or
**System Default**. A valid explicit microphone selection uses that device and
bypasses the System Default preference below.
-With **System Default**, Vocalinux leaves valid default or virtual inputs under
+With **System Default**, Voculinux leaves valid default or virtual inputs under
the audio system's control rather than pinning a hardware device.
On ALSA only, if PortAudio substitutes arbitrary hardware for the default input,
-Vocalinux prefers an input-capable `pulse` PCM on the same host API to follow the
+Voculinux prefers an input-capable `pulse` PCM on the same host API to follow the
microphone selected in desktop sound settings. If no suitable `pulse` PCM exists,
it keeps PortAudio's fallback device and logs a warning.
@@ -112,7 +112,7 @@ Parakeet runs NVIDIA NeMo ASR models through sherpa-onnx. The default bundle is
Pick the language you dictate in from **Language**, or leave it on auto-detect.
If you work in more than one language and switch keyboard layouts to do it, turn
-on **Follow keyboard layout** instead. Vocalinux then reads your active layout at
+on **Follow keyboard layout** instead. Voculinux then reads your active layout at
the start of every dictation and uses the matching language, so switching layout
switches dictation language with it. The Language picker greys out while this is
on and shows what your current layout resolves to; turning it off pins that
@@ -127,31 +127,31 @@ the configured primary layout.
### Activation via a KDE Plasma global shortcut
Instead of the built-in hotkey listener, you can let your desktop's global
-shortcut system trigger Vocalinux. On Wayland the built-in listener reads
+shortcut system trigger Voculinux. On Wayland the built-in listener reads
`/dev/input` (requiring membership in the `input` group and effectively acting
as a system-wide key reader). Delegating activation to the compositor avoids
this entirely: no `/dev/input` access and no `input` group needed just to
start/stop dictation. Text injection is unaffected.
-Enable it in Vocalinux:
+Enable it in Voculinux:
1. Open **Settings → Shortcuts** (the Keyboard Shortcuts group on the Dictation page)
2. Turn on **External Activation (Desktop Shortcut)**
The change applies immediately; you do not need to restart. The built-in key
listener stops, and a running instance exposes a D-Bus service on the session
-bus (`com.vocalinux.Vocalinux`). The CLI can forward commands to it:
+bus (`com.voculinux.Voculinux`). The CLI can forward commands to it:
```bash
-vocalinux --toggle # start if idle, stop if active
-vocalinux --start # start voice typing
-vocalinux --stop # stop voice typing
+voculinux --toggle # start if idle, stop if active
+voculinux --start # start voice typing
+voculinux --stop # stop voice typing
```
-Then bind a compositor shortcut to `vocalinux --toggle` on a native install.
+Then bind a compositor shortcut to `voculinux --toggle` on a native install.
For Flatpak, bind the `gdbus` command in
[Running without device access](../packaging/flatpak/README.md#running-without-device-access)
-instead, because `vocalinux --toggle` is not on the host PATH. A desktop
+instead, because `voculinux --toggle` is not on the host PATH. A desktop
shortcut only sends the key press, so it can toggle dictation but cannot
support push-to-talk because it never sees the release. On KDE Plasma:
@@ -159,16 +159,16 @@ support push-to-talk because it never sees the release. On KDE Plasma:
(older Plasma: **System Settings -> Shortcuts -> Custom Shortcuts -> Edit ->
New -> Global Shortcut -> Command/URL**).
-2. Bind a key combination of your choice to the command `vocalinux --toggle`
+2. Bind a key combination of your choice to the command `voculinux --toggle`
for a native install. For Flatpak, use the D-Bus command linked above.
Now your chosen key combination toggles dictation, handled by the compositor
-rather than by Vocalinux reading the keyboard directly. This works the same way
+rather than by Voculinux reading the keyboard directly. This works the same way
on other compositors that support binding a key to a command (e.g. GNOME custom
shortcuts, Sway/Hyprland `bindsym`/`bind`).
As an advanced alternative, you can set the same option in
-`~/.config/vocalinux/config.json` under `shortcuts`:
+`~/.config/voculinux/config.json` under `shortcuts`:
```json
"shortcuts": {
@@ -176,8 +176,8 @@ As an advanced alternative, you can set the same option in
}
```
-Quit Vocalinux before editing that file so the running app cannot overwrite
-the edit from its cached config. Start Vocalinux again after saving.
+Quit Voculinux before editing that file so the running app cannot overwrite
+the edit from its cached config. Start Voculinux again after saving.
### Model size (whisper.cpp / Whisper)
@@ -193,13 +193,13 @@ For whisper.cpp, also pick a **Specialization**: standard multilingual, English-
### Removing unused models
-If leftover files are on disk that are not the model currently selected, **Unused downloads** appears under the model info card. Expand it to delete leftovers one at a time. Confirming removes those files from `~/.local/share/vocalinux`. Packaged system-wide VOSK models are left alone.
+If leftover files are on disk that are not the model currently selected, **Unused downloads** appears under the model info card. Expand it to delete leftovers one at a time. Confirming removes those files from `~/.local/share/voculinux`. Packaged system-wide VOSK models are left alone.
### GPU
-whisper.cpp prefers Vulkan when the bundled pywhispercpp libraries include it, then CUDA, then CPU. Host tools such as `vulkaninfo` only describe the machine. The engine follows the libraries actually loaded. On multi-GPU machines a discrete Vulkan device is preferred; override under **Settings → Performance → Vulkan GPU**. Check logs with `vocalinux --debug`.
+whisper.cpp prefers Vulkan when the bundled pywhispercpp libraries include it, then CUDA, then CPU. Host tools such as `vulkaninfo` only describe the machine. The engine follows the libraries actually loaded. On multi-GPU machines a discrete Vulkan device is preferred; override under **Settings → Performance → Vulkan GPU**. Check logs with `voculinux --debug`.
-Pip wheels of pywhispercpp are often CUDA builds. In that case Vocalinux uses CUDA device 0. `install.sh` rebuilds pywhispercpp with Vulkan or CUDA when it can.
+Pip wheels of pywhispercpp are often CUDA builds. In that case Voculinux uses CUDA device 0. `install.sh` rebuilds pywhispercpp with Vulkan or CUDA when it can.
### Auto-pause and keep-alive
@@ -226,16 +226,16 @@ recording. This option is off by default.
## CLI
```bash
-vocalinux --help
-vocalinux --version
-vocalinux --debug
-vocalinux --engine whisper_cpp
-vocalinux --engine faster_whisper
-vocalinux --engine parakeet
-vocalinux --model medium.en-q5_0
-vocalinux --wayland
-vocalinux --start-minimized
-vocalinux --transcribe-file meeting.wav # diarized transcript on stdout, then exits
+voculinux --help
+voculinux --version
+voculinux --debug
+voculinux --engine whisper_cpp
+voculinux --engine faster_whisper
+voculinux --engine parakeet
+voculinux --model medium.en-q5_0
+voculinux --wayland
+voculinux --start-minimized
+voculinux --transcribe-file meeting.wav # diarized transcript on stdout, then exits
```
## Custom Dictionary Support
@@ -243,15 +243,15 @@ vocalinux --transcribe-file meeting.wav # diarized transcript on stdout, then
Open **Settings → Custom Dictionary** to configure two separate capabilities:
- **Custom terms** bias recognition toward product names, people, and jargon.
- They are read from `~/.config/vocalinux/dictionary.txt` by default, as UTF-8
+ They are read from `~/.config/voculinux/dictionary.txt` by default, as UTF-8
with one term per line. Blank lines and `#` comments are allowed, so the same
file remains friendly to an accessibility scanner. Use the add/remove editor
or choose a different readable terms file with the file picker.
- **Transcript corrections** replace a known misheard word or phrase after
transcription, for example `super base` with `Supabase`. Corrections are
- stored separately in `~/.config/vocalinux/custom-dictionary-corrections.json`.
+ stored separately in `~/.config/voculinux/custom-dictionary-corrections.json`.
-VocaLinux re-reads both files before each completed dictation segment, so an
+Voculinux re-reads both files before each completed dictation segment, so an
external edit applies to the next segment without restarting the app. Vocabulary
bias works with Whisper, whisper.cpp, and Faster Whisper. Corrections work with
every engine, including VOSK, Parakeet, and the configured remote API.
@@ -261,10 +261,10 @@ command-like misrecognition from acting, but avoid replacements that create a
voice command unless that is intentional. Correction replacements are not
automatically added to recognition bias.
-For a one-session terms override, start Vocalinux with:
+For a one-session terms override, start Voculinux with:
```bash
-vocalinux --dictionary-file /path/to/dictionary.txt
+voculinux --dictionary-file /path/to/dictionary.txt
```
This temporarily enables terms from that file without changing saved settings;
@@ -275,7 +275,7 @@ transcript corrections.
### Post-Processing
-Vocalinux can pipe each transcription result through a user-defined script before injecting it into your application. This lets you apply custom transformations — for example, grammar correction, abbreviation expansion, or domain-specific formatting.
+Voculinux can pipe each transcription result through a user-defined script before injecting it into your application. This lets you apply custom transformations — for example, grammar correction, abbreviation expansion, or domain-specific formatting.
**To configure:**
1. Open Settings from the tray icon menu (right-click)
@@ -295,19 +295,19 @@ Vocalinux can pipe each transcription result through a user-defined script befor
#!/bin/bash
tr '[:lower:]' '[:upper:]'
```
-Make the script executable (`chmod +x`) before setting the path in Vocalinux.
+Make the script executable (`chmod +x`) before setting the path in Voculinux.
## Troubleshooting
```bash
-vocalinux --debug
+voculinux --debug
```
See [TROUBLESHOOTING.md](TROUBLESHOOTING.md) for tray, audio, injection, and model issues. Distro notes: [DISTRO_COMPATIBILITY.md](DISTRO_COMPATIBILITY.md). Updates: [UPDATE.md](UPDATE.md). Help channels: [SUPPORT.md](../SUPPORT.md).
### Text injection backend
-Vocalinux types your dictated text using one of several backends. It picks one
+Voculinux types your dictated text using one of several backends. It picks one
automatically, and on most desktops the automatic choice is correct.
Autodetection can be wrong, though, and it fails in a way that is easy to
@@ -316,7 +316,7 @@ applications, IBus reports the text as delivered while nothing appears. If
dictation works in some windows (typically XWayland ones, like a browser) but
silently does nothing in others, that is the symptom.
-Pin the backend explicitly in `~/.config/vocalinux/config.json`:
+Pin the backend explicitly in `~/.config/voculinux/config.json`:
```json
{
@@ -350,19 +350,19 @@ particular application. Pinning `ibus` keeps the IBus path; pinning anything
else turns it off.
To try a backend for a single run without changing the saved setting, set
-`VOCALINUX_FORCE_BACKEND`, which overrides the config value. Set it to `auto`
+`VOCULINUX_FORCE_BACKEND`, which overrides the config value. Set it to `auto`
to ignore a saved pin for that run:
```bash
-VOCALINUX_FORCE_BACKEND=wtype vocalinux --debug
+VOCULINUX_FORCE_BACKEND=wtype voculinux --debug
```
-The setting and environment override are read at startup, so restart Vocalinux
+The setting and environment override are read at startup, so restart Voculinux
after editing `config.json`. The startup log first records a backend pin request;
it does not prove the backend was available or that text reached the focused
application. Later logs identify a fallback when a pin was not applied.
-If a pinned tool is unavailable, Vocalinux warns and continues with its normal
+If a pinned tool is unavailable, Voculinux warns and continues with its normal
fallback selection. `portal` needs a desktop implementing the
`org.freedesktop.portal.RemoteDesktop` interface (GNOME and KDE Plasma do;
most wlroots compositors do not). `ydotool` also needs a usable `/dev/uinput`
diff --git a/flake.nix b/flake.nix
index cda5e0c..663bf06 100644
--- a/flake.nix
+++ b/flake.nix
@@ -1,5 +1,5 @@
{
- description = "Vocalinux — free, offline voice dictation for Linux";
+ description = "Voculinux — free, offline voice dictation for Linux";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
@@ -21,40 +21,40 @@
pkgs = nixpkgs.legacyPackages.${system};
in
{
- vocalinux = pkgs.python3Packages.callPackage ./packaging/nix/package.nix {
+ voculinux = pkgs.python3Packages.callPackage ./packaging/nix/package.nix {
pywhispercpp = pkgs.python3Packages.callPackage ./packaging/nix/pywhispercpp.nix { };
src = self;
};
- default = self.packages.${system}.vocalinux;
+ default = self.packages.${system}.voculinux;
}
);
apps = forAllSystems (system: {
- vocalinux = {
+ voculinux = {
type = "app";
- program = "${self.packages.${system}.vocalinux}/bin/vocalinux";
+ program = "${self.packages.${system}.voculinux}/bin/voculinux";
};
- default = self.apps.${system}.vocalinux;
+ default = self.apps.${system}.voculinux;
});
overlays.default = final: prev: {
- vocalinux = self.packages.${prev.stdenv.hostPlatform.system}.vocalinux;
+ voculinux = self.packages.${prev.stdenv.hostPlatform.system}.voculinux;
};
- nixosModules.vocalinux =
+ nixosModules.voculinux =
{ pkgs, lib, ... }:
{
imports = [ ./packaging/nix/module.nix ];
- programs.vocalinux.package = lib.mkDefault self.packages.${pkgs.stdenv.hostPlatform.system}.vocalinux;
+ programs.voculinux.package = lib.mkDefault self.packages.${pkgs.stdenv.hostPlatform.system}.voculinux;
};
- nixosModules.default = self.nixosModules.vocalinux;
+ nixosModules.default = self.nixosModules.voculinux;
- homeManagerModules.vocalinux =
+ homeManagerModules.voculinux =
{ pkgs, lib, ... }:
{
imports = [ ./packaging/nix/home-manager.nix ];
- programs.vocalinux.package = lib.mkDefault self.packages.${pkgs.stdenv.hostPlatform.system}.vocalinux;
+ programs.voculinux.package = lib.mkDefault self.packages.${pkgs.stdenv.hostPlatform.system}.voculinux;
};
- homeManagerModules.default = self.homeManagerModules.vocalinux;
+ homeManagerModules.default = self.homeManagerModules.voculinux;
};
}
diff --git a/install.d/desktop.sh b/install.d/desktop.sh
index 05a3e3f..6205897 100644
--- a/install.d/desktop.sh
+++ b/install.d/desktop.sh
@@ -7,8 +7,8 @@ install_desktop_entry() {
print_info "Installing desktop entry..."
# Check if desktop entry file exists
- if [ ! -f "vocalinux.desktop" ]; then
- print_error "Desktop entry file not found: vocalinux.desktop"
+ if [ ! -f "voculinux.desktop" ]; then
+ print_error "Desktop entry file not found: voculinux.desktop"
return 1
fi
@@ -19,27 +19,27 @@ install_desktop_entry() {
}
# Copy desktop entry
- cp vocalinux.desktop "$DESKTOP_DIR/" || {
+ cp voculinux.desktop "$DESKTOP_DIR/" || {
print_error "Failed to copy desktop entry to $DESKTOP_DIR"
return 1
}
# Update the desktop entry to use the wrapper script with GI_TYPELIB_PATH
- WRAPPER_SCRIPT="$HOME/.local/bin/vocalinux-gui"
+ WRAPPER_SCRIPT="$HOME/.local/bin/voculinux-gui"
if [ ! -f "$WRAPPER_SCRIPT" ]; then
print_warning "Wrapper script not found at $WRAPPER_SCRIPT"
print_warning "Desktop entry may not work correctly"
else
# Update Exec line to include GI_TYPELIB_PATH for PyGObject
# Use the detected path for cross-distro compatibility
- sed -i "s|^Exec=vocalinux|Exec=env GI_TYPELIB_PATH=$GI_TYPELIB_DETECTED $WRAPPER_SCRIPT|" "$DESKTOP_DIR/vocalinux.desktop" || {
+ sed -i "s|^Exec=voculinux|Exec=env GI_TYPELIB_PATH=$GI_TYPELIB_DETECTED $WRAPPER_SCRIPT|" "$DESKTOP_DIR/voculinux.desktop" || {
print_warning "Failed to update desktop entry path"
}
print_info "Updated desktop entry to use wrapper script with GI_TYPELIB_PATH"
fi
# Make desktop entry executable
- chmod +x "$DESKTOP_DIR/vocalinux.desktop" || {
+ chmod +x "$DESKTOP_DIR/voculinux.desktop" || {
print_warning "Failed to make desktop entry executable"
}
@@ -64,10 +64,10 @@ install_icons() {
# List of icons to install
local ICONS=(
- "vocalinux.svg"
- "vocalinux-microphone.svg"
- "vocalinux-microphone-off.svg"
- "vocalinux-microphone-process.svg"
+ "voculinux.svg"
+ "voculinux-microphone.svg"
+ "voculinux-microphone-off.svg"
+ "voculinux-microphone-process.svg"
)
# Install each icon
@@ -85,10 +85,10 @@ install_icons() {
done
if [ "$INSTALLED_COUNT" -eq "${#ICONS[@]}" ]; then
- print_success "Installed all custom Vocalinux icons"
+ print_success "Installed all custom Voculinux icons"
return 0
elif [ "$INSTALLED_COUNT" -gt 0 ]; then
- print_warning "Installed $INSTALLED_COUNT/${#ICONS[@]} custom Vocalinux icons"
+ print_warning "Installed $INSTALLED_COUNT/${#ICONS[@]} custom Voculinux icons"
return 0
else
print_error "Failed to install any icons"
@@ -125,8 +125,8 @@ update_icon_cache() {
install_resources_to_venv() {
print_info "Installing resources to virtual environment..."
- # Target directory: $VENV_DIR/share/vocalinux/resources
- local VENV_RESOURCES_DIR="$VENV_DIR/share/vocalinux/resources"
+ # Target directory: $VENV_DIR/share/voculinux/resources
+ local VENV_RESOURCES_DIR="$VENV_DIR/share/voculinux/resources"
# Create directories
mkdir -p "$VENV_RESOURCES_DIR/icons/scalable" || {
diff --git a/install.d/interactive.sh b/install.d/interactive.sh
index 36dfb3f..3a7a304 100644
--- a/install.d/interactive.sh
+++ b/install.d/interactive.sh
@@ -27,7 +27,7 @@ run_interactive_install() {
EOF
- echo "Welcome! This guided installation will help you set up Vocalinux"
+ echo "Welcome! This guided installation will help you set up Voculinux"
echo "with the best options for your system."
echo ""
echo "Local engines (whisper.cpp, Whisper, Faster Whisper, VOSK) process audio on-device after you download a model."
@@ -38,11 +38,11 @@ EOF
# and update in place instead of redoing first-time setup. Choosing the full
# guided setup continues below and can re-point the engine deliberately.
if [[ "${EXISTING_INSTALL:-no}" == "yes" ]]; then
- echo "An existing Vocalinux installation was detected:"
+ echo "An existing Voculinux installation was detected:"
echo " Configuration: $CONFIG_DIR/config.json (kept unchanged by an upgrade)"
echo " Virtual env: $VENV_DIR (reused by an upgrade)"
echo ""
- echo " 1. Upgrade (keep current settings) - update Vocalinux only"
+ echo " 1. Upgrade (keep current settings) - update Voculinux only"
echo " 2. Full guided setup - choose engine, backend, and model options"
echo ""
@@ -330,7 +330,7 @@ EOF
echo " Remote Server: $REMOTE_DISPLAY"
fi
echo " Models: $MODELS_DISPLAY"
- echo " Install Location: ${INSTALL_DIR:-\$HOME/.local/share/vocalinux}"
+ echo " Install Location: ${INSTALL_DIR:-\$HOME/.local/share/voculinux}"
echo ""
read_prompt -p "Press Enter to continue with installation, or Ctrl+C to cancel..."
echo ""
diff --git a/install.d/models.sh b/install.d/models.sh
index ebd6549..c47bd89 100644
--- a/install.d/models.sh
+++ b/install.d/models.sh
@@ -191,7 +191,7 @@ install_whisper_model() {
print_info "Downloading Whisper tiny model..."
print_info "This may take a few minutes depending on your internet connection."
- local TEMP_FILE="$VOCALINUX_TMP_DIR/tiny.pt"
+ local TEMP_FILE="$VOCULINUX_TMP_DIR/tiny.pt"
if ! download_model_file "$TINY_MODEL_URL" "$TEMP_FILE" "Whisper model"; then
return 1
@@ -214,7 +214,7 @@ install_whisper_model() {
print_success "Whisper tiny model installed successfully ($MODEL_SIZE)"
# Create a marker file to indicate this model was pre-installed
- echo "$(date)" > "$WHISPER_DIR/.vocalinux_preinstalled"
+ echo "$(date)" > "$WHISPER_DIR/.voculinux_preinstalled"
return 0
else
@@ -241,7 +241,7 @@ install_vosk_models() {
# is deleted after unpacking. So whoever unpacks it records the verified zip
# digest in a stamp (here, and in the app's own downloader), and the directory
# is trusted only while that stamp matches what we pin today.
- local SMALL_MODEL_STAMP="$SMALL_MODEL_PATH/.vocalinux_verified"
+ local SMALL_MODEL_STAMP="$SMALL_MODEL_PATH/.voculinux_verified"
local EXPECTED_ZIP_DIGEST
EXPECTED_ZIP_DIGEST=$(pinned_digest_for "$SMALL_MODEL_ARCHIVE" || true)
if [ -d "$SMALL_MODEL_PATH" ]; then
@@ -282,7 +282,7 @@ install_vosk_models() {
print_info "Downloading small VOSK model (approximately 40MB)..."
print_info "This may take a few minutes depending on your internet connection."
- local TEMP_ZIP="$VOCALINUX_TMP_DIR/$(basename $SMALL_MODEL_URL)"
+ local TEMP_ZIP="$VOCULINUX_TMP_DIR/$(basename $SMALL_MODEL_URL)"
if ! download_model_file "$SMALL_MODEL_URL" "$TEMP_ZIP" "VOSK model"; then
return 1
@@ -334,13 +334,13 @@ install_vosk_models() {
fi
chmod -R 755 "$STAGING_DIR/$SMALL_MODEL_NAME"
- echo "$(date)" > "$STAGING_DIR/$SMALL_MODEL_NAME/.vocalinux_preinstalled"
+ echo "$(date)" > "$STAGING_DIR/$SMALL_MODEL_NAME/.voculinux_preinstalled"
# Record the digest this tree was extracted from, so a later run can tell a
# verified model from one that merely exists. Written before the swap: an
# unstamped tree is one this function would download all over again.
if [ -z "$EXPECTED_ZIP_DIGEST" ] ||
- ! printf '%s\n' "$EXPECTED_ZIP_DIGEST" > "$STAGING_DIR/$SMALL_MODEL_NAME/.vocalinux_verified"; then
+ ! printf '%s\n' "$EXPECTED_ZIP_DIGEST" > "$STAGING_DIR/$SMALL_MODEL_NAME/.voculinux_verified"; then
print_error "Could not record the verified digest for $SMALL_MODEL_NAME"
rm -rf "$STAGING_DIR"
return 1
@@ -418,7 +418,7 @@ install_whispercpp_model() {
print_info "Downloading whisper.cpp tiny model..."
print_info "This may take a few minutes depending on your internet connection."
- local TEMP_FILE="$VOCALINUX_TMP_DIR/ggml-tiny.bin"
+ local TEMP_FILE="$VOCULINUX_TMP_DIR/ggml-tiny.bin"
if ! download_model_file "$TINY_MODEL_URL" "$TEMP_FILE" "whisper.cpp model"; then
return 1
@@ -441,7 +441,7 @@ install_whispercpp_model() {
print_success "whisper.cpp tiny model installed successfully ($MODEL_SIZE)"
# Create a marker file to indicate this model was pre-installed
- echo "$(date)" > "$WHISPERCPP_DIR/.vocalinux_preinstalled"
+ echo "$(date)" > "$WHISPERCPP_DIR/.voculinux_preinstalled"
return 0
else
diff --git a/install.d/system_dependencies.sh b/install.d/system_dependencies.sh
index 6d25f85..81b14af 100644
--- a/install.d/system_dependencies.sh
+++ b/install.d/system_dependencies.sh
@@ -565,7 +565,7 @@ install_system_dependencies() {
print_error "Unsupported distribution family: $DISTRO_FAMILY"
print_info ""
print_info "Your distribution ($DISTRO_NAME) is not officially supported."
- print_info "However, you can still install Vocalinux manually:"
+ print_info "However, you can still install Voculinux manually:"
print_info ""
print_info "1. Run the dependency checker:"
print_info " bash scripts/check-system-deps.sh"
diff --git a/install.sh b/install.sh
index 0831b8c..a5238c8 100755
--- a/install.sh
+++ b/install.sh
@@ -1,6 +1,6 @@
#!/bin/bash
-# Vocalinux Installer
-# This script installs the Vocalinux application and its dependencies
+# Voculinux Installer
+# This script installs the Voculinux application and its dependencies
# -E: ERR trap propagates into functions/subshells
# -e: exit on unhandled command failure -u: error on unset variables
@@ -118,7 +118,7 @@ is_kde_plasma_session() {
print_kde_wayland_ibus_hint() {
print_warning "KDE Plasma Wayland detected."
print_info "For direct dictation into apps, open System Settings -> Keyboard -> Virtual Keyboard and select 'IBus Wayland'."
- print_info "After changing it, restart Vocalinux or log out and back in."
+ print_info "After changing it, restart Voculinux or log out and back in."
}
# Read a numeric PID from a file (instance.lock / engine.pid). Empty if missing/invalid.
@@ -133,9 +133,9 @@ read_pid_file() {
fi
}
-# True only for the Vocalinux app / IBus engine — not editors, shells, or tests
-# whose argv merely contains the string "vocalinux" (e.g. cwd under the repo).
-is_vocalinux_process() {
+# True only for the Voculinux app / IBus engine — not editors, shells, or tests
+# whose argv merely contains the string "voculinux" (e.g. cwd under the repo).
+is_voculinux_process() {
local pid="$1"
if [ "$pid" = "$$" ] || [ "$pid" = "$PPID" ]; then
@@ -163,18 +163,18 @@ is_vocalinux_process() {
return 0
fi
- # IBus engine: .../vocalinux/.../ibus_engine.py
- if [[ "$cmdline" == *"ibus_engine.py"* && "$cmdline" == *"vocalinux"* ]]; then
+ # IBus engine: .../voculinux/.../ibus_engine.py
+ if [[ "$cmdline" == *"ibus_engine.py"* && "$cmdline" == *"voculinux"* ]]; then
return 0
fi
# Console-script entrypoints. Setuptools scripts are executed as
- # `python …/bin/vocalinux`, so argv0 is python — scan every arg for the
- # script path (require …/bin/vocalinux to avoid matching a repo directory).
+ # `python …/bin/voculinux`, so argv0 is python — scan every arg for the
+ # script path (require …/bin/voculinux to avoid matching a repo directory).
local arg
while IFS= read -r -d '' arg; do
case "$arg" in
- vocalinux|vocalinux-gui|*/bin/vocalinux|*/bin/vocalinux-gui)
+ voculinux|voculinux-gui|*/bin/voculinux|*/bin/voculinux-gui)
return 0
;;
esac
@@ -184,16 +184,16 @@ is_vocalinux_process() {
}
# Prefer the PIDs the app writes; fall back to narrow entrypoint patterns only.
-# Deliberately does NOT use `pgrep -f vocalinux` (matches editors/shells/cwd paths).
-get_vocalinux_pids() {
+# Deliberately does NOT use `pgrep -f voculinux` (matches editors/shells/cwd paths).
+get_voculinux_pids() {
local data_home="${XDG_DATA_HOME:-$HOME/.local/share}"
local -A seen=()
local pid candidate
local -a candidates=()
for candidate in \
- "$(read_pid_file "$data_home/vocalinux/instance.lock")" \
- "$(read_pid_file "$data_home/vocalinux-ibus/engine.pid")"
+ "$(read_pid_file "$data_home/voculinux/instance.lock")" \
+ "$(read_pid_file "$data_home/voculinux-ibus/engine.pid")"
do
[ -n "$candidate" ] && candidates+=("$candidate")
done
@@ -202,16 +202,16 @@ get_vocalinux_pids() {
while read -r candidate; do
[ -n "$candidate" ] && candidates+=("$candidate")
done < <(
- pgrep -u "$(id -u)" -x vocalinux 2>/dev/null || true
- pgrep -u "$(id -u)" -x vocalinux-gui 2>/dev/null || true
- pgrep -u "$(id -u)" -f -- '-m vocalinux\.main' 2>/dev/null || true
- pgrep -u "$(id -u)" -f -- 'vocalinux/.*/ibus_engine\.py' 2>/dev/null || true
+ pgrep -u "$(id -u)" -x voculinux 2>/dev/null || true
+ pgrep -u "$(id -u)" -x voculinux-gui 2>/dev/null || true
+ pgrep -u "$(id -u)" -f -- '-m voculinux\.main' 2>/dev/null || true
+ pgrep -u "$(id -u)" -f -- 'voculinux/.*/ibus_engine\.py' 2>/dev/null || true
)
for pid in "${candidates[@]}"; do
[ -n "${seen[$pid]:-}" ] && continue
seen[$pid]=1
- if is_vocalinux_process "$pid"; then
+ if is_voculinux_process "$pid"; then
echo "$pid"
fi
done
@@ -219,10 +219,10 @@ get_vocalinux_pids() {
check_running_processes() {
local PIDS
- PIDS=$(get_vocalinux_pids || true)
+ PIDS=$(get_voculinux_pids || true)
if [ -n "$PIDS" ]; then
- print_warning "Found running Vocalinux process(es):"
+ print_warning "Found running Voculinux process(es):"
local pid
for pid in $PIDS; do
local cmd
@@ -232,24 +232,24 @@ check_running_processes() {
echo ""
if [[ "$NON_INTERACTIVE" == "yes" ]]; then
- print_info "Non-interactive mode: stopping Vocalinux automatically..."
+ print_info "Non-interactive mode: stopping Voculinux automatically..."
else
- read_prompt -p "Vocalinux must be stopped before installation. Kill running process(es)? (Y/n) " -n 1 -r
+ read_prompt -p "Voculinux must be stopped before installation. Kill running process(es)? (Y/n) " -n 1 -r
echo
if [[ $REPLY =~ ^[Nn]$ ]]; then
- print_error "Cannot proceed with installation while Vocalinux is running."
- print_info "Please stop Vocalinux manually and run the installer again."
+ print_error "Cannot proceed with installation while Voculinux is running."
+ print_info "Please stop Voculinux manually and run the installer again."
exit "$EXIT_USER_ABORT"
fi
fi
- print_info "Stopping Vocalinux..."
+ print_info "Stopping Voculinux..."
# shellcheck disable=SC2086
echo $PIDS | xargs -r kill -TERM 2>/dev/null || true
sleep 2
local REMAINING_PIDS
- REMAINING_PIDS=$(get_vocalinux_pids || true)
+ REMAINING_PIDS=$(get_voculinux_pids || true)
if [ -n "$REMAINING_PIDS" ]; then
print_warning "Some processes still running, forcing termination..."
@@ -259,13 +259,13 @@ check_running_processes() {
fi
local FINAL_PIDS
- FINAL_PIDS=$(get_vocalinux_pids || true)
+ FINAL_PIDS=$(get_voculinux_pids || true)
if [ -n "$FINAL_PIDS" ]; then
- print_error "Could not terminate all Vocalinux processes: $FINAL_PIDS"
+ print_error "Could not terminate all Voculinux processes: $FINAL_PIDS"
print_error "Please manually kill these processes and run the installer again."
exit "$EXIT_USER_ABORT"
else
- print_success "All Vocalinux processes stopped"
+ print_success "All Voculinux processes stopped"
fi
fi
}
@@ -373,7 +373,7 @@ while [[ $# -gt 0 ]]; do
shift
;;
--help)
- echo "Vocalinux Installer"
+ echo "Voculinux Installer"
echo ""
echo "Usage: $0 [options]"
echo ""
@@ -410,7 +410,7 @@ while [[ $# -gt 0 ]]; do
echo " $0 --dev --test # Dev mode with tests"
echo ""
echo "During installation a full transcript is saved to"
- echo " ~/.local/state/vocalinux/install-.log"
+ echo " ~/.local/state/voculinux/install-.log"
echo ""
echo "Exit codes:"
echo " 0 success"
@@ -437,7 +437,7 @@ fi
# Global install log: everything (stdout + stderr) is teed to this file so
# failures can be debugged after the fact. The path is printed at exit.
# ---------------------------------------------------------------------------
-INSTALL_LOG_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/vocalinux"
+INSTALL_LOG_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/voculinux"
if ! mkdir -p "$INSTALL_LOG_DIR" 2>/dev/null; then
INSTALL_LOG_DIR="${TMPDIR:-/tmp}"
fi
@@ -447,18 +447,18 @@ exec > >(tee -a "$INSTALL_LOG_FILE") 2>&1
# Scratch directory for pip logs, model downloads, and other temps.
# Removed on success; kept for inspection (with a notice) when the install fails.
# Exporting TMPDIR routes pip/wget/curl scratch files into this directory.
-VOCALINUX_TMP_DIR="$(mktemp -d "${TMPDIR:-/tmp}/vocalinux-install.XXXXXXXX")"
-export TMPDIR="$VOCALINUX_TMP_DIR"
+VOCULINUX_TMP_DIR="$(mktemp -d "${TMPDIR:-/tmp}/voculinux-install.XXXXXXXX")"
+export TMPDIR="$VOCULINUX_TMP_DIR"
cleanup_on_exit() {
local rc=$?
if [ "$rc" -eq "$EXIT_OK" ]; then
- rm -rf "$VOCALINUX_TMP_DIR"
+ rm -rf "$VOCULINUX_TMP_DIR"
else
print_error ""
print_error "Installation did not complete (exit code $rc)."
print_error "Full install log: $INSTALL_LOG_FILE"
- print_error "Scratch files kept for inspection: $VOCALINUX_TMP_DIR"
+ print_error "Scratch files kept for inspection: $VOCULINUX_TMP_DIR"
fi
}
trap cleanup_on_exit EXIT
@@ -478,7 +478,7 @@ cat << "EOF"
EOF
-print_info "Vocalinux Installer"
+print_info "Voculinux Installer"
print_info "=============================="
echo ""
@@ -509,21 +509,21 @@ resolve_install_tag() {
resolve_install_tag
-# Check if running from within the vocalinux repo or remotely (via curl)
-# VOCALINUX_REPO_URL overrides the clone source so the remote-install gate can
+# Check if running from within the voculinux repo or remotely (via curl)
+# VOCULINUX_REPO_URL overrides the clone source so the remote-install gate can
# serve a tag from a local mirror; public installs use the repository below.
-REPO_URL="${VOCALINUX_REPO_URL:-https://github.com/VocaHQ/vocalinux.git}"
+REPO_URL="${VOCULINUX_REPO_URL:-https://github.com/VocaHQ/vocalinux.git}"
INSTALL_DIR=""
-CLEANUP_ON_EXIT="${VOCALINUX_REMOTE_INSTALL:-no}"
+CLEANUP_ON_EXIT="${VOCULINUX_REMOTE_INSTALL:-no}"
handoff_to_tagged_installer() {
local tagged_installer="$INSTALL_DIR/install.sh"
- local remote_venv="$HOME/.local/share/vocalinux/venv"
+ local remote_venv="$HOME/.local/share/voculinux/venv"
- if grep -q 'CLEANUP_ON_EXIT="${VOCALINUX_REMOTE_INSTALL:-no}"' "$tagged_installer"; then
- export VOCALINUX_REMOTE_INSTALL=yes
- export TMPDIR="$(dirname "$VOCALINUX_TMP_DIR")"
- rmdir "$VOCALINUX_TMP_DIR"
+ if grep -q 'CLEANUP_ON_EXIT="${VOCULINUX_REMOTE_INSTALL:-no}"' "$tagged_installer"; then
+ export VOCULINUX_REMOTE_INSTALL=yes
+ export TMPDIR="$(dirname "$VOCULINUX_TMP_DIR")"
+ rmdir "$VOCULINUX_TMP_DIR"
# A bootstrap read from a pipe (curl | bash) leaves its unread tail on
# stdin: bash hands the pipe to the tagged installer, which reads its
# commands from a file instead, so nothing drains it. A producer still
@@ -537,12 +537,12 @@ handoff_to_tagged_installer() {
fi
bash "$tagged_installer" "${INSTALLER_ARGS[@]}" "--venv-dir=$remote_venv" || return $?
- if [ ! -f "$INSTALL_DIR/activate-vocalinux.sh" ]; then
- print_error "The tagged installer did not create activate-vocalinux.sh."
+ if [ ! -f "$INSTALL_DIR/activate-voculinux.sh" ]; then
+ print_error "The tagged installer did not create activate-voculinux.sh."
return 1
fi
mkdir -p "$HOME/.local/bin"
- mv "$INSTALL_DIR/activate-vocalinux.sh" "$HOME/.local/bin/activate-vocalinux.sh"
+ mv "$INSTALL_DIR/activate-voculinux.sh" "$HOME/.local/bin/activate-voculinux.sh"
}
# Function to check and install git if needed
@@ -664,17 +664,17 @@ ensure_git_installed() {
print_success "git installed successfully!"
}
-# Check if running from within the vocalinux repository
-# Validate that pyproject.toml/setup.py actually belongs to vocalinux before entering local repo mode
-IS_VOCALINUX_LOCAL=false
-if [ -f "pyproject.toml" ] && grep -q 'name = "vocalinux"' "pyproject.toml" 2>/dev/null; then
- IS_VOCALINUX_LOCAL=true
-elif [ -f "setup.py" ] && grep -q "vocalinux" "setup.py" 2>/dev/null; then
- IS_VOCALINUX_LOCAL=true
+# Check if running from within the voculinux repository
+# Validate that pyproject.toml/setup.py actually belongs to voculinux before entering local repo mode
+IS_VOCULINUX_LOCAL=false
+if [ -f "pyproject.toml" ] && grep -q 'name = "voculinux"' "pyproject.toml" 2>/dev/null; then
+ IS_VOCULINUX_LOCAL=true
+elif [ -f "setup.py" ] && grep -q "voculinux" "setup.py" 2>/dev/null; then
+ IS_VOCULINUX_LOCAL=true
fi
-if [ "$IS_VOCALINUX_LOCAL" = true ]; then
- # Running from within the vocalinux repo
+if [ "$IS_VOCULINUX_LOCAL" = true ]; then
+ # Running from within the voculinux repo
INSTALL_DIR="$(pwd)"
print_info "Running from local repository: $INSTALL_DIR"
# Convert relative VENV_DIR to absolute for wrapper scripts.
@@ -690,26 +690,26 @@ else
print_error "Re-run with an explicit release tag, e.g.: --tag="
exit "$EXIT_NETWORK"
fi
- print_info "Installing Vocalinux version: ${INSTALL_TAG}"
+ print_info "Installing Voculinux version: ${INSTALL_TAG}"
# Ensure git is installed before attempting to clone
ensure_git_installed
- INSTALL_DIR="$HOME/.local/share/vocalinux-install"
+ INSTALL_DIR="$HOME/.local/share/voculinux-install"
mkdir -p "$INSTALL_DIR"
if [ -d "$INSTALL_DIR/.git" ]; then
print_info "Updating existing clone..."
cd "$INSTALL_DIR"
if ! git fetch origin tag "$INSTALL_TAG" || ! git reset --hard "$INSTALL_TAG"; then
- print_error "Failed to update the Vocalinux clone to $INSTALL_TAG."
+ print_error "Failed to update the Voculinux clone to $INSTALL_TAG."
print_error "Check the install log and your network connection: $INSTALL_LOG_FILE"
exit "$EXIT_NETWORK"
fi
else
rm -rf "$INSTALL_DIR"
git clone --depth 1 --branch "$INSTALL_TAG" "$REPO_URL" "$INSTALL_DIR" || {
- print_error "Failed to clone Vocalinux repository"
+ print_error "Failed to clone Voculinux repository"
exit "$EXIT_NETWORK"
}
cd "$INSTALL_DIR"
@@ -1270,7 +1270,7 @@ detect_distro
# Check compatibility. These tiers mirror docs/DISTRO_COMPATIBILITY.md, and the
# distro matrix builds on ubuntu, debian and fedora. Nothing here decides whether
-# the install can proceed: what Vocalinux needs is an interpreter at the floor
+# the install can proceed: what Voculinux needs is an interpreter at the floor
# and that interpreter's distro PyGObject, checked by check_python_version()
# (fatal) and require_distro_gi() further down. This block only says how much
# help the package step is likely to be, so it must not turn away a distro the
@@ -1286,7 +1286,7 @@ case "$DISTRO_FAMILY" in
;;
*)
print_warning "This installer has not been tested on $DISTRO_NAME; you may need to install dependencies manually."
- print_warning "Vocalinux itself does not care which distribution it runs on, only that Python and PyGObject are new enough."
+ print_warning "Voculinux itself does not care which distribution it runs on, only that Python and PyGObject are new enough."
if [[ "$NON_INTERACTIVE" == "yes" ]]; then
print_info "Non-interactive mode: continuing anyway..."
else
@@ -1301,8 +1301,8 @@ esac
# Define XDG directories early: existing-install detection and the mode menu
# need CONFIG_DIR before system dependency installation asks anything.
-CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/vocalinux"
-DATA_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/vocalinux"
+CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/voculinux"
+DATA_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/voculinux"
DESKTOP_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/applications"
ICON_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/icons/hicolor/scalable/apps"
@@ -1322,7 +1322,7 @@ choose_installation_mode() {
echo ""
echo "Installation Mode:"
if [[ "${EXISTING_INSTALL:-no}" == "yes" ]]; then
- echo " 1. Upgrade (keep current settings) - update Vocalinux, keep your setup"
+ echo " 1. Upgrade (keep current settings) - update Voculinux, keep your setup"
echo " 2. Interactive - guided setup with recommendations"
echo " 3. Automatic - quick install with defaults (whisper.cpp)"
echo ""
@@ -1653,7 +1653,7 @@ install_pinned_build_tools() {
print_info "Installing pinned pip and source-build tools..."
"$VENV_DIR/bin/python" -m pip install --require-hashes --no-deps \
--only-binary=:all: --ignore-installed \
- -r "$reqs_file" --log "$VOCALINUX_TMP_DIR/bootstrap.log"
+ -r "$reqs_file" --log "$VOCULINUX_TMP_DIR/bootstrap.log"
}
install_pinned_build_tools || {
print_error "Failed to install the pinned build tools. Check requirements/installer-build.txt."
@@ -1668,15 +1668,15 @@ if [[ "$CLEANUP_ON_EXIT" == "yes" ]]; then
else
ACTIVATION_SCRIPT_DIR="."
fi
-ACTIVATION_SCRIPT="$ACTIVATION_SCRIPT_DIR/activate-vocalinux.sh"
+ACTIVATION_SCRIPT="$ACTIVATION_SCRIPT_DIR/activate-voculinux.sh"
cat > "$ACTIVATION_SCRIPT" << EOF
#!/bin/bash
-# This script activates the Vocalinux virtual environment
+# This script activates the Voculinux virtual environment
export PYTHONNOUSERSITE=1
source "$VENV_DIR/bin/activate"
-echo "Vocalinux virtual environment activated."
-echo "To start the application, run: vocalinux"
+echo "Voculinux virtual environment activated."
+echo "To start the application, run: voculinux"
EOF
chmod +x "$ACTIVATION_SCRIPT"
print_info "Created activation script: $ACTIVATION_SCRIPT"
@@ -1897,7 +1897,7 @@ install_cpu_pywhispercpp() {
pip_reinstall_pywhispercpp() {
local pip_log="$1"
shift
- local reqs_file="$VOCALINUX_TMP_DIR/pywhispercpp.txt"
+ local reqs_file="$VOCULINUX_TMP_DIR/pywhispercpp.txt"
"$VENV_DIR/bin/python" "$INSTALL_DIR/scripts/installer_requirements.py" \
"$INSTALL_DIR/requirements/runtime.txt" "$reqs_file" --package pywhispercpp || return 1
# --no-deps preserves the locked runtime and avoids reinstalling numpy
@@ -2190,7 +2190,7 @@ install_whispercpp_with_gpu_support() {
fi
if ! is_pywhispercpp_installed; then
- print_warning "pywhispercpp is still unavailable; setting VOSK as the default engine so Vocalinux can start."
+ print_warning "pywhispercpp is still unavailable; setting VOSK as the default engine so Voculinux can start."
print_warning "You can switch back to whisper.cpp from Settings after reinstalling pywhispercpp."
SELECTED_ENGINE="vosk"
@@ -2304,7 +2304,7 @@ pip_install_extras_skip_pygobject() {
# Function to install Python package with error handling and verification
install_python_package() {
# Pip logs live in the install scratch dir so a failed run can keep them.
- local PIP_LOG_DIR="$VOCALINUX_TMP_DIR/pip"
+ local PIP_LOG_DIR="$VOCULINUX_TMP_DIR/pip"
mkdir -p "$PIP_LOG_DIR"
local PIP_LOG_FILE="$PIP_LOG_DIR/pip_log.txt"
@@ -2351,21 +2351,21 @@ PY
print_success "Neural VAD support installed and verified successfully."
else
print_warning "Neural VAD dependencies installed, but Silero VAD could not be verified."
- print_warning "Vocalinux will use amplitude-based VAD until this is resolved."
+ print_warning "Voculinux will use amplitude-based VAD until this is resolved."
fi
else
print_warning "Failed to install neural VAD support."
- print_warning "Vocalinux will still work using amplitude-based VAD."
+ print_warning "Voculinux will still work using amplitude-based VAD."
print_warning "Check the pip log for details: $PIP_LOG_FILE"
fi
}
if [[ "$DEV_MODE" == "yes" ]]; then
- print_info "Installing Vocalinux in development mode..."
+ print_info "Installing Voculinux in development mode..."
# Install in development mode with logging
pip_install_project_skip_pygobject "$PIP_LOG_FILE" -e . || {
- print_error "Failed to install Vocalinux in development mode."
+ print_error "Failed to install Voculinux in development mode."
print_error "Check the pip log for details: $PIP_LOG_FILE"
return 1
}
@@ -2389,11 +2389,11 @@ PY
install_whispercpp_with_gpu_support "$PIP_LOG_FILE"
fi
else
- print_info "Installing Vocalinux..."
+ print_info "Installing Voculinux..."
# Install the package with logging (includes pywhispercpp by default)
pip_install_project_skip_pygobject "$PIP_LOG_FILE" . || {
- print_error "Failed to install Vocalinux."
+ print_error "Failed to install Voculinux."
print_error "Check the pip log for details: $PIP_LOG_FILE"
return 1
}
@@ -2701,8 +2701,8 @@ FASTER_WHISPER_CONFIG
# Verify installation
if verify_package_installed; then
- print_success "Vocalinux package installed successfully!"
- # Pip logs stay under VOCALINUX_TMP_DIR; the EXIT trap removes that
+ print_success "Voculinux package installed successfully!"
+ # Pip logs stay under VOCULINUX_TMP_DIR; the EXIT trap removes that
# directory on success and keeps it when a later step fails.
# GI_TYPELIB_PATH was already detected at the start of install_python_package
@@ -2720,10 +2720,10 @@ else
exec $EXEC_CMD
fi'
- # Create vocalinux wrapper script
- cat > "$HOME/.local/bin/vocalinux" << WRAPPER_EOF
+ # Create voculinux wrapper script
+ cat > "$HOME/.local/bin/voculinux" << WRAPPER_EOF
#!/bin/bash
-# Wrapper script for Vocalinux that sets required environment variables
+# Wrapper script for Voculinux that sets required environment variables
# and applies the 'input' group for keyboard shortcuts on Wayland
export PYTHONNOUSERSITE=1
export GI_TYPELIB_PATH=$GI_TYPELIB_DETECTED
@@ -2754,16 +2754,16 @@ if [ -n "\$PYWHISPERCPP_LIBRARY_PATH" ]; then
export LD_LIBRARY_PATH="\$PYWHISPERCPP_LIBRARY_PATH\${LD_LIBRARY_PATH:+:\$LD_LIBRARY_PATH}"
fi
-EXEC_CMD="$VENV_DIR/bin/vocalinux \$*"
+EXEC_CMD="$VENV_DIR/bin/voculinux \$*"
$SG_CHECK
WRAPPER_EOF
- chmod +x "$HOME/.local/bin/vocalinux"
- print_info "Created wrapper: ~/.local/bin/vocalinux"
+ chmod +x "$HOME/.local/bin/voculinux"
+ print_info "Created wrapper: ~/.local/bin/voculinux"
- # Create vocalinux-gui wrapper script
- cat > "$HOME/.local/bin/vocalinux-gui" << WRAPPER_EOF
+ # Create voculinux-gui wrapper script
+ cat > "$HOME/.local/bin/voculinux-gui" << WRAPPER_EOF
#!/bin/bash
-# Wrapper script for Vocalinux GUI that sets required environment variables
+# Wrapper script for Voculinux GUI that sets required environment variables
# and applies the 'input' group for keyboard shortcuts on Wayland
export PYTHONNOUSERSITE=1
export GI_TYPELIB_PATH=$GI_TYPELIB_DETECTED
@@ -2794,11 +2794,11 @@ if [ -n "\$PYWHISPERCPP_LIBRARY_PATH" ]; then
export LD_LIBRARY_PATH="\$PYWHISPERCPP_LIBRARY_PATH\${LD_LIBRARY_PATH:+:\$LD_LIBRARY_PATH}"
fi
-EXEC_CMD="$VENV_DIR/bin/vocalinux-gui \$*"
+EXEC_CMD="$VENV_DIR/bin/voculinux-gui \$*"
$SG_CHECK
WRAPPER_EOF
- chmod +x "$HOME/.local/bin/vocalinux-gui"
- print_info "Created wrapper: ~/.local/bin/vocalinux-gui"
+ chmod +x "$HOME/.local/bin/voculinux-gui"
+ print_info "Created wrapper: ~/.local/bin/voculinux-gui"
# Check if ~/.local/bin is in PATH
if [[ ":$PATH:" != *":$HOME/.local/bin:"* ]]; then
@@ -2809,7 +2809,7 @@ WRAPPER_EOF
return 0
else
- print_error "Vocalinux package installation verification failed."
+ print_error "Voculinux package installation verification failed."
print_error "Check the pip log for details: $PIP_LOG_FILE"
return 1
fi
@@ -2817,7 +2817,7 @@ WRAPPER_EOF
# Install Python package
if ! install_python_package; then
- print_error "Failed to install Vocalinux package. Installation cannot continue."
+ print_error "Failed to install Voculinux package. Installation cannot continue."
exit "$EXIT_NETWORK"
fi
@@ -2907,7 +2907,7 @@ PY
if [[ "${UPGRADE_MODE:-no}" == "yes" ]]; then
# Upgrade mode never rewrites config.json: report instead of repairing.
- print_error "Vocalinux cannot start with this configuration and the engine is not installed."
+ print_error "Voculinux cannot start with this configuration and the engine is not installed."
print_error "Install the engine: $VENV_DIR/bin/pip install $(engine_pip_name "$CONFIGURED_ENGINE")"
print_error "or edit $CONFIG_FILE and set speech_recognition.engine to an installed engine."
return 1
@@ -2934,7 +2934,7 @@ PY
fi
done
- print_error "Vocalinux cannot start with this configuration and no working engine is available."
+ print_error "Voculinux cannot start with this configuration and no working engine is available."
print_error "Install the engine: $VENV_DIR/bin/pip install $(engine_pip_name "$CONFIGURED_ENGINE")"
print_error "or edit $CONFIG_FILE and set speech_recognition.engine to an installed engine."
return 1
@@ -2954,7 +2954,7 @@ run_tests() {
# Check if pytest is installed in the virtual environment
if ! "$VENV_DIR/bin/python" -c "import pytest" &>/dev/null; then
print_info "Installing pytest and related packages..."
- local PIP_LOG_FILE="$VOCALINUX_TMP_DIR/test-deps.log"
+ local PIP_LOG_FILE="$VOCULINUX_TMP_DIR/test-deps.log"
pip_install_extras_skip_pygobject "$PIP_LOG_FILE" dev || {
print_error "Failed to install pytest. Cannot run tests."
return 1
@@ -2962,7 +2962,7 @@ run_tests() {
fi
# Create a directory for test results
- local TEST_RESULTS_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/vocalinux/test_results"
+ local TEST_RESULTS_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/voculinux/test_results"
mkdir -p "$TEST_RESULTS_DIR"
local TEST_RESULTS_FILE="$TEST_RESULTS_DIR/pytest_$(date +%Y%m%d_%H%M%S).xml"
@@ -3007,21 +3007,21 @@ verify_installation() {
ISSUES=$((ISSUES + 1))
fi
- # Check if vocalinux command is available
- if ! command -v vocalinux &>/dev/null && [ ! -f "$VENV_DIR/bin/vocalinux" ]; then
- print_error "Vocalinux command not found."
+ # Check if voculinux command is available
+ if ! command -v voculinux &>/dev/null && [ ! -f "$VENV_DIR/bin/voculinux" ]; then
+ print_error "Voculinux command not found."
ISSUES=$((ISSUES + 1))
fi
# Check if desktop entry is installed
- if [ ! -f "$DESKTOP_DIR/vocalinux.desktop" ]; then
+ if [ ! -f "$DESKTOP_DIR/voculinux.desktop" ]; then
print_warning "Desktop entry not found. Application may not appear in application menu."
ISSUES=$((ISSUES + 1))
fi
# Check if icons are installed
local ICON_COUNT=0
- for icon in vocalinux.svg vocalinux-microphone.svg vocalinux-microphone-off.svg vocalinux-microphone-process.svg; do
+ for icon in voculinux.svg voculinux-microphone.svg voculinux-microphone-off.svg voculinux-microphone-process.svg; do
if [ -f "$ICON_DIR/$icon" ]; then
ICON_COUNT=$((ICON_COUNT + 1))
fi
@@ -3034,7 +3034,7 @@ verify_installation() {
# Check if Python package is importable using venv python
if ! "$VENV_DIR/bin/python" -c "import vocalinux" &>/dev/null; then
- print_error "Vocalinux Python package cannot be imported."
+ print_error "Voculinux Python package cannot be imported."
ISSUES=$((ISSUES + 1))
fi
@@ -3094,7 +3094,7 @@ EOF
# Success or warning message
if [ "$ISSUES" -eq 0 ]; then
- print_success "Vocalinux has been installed successfully!"
+ print_success "Voculinux has been installed successfully!"
else
print_warning "Installation complete with $ISSUES minor issue(s)"
print_warning "The application should still work normally."
@@ -3141,12 +3141,12 @@ EOF
echo " 📦 What Was Installed"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
- echo " Application: Vocalinux (voice dictation for Linux)"
+ echo " Application: Voculinux (voice dictation for Linux)"
echo " Engine: $ENGINE_DISPLAY_NAME"
if [[ -n "$BACKEND_INFO" ]]; then
echo " Backend: $BACKEND_INFO"
fi
- echo " Location: ${INSTALL_DIR:-\$HOME/.local/share/vocalinux}"
+ echo " Location: ${INSTALL_DIR:-\$HOME/.local/share/voculinux}"
echo " Virtual Env: $VENV_DIR"
echo " Config: $CONFIG_DIR"
echo ""
@@ -3155,9 +3155,9 @@ EOF
echo " 🚀 Getting Started"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
- echo "1. Launch Vocalinux"
- echo " • From app menu: Look for 'Vocalinux'"
- echo " • From terminal: Run 'vocalinux' command"
+ echo "1. Launch Voculinux"
+ echo " • From app menu: Look for 'Voculinux'"
+ echo " • From terminal: Run 'voculinux' command"
echo ""
echo "2. Find the icon in your system tray (top bar)"
echo " • Click for settings and status"
@@ -3180,16 +3180,16 @@ EOF
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
- echo " 🔧 Managing Vocalinux"
+ echo " 🔧 Managing Voculinux"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo "Commands:"
- echo " vocalinux Start the application"
- echo " vocalinux --debug Start with debug logging"
- echo " vocalinux-gui Open settings GUI"
+ echo " voculinux Start the application"
+ echo " voculinux --debug Start with debug logging"
+ echo " voculinux-gui Open settings GUI"
echo ""
echo "To activate the virtual environment:"
- echo " source ${ACTIVATION_SCRIPT:-activate-vocalinux.sh}"
+ echo " source ${ACTIVATION_SCRIPT:-activate-voculinux.sh}"
echo ""
echo "To uninstall:"
echo " ./uninstall.sh"
@@ -3215,10 +3215,10 @@ EOF
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo ""
echo "Virtual environment: $VENV_DIR"
- echo "Desktop entry: $DESKTOP_DIR/vocalinux.desktop"
+ echo "Desktop entry: $DESKTOP_DIR/voculinux.desktop"
echo "Configuration: $CONFIG_DIR"
echo "Data directory: $DATA_DIR"
- echo "Wrapper script: $HOME/.local/bin/vocalinux"
+ echo "Wrapper script: $HOME/.local/bin/voculinux"
echo ""
fi
}
diff --git a/justfile b/justfile
index b48ac0c..4ce40d5 100644
--- a/justfile
+++ b/justfile
@@ -1,4 +1,4 @@
-# Vocalinux justfile
+# Voculinux justfile
# Convenient commands for development
# Run `just` to list all recipes. Python tooling runs through `uv run` against
# .venv/ — run `just deps` after cloning (requires uv).
@@ -47,7 +47,7 @@ _check_build_deps:
_tooling: _check_build_deps
uv sync --inexact {{DEV_EXTRAS}}
-# Install Vocalinux
+# Install Voculinux
install:
./install.sh
@@ -149,7 +149,7 @@ aur-gate:
uv pip install --no-config --python "$WORK/venv/bin/python" \
--require-hashes --no-deps --only-binary=:all: -r requirements/release-build.txt
"$WORK/venv/bin/python" scripts/prepare_aur_source.py \
- --local-unattested --sdist "$WORK"/dist/vocalinux-*.tar.gz --output "$WORK/source"
+ --local-unattested --sdist "$WORK"/dist/voculinux-*.tar.gz --output "$WORK/source"
docker run --rm -v "$PWD:/repo:ro" -v "$WORK/source:/aur-source:ro" \
-e AUR_SOURCE=/aur-source archlinux:latest bash /repo/packaging/aur/build-test.sh
@@ -294,11 +294,11 @@ clean:
# Run the installed application
run:
- vocalinux
+ voculinux
# Run the installed application with debug logging
run-debug:
- vocalinux --debug
+ voculinux --debug
# Run from source
run-source: _tooling
@@ -314,4 +314,4 @@ pre-commit: _tooling
# Print the current version
version:
- @uv run --no-sync python -c "from src.vocalinux.version import __version__; print(__version__)"
+ @uv run --no-sync python -c "from src.voculinux.version import __version__; print(__version__)"
diff --git a/packaging/appimage/boot-test.sh b/packaging/appimage/boot-test.sh
index 4b92601..fe9e76c 100755
--- a/packaging/appimage/boot-test.sh
+++ b/packaging/appimage/boot-test.sh
@@ -130,7 +130,7 @@ if [ "$status" -ne 124 ] && [ "$status" -ne 0 ] && [ "$status" -ne 143 ]; then
fail "the app exited with $status instead of running"
fi
-grep -q "Initializing Vocalinux" "$LOG" || {
+grep -q "Initializing Voculinux" "$LOG" || {
tail -n 30 "$LOG" >&2
fail "startup never reached component initialisation"
}
diff --git a/packaging/appimage/build.sh b/packaging/appimage/build.sh
index bc2b9c1..baa5b8b 100755
--- a/packaging/appimage/build.sh
+++ b/packaging/appimage/build.sh
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
-# Build a relocatable AppImage for Vocalinux, natively for whichever
+# Build a relocatable AppImage for Voculinux, natively for whichever
# architecture this script runs on (x86_64 or aarch64) - no cross-compiling.
#
# Usage: build.sh [output-dir]
@@ -26,10 +26,10 @@
# pywhispercpp from source with GGML_VULKAN=1 when Vulkan headers and a
# shader compiler are on the build host. The AppImage uses the host Vulkan
# loader/ICDs at runtime (do not bundle NVIDIA/AMD driver ICDs).
-# Set VOCALINUX_APPIMAGE_REQUIRE_VULKAN=1 in CI so a failed rebuild fails
+# Set VOCULINUX_APPIMAGE_REQUIRE_VULKAN=1 in CI so a failed rebuild fails
# the job instead of shipping a CPU-only image. Set
-# VOCALINUX_APPIMAGE_SKIP_VULKAN=1 to force the CPU wheel.
-# A build that produced libggml-vulkan.so is kept in VOCALINUX_APPIMAGE_CACHE
+# VOCULINUX_APPIMAGE_SKIP_VULKAN=1 to force the CPU wheel.
+# A build that produced libggml-vulkan.so is kept in VOCULINUX_APPIMAGE_CACHE
# and reused while the base image, tool_checksums.txt, and the pywhispercpp
# pin are unchanged. A CPU-only build is not cached.
set -euo pipefail
@@ -113,7 +113,7 @@ checkout_pinned() {
git -C "$dest" checkout -q FETCH_HEAD
}
-# Seed typelibs Vocalinux imports directly, plus transitive GIR deps that Gtk
+# Seed typelibs Voculinux imports directly, plus transitive GIR deps that Gtk
# and AppIndicator require (xlib, Dbusmenu, …). Without those, GI falls back to
# the builder's baked-in path (/usr/lib/x86_64-linux-gnu/girepository-1.0), which
# does not exist on Fedora/openSUSE/Arch — startup then reports "missing GTK3".
@@ -241,7 +241,7 @@ uv_install() {
"$UV" pip install --python "$PY_BIN" --prefix "$APPDIR/usr" "$@"
}
-echo "== Installing Vocalinux + runtime deps into the bundle =="
+echo "== Installing Voculinux + runtime deps into the bundle =="
# From the lock, not from whatever PyPI serves today. vad.txt is a superset of
# runtime.txt (a test keeps it that way, so this is one resolution rather than
# two); appimage.txt adds the PyGObject the exports leave out. The wheel is last
@@ -253,15 +253,15 @@ uv_install --require-hashes --no-deps -r "$REPO_ROOT/requirements/appimage.txt"
uv_install --no-deps "$WHEEL"
echo "== Adding desktop entry + icon =="
-install -Dm644 "$REPO_ROOT/vocalinux.desktop" "$APPDIR/usr/share/applications/vocalinux.desktop"
+install -Dm644 "$REPO_ROOT/voculinux.desktop" "$APPDIR/usr/share/applications/voculinux.desktop"
# AppImage desktop integration expects Exec=AppRun; set WM class for the tray app.
sed -i \
-e 's|^Exec=.*|Exec=AppRun|' \
-e '/^StartupWMClass=/d' \
- "$APPDIR/usr/share/applications/vocalinux.desktop"
-printf 'StartupWMClass=vocalinux\n' >> "$APPDIR/usr/share/applications/vocalinux.desktop"
-install -Dm644 "$REPO_ROOT/resources/icons/scalable/vocalinux.svg" \
- "$APPDIR/usr/share/icons/hicolor/scalable/apps/vocalinux.svg"
+ "$APPDIR/usr/share/applications/voculinux.desktop"
+printf 'StartupWMClass=voculinux\n' >> "$APPDIR/usr/share/applications/voculinux.desktop"
+install -Dm644 "$REPO_ROOT/resources/icons/scalable/voculinux.svg" \
+ "$APPDIR/usr/share/icons/hicolor/scalable/apps/voculinux.svg"
copy_typelibs() {
local dest="$1"
@@ -363,7 +363,7 @@ ensure_build_tools() {
# ggml demands glslc (`find_package(Vulkan COMPONENTS glslc REQUIRED)`) and the
# base image packages none, so build it from the pinned shaderc commit — ~4 min
-# on a runner, and CI caches it in VOCALINUX_APPIMAGE_CACHE since the commit is
+# on a runner, and CI caches it in VOCULINUX_APPIMAGE_CACHE since the commit is
# its only input.
ensure_glslc() {
if command -v glslc >/dev/null 2>&1; then
@@ -372,7 +372,7 @@ ensure_glslc() {
fi
local commit cache_dir src
commit="$(pin_field shaderc 3)"
- cache_dir="${VOCALINUX_APPIMAGE_CACHE:-${XDG_CACHE_HOME:-$HOME/.cache}/vocalinux-appimage}/glslc-${commit}-${ARCH}"
+ cache_dir="${VOCULINUX_APPIMAGE_CACHE:-${XDG_CACHE_HOME:-$HOME/.cache}/voculinux-appimage}/glslc-${commit}-${ARCH}"
if [ ! -x "$cache_dir/glslc" ]; then
echo "== Building glslc from shaderc ${commit:0:12} (this image packages none) =="
ensure_build_tools
@@ -486,7 +486,7 @@ _compile_pywhispercpp_vulkan() {
if ! has_vulkan_build_deps; then
echo "Vulkan build deps missing (libvulkan-dev plus a C++ compiler)." >&2
if [ "$require_vulkan" = "1" ]; then
- echo "VOCALINUX_APPIMAGE_REQUIRE_VULKAN=1: refusing to ship a CPU-only AppImage." >&2
+ echo "VOCULINUX_APPIMAGE_REQUIRE_VULKAN=1: refusing to ship a CPU-only AppImage." >&2
exit 1
fi
echo "Warning: AppImage will use a CPU-only baseline pywhispercpp build." >&2
@@ -547,13 +547,13 @@ _compile_pywhispercpp_vulkan() {
}
rebuild_pywhispercpp_vulkan() {
- local require_vulkan="${VOCALINUX_APPIMAGE_REQUIRE_VULKAN:-0}"
- if [ "${VOCALINUX_APPIMAGE_SKIP_VULKAN:-0}" = "1" ]; then
- echo "== Skipping pywhispercpp Vulkan rebuild (VOCALINUX_APPIMAGE_SKIP_VULKAN=1) =="
+ local require_vulkan="${VOCULINUX_APPIMAGE_REQUIRE_VULKAN:-0}"
+ if [ "${VOCULINUX_APPIMAGE_SKIP_VULKAN:-0}" = "1" ]; then
+ echo "== Skipping pywhispercpp Vulkan rebuild (VOCULINUX_APPIMAGE_SKIP_VULKAN=1) =="
return 0
fi
- # The Vocalinux wheel was installed above and is not part of this cache.
+ # The Voculinux wheel was installed above and is not part of this cache.
# A hit still replaces the CPU pywhispercpp wheel the lock just installed,
# and it does not run _compile_pywhispercpp_vulkan.
local cache_dir site
@@ -593,8 +593,8 @@ export DEPLOY_GTK_VERSION=3
"$TOOLDIR/linuxdeploy" --appdir "$APPDIR" \
--plugin gtk \
-e "$APPDIR/usr/bin/python3" \
- -d "$APPDIR/usr/share/applications/vocalinux.desktop" \
- -i "$APPDIR/usr/share/icons/hicolor/scalable/apps/vocalinux.svg"
+ -d "$APPDIR/usr/share/applications/voculinux.desktop" \
+ -i "$APPDIR/usr/share/icons/hicolor/scalable/apps/voculinux.svg"
# The plugin can change the bundle after PyGObject was installed. Check the
# package and the version-agnostic Python path that AppRun and the GI smoke use
@@ -689,14 +689,14 @@ GTK_HOOK="$APPDIR/apprun-hooks/linuxdeploy-plugin-gtk.sh"
if [ -f "$GTK_HOOK" ]; then
# Upstream forces GDK_BACKEND=x11 even on Wayland, which breaks hover/focus
# for GTK widgets under Plasma (XWayland). Prefer native Wayland unless the
- # user opts into X11 via VOCALINUX_FORCE_X11=1.
+ # user opts into X11 via VOCULINUX_FORCE_X11=1.
"$APPDIR/usr/bin/python3" - "$GTK_HOOK" <<'PY'
import pathlib, re, sys
path = pathlib.Path(sys.argv[1])
text = path.read_text()
replacement = (
'# Prefer Wayland when available; force X11 only when requested.\n'
- 'if [ "${VOCALINUX_FORCE_X11:-0}" = "1" ]; then\n'
+ 'if [ "${VOCULINUX_FORCE_X11:-0}" = "1" ]; then\n'
' export GDK_BACKEND=x11\n'
'elif [ -n "${WAYLAND_DISPLAY:-}" ] || [ "${XDG_SESSION_TYPE:-}" = "wayland" ]; then\n'
' export GDK_BACKEND=wayland\n'
@@ -727,13 +727,13 @@ smoke_gi_imports() {
local appdir="$1"
unshare --user --mount --map-root-user bash -c "
set -euo pipefail
- mkdir -p /tmp/vocalinux-empty-gi
+ mkdir -p /tmp/voculinux-empty-gi
for d in /usr/lib/x86_64-linux-gnu/girepository-1.0 \
/usr/lib/aarch64-linux-gnu/girepository-1.0 \
/usr/lib/girepository-1.0 \
/usr/lib64/girepository-1.0; do
if [ -d \"\$d\" ]; then
- mount --bind /tmp/vocalinux-empty-gi \"\$d\"
+ mount --bind /tmp/voculinux-empty-gi \"\$d\"
fi
done
export PYTHONHOME='$appdir/usr'
@@ -797,6 +797,6 @@ else
fi
echo "== Packaging AppImage =="
-OUTPUT="$OUTDIR/Vocalinux-${VERSION}-${ARCH}.AppImage"
+OUTPUT="$OUTDIR/Voculinux-${VERSION}-${ARCH}.AppImage"
ARCH="$ARCH" "$TOOLDIR/appimagetool" "$APPDIR" "$OUTPUT"
echo "Built $OUTPUT"
diff --git a/packaging/appimage/container-build.sh b/packaging/appimage/container-build.sh
index 47ab221..c8e7e12 100755
--- a/packaging/appimage/container-build.sh
+++ b/packaging/appimage/container-build.sh
@@ -6,7 +6,7 @@
# tool_checksums.txt. This script is the part that runs inside that image; the
# way in is docker-build.sh, which both CI and `just appimage` call:
#
-# bash packaging/appimage/docker-build.sh dist/vocalinux-0.16.0-py3-none-any.whl 0.16.0 dist
+# bash packaging/appimage/docker-build.sh dist/voculinux-0.16.0-py3-none-any.whl 0.16.0 dist
#
# Only the interpreter and the Python packages are pinned by digest; these apt
# packages are whatever the pinned image resolves to. That is the trade the base
@@ -34,5 +34,5 @@ bash "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")/build.sh" "$@"
# results back to whoever started it (docker-build.sh passes its own ids).
if [ -n "${HOST_UID:-}" ]; then
chown -R "${HOST_UID}:${HOST_GID:-$HOST_UID}" "${3:-dist}" \
- "${VOCALINUX_APPIMAGE_CACHE:-/cache}" 2>/dev/null || true
+ "${VOCULINUX_APPIMAGE_CACHE:-/cache}" 2>/dev/null || true
fi
diff --git a/packaging/appimage/docker-build.sh b/packaging/appimage/docker-build.sh
index 517dc9c..113344b 100755
--- a/packaging/appimage/docker-build.sh
+++ b/packaging/appimage/docker-build.sh
@@ -8,9 +8,9 @@
# the AppImage links against, and building on the host instead means shipping
# whatever that host happens to run.
#
-# Honours VOCALINUX_APPIMAGE_REQUIRE_VULKAN / _SKIP_VULKAN like build.sh, and
-# keeps glslc and the pywhispercpp Vulkan build in VOCALINUX_APPIMAGE_CACHE
-# (~/.cache/vocalinux-appimage by default) so the next build reuses them.
+# Honours VOCULINUX_APPIMAGE_REQUIRE_VULKAN / _SKIP_VULKAN like build.sh, and
+# keeps glslc and the pywhispercpp Vulkan build in VOCULINUX_APPIMAGE_CACHE
+# (~/.cache/voculinux-appimage by default) so the next build reuses them.
set -euo pipefail
REPO_ROOT="$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")/../.." && pwd)"
@@ -20,7 +20,7 @@ if [ -z "$IMAGE" ]; then
exit 1
fi
-CACHE="${VOCALINUX_APPIMAGE_CACHE:-${XDG_CACHE_HOME:-$HOME/.cache}/vocalinux-appimage}"
+CACHE="${VOCULINUX_APPIMAGE_CACHE:-${XDG_CACHE_HOME:-$HOME/.cache}/voculinux-appimage}"
mkdir -p "$CACHE"
# The wheel and output dir are given as host paths; the repo is mounted at the
@@ -31,9 +31,9 @@ exec docker run --rm \
--security-opt seccomp=unconfined \
-v "$REPO_ROOT:$REPO_ROOT" -w "$REPO_ROOT" \
-v "$CACHE:/cache" \
- -e VOCALINUX_APPIMAGE_CACHE=/cache \
- -e VOCALINUX_APPIMAGE_REQUIRE_VULKAN \
- -e VOCALINUX_APPIMAGE_SKIP_VULKAN \
+ -e VOCULINUX_APPIMAGE_CACHE=/cache \
+ -e VOCULINUX_APPIMAGE_REQUIRE_VULKAN \
+ -e VOCULINUX_APPIMAGE_SKIP_VULKAN \
-e CMAKE_BUILD_PARALLEL_LEVEL \
-e HOST_UID="$(id -u)" \
-e HOST_GID="$(id -g)" \
diff --git a/packaging/appimage/native-cache-id.sh b/packaging/appimage/native-cache-id.sh
index d24084a..407f970 100755
--- a/packaging/appimage/native-cache-id.sh
+++ b/packaging/appimage/native-cache-id.sh
@@ -5,16 +5,16 @@
# from it), every pin in tool_checksums.txt, the cmake/ninja pins in
# requirements/appimage-tools.txt, the Vulkan flags in build.sh, and the
# pywhispercpp sdist install.sh names. It does not depend on the rest of the
-# Vocalinux sources, so this id ignores the git commit and the Actions run id
+# Voculinux sources, so this id ignores the git commit and the Actions run id
# on purpose: putting either in the cache key would rebuild on every push.
set -euo pipefail
here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
repo="$(cd "$here/../.." && pwd)"
-pins="${VOCALINUX_PINS:-$repo/packaging/appimage/tool_checksums.txt}"
-install_sh="${VOCALINUX_INSTALL_SH:-$repo/install.sh}"
-tools="${VOCALINUX_APPIMAGE_TOOLS:-$repo/requirements/appimage-tools.txt}"
-build_sh="${VOCALINUX_BUILD_SH:-$repo/packaging/appimage/build.sh}"
+pins="${VOCULINUX_PINS:-$repo/packaging/appimage/tool_checksums.txt}"
+install_sh="${VOCULINUX_INSTALL_SH:-$repo/install.sh}"
+tools="${VOCULINUX_APPIMAGE_TOOLS:-$repo/requirements/appimage-tools.txt}"
+build_sh="${VOCULINUX_BUILD_SH:-$repo/packaging/appimage/build.sh}"
base="$(awk '$1=="base-image" {print $3; exit}' "$pins")"
if [ -z "$base" ]; then
diff --git a/packaging/appimage/native-cache.sh b/packaging/appimage/native-cache.sh
index ed29685..f6f2df5 100755
--- a/packaging/appimage/native-cache.sh
+++ b/packaging/appimage/native-cache.sh
@@ -12,7 +12,7 @@ _NATIVE_CACHE_HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
pywhispercpp_native_cache_dir() {
local arch="$1"
local root id
- root="${VOCALINUX_APPIMAGE_CACHE:-${XDG_CACHE_HOME:-$HOME/.cache}/vocalinux-appimage}"
+ root="${VOCULINUX_APPIMAGE_CACHE:-${XDG_CACHE_HOME:-$HOME/.cache}/voculinux-appimage}"
id="$(bash "$_NATIVE_CACHE_HERE/native-cache-id.sh")"
printf '%s\n' "$root/pywhispercpp-vulkan-${arch}-${id}"
}
@@ -26,7 +26,7 @@ pywhispercpp_cache_has_vulkan() {
}
# Copy the pywhispercpp install out of a site-packages directory.
-# Leaves the rest of the prefix (Vocalinux, numpy, …) where it is.
+# Leaves the rest of the prefix (Voculinux, numpy, …) where it is.
pywhispercpp_cache_publish() {
local site="$1" dest="$2"
local parent staging pattern backup
diff --git a/packaging/aur/build-test.sh b/packaging/aur/build-test.sh
index 3808c9f..3085c5d 100644
--- a/packaging/aur/build-test.sh
+++ b/packaging/aur/build-test.sh
@@ -108,10 +108,10 @@ echo "== Satisfy the AUR-resolved depends for dependency resolution =="
STUB="$WORKDIR/stub"
mkdir -p "$STUB"
cat >"$STUB/PKGBUILD" </dev/null
# The console script proves the wheel's entry points landed; the imports walk
# every depends entry the package declares (gi/Gtk/AppIndicator, IBus, cairo,
# pyaudio, numpy, requests, tqdm, psutil, evdev, xlib, pynput).
-vocalinux --version
+voculinux --version
python - "$_version" <<'PY' || fail "the installed package does not import or has the wrong version"
import sys
from importlib.metadata import version
-assert version("vocalinux") == sys.argv[1], "installed distribution version differs from the sdist"
+assert version("voculinux") == sys.argv[1], "installed distribution version differs from the sdist"
import vocalinux.main
import vocalinux.ui.tray_indicator
@@ -196,13 +196,13 @@ if [ "${AUR_SOURCE_ONLY:-0}" = 1 ]; then
exit 0
fi
-echo "== Build vocalinux-bin against a stub AppImage =="
+echo "== Build voculinux-bin against a stub AppImage =="
# The -bin package's arch sources are the published release assets, which do
# not exist for an untagged HEAD. A placeholder exercises the same package()
# install path on this arch; the pinned sums still describe the real assets,
# so this stage skips checksum verification — release.yml's updpkgsums keeps
# the published PKGBUILD pinned to the actual files.
-BINPKGDIR="$REPO/packaging/aur/vocalinux-bin"
+BINPKGDIR="$REPO/packaging/aur/voculinux-bin"
[ -f "$BINPKGDIR/PKGBUILD" ] || fail "$BINPKGDIR/PKGBUILD not found"
# shellcheck source=/dev/null
source "$BINPKGDIR/PKGBUILD"
@@ -214,10 +214,10 @@ pacman_retry -S --needed --noconfirm --asdeps "${depends[@]}" >/dev/null
# directory as that user — makepkg writes into it as `builder`.
BINBUILD="$WORKDIR/binpkg"
runuser -u builder -- mkdir -p "$BINBUILD"
-cp "$BINPKGDIR/PKGBUILD" "$BINPKGDIR/vocalinux.desktop" \
- "$BINPKGDIR/vocalinux.svg" "$BINPKGDIR/LICENSE" "$BINBUILD/"
+cp "$BINPKGDIR/PKGBUILD" "$BINPKGDIR/voculinux.desktop" \
+ "$BINPKGDIR/voculinux.svg" "$BINPKGDIR/LICENSE" "$BINBUILD/"
CARCH="$(uname -m)"
-printf 'aur gate stub\n' >"$BINBUILD/Vocalinux-${_tag}-${CARCH}.AppImage"
+printf 'aur gate stub\n' >"$BINBUILD/Voculinux-${_tag}-${CARCH}.AppImage"
(
cd "$BINBUILD"
diff --git a/packaging/aur/vocalinux-bin/LICENSE b/packaging/aur/voculinux-bin/LICENSE
similarity index 100%
rename from packaging/aur/vocalinux-bin/LICENSE
rename to packaging/aur/voculinux-bin/LICENSE
diff --git a/packaging/aur/vocalinux-bin/PKGBUILD b/packaging/aur/voculinux-bin/PKGBUILD
similarity index 70%
rename from packaging/aur/vocalinux-bin/PKGBUILD
rename to packaging/aur/voculinux-bin/PKGBUILD
index 1316cdd..7f83139 100644
--- a/packaging/aur/vocalinux-bin/PKGBUILD
+++ b/packaging/aur/voculinux-bin/PKGBUILD
@@ -1,7 +1,7 @@
# Maintainer: Jatin K Malik
# Updated by .github/workflows/release.yml on v* tags. Setup: docs/AUR.md
-pkgname=vocalinux-bin
+pkgname=voculinux-bin
# AUR pkgver cannot contain hyphens (v0.14.0-beta -> 0.14.0beta).
pkgver=0.17.0
_tag=0.17.0
@@ -28,17 +28,17 @@ optdepends=(
'wl-clipboard: Wayland clipboard (wl-copy/wl-paste) injection fallbacks'
'ydotool: uinput keystroke injection fallback'
)
-provides=('vocalinux')
-conflicts=('vocalinux' 'vocalinux-git')
+provides=('voculinux')
+conflicts=('voculinux' 'voculinux-git')
# Stripping would rewrite the runtime header of a self-mounting ELF.
options=('!strip')
source=(
- 'vocalinux.desktop'
- 'vocalinux.svg'
+ 'voculinux.desktop'
+ 'voculinux.svg'
'LICENSE'
)
-source_x86_64=("Vocalinux-${_tag}-x86_64.AppImage::https://github.com/VocaHQ/vocalinux/releases/download/v${_tag}/Vocalinux-${_tag}-x86_64.AppImage")
-source_aarch64=("Vocalinux-${_tag}-aarch64.AppImage::https://github.com/VocaHQ/vocalinux/releases/download/v${_tag}/Vocalinux-${_tag}-aarch64.AppImage")
+source_x86_64=("Voculinux-${_tag}-x86_64.AppImage::https://github.com/VocaHQ/vocalinux/releases/download/v${_tag}/Voculinux-${_tag}-x86_64.AppImage")
+source_aarch64=("Voculinux-${_tag}-aarch64.AppImage::https://github.com/VocaHQ/vocalinux/releases/download/v${_tag}/Voculinux-${_tag}-aarch64.AppImage")
sha256sums=('837006a9c689146308eae8c57cba1cdcc06673a108e72f39231837c6f63ae487'
'128b8939ffc00314a55d0600ab29c6a92dfb116138e088c59579a086616ec8ec'
'8486a10c4393cee1c25392769ddd3b2d6c242d6ec7928e1414efff7dfb2f07ef')
@@ -46,16 +46,16 @@ sha256sums_x86_64=('1a87408bf5bd8f9176c395a4da9ce28c68a1a7585bd67f125ff6037c4328
sha256sums_aarch64=('b256fe8577e2733a4da3ae4f9c2b9717f10017ad8328b832070ce04edc996a7d')
package() {
- install -Dm755 "Vocalinux-${_tag}-${CARCH}.AppImage" \
- "${pkgdir}/opt/${pkgname}/Vocalinux-${_tag}-${CARCH}.AppImage"
+ install -Dm755 "Voculinux-${_tag}-${CARCH}.AppImage" \
+ "${pkgdir}/opt/${pkgname}/Voculinux-${_tag}-${CARCH}.AppImage"
- install -Dm644 vocalinux.desktop \
- "${pkgdir}/usr/share/applications/vocalinux.desktop"
- install -Dm644 vocalinux.svg \
- "${pkgdir}/usr/share/icons/hicolor/scalable/apps/vocalinux.svg"
+ install -Dm644 voculinux.desktop \
+ "${pkgdir}/usr/share/applications/voculinux.desktop"
+ install -Dm644 voculinux.svg \
+ "${pkgdir}/usr/share/icons/hicolor/scalable/apps/voculinux.svg"
install -Dm644 LICENSE "${pkgdir}/usr/share/licenses/${pkgname}/LICENSE"
install -dm755 "${pkgdir}/usr/bin"
- ln -s "/opt/${pkgname}/Vocalinux-${_tag}-${CARCH}.AppImage" \
- "${pkgdir}/usr/bin/vocalinux"
+ ln -s "/opt/${pkgname}/Voculinux-${_tag}-${CARCH}.AppImage" \
+ "${pkgdir}/usr/bin/voculinux"
}
diff --git a/packaging/aur/vocalinux-bin/vocalinux.desktop b/packaging/aur/voculinux-bin/voculinux.desktop
similarity index 87%
rename from packaging/aur/vocalinux-bin/vocalinux.desktop
rename to packaging/aur/voculinux-bin/voculinux.desktop
index 2fddf9b..42be6a5 100644
--- a/packaging/aur/vocalinux-bin/vocalinux.desktop
+++ b/packaging/aur/voculinux-bin/voculinux.desktop
@@ -1,11 +1,11 @@
[Desktop Entry]
Version=1.0
Type=Application
-Name=Vocalinux
+Name=Voculinux
Comment=Seamless voice dictation system for Linux
GenericName=Voice Typing
-Exec=vocalinux
-Icon=vocalinux
+Exec=voculinux
+Icon=voculinux
Terminal=false
Categories=Utility;Accessibility;AudioVideo;
Keywords=voice;typing;dictation;speech;recognition;transcription;accessibility;
diff --git a/src/vocalinux/resources/icons/scalable/vocalinux.svg b/packaging/aur/voculinux-bin/voculinux.svg
similarity index 93%
rename from src/vocalinux/resources/icons/scalable/vocalinux.svg
rename to packaging/aur/voculinux-bin/voculinux.svg
index 5b522ea..7f8ffb0 100644
--- a/src/vocalinux/resources/icons/scalable/vocalinux.svg
+++ b/packaging/aur/voculinux-bin/voculinux.svg
@@ -1,4 +1,4 @@
-
-
Vocalinux 0.14.0-beta as Flatpak: whisper.cpp with Vulkan, XDG config/models/logs, XWayland text injection, and system tray integration.
+
Voculinux 0.14.0-beta as Flatpak: whisper.cpp with Vulkan, XDG config/models/logs, XWayland text injection, and system tray integration.
Self-hosted, signed OSTree repository for
- Vocalinux — published on every stable
+ Voculinux — published on every stable
tagged release, so installs auto-update via flatpak update.
The GNOME runtime still comes from Flathub — the
.flatpakref declares RuntimeRepo so flatpak
- finds it there. Vocalinux itself is not on Flathub.
+ finds it there. Voculinux itself is not on Flathub.
Source code ·
diff --git a/packaging/native/build.sh b/packaging/native/build.sh
index 6efbc81..8a65290 100755
--- a/packaging/native/build.sh
+++ b/packaging/native/build.sh
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
-# Build vocalinux__.deb and vocalinux-..rpm.
+# Build voculinux__.deb and voculinux-..rpm.
#
-# Usage: build.sh [output-dir]
+# Usage: build.sh [output-dir]
# version release version, e.g. 0.18.0 or 0.19.0-beta
#
# CI and releases run this inside docker-build.sh's pinned Debian 12 image;
@@ -63,18 +63,18 @@ NFPM="$TOOLS/nfpm"
PAYLOAD="$TOOLS/payload"
DOC="$TOOLS/pkg-doc"
install -d \
- "$PAYLOAD/usr/lib/vocalinux/app" \
- "$PAYLOAD/usr/lib/vocalinux/vendor" \
+ "$PAYLOAD/usr/lib/voculinux/app" \
+ "$PAYLOAD/usr/lib/voculinux/vendor" \
"$PAYLOAD/usr/bin" \
"$PAYLOAD/usr/share/applications" \
"$PAYLOAD/usr/share/icons/hicolor/scalable/apps" \
"$DOC"
# --- application payload ------------------------------------------------
-# The wheel is a zip; -m zipfile lays out vocalinux/ and its dist-info
+# The wheel is a zip; -m zipfile lays out voculinux/ and its dist-info
# exactly where pip --target would, without pip's EXTERNALLY-MANAGED refusal
# on Debian 12.
-python3 -m zipfile -e "$WHEEL" "$PAYLOAD/usr/lib/vocalinux/app/"
+python3 -m zipfile -e "$WHEEL" "$PAYLOAD/usr/lib/voculinux/app/"
# --- vendored wheels -----------------------------------------------------
# Download each supported CPython's pywhispercpp wheel — it has no abi3 tag,
@@ -99,7 +99,7 @@ for PYV in $VENDOR_PYS; do
--python-version "$PYV" -r "$PINS_VENDOR" -d "$TOOLS/wheels/$PYV" >/dev/null
done
for VENDOR_WHEEL in "$TOOLS"/wheels/*/*.whl; do
- python3 -m zipfile -e "$VENDOR_WHEEL" "$PAYLOAD/usr/lib/vocalinux/vendor/"
+ python3 -m zipfile -e "$VENDOR_WHEEL" "$PAYLOAD/usr/lib/voculinux/vendor/"
done
# --- portable libggml-cpu -------------------------------------------------
@@ -144,7 +144,7 @@ swapped=0
while IFS= read -r vendored; do
cp "$BASELINE_CPU" "$vendored"
swapped=$((swapped + 1))
-done < <(find "$PAYLOAD/usr/lib/vocalinux/vendor" -name 'libggml-cpu*.so*')
+done < <(find "$PAYLOAD/usr/lib/voculinux/vendor" -name 'libggml-cpu*.so*')
[ "$swapped" -gt 0 ] || fail "found no vendored libggml-cpu to replace"
# The baseline library's own NEEDED entries use the unmangled sonames
# (libggml-base.so.0, libgomp.so.1), so alias the vendored copies — the same
@@ -157,30 +157,30 @@ while IFS= read -r libs_dir; do
vendored_gomp="$(find "$libs_dir" -name 'libgomp*.so*' | head -1)"
[ -n "$vendored_gomp" ] || fail "no vendored libgomp in $libs_dir"
cp "$vendored_gomp" "$libs_dir/libgomp.so.1"
-done < <(find "$PAYLOAD/usr/lib/vocalinux/vendor" -type d -name 'pywhispercpp.libs')
+done < <(find "$PAYLOAD/usr/lib/voculinux/vendor" -type d -name 'pywhispercpp.libs')
# --- launchers -----------------------------------------------------------
# Same environment install.sh's wrapper establishes: the vendored
# pywhispercpp.libs on LD_LIBRARY_PATH, user site-packages off so they cannot
# shadow the distro modules, and sg input so evdev hotkeys work on Wayland
# when the user is already in the input group but the session has not picked
-# up the membership yet. vocalinux-gui exists because the wheel declares a
+# up the membership yet. voculinux-gui exists because the wheel declares a
# gui-script of that name; on Linux it runs the same entry.
write_launcher() {
local path="$1"
cat > "$path" <<'LAUNCHER_EOF'
#!/bin/sh
-# Launcher for the distro-packaged Vocalinux. The vendored wheels (the
+# Launcher for the distro-packaged Voculinux. The vendored wheels (the
# pywhispercpp/pynput copies Debian and Fedora do not ship) live under
-# /usr/lib/vocalinux/vendor with the app itself under .../app; the loader in
+# /usr/lib/voculinux/vendor with the app itself under .../app; the loader in
# utils/pywhispercpp_loader.py finds the bundled .so files from sys.path.
PYTHONNOUSERSITE=1
-VOCALINUX_VENDOR="/usr/lib/vocalinux/vendor"
-if [ -d "$VOCALINUX_VENDOR/pywhispercpp.libs" ]; then
- LD_LIBRARY_PATH="$VOCALINUX_VENDOR/pywhispercpp.libs${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
+VOCULINUX_VENDOR="/usr/lib/voculinux/vendor"
+if [ -d "$VOCULINUX_VENDOR/pywhispercpp.libs" ]; then
+ LD_LIBRARY_PATH="$VOCULINUX_VENDOR/pywhispercpp.libs${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
export LD_LIBRARY_PATH
fi
-export PYTHONNOUSERSITE PYTHONPATH="/usr/lib/vocalinux/app:$VOCALINUX_VENDOR${PYTHONPATH:+:$PYTHONPATH}"
+export PYTHONNOUSERSITE PYTHONPATH="/usr/lib/voculinux/app:$VOCULINUX_VENDOR${PYTHONPATH:+:$PYTHONPATH}"
if grep -q "^input:.*\b$(whoami)\b" /etc/group 2>/dev/null \
&& ! groups | grep -q "\binput\b" && command -v sg >/dev/null 2>&1; then
# sg(1) takes a single command string, so each argument is re-quoted for
@@ -196,14 +196,14 @@ exec /usr/bin/python3 -m vocalinux.main "$@"
LAUNCHER_EOF
chmod 755 "$path"
}
-write_launcher "$PAYLOAD/usr/bin/vocalinux"
-write_launcher "$PAYLOAD/usr/bin/vocalinux-gui"
+write_launcher "$PAYLOAD/usr/bin/voculinux"
+write_launcher "$PAYLOAD/usr/bin/voculinux-gui"
# --- desktop entry, icon, license ----------------------------------------
-install -Dm644 "$REPO_ROOT/vocalinux.desktop" \
- "$PAYLOAD/usr/share/applications/vocalinux.desktop"
-install -Dm644 "$REPO_ROOT/resources/icons/scalable/vocalinux.svg" \
- "$PAYLOAD/usr/share/icons/hicolor/scalable/apps/vocalinux.svg"
+install -Dm644 "$REPO_ROOT/voculinux.desktop" \
+ "$PAYLOAD/usr/share/applications/voculinux.desktop"
+install -Dm644 "$REPO_ROOT/resources/icons/scalable/voculinux.svg" \
+ "$PAYLOAD/usr/share/icons/hicolor/scalable/apps/voculinux.svg"
install -Dm644 "$REPO_ROOT/LICENSE" "$DOC/LICENSE"
# --- package -------------------------------------------------------------
diff --git a/packaging/native/nfpm.yaml b/packaging/native/nfpm.yaml
index 111a98b..260d356 100644
--- a/packaging/native/nfpm.yaml
+++ b/packaging/native/nfpm.yaml
@@ -8,8 +8,8 @@
# the gi typelibs come from the distribution, and so do every Python
# dependency the distros package. Only pywhispercpp and pynput are vendored —
# pywhispercpp is not packaged by Debian or Fedora at all, and pynput is
-# missing from Fedora — both under /usr/lib/vocalinux/vendor/, on sys.path via
-# the launcher in /usr/bin/vocalinux. Vendoring the pywhispercpp wheel per
+# missing from Fedora — both under /usr/lib/voculinux/vendor/, on sys.path via
+# the launcher in /usr/bin/voculinux. Vendoring the pywhispercpp wheel per
# supported CPython is what keeps the package free of a bundled interpreter.
#
# Version: VOCA_VERSION is the tag without its leading v and without a
@@ -17,7 +17,7 @@
# nfpm maps a prerelease to 0.19.0~beta-1, which orders before the stable
# 0.19.0-1 in both formats.
-name: vocalinux
+name: voculinux
arch: ${VOCA_ARCH}
platform: linux
version: ${VOCA_VERSION}
@@ -31,12 +31,12 @@ description: |
transcribe speech locally (whisper.cpp by default), and type into the
focused window. GTK, PyGObject and the interpreter come from the
distribution; pywhispercpp and pynput are vendored under
- /usr/lib/vocalinux/vendor because neither distro packages them.
+ /usr/lib/voculinux/vendor because neither distro packages them.
homepage: https://github.com/VocaHQ/vocalinux
license: AGPL-3.0-only
contents:
- # The staged payload tree: /usr/lib/vocalinux/{app,vendor}, the launchers in
+ # The staged payload tree: /usr/lib/voculinux/{app,vendor}, the launchers in
# /usr/bin, the desktop file and the hicolor icon. build.sh writes it.
- src: ./payload/
dst: /
@@ -45,10 +45,10 @@ contents:
# License placement differs between the formats: Debian policy wants the
# copyright file under /usr/share/doc, Fedora marks /usr/share/licenses.
- src: ./pkg-doc/LICENSE
- dst: /usr/share/doc/vocalinux/copyright
+ dst: /usr/share/doc/voculinux/copyright
packager: deb
- src: ./pkg-doc/LICENSE
- dst: /usr/share/licenses/vocalinux/LICENSE
+ dst: /usr/share/licenses/voculinux/LICENSE
packager: rpm
overrides:
diff --git a/packaging/native/smoke-test.sh b/packaging/native/smoke-test.sh
index 471aa81..a71cb4b 100755
--- a/packaging/native/smoke-test.sh
+++ b/packaging/native/smoke-test.sh
@@ -52,17 +52,17 @@ echo "== installed: $PKG"
# before check_dependencies() touches GTK, so it proves the wrapper, the
# PYTHONPATH layout and the entry module's import chain — the dependency
# typelibs are exercised by the import smoke below.
-vocalinux --version
-vocalinux-gui --version
+voculinux --version
+voculinux-gui --version
# Import smoke in the shape of the AUR gate: the app modules, the vendored
# pywhispercpp wheel, and the distro gi/GTK typelibs, all through the same
# interpreter and environment the launcher sets up. pynput is only checked
# for presence: its __init__ selects a display backend and raises ImportError
# with no DISPLAY, which is why the app guards it with PYNPUT_AVAILABLE.
-PYTHONPATH="/usr/lib/vocalinux/app:/usr/lib/vocalinux/vendor" \
+PYTHONPATH="/usr/lib/voculinux/app:/usr/lib/voculinux/vendor" \
PYTHONNOUSERSITE=1 \
-LD_LIBRARY_PATH="/usr/lib/vocalinux/vendor/pywhispercpp.libs" \
+LD_LIBRARY_PATH="/usr/lib/voculinux/vendor/pywhispercpp.libs" \
/usr/bin/python3 - <<'PY'
import importlib
import importlib.util
@@ -83,11 +83,11 @@ for module in MODULES:
importlib.import_module(module)
spec = importlib.util.find_spec("pynput")
-assert spec and spec.origin and spec.origin.startswith("/usr/lib/vocalinux/vendor/"), \
+assert spec and spec.origin and spec.origin.startswith("/usr/lib/voculinux/vendor/"), \
f"vendored pynput not found on sys.path: {spec}"
tag = f"cpython-{sys.version_info.major}{sys.version_info.minor}-"
-exts = [p.name for p in Path("/usr/lib/vocalinux/vendor").glob("_pywhispercpp.*.so")]
+exts = [p.name for p in Path("/usr/lib/voculinux/vendor").glob("_pywhispercpp.*.so")]
assert any(tag in name for name in exts), \
f"no _pywhispercpp extension for {tag[:-1]} among {exts}"
diff --git a/packaging/nix/README.md b/packaging/nix/README.md
index 64ea09e..11e1463 100644
--- a/packaging/nix/README.md
+++ b/packaging/nix/README.md
@@ -1,6 +1,6 @@
-# Vocalinux for Nix
+# Voculinux for Nix
-A flake that builds Vocalinux against nixpkgs: GTK 3, PyGObject and the
+A flake that builds Voculinux against nixpkgs: GTK 3, PyGObject and the
AppIndicator typelib come from nixpkgs, and `pywhispercpp` — which nixpkgs
does not package — is built from its PyPI sdist (it vendors whisper.cpp and
pybind11). Every host tool the app probes for (`xdotool`, `wtype`, `ydotool`,
@@ -24,14 +24,14 @@ nix profile install github:VocaHQ/vocalinux
```nix
{
- inputs.vocalinux.url = "github:VocaHQ/vocalinux";
+ inputs.voculinux.url = "github:VocaHQ/vocalinux";
- outputs = { nixpkgs, vocalinux, ... }: {
+ outputs = { nixpkgs, voculinux, ... }: {
nixosConfigurations.host = nixpkgs.lib.nixosSystem {
modules = [
- vocalinux.nixosModules.vocalinux
+ voculinux.nixosModules.voculinux
{
- programs.vocalinux.enable = true;
+ programs.voculinux.enable = true;
users.users.you.extraGroups = [ "input" "uinput" ];
}
];
@@ -53,14 +53,14 @@ and can skip the group lines entirely.
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
inputs.home-manager.url = "github:nix-community/home-manager";
inputs.home-manager.inputs.nixpkgs.follows = "nixpkgs";
- inputs.vocalinux.url = "github:VocaHQ/vocalinux";
+ inputs.voculinux.url = "github:VocaHQ/vocalinux";
- outputs = { nixpkgs, home-manager, vocalinux, ... }: {
+ outputs = { nixpkgs, home-manager, voculinux, ... }: {
homeConfigurations.you = home-manager.lib.homeManagerConfiguration {
pkgs = nixpkgs.legacyPackages.x86_64-linux;
modules = [
- vocalinux.homeManagerModules.vocalinux
- { programs.vocalinux.enable = true; }
+ voculinux.homeManagerModules.voculinux
+ { programs.voculinux.enable = true; }
];
};
};
diff --git a/packaging/nix/home-manager.nix b/packaging/nix/home-manager.nix
index e4f3e75..19e6541 100644
--- a/packaging/nix/home-manager.nix
+++ b/packaging/nix/home-manager.nix
@@ -1,4 +1,4 @@
-# Home Manager module for Vocalinux.
+# Home Manager module for Voculinux.
#
# Installs the package into the user profile; device permissions are a
# system concern, so pair it with the NixOS module (or the manual group
@@ -6,16 +6,16 @@
{ config, lib, pkgs, ... }:
let
- cfg = config.programs.vocalinux;
+ cfg = config.programs.voculinux;
in
{
- options.programs.vocalinux = {
- enable = lib.mkEnableOption "Vocalinux voice dictation";
+ options.programs.voculinux = {
+ enable = lib.mkEnableOption "Voculinux voice dictation";
package = lib.mkOption {
type = lib.types.package;
- defaultText = "the package built by the vocalinux flake";
- description = "The vocalinux package to install.";
+ defaultText = "the package built by the voculinux flake";
+ description = "The voculinux package to install.";
};
};
diff --git a/packaging/nix/module.nix b/packaging/nix/module.nix
index 0473e2e..9ebfc00 100644
--- a/packaging/nix/module.nix
+++ b/packaging/nix/module.nix
@@ -1,9 +1,9 @@
-# NixOS module for Vocalinux.
+# NixOS module for Voculinux.
#
# The flake wraps this file and injects the flake-built package as the
-# default (programs.vocalinux.package), so importing the module through
-# nixosModules.vocalinux needs no extra wiring. Imported on its own, set
-# programs.vocalinux.package to a vocalinux derivation.
+# default (programs.voculinux.package), so importing the module through
+# nixosModules.voculinux needs no extra wiring. Imported on its own, set
+# programs.voculinux.package to a voculinux derivation.
#
# What it cannot do for you: membership in the "input" group is per-user,
# so the module documents it and each user opts in:
@@ -16,16 +16,16 @@
{ config, lib, pkgs, ... }:
let
- cfg = config.programs.vocalinux;
+ cfg = config.programs.voculinux;
in
{
- options.programs.vocalinux = {
- enable = lib.mkEnableOption "Vocalinux voice dictation";
+ options.programs.voculinux = {
+ enable = lib.mkEnableOption "Voculinux voice dictation";
package = lib.mkOption {
type = lib.types.package;
- defaultText = "the package built by the vocalinux flake";
- description = "The vocalinux package to install.";
+ defaultText = "the package built by the voculinux flake";
+ description = "The voculinux package to install.";
};
};
diff --git a/packaging/nix/package.nix b/packaging/nix/package.nix
index da069f1..7601249 100644
--- a/packaging/nix/package.nix
+++ b/packaging/nix/package.nix
@@ -1,6 +1,6 @@
-# Vocalinux for Nix.
+# Voculinux for Nix.
#
-# Consumed by the repo flake (packages..vocalinux) and buildable with
+# Consumed by the repo flake (packages..voculinux) and buildable with
# plain callPackage:
#
# pkgs.python3Packages.callPackage ./packaging/nix/package.nix {
@@ -75,7 +75,7 @@ let
];
in
buildPythonApplication {
- pname = "vocalinux";
+ pname = "voculinux";
# Track src/vocalinux/version.py so release bumps need no edit here.
# builtins.match is POSIX ERE (no \s class), so flatten newlines first.
@@ -136,15 +136,15 @@ buildPythonApplication {
'';
postInstall = ''
- install -Dm644 vocalinux.desktop \
- $out/share/applications/vocalinux.desktop
- install -Dm644 resources/icons/scalable/vocalinux.svg \
- $out/share/icons/hicolor/scalable/apps/vocalinux.svg
+ install -Dm644 voculinux.desktop \
+ $out/share/applications/voculinux.desktop
+ install -Dm644 resources/icons/scalable/voculinux.svg \
+ $out/share/icons/hicolor/scalable/apps/voculinux.svg
'';
dontCheck = true; # test suite needs a session bus and X display
- pythonImportsCheck = [ "vocalinux" ];
+ pythonImportsCheck = [ "voculinux" ];
meta = {
description = "Free, offline voice dictation for Linux";
@@ -155,11 +155,11 @@ buildPythonApplication {
Wayland/evdev shortcuts and ydotool injection need device access: on
NixOS enable hardware.uinput and add your user to the "input" and
- "uinput" groups; the programs.vocalinux NixOS module does the first part.
+ "uinput" groups; the programs.voculinux NixOS module does the first part.
'';
homepage = "https://github.com/VocaHQ/vocalinux";
license = lib.licenses.agpl3Only;
- mainProgram = "vocalinux";
+ mainProgram = "voculinux";
platforms = lib.platforms.linux;
};
}
diff --git a/packaging/nix/pywhispercpp.nix b/packaging/nix/pywhispercpp.nix
index 3a5fa48..bbf5a4d 100644
--- a/packaging/nix/pywhispercpp.nix
+++ b/packaging/nix/pywhispercpp.nix
@@ -52,7 +52,7 @@ buildPythonPackage rec {
env = {
# The sdist ships no version.txt; setup.py falls back to this env var.
PYWHISPERCPP_VERSION = version;
- # Build Vulkan as a shared backend: Vocalinux's GPU detector looks for
+ # Build Vulkan as a shared backend: Voculinux's GPU detector looks for
# libggml-vulkan.so. CMake's build-tree RPATH can leak /build into the
# wheel; disable CMake RPATHs and let autoPatchelfHook set Nix runtime paths.
CMAKE_ARGS = "-DBUILD_SHARED_LIBS=ON -DGGML_NATIVE=OFF -DGGML_VULKAN=ON -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_SKIP_RPATH=ON";
diff --git a/pyproject.toml b/pyproject.toml
index 663110a..0b46612 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -5,7 +5,7 @@ requires = ["setuptools>=77"]
build-backend = "setuptools.build_meta"
[project]
-name = "vocalinux"
+name = "voculinux"
dynamic = ["version"]
description = "A seamless voice dictation system for Linux"
readme = "README.md"
@@ -117,10 +117,10 @@ lint = [
]
[project.scripts]
-vocalinux = "vocalinux.main:main"
+voculinux = "vocalinux.main:main"
[project.gui-scripts]
-vocalinux-gui = "vocalinux.main:main"
+voculinux-gui = "vocalinux.main:main"
[project.urls]
Homepage = "https://github.com/VocaHQ/vocalinux"
diff --git a/requirements/dev.txt b/requirements/dev.txt
index 99ac617..5b10651 100644
--- a/requirements/dev.txt
+++ b/requirements/dev.txt
@@ -360,7 +360,7 @@ evdev==1.9.3 ; sys_platform == 'linux' or 'linux' in sys_platform \
--hash=sha256:2c140e01ac8437758fa23fe5c871397412461f42d421aa20241dc8fe8cfccbc9
# via
# pynput
- # vocalinux
+ # voculinux
filelock==4.2.1 \
--hash=sha256:7be2662e9e826b9bba28afc0f843a123280d799a2ea44bb5d35ccec67905ae44 \
--hash=sha256:c4c937ccac2a813cee448e662a56366cfb374c0f8702e75f295c412cc1c5d5a3
@@ -547,7 +547,7 @@ mypy==2.3.1 \
--hash=sha256:ef0c6335cda9d807f8193d8ff6204a72bc909fa9882aacbca14f43cdb7188306 \
--hash=sha256:f5d716048611e85ca9eefb2e1baa5d73ede389b5820ded260ea27c757d667af8 \
--hash=sha256:ff715e45b2231a8e85de1d163d1b42791e4d7aab8f5145f85fee1b710b735aff
- # via vocalinux
+ # via voculinux
mypy-extensions==1.1.0 \
--hash=sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505 \
--hash=sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558
@@ -633,7 +633,7 @@ numpy==2.4.6 ; python_full_version < '3.12' \
--hash=sha256:f74a575920ab21fe304421a3fc28793d82e299cae9eccb37084e9fc7f3617c20
# via
# pywhispercpp
- # vocalinux
+ # voculinux
numpy==2.5.2 ; python_full_version >= '3.12' \
--hash=sha256:0090ccdd57ec2703e9b49d0bf554767370581c1dd0a6b2bb2b2d9def317d042a \
--hash=sha256:078f9b027b478c9379b9677babbf0f8b8f1ecfada27636d7b9a93990c638739f \
@@ -703,7 +703,7 @@ numpy==2.5.2 ; python_full_version >= '3.12' \
--hash=sha256:fd0d703772bba096843785bd38371e31bb4a0c1151497ad5739d182114a73f7f
# via
# pywhispercpp
- # vocalinux
+ # voculinux
packaging==26.3 \
--hash=sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79 \
--hash=sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c
@@ -733,7 +733,7 @@ pluggy==1.6.0 \
pre-commit==4.6.2 \
--hash=sha256:8f5d7bfb021ecdbcd9d49d89847082dd24172ccde534390081a679ad046e2441 \
--hash=sha256:e2dde9a75d3bce11bd3831c26d134df00a2803c1d818be6a0383c3dcda25dc4e
- # via vocalinux
+ # via voculinux
psutil==7.2.2 \
--hash=sha256:0746f5f8d406af344fd547f1c8daa5f5c33dbc293bb8d6a16d80b4bb88f59372 \
--hash=sha256:076a2d2f923fd4821644f5ba89f059523da90dc9014e85f8e45a5774ca5bc6f9 \
@@ -756,7 +756,7 @@ psutil==7.2.2 \
--hash=sha256:ed0cace939114f62738d808fdcecd4c869222507e266e574799e9c0faa17d486 \
--hash=sha256:eed63d3b4d62449571547b60578c5b2c4bcccc5387148db46e0c2313dad0ee00 \
--hash=sha256:fd04ef36b4a6d599bbdb225dd1d3f51e00105f6d48a28f006da7f9822f2606d8
- # via vocalinux
+ # via voculinux
pyaudio==0.2.14 \
--hash=sha256:12f2f1ba04e06ff95d80700a78967897a489c05e093e3bffa05a84ed9c0a7fa3 \
--hash=sha256:506b32a595f8693811682ab4b127602d404df7dfc453b499c91a80d0f7bad289 \
@@ -765,7 +765,7 @@ pyaudio==0.2.14 \
--hash=sha256:78dfff3879b4994d1f4fc6485646a57755c6ee3c19647a491f790a0895bd2f87 \
--hash=sha256:95328285b4dab57ea8c52a4a996cb52be6d629353315be5bfda403d15932a497 \
--hash=sha256:bbeb01d36a2f472ae5ee5e1451cacc42112986abe622f735bb870a5db77cf903
- # via vocalinux
+ # via voculinux
pycairo==1.29.1 ; sys_platform == 'linux' \
--hash=sha256:4fbd26b4af24c9787d84cf5448e34eb8dca064b732479aaecd03109520eebd5f
# via pygobject
@@ -784,7 +784,7 @@ pygments==2.21.0 \
pynput==1.8.2 \
--hash=sha256:8cc38cf13a6ab2749cb375678be8a0fd705d7ce49c8001ff5db4007a723bbef1 \
--hash=sha256:f493c87157cd3861b4468f7f896857051762f44ed26f1b641e7cc5840a457087
- # via vocalinux
+ # via voculinux
pyobjc-core==12.2.2 ; sys_platform == 'darwin' \
--hash=sha256:122e6ad302a2abf5d4d4adb0156db751600ddf2768441696cba17b31323085e7 \
--hash=sha256:2062e8ad30a310441cd022544a897553408bebeaa7820d5edba3c96fd7fd693b \
@@ -853,7 +853,7 @@ pyobjc-framework-quartz==12.2.2 ; sys_platform == 'darwin' \
pysocks==1.7.1 \
--hash=sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5 \
--hash=sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0
- # via vocalinux
+ # via voculinux
pytest==9.1.1 \
--hash=sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313 \
--hash=sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c
@@ -861,19 +861,19 @@ pytest==9.1.1 \
# pytest-cov
# pytest-mock
# pytest-timeout
- # vocalinux
+ # voculinux
pytest-cov==7.1.0 \
--hash=sha256:30674f2b5f6351aa09702a9c8c364f6a01c27aae0c1366ae8016160d1efc56b2 \
--hash=sha256:a0461110b7865f9a271aa1b51e516c9a95de9d696734a2f71e3e78f46e1d4678
- # via vocalinux
+ # via voculinux
pytest-mock==3.15.1 \
--hash=sha256:0a25e2eb88fe5168d535041d09a4529a188176ae608a6d249ee65abc0949630d \
--hash=sha256:1849a238f6f396da19762269de72cb1814ab44416fa73a8686deac10b0d87a0f
- # via vocalinux
+ # via voculinux
pytest-timeout==2.4.0 \
--hash=sha256:7e68e90b01f9eff71332b25001f85c75495fc4e3a836701876183c4bcfd0540a \
--hash=sha256:c42667e5cdadb151aeb5b26d114aff6bdf5a907f176a007a30b940d3d865b5c2
- # via vocalinux
+ # via voculinux
python-discovery==1.6.4 \
--hash=sha256:530179cc51a1816d512b15635b3dc931295ae12efb183783ad31190a5d425d2b \
--hash=sha256:bc70d31f0ec5de11eda13d4d64c16e24b3506a65984684f2b6c98cb83b2ea9df
@@ -948,7 +948,7 @@ pywhispercpp==1.5.0 \
--hash=sha256:f5d13b4a7e34b9f4eebf70bff150ec36f4145c580bd5d812b9a3139611e7433c \
--hash=sha256:f9b1cd9dd4c3eb7fb2b777529eb62618e58a6bb05be20f82b7b1afe3d0b12274 \
--hash=sha256:fbdbb1bb236f4481ff6ea475aed9ed091393ddb02271df309645d71de207778d
- # via vocalinux
+ # via voculinux
pyyaml==6.0.3 \
--hash=sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c \
--hash=sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3 \
@@ -1000,13 +1000,13 @@ pyyaml==6.0.3 \
--hash=sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0
# via
# pre-commit
- # vocalinux
+ # voculinux
requests==2.34.2 \
--hash=sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0 \
--hash=sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed
# via
# pywhispercpp
- # vocalinux
+ # voculinux
six==1.17.0 \
--hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \
--hash=sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81
diff --git a/requirements/faster-whisper.txt b/requirements/faster-whisper.txt
index c505b3b..9daaff8 100644
--- a/requirements/faster-whisper.txt
+++ b/requirements/faster-whisper.txt
@@ -215,10 +215,10 @@ evdev==1.9.3 ; sys_platform == 'linux' or 'linux' in sys_platform \
--hash=sha256:2c140e01ac8437758fa23fe5c871397412461f42d421aa20241dc8fe8cfccbc9
# via
# pynput
- # vocalinux
+ # voculinux
faster-whisper==1.2.1 \
--hash=sha256:79a66ad50688c0b794dd501dc340a736992a6342f7f95e5811be60b5224a26a7
- # via vocalinux
+ # via voculinux
filelock==4.2.1 \
--hash=sha256:7be2662e9e826b9bba28afc0f843a123280d799a2ea44bb5d35ccec67905ae44 \
--hash=sha256:c4c937ccac2a813cee448e662a56366cfb374c0f8702e75f295c412cc1c5d5a3
@@ -351,7 +351,7 @@ numpy==2.4.6 ; python_full_version < '3.12' \
# ctranslate2
# onnxruntime
# pywhispercpp
- # vocalinux
+ # voculinux
numpy==2.5.2 ; python_full_version >= '3.12' \
--hash=sha256:0090ccdd57ec2703e9b49d0bf554767370581c1dd0a6b2bb2b2d9def317d042a \
--hash=sha256:078f9b027b478c9379b9677babbf0f8b8f1ecfada27636d7b9a93990c638739f \
@@ -423,7 +423,7 @@ numpy==2.5.2 ; python_full_version >= '3.12' \
# ctranslate2
# onnxruntime
# pywhispercpp
- # vocalinux
+ # voculinux
onnxruntime==1.29.0 \
--hash=sha256:07c5907474dec4a2792fd7626b753dc66707808385a6d9eecf993db0066a9d0f \
--hash=sha256:0d4f427afac434b0070fe992b540ddf20a7aff2265f760f314d91331935b6b98 \
@@ -492,7 +492,7 @@ psutil==7.2.2 \
--hash=sha256:ed0cace939114f62738d808fdcecd4c869222507e266e574799e9c0faa17d486 \
--hash=sha256:eed63d3b4d62449571547b60578c5b2c4bcccc5387148db46e0c2313dad0ee00 \
--hash=sha256:fd04ef36b4a6d599bbdb225dd1d3f51e00105f6d48a28f006da7f9822f2606d8
- # via vocalinux
+ # via voculinux
pyaudio==0.2.14 \
--hash=sha256:12f2f1ba04e06ff95d80700a78967897a489c05e093e3bffa05a84ed9c0a7fa3 \
--hash=sha256:506b32a595f8693811682ab4b127602d404df7dfc453b499c91a80d0f7bad289 \
@@ -501,14 +501,14 @@ pyaudio==0.2.14 \
--hash=sha256:78dfff3879b4994d1f4fc6485646a57755c6ee3c19647a491f790a0895bd2f87 \
--hash=sha256:95328285b4dab57ea8c52a4a996cb52be6d629353315be5bfda403d15932a497 \
--hash=sha256:bbeb01d36a2f472ae5ee5e1451cacc42112986abe622f735bb870a5db77cf903
- # via vocalinux
+ # via voculinux
pycairo==1.29.1 ; sys_platform == 'linux' \
--hash=sha256:4fbd26b4af24c9787d84cf5448e34eb8dca064b732479aaecd03109520eebd5f
# via pygobject
pynput==1.8.2 \
--hash=sha256:8cc38cf13a6ab2749cb375678be8a0fd705d7ce49c8001ff5db4007a723bbef1 \
--hash=sha256:f493c87157cd3861b4468f7f896857051762f44ed26f1b641e7cc5840a457087
- # via vocalinux
+ # via voculinux
pyobjc-core==12.2.2 ; sys_platform == 'darwin' \
--hash=sha256:122e6ad302a2abf5d4d4adb0156db751600ddf2768441696cba17b31323085e7 \
--hash=sha256:2062e8ad30a310441cd022544a897553408bebeaa7820d5edba3c96fd7fd693b \
@@ -577,7 +577,7 @@ pyobjc-framework-quartz==12.2.2 ; sys_platform == 'darwin' \
pysocks==1.7.1 \
--hash=sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5 \
--hash=sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0
- # via vocalinux
+ # via voculinux
python-xlib==0.33 ; 'linux' in sys_platform \
--hash=sha256:55af7906a2c75ce6cb280a584776080602444f75815a7aff4d287bb2d7018b32 \
--hash=sha256:c3534038d42e0df2f1392a1b30a15a4ff5fdc2b86cfa94f072bf11b10a164398
@@ -619,7 +619,7 @@ pywhispercpp==1.5.0 \
--hash=sha256:f5d13b4a7e34b9f4eebf70bff150ec36f4145c580bd5d812b9a3139611e7433c \
--hash=sha256:f9b1cd9dd4c3eb7fb2b777529eb62618e58a6bb05be20f82b7b1afe3d0b12274 \
--hash=sha256:fbdbb1bb236f4481ff6ea475aed9ed091393ddb02271df309645d71de207778d
- # via vocalinux
+ # via voculinux
pyyaml==6.0.3 \
--hash=sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c \
--hash=sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3 \
@@ -677,7 +677,7 @@ requests==2.34.2 \
--hash=sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed
# via
# pywhispercpp
- # vocalinux
+ # voculinux
six==1.17.0 \
--hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \
--hash=sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81
diff --git a/requirements/parakeet.txt b/requirements/parakeet.txt
index 26cd13f..7cabbfe 100644
--- a/requirements/parakeet.txt
+++ b/requirements/parakeet.txt
@@ -154,7 +154,7 @@ evdev==1.9.3 ; sys_platform == 'linux' or 'linux' in sys_platform \
--hash=sha256:2c140e01ac8437758fa23fe5c871397412461f42d421aa20241dc8fe8cfccbc9
# via
# pynput
- # vocalinux
+ # voculinux
idna==3.19 \
--hash=sha256:5e0811a4383b21dc5838069f801c4fb62113b7447663d2530d2bd6e77b49bf15 \
--hash=sha256:815e7be7a7806d54abb586dc943addc79e8b2ee16915059658cbeff4b1b43bf4
@@ -234,7 +234,7 @@ numpy==2.4.6 ; python_full_version < '3.12' \
--hash=sha256:f74a575920ab21fe304421a3fc28793d82e299cae9eccb37084e9fc7f3617c20
# via
# pywhispercpp
- # vocalinux
+ # voculinux
numpy==2.5.2 ; python_full_version >= '3.12' \
--hash=sha256:0090ccdd57ec2703e9b49d0bf554767370581c1dd0a6b2bb2b2d9def317d042a \
--hash=sha256:078f9b027b478c9379b9677babbf0f8b8f1ecfada27636d7b9a93990c638739f \
@@ -304,7 +304,7 @@ numpy==2.5.2 ; python_full_version >= '3.12' \
--hash=sha256:fd0d703772bba096843785bd38371e31bb4a0c1151497ad5739d182114a73f7f
# via
# pywhispercpp
- # vocalinux
+ # voculinux
platformdirs==4.11.3 \
--hash=sha256:5ed065d443751de711da036041a7a214122efc4a4de393b3f4137ba5576540e7 \
--hash=sha256:66a73d38a849810252df809a3d8bcbda8e26f6c189920e7535ad608a48dbb5ab
@@ -331,7 +331,7 @@ psutil==7.2.2 \
--hash=sha256:ed0cace939114f62738d808fdcecd4c869222507e266e574799e9c0faa17d486 \
--hash=sha256:eed63d3b4d62449571547b60578c5b2c4bcccc5387148db46e0c2313dad0ee00 \
--hash=sha256:fd04ef36b4a6d599bbdb225dd1d3f51e00105f6d48a28f006da7f9822f2606d8
- # via vocalinux
+ # via voculinux
pyaudio==0.2.14 \
--hash=sha256:12f2f1ba04e06ff95d80700a78967897a489c05e093e3bffa05a84ed9c0a7fa3 \
--hash=sha256:506b32a595f8693811682ab4b127602d404df7dfc453b499c91a80d0f7bad289 \
@@ -340,14 +340,14 @@ pyaudio==0.2.14 \
--hash=sha256:78dfff3879b4994d1f4fc6485646a57755c6ee3c19647a491f790a0895bd2f87 \
--hash=sha256:95328285b4dab57ea8c52a4a996cb52be6d629353315be5bfda403d15932a497 \
--hash=sha256:bbeb01d36a2f472ae5ee5e1451cacc42112986abe622f735bb870a5db77cf903
- # via vocalinux
+ # via voculinux
pycairo==1.29.1 ; sys_platform == 'linux' \
--hash=sha256:4fbd26b4af24c9787d84cf5448e34eb8dca064b732479aaecd03109520eebd5f
# via pygobject
pynput==1.8.2 \
--hash=sha256:8cc38cf13a6ab2749cb375678be8a0fd705d7ce49c8001ff5db4007a723bbef1 \
--hash=sha256:f493c87157cd3861b4468f7f896857051762f44ed26f1b641e7cc5840a457087
- # via vocalinux
+ # via voculinux
pyobjc-core==12.2.2 ; sys_platform == 'darwin' \
--hash=sha256:122e6ad302a2abf5d4d4adb0156db751600ddf2768441696cba17b31323085e7 \
--hash=sha256:2062e8ad30a310441cd022544a897553408bebeaa7820d5edba3c96fd7fd693b \
@@ -416,7 +416,7 @@ pyobjc-framework-quartz==12.2.2 ; sys_platform == 'darwin' \
pysocks==1.7.1 \
--hash=sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5 \
--hash=sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0
- # via vocalinux
+ # via voculinux
python-xlib==0.33 ; 'linux' in sys_platform \
--hash=sha256:55af7906a2c75ce6cb280a584776080602444f75815a7aff4d287bb2d7018b32 \
--hash=sha256:c3534038d42e0df2f1392a1b30a15a4ff5fdc2b86cfa94f072bf11b10a164398
@@ -458,13 +458,13 @@ pywhispercpp==1.5.0 \
--hash=sha256:f5d13b4a7e34b9f4eebf70bff150ec36f4145c580bd5d812b9a3139611e7433c \
--hash=sha256:f9b1cd9dd4c3eb7fb2b777529eb62618e58a6bb05be20f82b7b1afe3d0b12274 \
--hash=sha256:fbdbb1bb236f4481ff6ea475aed9ed091393ddb02271df309645d71de207778d
- # via vocalinux
+ # via voculinux
requests==2.34.2 \
--hash=sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0 \
--hash=sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed
# via
# pywhispercpp
- # vocalinux
+ # voculinux
sherpa-onnx==1.13.7 \
--hash=sha256:01c4d001390f282bef653d229dce5d9da5009a804999449e33f890139f1f2da0 \
--hash=sha256:026917d88fde36d5d86661e4a61c968dd741f43a96773ad742da13bffd030471 \
@@ -507,7 +507,7 @@ sherpa-onnx==1.13.7 \
--hash=sha256:ed40aee149f9e2e47d0b5cf1be21b2d662e5816bebdabdcdbbdb98b8a9928cbe \
--hash=sha256:fce7cfab223d6bee0a58fa940b5057e2f3cf63613928b88e09ac99b477e40be0 \
--hash=sha256:fed61cc23dba8f212eeb2723d2e90108d6de95734c5ae427aeafdb10f09ec184
- # via vocalinux
+ # via voculinux
sherpa-onnx-core==1.13.7 ; platform_machine != 'armv7l' \
--hash=sha256:07de22f590299a68d9b5c985264f380579600a831ee95510ab12f4068800d08c \
--hash=sha256:861c1e18fbf9bd2c725992c5a1797efe1b934b7df7bb18986d1fdc60e91290c9 \
@@ -522,7 +522,7 @@ sherpa-onnx-core==1.13.7 ; platform_machine != 'armv7l' \
--hash=sha256:e1e6333ecde50c69b8a43feff6eedf1033ec2a3fe58009506572bd717fc78e42 \
--hash=sha256:e3066e94c24c898c5794e08507f955e14bc904299bac80f357d0bcb7d93e3825 \
--hash=sha256:f48029e0c79b4cc654076806cbf62094a51dcd26c6bd1ce17db3bad03aff02b1
- # via vocalinux
+ # via voculinux
six==1.17.0 \
--hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \
--hash=sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81
diff --git a/requirements/runtime.txt b/requirements/runtime.txt
index e6c7a45..00ed714 100644
--- a/requirements/runtime.txt
+++ b/requirements/runtime.txt
@@ -154,7 +154,7 @@ evdev==1.9.3 ; sys_platform == 'linux' or 'linux' in sys_platform \
--hash=sha256:2c140e01ac8437758fa23fe5c871397412461f42d421aa20241dc8fe8cfccbc9
# via
# pynput
- # vocalinux
+ # voculinux
idna==3.19 \
--hash=sha256:5e0811a4383b21dc5838069f801c4fb62113b7447663d2530d2bd6e77b49bf15 \
--hash=sha256:815e7be7a7806d54abb586dc943addc79e8b2ee16915059658cbeff4b1b43bf4
@@ -234,7 +234,7 @@ numpy==2.4.6 ; python_full_version < '3.12' \
--hash=sha256:f74a575920ab21fe304421a3fc28793d82e299cae9eccb37084e9fc7f3617c20
# via
# pywhispercpp
- # vocalinux
+ # voculinux
numpy==2.5.2 ; python_full_version >= '3.12' \
--hash=sha256:0090ccdd57ec2703e9b49d0bf554767370581c1dd0a6b2bb2b2d9def317d042a \
--hash=sha256:078f9b027b478c9379b9677babbf0f8b8f1ecfada27636d7b9a93990c638739f \
@@ -304,7 +304,7 @@ numpy==2.5.2 ; python_full_version >= '3.12' \
--hash=sha256:fd0d703772bba096843785bd38371e31bb4a0c1151497ad5739d182114a73f7f
# via
# pywhispercpp
- # vocalinux
+ # voculinux
platformdirs==4.11.3 \
--hash=sha256:5ed065d443751de711da036041a7a214122efc4a4de393b3f4137ba5576540e7 \
--hash=sha256:66a73d38a849810252df809a3d8bcbda8e26f6c189920e7535ad608a48dbb5ab
@@ -331,7 +331,7 @@ psutil==7.2.2 \
--hash=sha256:ed0cace939114f62738d808fdcecd4c869222507e266e574799e9c0faa17d486 \
--hash=sha256:eed63d3b4d62449571547b60578c5b2c4bcccc5387148db46e0c2313dad0ee00 \
--hash=sha256:fd04ef36b4a6d599bbdb225dd1d3f51e00105f6d48a28f006da7f9822f2606d8
- # via vocalinux
+ # via voculinux
pyaudio==0.2.14 \
--hash=sha256:12f2f1ba04e06ff95d80700a78967897a489c05e093e3bffa05a84ed9c0a7fa3 \
--hash=sha256:506b32a595f8693811682ab4b127602d404df7dfc453b499c91a80d0f7bad289 \
@@ -340,14 +340,14 @@ pyaudio==0.2.14 \
--hash=sha256:78dfff3879b4994d1f4fc6485646a57755c6ee3c19647a491f790a0895bd2f87 \
--hash=sha256:95328285b4dab57ea8c52a4a996cb52be6d629353315be5bfda403d15932a497 \
--hash=sha256:bbeb01d36a2f472ae5ee5e1451cacc42112986abe622f735bb870a5db77cf903
- # via vocalinux
+ # via voculinux
pycairo==1.29.1 ; sys_platform == 'linux' \
--hash=sha256:4fbd26b4af24c9787d84cf5448e34eb8dca064b732479aaecd03109520eebd5f
# via pygobject
pynput==1.8.2 \
--hash=sha256:8cc38cf13a6ab2749cb375678be8a0fd705d7ce49c8001ff5db4007a723bbef1 \
--hash=sha256:f493c87157cd3861b4468f7f896857051762f44ed26f1b641e7cc5840a457087
- # via vocalinux
+ # via voculinux
pyobjc-core==12.2.2 ; sys_platform == 'darwin' \
--hash=sha256:122e6ad302a2abf5d4d4adb0156db751600ddf2768441696cba17b31323085e7 \
--hash=sha256:2062e8ad30a310441cd022544a897553408bebeaa7820d5edba3c96fd7fd693b \
@@ -416,7 +416,7 @@ pyobjc-framework-quartz==12.2.2 ; sys_platform == 'darwin' \
pysocks==1.7.1 \
--hash=sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5 \
--hash=sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0
- # via vocalinux
+ # via voculinux
python-xlib==0.33 ; 'linux' in sys_platform \
--hash=sha256:55af7906a2c75ce6cb280a584776080602444f75815a7aff4d287bb2d7018b32 \
--hash=sha256:c3534038d42e0df2f1392a1b30a15a4ff5fdc2b86cfa94f072bf11b10a164398
@@ -458,13 +458,13 @@ pywhispercpp==1.5.0 \
--hash=sha256:f5d13b4a7e34b9f4eebf70bff150ec36f4145c580bd5d812b9a3139611e7433c \
--hash=sha256:f9b1cd9dd4c3eb7fb2b777529eb62618e58a6bb05be20f82b7b1afe3d0b12274 \
--hash=sha256:fbdbb1bb236f4481ff6ea475aed9ed091393ddb02271df309645d71de207778d
- # via vocalinux
+ # via voculinux
requests==2.34.2 \
--hash=sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0 \
--hash=sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed
# via
# pywhispercpp
- # vocalinux
+ # voculinux
six==1.17.0 \
--hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \
--hash=sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81
diff --git a/requirements/vad.txt b/requirements/vad.txt
index 3be2e38..d695b04 100644
--- a/requirements/vad.txt
+++ b/requirements/vad.txt
@@ -154,7 +154,7 @@ evdev==1.9.3 ; sys_platform == 'linux' or 'linux' in sys_platform \
--hash=sha256:2c140e01ac8437758fa23fe5c871397412461f42d421aa20241dc8fe8cfccbc9
# via
# pynput
- # vocalinux
+ # voculinux
flatbuffers==25.12.19 \
--hash=sha256:7634f50c427838bb021c2d66a3d1168e9d199b0607e6329399f04846d42e20b4
# via onnxruntime
@@ -238,7 +238,7 @@ numpy==2.4.6 ; python_full_version < '3.12' \
# via
# onnxruntime
# pywhispercpp
- # vocalinux
+ # voculinux
numpy==2.5.2 ; python_full_version >= '3.12' \
--hash=sha256:0090ccdd57ec2703e9b49d0bf554767370581c1dd0a6b2bb2b2d9def317d042a \
--hash=sha256:078f9b027b478c9379b9677babbf0f8b8f1ecfada27636d7b9a93990c638739f \
@@ -309,7 +309,7 @@ numpy==2.5.2 ; python_full_version >= '3.12' \
# via
# onnxruntime
# pywhispercpp
- # vocalinux
+ # voculinux
onnxruntime==1.29.0 \
--hash=sha256:07c5907474dec4a2792fd7626b753dc66707808385a6d9eecf993db0066a9d0f \
--hash=sha256:0d4f427afac434b0070fe992b540ddf20a7aff2265f760f314d91331935b6b98 \
@@ -335,7 +335,7 @@ onnxruntime==1.29.0 \
--hash=sha256:e2128f31f449e922c62dbe5d8b6b7b079f0bcaf2d56a102fa203cb6e5bb5ab19 \
--hash=sha256:e417ef8628dcce310d2d53023e750ea298ec14d4341ae6dc3a572bfd9bc7fa97 \
--hash=sha256:e74b278af1d949876f5d91d1268fd6c680e79f2bac194967394eaba9fdf69e7e
- # via vocalinux
+ # via voculinux
packaging==26.3 \
--hash=sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79 \
--hash=sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c
@@ -376,7 +376,7 @@ psutil==7.2.2 \
--hash=sha256:ed0cace939114f62738d808fdcecd4c869222507e266e574799e9c0faa17d486 \
--hash=sha256:eed63d3b4d62449571547b60578c5b2c4bcccc5387148db46e0c2313dad0ee00 \
--hash=sha256:fd04ef36b4a6d599bbdb225dd1d3f51e00105f6d48a28f006da7f9822f2606d8
- # via vocalinux
+ # via voculinux
pyaudio==0.2.14 \
--hash=sha256:12f2f1ba04e06ff95d80700a78967897a489c05e093e3bffa05a84ed9c0a7fa3 \
--hash=sha256:506b32a595f8693811682ab4b127602d404df7dfc453b499c91a80d0f7bad289 \
@@ -385,14 +385,14 @@ pyaudio==0.2.14 \
--hash=sha256:78dfff3879b4994d1f4fc6485646a57755c6ee3c19647a491f790a0895bd2f87 \
--hash=sha256:95328285b4dab57ea8c52a4a996cb52be6d629353315be5bfda403d15932a497 \
--hash=sha256:bbeb01d36a2f472ae5ee5e1451cacc42112986abe622f735bb870a5db77cf903
- # via vocalinux
+ # via voculinux
pycairo==1.29.1 ; sys_platform == 'linux' \
--hash=sha256:4fbd26b4af24c9787d84cf5448e34eb8dca064b732479aaecd03109520eebd5f
# via pygobject
pynput==1.8.2 \
--hash=sha256:8cc38cf13a6ab2749cb375678be8a0fd705d7ce49c8001ff5db4007a723bbef1 \
--hash=sha256:f493c87157cd3861b4468f7f896857051762f44ed26f1b641e7cc5840a457087
- # via vocalinux
+ # via voculinux
pyobjc-core==12.2.2 ; sys_platform == 'darwin' \
--hash=sha256:122e6ad302a2abf5d4d4adb0156db751600ddf2768441696cba17b31323085e7 \
--hash=sha256:2062e8ad30a310441cd022544a897553408bebeaa7820d5edba3c96fd7fd693b \
@@ -461,7 +461,7 @@ pyobjc-framework-quartz==12.2.2 ; sys_platform == 'darwin' \
pysocks==1.7.1 \
--hash=sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5 \
--hash=sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0
- # via vocalinux
+ # via voculinux
python-xlib==0.33 ; 'linux' in sys_platform \
--hash=sha256:55af7906a2c75ce6cb280a584776080602444f75815a7aff4d287bb2d7018b32 \
--hash=sha256:c3534038d42e0df2f1392a1b30a15a4ff5fdc2b86cfa94f072bf11b10a164398
@@ -503,13 +503,13 @@ pywhispercpp==1.5.0 \
--hash=sha256:f5d13b4a7e34b9f4eebf70bff150ec36f4145c580bd5d812b9a3139611e7433c \
--hash=sha256:f9b1cd9dd4c3eb7fb2b777529eb62618e58a6bb05be20f82b7b1afe3d0b12274 \
--hash=sha256:fbdbb1bb236f4481ff6ea475aed9ed091393ddb02271df309645d71de207778d
- # via vocalinux
+ # via voculinux
requests==2.34.2 \
--hash=sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0 \
--hash=sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed
# via
# pywhispercpp
- # vocalinux
+ # voculinux
six==1.17.0 \
--hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \
--hash=sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81
diff --git a/requirements/vosk.txt b/requirements/vosk.txt
index d1471a2..c5e2612 100644
--- a/requirements/vosk.txt
+++ b/requirements/vosk.txt
@@ -244,7 +244,7 @@ evdev==1.9.3 ; sys_platform == 'linux' or 'linux' in sys_platform \
--hash=sha256:2c140e01ac8437758fa23fe5c871397412461f42d421aa20241dc8fe8cfccbc9
# via
# pynput
- # vocalinux
+ # voculinux
idna==3.19 \
--hash=sha256:5e0811a4383b21dc5838069f801c4fb62113b7447663d2530d2bd6e77b49bf15 \
--hash=sha256:815e7be7a7806d54abb586dc943addc79e8b2ee16915059658cbeff4b1b43bf4
@@ -324,7 +324,7 @@ numpy==2.4.6 ; python_full_version < '3.12' \
--hash=sha256:f74a575920ab21fe304421a3fc28793d82e299cae9eccb37084e9fc7f3617c20
# via
# pywhispercpp
- # vocalinux
+ # voculinux
numpy==2.5.2 ; python_full_version >= '3.12' \
--hash=sha256:0090ccdd57ec2703e9b49d0bf554767370581c1dd0a6b2bb2b2d9def317d042a \
--hash=sha256:078f9b027b478c9379b9677babbf0f8b8f1ecfada27636d7b9a93990c638739f \
@@ -394,7 +394,7 @@ numpy==2.5.2 ; python_full_version >= '3.12' \
--hash=sha256:fd0d703772bba096843785bd38371e31bb4a0c1151497ad5739d182114a73f7f
# via
# pywhispercpp
- # vocalinux
+ # voculinux
platformdirs==4.11.3 \
--hash=sha256:5ed065d443751de711da036041a7a214122efc4a4de393b3f4137ba5576540e7 \
--hash=sha256:66a73d38a849810252df809a3d8bcbda8e26f6c189920e7535ad608a48dbb5ab
@@ -421,7 +421,7 @@ psutil==7.2.2 \
--hash=sha256:ed0cace939114f62738d808fdcecd4c869222507e266e574799e9c0faa17d486 \
--hash=sha256:eed63d3b4d62449571547b60578c5b2c4bcccc5387148db46e0c2313dad0ee00 \
--hash=sha256:fd04ef36b4a6d599bbdb225dd1d3f51e00105f6d48a28f006da7f9822f2606d8
- # via vocalinux
+ # via voculinux
pyaudio==0.2.14 \
--hash=sha256:12f2f1ba04e06ff95d80700a78967897a489c05e093e3bffa05a84ed9c0a7fa3 \
--hash=sha256:506b32a595f8693811682ab4b127602d404df7dfc453b499c91a80d0f7bad289 \
@@ -430,7 +430,7 @@ pyaudio==0.2.14 \
--hash=sha256:78dfff3879b4994d1f4fc6485646a57755c6ee3c19647a491f790a0895bd2f87 \
--hash=sha256:95328285b4dab57ea8c52a4a996cb52be6d629353315be5bfda403d15932a497 \
--hash=sha256:bbeb01d36a2f472ae5ee5e1451cacc42112986abe622f735bb870a5db77cf903
- # via vocalinux
+ # via voculinux
pycairo==1.29.1 ; sys_platform == 'linux' \
--hash=sha256:4fbd26b4af24c9787d84cf5448e34eb8dca064b732479aaecd03109520eebd5f
# via pygobject
@@ -441,7 +441,7 @@ pycparser==3.0 ; implementation_name != 'PyPy' \
pynput==1.8.2 \
--hash=sha256:8cc38cf13a6ab2749cb375678be8a0fd705d7ce49c8001ff5db4007a723bbef1 \
--hash=sha256:f493c87157cd3861b4468f7f896857051762f44ed26f1b641e7cc5840a457087
- # via vocalinux
+ # via voculinux
pyobjc-core==12.2.2 ; sys_platform == 'darwin' \
--hash=sha256:122e6ad302a2abf5d4d4adb0156db751600ddf2768441696cba17b31323085e7 \
--hash=sha256:2062e8ad30a310441cd022544a897553408bebeaa7820d5edba3c96fd7fd693b \
@@ -510,7 +510,7 @@ pyobjc-framework-quartz==12.2.2 ; sys_platform == 'darwin' \
pysocks==1.7.1 \
--hash=sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5 \
--hash=sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0
- # via vocalinux
+ # via voculinux
python-xlib==0.33 ; 'linux' in sys_platform \
--hash=sha256:55af7906a2c75ce6cb280a584776080602444f75815a7aff4d287bb2d7018b32 \
--hash=sha256:c3534038d42e0df2f1392a1b30a15a4ff5fdc2b86cfa94f072bf11b10a164398
@@ -552,13 +552,13 @@ pywhispercpp==1.5.0 \
--hash=sha256:f5d13b4a7e34b9f4eebf70bff150ec36f4145c580bd5d812b9a3139611e7433c \
--hash=sha256:f9b1cd9dd4c3eb7fb2b777529eb62618e58a6bb05be20f82b7b1afe3d0b12274 \
--hash=sha256:fbdbb1bb236f4481ff6ea475aed9ed091393ddb02271df309645d71de207778d
- # via vocalinux
+ # via voculinux
requests==2.34.2 \
--hash=sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0 \
--hash=sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed
# via
# pywhispercpp
- # vocalinux
+ # voculinux
# vosk
six==1.17.0 \
--hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \
@@ -584,7 +584,7 @@ vosk==0.3.45 \
--hash=sha256:4221f83287eefe5abbe54fc6f1da5774e9e3ffcbbdca1705a466b341093b072e \
--hash=sha256:54efb47dd890e544e9e20f0316413acec7f8680d04ec095c6140ab4e70262704 \
--hash=sha256:6994ddc68556c7e5730c3b6f6bad13320e3519b13ce3ed2aa25a86724e7c10ac
- # via vocalinux
+ # via voculinux
websockets==17.0.1 \
--hash=sha256:02ed63bf26dda9fa27df730a41f6664586c4ee05972c8fb667ce1725b3fd13d3 \
--hash=sha256:02f0b037a737d0cb0c33866c97bcd1a0b73170dfbf42d69d8fb86f51002fd5ae \
diff --git a/resources/icons/scalable/vocalinux-microphone-off.svg b/resources/icons/scalable/voculinux-microphone-off.svg
similarity index 93%
rename from resources/icons/scalable/vocalinux-microphone-off.svg
rename to resources/icons/scalable/voculinux-microphone-off.svg
index 826e120..7792b28 100644
--- a/resources/icons/scalable/vocalinux-microphone-off.svg
+++ b/resources/icons/scalable/voculinux-microphone-off.svg
@@ -1,4 +1,4 @@
-
+
diff --git a/src/vocalinux/resources/icons/scalable/vocalinux-microphone-process.svg b/resources/icons/scalable/voculinux-microphone-process.svg
similarity index 93%
rename from src/vocalinux/resources/icons/scalable/vocalinux-microphone-process.svg
rename to resources/icons/scalable/voculinux-microphone-process.svg
index 7b9d9c3..9f11044 100644
--- a/src/vocalinux/resources/icons/scalable/vocalinux-microphone-process.svg
+++ b/resources/icons/scalable/voculinux-microphone-process.svg
@@ -1,4 +1,4 @@
-
+
diff --git a/src/vocalinux/resources/icons/scalable/vocalinux-microphone.svg b/resources/icons/scalable/voculinux-microphone.svg
similarity index 93%
rename from src/vocalinux/resources/icons/scalable/vocalinux-microphone.svg
rename to resources/icons/scalable/voculinux-microphone.svg
index 4a9a4dd..48e136d 100644
--- a/src/vocalinux/resources/icons/scalable/vocalinux-microphone.svg
+++ b/resources/icons/scalable/voculinux-microphone.svg
@@ -1,4 +1,4 @@
-
+
diff --git a/resources/icons/scalable/vocalinux.svg b/resources/icons/scalable/voculinux.svg
similarity index 93%
rename from resources/icons/scalable/vocalinux.svg
rename to resources/icons/scalable/voculinux.svg
index 5b522ea..7f8ffb0 100644
--- a/resources/icons/scalable/vocalinux.svg
+++ b/resources/icons/scalable/voculinux.svg
@@ -1,4 +1,4 @@
-
+
diff --git a/resources/promo/vocalinux-cover.png b/resources/promo/voculinux-cover.png
similarity index 100%
rename from resources/promo/vocalinux-cover.png
rename to resources/promo/voculinux-cover.png
diff --git a/scripts/build_reproducible_wheel.py b/scripts/build_reproducible_wheel.py
index 762733b..ea5961f 100755
--- a/scripts/build_reproducible_wheel.py
+++ b/scripts/build_reproducible_wheel.py
@@ -232,7 +232,7 @@ def _build(python: str, output: Path, diagnostics: Path) -> None:
env,
diagnostics / "inputs.log",
)
- with tempfile.TemporaryDirectory(prefix="vocalinux-wheel-") as temporary:
+ with tempfile.TemporaryDirectory(prefix="voculinux-wheel-") as temporary:
scratch = Path(temporary)
source = scratch / "snapshot"
source.mkdir()
diff --git a/scripts/check-system-deps.sh b/scripts/check-system-deps.sh
index ab11222..703e1aa 100755
--- a/scripts/check-system-deps.sh
+++ b/scripts/check-system-deps.sh
@@ -6,7 +6,7 @@ check_deps() {
MISSING=0
WARNINGS=0
- echo "Checking Vocalinux system dependencies..."
+ echo "Checking Voculinux system dependencies..."
echo ""
# Check for Python 3.11+ (requires-python in pyproject.toml)
diff --git a/scripts/generate-model-checksums.py b/scripts/generate-model-checksums.py
index bc581fe..3031121 100755
--- a/scripts/generate-model-checksums.py
+++ b/scripts/generate-model-checksums.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
"""Regenerate src/vocalinux/utils/model_checksums.txt from upstream metadata.
-Vocalinux downloads 40MB-2GB speech models at install time and on first run,
+Voculinux downloads 40MB-2GB speech models at install time and on first run,
then hands them to native code (whisper.cpp loads its ggml files through
``ctypes.cdll``). Nothing about that is safe unless we know what we received,
so every downloader checks the file against a hash pinned *in this repository*
@@ -46,7 +46,7 @@ from typing import Iterable, NamedTuple
REPO_ROOT = Path(__file__).resolve().parents[1]
SRC = REPO_ROOT / "src"
-MANIFEST = SRC / "vocalinux" / "utils" / "model_checksums.txt"
+MANIFEST = SRC / "voculinux" / "utils" / "model_checksums.txt"
HF_REPO = "ggerganov/whisper.cpp"
HF_API = f"https://huggingface.co/api/models/{HF_REPO}?blobs=true"
@@ -65,7 +65,7 @@ class Entry(NamedTuple):
def _fetch_json(url: str):
- request = urllib.request.Request(url, headers={"User-Agent": "vocalinux-checksum-generator"})
+ request = urllib.request.Request(url, headers={"User-Agent": "voculinux-checksum-generator"})
with urllib.request.urlopen(request, timeout=TIMEOUT) as response: # noqa: S310
return json.load(response)
@@ -93,7 +93,7 @@ def _download_and_hash(url: str, expected_md5: str) -> tuple[str, int]:
for rather than pinning either one.
"""
sha256, md5, size = hashlib.sha256(), hashlib.md5(), 0
- request = urllib.request.Request(url, headers={"User-Agent": "vocalinux-checksum-generator"})
+ request = urllib.request.Request(url, headers={"User-Agent": "voculinux-checksum-generator"})
with urllib.request.urlopen(request, timeout=TIMEOUT) as response: # noqa: S310
for chunk in iter(lambda: response.read(1024 * 1024), b""):
sha256.update(chunk)
@@ -306,7 +306,7 @@ def _vosk_entries(wanted: Iterable[str], refresh: bool) -> list[Entry]:
def _render(entries: list[Entry], revision: str) -> str:
width = max(len(entry.filename) for entry in entries)
lines = [
- "# Checksums for every speech model Vocalinux downloads.",
+ "# Checksums for every speech model Voculinux downloads.",
"#",
"# Generated by scripts/generate-model-checksums.py -- do not edit by hand.",
"# Regenerate with `just model-checksums` after adding a model to",
diff --git a/scripts/generate_sounds.py b/scripts/generate_sounds.py
index 12c25ed..bf53f85 100755
--- a/scripts/generate_sounds.py
+++ b/scripts/generate_sounds.py
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
-"""Generate Vocalinux notification WAVs.
+"""Generate Voculinux notification WAVs.
Writes 16-bit PCM mono files at 44.1 kHz into resources/sounds/:
diff --git a/scripts/install-remote-test.sh b/scripts/install-remote-test.sh
index d399f94..0aa2a03 100755
--- a/scripts/install-remote-test.sh
+++ b/scripts/install-remote-test.sh
@@ -14,7 +14,7 @@
# fetch+reset over the existing clone.
#
# The remote is a local mirror so the gate answers for *this commit*: the tag
-# is published from HEAD's tree and VOCALINUX_REPO_URL points the bootstrap at
+# is published from HEAD's tree and VOCULINUX_REPO_URL points the bootstrap at
# it. A gate that cloned the public repo would install the last release, not
# the checkout under test. The tag's own install.sh is the bootstrap: the #701
# guardrail allows the bootstrap to come from main, and this commit's copy is
@@ -37,10 +37,10 @@ INSTALL_HOME="/home/$INSTALL_USER"
# Opaque on purpose: a name the public repository cannot already carry, so a
# silent fallback to GitHub fails loudly instead of installing the wrong ref.
GATE_TAG="${GATE_TAG:-v0.0.0-remote-gate}"
-MIRROR="/srv/vocalinux-remote.git"
+MIRROR="/srv/voculinux-remote.git"
BOOTSTRAP="/tmp/vl.sh"
-CLONE_DIR="$INSTALL_HOME/.local/share/vocalinux-install"
-REMOTE_VENV="$INSTALL_HOME/.local/share/vocalinux/venv"
+CLONE_DIR="$INSTALL_HOME/.local/share/voculinux-install"
+REMOTE_VENV="$INSTALL_HOME/.local/share/voculinux/venv"
fail() {
echo "FAIL: $*" >&2
@@ -48,11 +48,11 @@ fail() {
exit 1
}
-# install.sh writes a full transcript under ~/.local/state/vocalinux/. It is the
+# install.sh writes a full transcript under ~/.local/state/voculinux/. It is the
# only place the per-distro package manager output survives.
dump_install_log() {
local log
- log="$(ls -1t "$INSTALL_HOME"/.local/state/vocalinux/install-*.log 2>/dev/null | head -n1 || true)"
+ log="$(ls -1t "$INSTALL_HOME"/.local/state/voculinux/install-*.log 2>/dev/null | head -n1 || true)"
if [ -n "$log" ]; then
echo "== last 200 lines of $log ==" >&2
tail -n 200 "$log" >&2
@@ -142,9 +142,9 @@ chmod 0644 "$BOOTSTRAP"
run_remote_install() {
# cd to $INSTALL_HOME so the bootstrap sees no checkout: local mode is chosen
- # by a pyproject.toml naming vocalinux in the working directory, and the
+ # by a pyproject.toml naming voculinux in the working directory, and the
# remote path is the one under test.
- su - "$INSTALL_USER" -c "cd '$INSTALL_HOME' && VOCALINUX_REPO_URL='file://$MIRROR' bash '$BOOTSTRAP' --auto --skip-models '--tag=$GATE_TAG'"
+ su - "$INSTALL_USER" -c "cd '$INSTALL_HOME' && VOCULINUX_REPO_URL='file://$MIRROR' bash '$BOOTSTRAP' --auto --skip-models '--tag=$GATE_TAG'"
}
# The user's literal `curl | bash`: installer code reaches bash on a pipe while
@@ -187,7 +187,7 @@ drip "$bootstrap" | bash -s -- "$@"
EOF
chmod 0755 "$PIPED_FEED"
run_remote_install_piped() {
- su - "$INSTALL_USER" -c "cd '$INSTALL_HOME' && VOCALINUX_REPO_URL='file://$MIRROR' script -qec \"'$PIPED_FEED' '$BOOTSTRAP' --auto --skip-models '--tag=$GATE_TAG'\" /dev/null"
+ su - "$INSTALL_USER" -c "cd '$INSTALL_HOME' && VOCULINUX_REPO_URL='file://$MIRROR' script -qec \"'$PIPED_FEED' '$BOOTSTRAP' --auto --skip-models '--tag=$GATE_TAG'\" /dev/null"
}
assert_remote_install() {
@@ -223,20 +223,20 @@ assert_remote_install() {
[ -x "$REMOTE_VENV/bin/python" ] \
|| fail "no remote venv at $REMOTE_VENV; the handoff's --venv-dir did not reach the tagged installer"
# The remote marker relocates the activation helper to ~/.local/bin only when
- # VOCALINUX_REMOTE_INSTALL survives the exec.
- [ -f "$INSTALL_HOME/.local/bin/activate-vocalinux.sh" ] \
- || fail "no ~/.local/bin/activate-vocalinux.sh; the remote marker did not survive the handoff"
+ # VOCULINUX_REMOTE_INSTALL survives the exec.
+ [ -f "$INSTALL_HOME/.local/bin/activate-voculinux.sh" ] \
+ || fail "no ~/.local/bin/activate-voculinux.sh; the remote marker did not survive the handoff"
# --skip-models forwarded: a model in the data dir means the tagged installer
# re-parsed arguments the handoff did not deliver.
- if [ -d "$INSTALL_HOME/.local/share/vocalinux/models" ]; then
- [ -z "$(find "$INSTALL_HOME/.local/share/vocalinux/models" -type f -print -quit)" ] \
+ if [ -d "$INSTALL_HOME/.local/share/voculinux/models" ]; then
+ [ -z "$(find "$INSTALL_HOME/.local/share/voculinux/models" -type f -print -quit)" ] \
|| fail "models were downloaded; --skip-models did not survive the handoff"
fi
echo "== Assert: the installed app is there and answers =="
- [ -x "$INSTALL_HOME/.local/bin/vocalinux" ] || fail "no wrapper at ~/.local/bin/vocalinux"
- [ -x "$INSTALL_HOME/.local/bin/vocalinux-gui" ] || fail "no wrapper at ~/.local/bin/vocalinux-gui"
- [ -f "$INSTALL_HOME/.local/share/applications/vocalinux.desktop" ] \
+ [ -x "$INSTALL_HOME/.local/bin/voculinux" ] || fail "no wrapper at ~/.local/bin/voculinux"
+ [ -x "$INSTALL_HOME/.local/bin/voculinux-gui" ] || fail "no wrapper at ~/.local/bin/voculinux-gui"
+ [ -f "$INSTALL_HOME/.local/share/applications/voculinux.desktop" ] \
|| fail "no desktop entry; install_desktop_entry did not run"
# The version the wrapper reports must be the tag's own, not an assertion
@@ -244,13 +244,13 @@ assert_remote_install() {
local expected_version version_output
expected_version="$(grep -oP '__version__\s*=\s*"\K[^"]+' "$CLONE_DIR/src/vocalinux/version.py")" \
|| fail "cannot read __version__ from the clone's version.py"
- version_output="$(su - "$INSTALL_USER" -c "'$INSTALL_HOME/.local/bin/vocalinux' --version")" \
+ version_output="$(su - "$INSTALL_USER" -c "'$INSTALL_HOME/.local/bin/voculinux' --version")" \
|| fail "the installed wrapper cannot report a version"
case "$version_output" in
*"$expected_version"*) ;;
*) fail "wrapper reports '$version_output', expected the tag's $expected_version" ;;
esac
- echo " vocalinux --version: $version_output"
+ echo " voculinux --version: $version_output"
# Same blind spots as the local gate: the injection binaries are reached
# through subprocess, and the IBus runtime only where the package list
@@ -320,7 +320,7 @@ su - "$INSTALL_USER" -c "git -C '$CLONE_DIR' reset --hard '$AWAY_SHA' \
[ -z "$(git -C "$CLONE_DIR" tag -l "$GATE_TAG")" ] \
|| fail "the clone kept refs/tags/$GATE_TAG; the re-run proves nothing"
run_remote_install_piped || fail "the terminal-backed piped install exited non-zero over the existing clone"
-grep -l "Updating existing clone" "$INSTALL_HOME"/.local/state/vocalinux/install-*.log >/dev/null 2>&1 \
+grep -l "Updating existing clone" "$INSTALL_HOME"/.local/state/voculinux/install-*.log >/dev/null 2>&1 \
|| fail "no install log shows 'Updating existing clone'; the fetch arm did not run"
assert_remote_install
diff --git a/scripts/install-test.sh b/scripts/install-test.sh
index f31f0b9..ada6378 100755
--- a/scripts/install-test.sh
+++ b/scripts/install-test.sh
@@ -17,7 +17,7 @@
# exercise a path no user takes.
#
# Local mode only: install.sh chooses it by finding a pyproject.toml naming
-# vocalinux in the working directory, so extracting the tree and running from it
+# voculinux in the working directory, so extracting the tree and running from it
# tests this commit. Remote mode (curl | bash, which clones the latest tag) is
# not covered here.
#
@@ -33,7 +33,7 @@ INSTALL_HOME="/home/$INSTALL_USER"
# Local mode puts the venv inside the tree, which is why the checkout is copied
# rather than written to: a bind-mounted host tree would come back owned by a
# container uid with a venv in it.
-TREE="$INSTALL_HOME/vocalinux"
+TREE="$INSTALL_HOME/voculinux"
fail() {
echo "FAIL: $*" >&2
@@ -41,11 +41,11 @@ fail() {
exit 1
}
-# install.sh writes a full transcript under ~/.local/state/vocalinux/. It is the
+# install.sh writes a full transcript under ~/.local/state/voculinux/. It is the
# only place the per-distro package manager output survives.
dump_install_log() {
local log
- log="$(ls -1t "$INSTALL_HOME"/.local/state/vocalinux/install-*.log 2>/dev/null | head -n1 || true)"
+ log="$(ls -1t "$INSTALL_HOME"/.local/state/voculinux/install-*.log 2>/dev/null | head -n1 || true)"
if [ -n "$log" ]; then
echo "== last 200 lines of $log ==" >&2
tail -n 200 "$log" >&2
@@ -132,8 +132,8 @@ echo " install took $(( $(date +%s) - START ))s"
echo "== Smoke: is there an installation, and does it import =="
VENV="$TREE/venv"
[ -x "$VENV/bin/python" ] || fail "no venv interpreter at $VENV/bin/python"
-[ -x "$INSTALL_HOME/.local/bin/vocalinux" ] || fail "no wrapper at ~/.local/bin/vocalinux"
-[ -f "$INSTALL_HOME/.local/share/applications/vocalinux.desktop" ] \
+[ -x "$INSTALL_HOME/.local/bin/voculinux" ] || fail "no wrapper at ~/.local/bin/voculinux"
+[ -f "$INSTALL_HOME/.local/share/applications/voculinux.desktop" ] \
|| fail "no desktop entry; install_desktop_entry did not run"
# The injection backends are reached through subprocess, not GI, so no typelib
@@ -159,7 +159,7 @@ esac
# Through the wrapper rather than the venv directly: the wrapper is what the
# desktop entry and the user's PATH invoke, and it carries the GI_TYPELIB_PATH
# and pywhispercpp library-path resolution the bare console script does not.
-su - "$INSTALL_USER" -c "'$INSTALL_HOME/.local/bin/vocalinux' --version" \
+su - "$INSTALL_USER" -c "'$INSTALL_HOME/.local/bin/voculinux' --version" \
|| fail "the installed wrapper cannot report a version"
su - "$INSTALL_USER" -c "'$VENV/bin/python' - " <<'PY' || fail "the installation does not import"
diff --git a/scripts/prepare_aur_source.py b/scripts/prepare_aur_source.py
index cfc51c5..cc73345 100644
--- a/scripts/prepare_aur_source.py
+++ b/scripts/prepare_aur_source.py
@@ -22,7 +22,7 @@ from pathlib import Path
from packaging.version import Version
ROOT = Path(__file__).resolve().parents[1]
-TEMPLATE = ROOT / "packaging/aur/vocalinux/PKGBUILD"
+TEMPLATE = ROOT / "packaging/aur/voculinux/PKGBUILD"
REPOSITORY = "VocaHQ/vocalinux"
@@ -33,14 +33,14 @@ def digest(path: Path) -> str:
def sdist_version(sdist: Path) -> str:
- """Require one canonical Vocalinux sdist with matching top-level metadata."""
- match = re.fullmatch(r"vocalinux-([0-9][A-Za-z0-9.+!]*)\.tar\.gz", sdist.name)
+ """Require one canonical Voculinux sdist with matching top-level metadata."""
+ match = re.fullmatch(r"voculinux-([0-9][A-Za-z0-9.+!]*)\.tar\.gz", sdist.name)
if not match:
- raise ValueError("expected a canonical vocalinux-VERSION.tar.gz sdist")
+ raise ValueError("expected a canonical voculinux-VERSION.tar.gz sdist")
version = match[1]
if str(Version(version)) != version:
raise ValueError("sdist filename version is not canonical")
- root = f"vocalinux-{version}"
+ root = f"voculinux-{version}"
with tarfile.open(sdist, "r:gz") as archive:
members = archive.getmembers()
if any(
@@ -55,7 +55,7 @@ def sdist_version(sdist: Path) -> str:
assert stream is not None
with stream:
info = BytesParser().parse(stream)
- if info.get_all("Name") != ["vocalinux"] or info.get_all("Version") != [version]:
+ if info.get_all("Name") != ["voculinux"] or info.get_all("Version") != [version]:
raise ValueError("sdist metadata does not match its filename")
return version
diff --git a/scripts/sync_flatpak_deps.py b/scripts/sync_flatpak_deps.py
index 0119a2b..fc0982f 100755
--- a/scripts/sync_flatpak_deps.py
+++ b/scripts/sync_flatpak_deps.py
@@ -47,7 +47,7 @@ from packaging.utils import canonicalize_name
REPO_ROOT = Path(__file__).resolve().parents[1]
EXPORT = REPO_ROOT / "requirements" / "vad.txt"
DEPS_YAML = REPO_ROOT / "packaging" / "flatpak" / "python3-dependencies.yaml"
-MANIFEST = REPO_ROOT / "packaging" / "flatpak" / "com.vocalinux.Vocalinux.yml"
+MANIFEST = REPO_ROOT / "packaging" / "flatpak" / "com.voculinux.Voculinux.yml"
#: The environment the Flatpak build resolves for. GNOME 50 ships Python 3.13.
#: numpy's lock entry splits at `python_full_version >= '3.12'`; onnxruntime's
diff --git a/scripts/test_remote_server.py b/scripts/test_remote_server.py
index 52a933d..8b31fc5 100755
--- a/scripts/test_remote_server.py
+++ b/scripts/test_remote_server.py
@@ -1,8 +1,8 @@
#!/usr/bin/env python3
"""
-Vocalinux Remote API Test Server
+Voculinux Remote API Test Server
-A simple mock server for testing Vocalinux's remote API feature.
+A simple mock server for testing Voculinux's remote API feature.
Supports whisper.cpp (/inference) and OpenAI/FunASR-compatible
(/v1/audio/transcriptions) formats.
@@ -22,7 +22,7 @@ from http.server import BaseHTTPRequestHandler, HTTPServer
class RemoteAPITestHandler(BaseHTTPRequestHandler):
- """HTTP request handler for testing Vocalinux remote API."""
+ """HTTP request handler for testing Voculinux remote API."""
def log_message(self, format, *args):
"""Custom log format with timestamp."""
@@ -37,7 +37,7 @@ class RemoteAPITestHandler(BaseHTTPRequestHandler):
self.end_headers()
response = {
"status": "ok",
- "message": "Vocalinux Remote API Test Server",
+ "message": "Voculinux Remote API Test Server",
"endpoints": [
"/inference (whisper.cpp format)",
"/v1/audio/transcriptions (OpenAI/FunASR format)",
@@ -138,7 +138,7 @@ class RemoteAPITestHandler(BaseHTTPRequestHandler):
if "test" in filename.lower():
return "This is a test transcription from the mock server."
elif "hello" in filename.lower():
- return "Hello, this is Vocalinux testing the remote API."
+ return "Hello, this is Voculinux testing the remote API."
elif "long" in filename.lower():
return (
"This is a longer transcription to test how the system handles "
@@ -159,7 +159,7 @@ class DelayedHTTPServer(HTTPServer):
def main():
parser = argparse.ArgumentParser(
- description="Vocalinux Remote API Test Server"
+ description="Voculinux Remote API Test Server"
)
parser.add_argument(
"--port",
@@ -183,7 +183,7 @@ def main():
args = parser.parse_args()
print("=" * 60)
- print("Vocalinux Remote API Test Server")
+ print("Voculinux Remote API Test Server")
print("=" * 60)
print(f"Listening on: http://{args.host}:{args.port}")
print(f"Processing delay: {args.delay}s")
diff --git a/scripts/verify_release.py b/scripts/verify_release.py
index 0649dbc..0ef6a55 100755
--- a/scripts/verify_release.py
+++ b/scripts/verify_release.py
@@ -26,7 +26,7 @@ import subprocess
import sys
MANIFEST = "SHA256SUMS"
-PYPI_PROJECT = "vocalinux"
+PYPI_PROJECT = "voculinux"
PYPI_SUFFIXES = (".whl", ".tar.gz")
PYPI_TIMEOUT = 30
diff --git a/snap/gui/vocalinux.desktop b/snap/gui/voculinux.desktop
similarity index 65%
rename from snap/gui/vocalinux.desktop
rename to snap/gui/voculinux.desktop
index 7263676..8892434 100644
--- a/snap/gui/vocalinux.desktop
+++ b/snap/gui/voculinux.desktop
@@ -1,15 +1,15 @@
[Desktop Entry]
Version=1.0
Type=Application
-Name=Vocalinux
+Name=Voculinux
Comment=Free, offline voice dictation for Linux
GenericName=Voice Typing
-Exec=vocalinux
-Icon=${SNAP}/usr/share/icons/hicolor/scalable/apps/vocalinux.svg
+Exec=voculinux
+Icon=${SNAP}/usr/share/icons/hicolor/scalable/apps/voculinux.svg
Terminal=false
Categories=Utility;Accessibility;AudioVideo;
Keywords=voice;typing;dictation;speech;recognition;transcription;accessibility;
StartupNotify=true
-StartupWMClass=com.vocalinux.Vocalinux
+StartupWMClass=com.voculinux.Voculinux
X-GNOME-UsesNotifications=true
-X-SnapInstanceName=vocalinux
+X-SnapInstanceName=voculinux
diff --git a/snap/gui/vocalinux.png b/snap/gui/voculinux.png
similarity index 100%
rename from snap/gui/vocalinux.png
rename to snap/gui/voculinux.png
diff --git a/snap/local/build.py b/snap/local/build.py
index c260289..b14e952 100644
--- a/snap/local/build.py
+++ b/snap/local/build.py
@@ -54,7 +54,7 @@ def relocate_scripts(install: Path, tooling: Path) -> None:
"if __name__ == '__main__':\n"
" sys.exit(main())\n"
)
- for name in ("vocalinux", "vocalinux-gui"):
+ for name in ("voculinux", "voculinux-gui"):
path = install / "bin" / name
if path.is_symlink() or not path.is_file():
raise RuntimeError(f"Missing installed entry point: {path}")
diff --git a/snap/local/check_runtime.py b/snap/local/check_runtime.py
index 7368c03..4c33d34 100644
--- a/snap/local/check_runtime.py
+++ b/snap/local/check_runtime.py
@@ -17,7 +17,7 @@ import runpy
import sys
from pathlib import Path
-MANIFEST = Path("usr/share/vocalinux/python-inputs.json")
+MANIFEST = Path("usr/share/voculinux/python-inputs.json")
def normalize(name: str) -> str:
@@ -80,7 +80,7 @@ def record(root: Path, source: Path) -> None:
if importlib.metadata.version(name) != expected_version:
raise RuntimeError(f"Build tool {name} differs from its locked version")
expected = locked_versions(source / "requirements/runtime.txt")
- expected["vocalinux"] = runpy.run_path(str(source / "src/vocalinux/version.py"))["__version__"]
+ expected["voculinux"] = runpy.run_path(str(source / "src/vocalinux/version.py"))["__version__"]
audit(root, expected)
manifest = {
"python": list(sys.version_info[:2]),
diff --git a/snap/local/smoke-test.sh b/snap/local/smoke-test.sh
index cc2b983..97844c2 100644
--- a/snap/local/smoke-test.sh
+++ b/snap/local/smoke-test.sh
@@ -7,16 +7,16 @@ if [ "$#" -ne 1 ] || [ ! -f "$1" ]; then
echo "Usage: bash snap/local/smoke-test.sh PATH.snap" >&2
exit 1
fi
-if snap list vocalinux >/dev/null 2>&1; then
- echo "Refusing to replace an existing Vocalinux snap; use a disposable host" >&2
+if snap list voculinux >/dev/null 2>&1; then
+ echo "Refusing to replace an existing Voculinux snap; use a disposable host" >&2
exit 1
fi
sudo snap install --dangerous "$1"
-snap run vocalinux --version
+snap run voculinux --version
# --shell does not run the application's command chain. Explicitly enter the
# same GNOME desktop-launch environment before checking the installed payload.
-PYNPUT_BACKEND=dummy snap run --shell vocalinux -c '
+PYNPUT_BACKEND=dummy snap run --shell voculinux -c '
exec "$SNAP/snap/command-chain/desktop-launch" "$SNAP/bin/python3" \
- "$SNAP/usr/lib/vocalinux/check_runtime.py" --root "$SNAP"
+ "$SNAP/usr/lib/voculinux/check_runtime.py" --root "$SNAP"
'
diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml
index 6f5ebdd..6adea3d 100644
--- a/snap/snapcraft.yaml
+++ b/snap/snapcraft.yaml
@@ -1,4 +1,4 @@
-# Vocalinux Snap packaging
+# Voculinux Snap packaging
#
# First ship: strict confinement, default whisper.cpp engine path, GTK tray UI,
# mic capture, model download, and text injection (RemoteDesktop portal, wtype, xdotool).
@@ -8,15 +8,15 @@
# snapcraft pack
# See docs/SNAP.md for controlled inputs, the build gate and verification limits.
-name: vocalinux
+name: voculinux
base: core24 # Ubuntu 24.04 / Python 3.12 (project requires-python >=3.11)
# Fallback version; live version is set from src/vocalinux/version.py via
-# adopt-info + craftctl set in the vocalinux part (required for craftctl).
+# adopt-info + craftctl set in the voculinux part (required for craftctl).
version: "0.17.0"
-adopt-info: vocalinux
+adopt-info: voculinux
summary: Free offline voice dictation for Linux
description: |
- Vocalinux is free voice typing for Linux. Hold a shortcut or toggle dictation, and text lands in almost any app on X11 or Wayland.
+ Voculinux is free voice typing for Linux. Hold a shortcut or toggle dictation, and text lands in almost any app on X11 or Wayland.
Speech recognition runs on your machine after you download a model. No Voca account. No cloud transcription on the default path.
@@ -29,33 +29,33 @@ description: |
- Text injection via the Wayland RemoteDesktop portal, wtype, or xdotool
Sandbox notes:
- - Global hotkeys need: sudo snap connect vocalinux:raw-input
- and sudo snap connect vocalinux:hardware-observe
+ - Global hotkeys need: sudo snap connect voculinux:raw-input
+ and sudo snap connect voculinux:hardware-observe
- Native Wayland typing uses the RemoteDesktop portal: the compositor
asks once on first dictation. The snap ships no uinput plug and no
ydotool; the Store denied the super-privileged grant.
- KDE Plasma: KWin's portal can mistype letter case (KDE bug 489021);
set "Virtual Keyboard = IBus Wayland" so the IBus path delivers text.
- - Microphone may need: sudo snap connect vocalinux:audio-record
+ - Microphone may need: sudo snap connect voculinux:audio-record
The microphone list comes from the sound server, so pick a device
in Settings rather than relying on the system default.
- whisper.cpp runs on the CPU in this snap; it has no GPU backend.
For Vulkan acceleration install the AppImage or use install.sh.
- - Config and models live under ~/snap/vocalinux/
+ - Config and models live under ~/snap/voculinux/
grade: stable
confinement: strict
license: AGPL-3.0-only
-icon: snap/gui/vocalinux.png
+icon: snap/gui/voculinux.png
contact: https://github.com/VocaHQ/vocalinux/issues
issues: https://github.com/VocaHQ/vocalinux/issues
-website: https://vocalinux.com
+website: https://voculinux.com
source-code: https://github.com/VocaHQ/vocalinux
donation: https://github.com/sponsors/jatinkrmalik
apps:
- vocalinux:
- command: bin/vocalinux
+ voculinux:
+ command: bin/voculinux
extensions: [gnome]
plugs:
# gnome extension already grants desktop, desktop-legacy, gsettings,
@@ -67,17 +67,17 @@ apps:
- network-bind # optional remote_api engine
# Global hotkeys via python-evdev (/dev/input/event*).
# Super-privileged: not auto-connected; user must:
- # sudo snap connect vocalinux:raw-input
+ # sudo snap connect voculinux:raw-input
- raw-input
# Needed for /proc/bus/input/devices; not auto-connected:
- # sudo snap connect vocalinux:hardware-observe
+ # sudo snap connect voculinux:hardware-observe
- hardware-observe
# No uinput plug; the RemoteDesktop portal types on Wayland instead.
# The Store denied the super-privileged grant
# (https://forum.snapcraft.io/t/53528), and ydotool is not staged
# because it cannot reach /dev/uinput under confinement.
- common-id: com.vocalinux.Vocalinux
- desktop: usr/share/applications/vocalinux.desktop
+ common-id: com.voculinux.Voculinux
+ desktop: usr/share/applications/voculinux.desktop
environment:
# Prefer bundled CLI helpers (xdotool, xsel, xclip, wl-copy).
# Do NOT prepend $SNAP/usr/lib over the gnome extension platform path:
@@ -103,7 +103,7 @@ layout:
bind: $SNAP/usr/lib/$CRAFT_ARCH_TRIPLET/alsa-lib
parts:
- vocalinux:
+ voculinux:
# The Python plugin would resolve dependencies and build tools again.
plugin: nil
source: .
@@ -151,13 +151,13 @@ parts:
--source "${CRAFT_PART_BUILD}" --install "${CRAFT_PART_INSTALL}" \
--work "${CRAFT_PART_BUILD}/.snap-python-build"
install -Dm644 "${CRAFT_PART_SRC}/snap/local/check_runtime.py" \
- "${CRAFT_PART_INSTALL}/usr/lib/vocalinux/check_runtime.py"
- install -Dm644 "${CRAFT_PROJECT_DIR}/snap/gui/vocalinux.desktop" \
- "${CRAFT_PART_INSTALL}/usr/share/applications/vocalinux.desktop"
- install -Dm644 "${CRAFT_PROJECT_DIR}/resources/icons/scalable/vocalinux.svg" \
- "${CRAFT_PART_INSTALL}/usr/share/icons/hicolor/scalable/apps/vocalinux.svg"
+ "${CRAFT_PART_INSTALL}/usr/lib/voculinux/check_runtime.py"
+ install -Dm644 "${CRAFT_PROJECT_DIR}/snap/gui/voculinux.desktop" \
+ "${CRAFT_PART_INSTALL}/usr/share/applications/voculinux.desktop"
+ install -Dm644 "${CRAFT_PROJECT_DIR}/resources/icons/scalable/voculinux.svg" \
+ "${CRAFT_PART_INSTALL}/usr/share/icons/hicolor/scalable/apps/voculinux.svg"
# meta/gui is what snapd uses for the store/desktop icon when present.
- install -Dm644 "${CRAFT_PROJECT_DIR}/resources/icons/scalable/vocalinux.svg" \
+ install -Dm644 "${CRAFT_PROJECT_DIR}/resources/icons/scalable/voculinux.svg" \
"${CRAFT_PART_INSTALL}/meta/gui/icon.svg"
install -Dm644 "${CRAFT_PROJECT_DIR}/snap/local/alsa/asound.conf" \
"${CRAFT_PART_INSTALL}/etc/asound.conf"
diff --git a/src/vocalinux/__init__.py b/src/vocalinux/__init__.py
index a9e460b..9987416 100644
--- a/src/vocalinux/__init__.py
+++ b/src/vocalinux/__init__.py
@@ -1,5 +1,5 @@
"""
-Vocalinux - A seamless voice dictation system for Linux
+Voculinux - A seamless voice dictation system for Linux
Note: GTK-dependent modules are imported lazily in main.py to allow
the package to be imported even when system GTK typelibs are not available.
diff --git a/src/vocalinux/app_identity.py b/src/vocalinux/app_identity.py
index 444e6fe..697e676 100644
--- a/src/vocalinux/app_identity.py
+++ b/src/vocalinux/app_identity.py
@@ -1,68 +1,74 @@
-"""Central user-visible application identity for Vocalinux.
+"""Central user-visible application identity for Voculinux.
-Ticket #17 prefactor: every user-visible identity string that is hardcoded in
-more than one place is driven from this single module. No value changes here;
-the rename ticket (#18) flips them in one place instead of a scavenger hunt.
+Ticket #18 rename: every user-visible identity string that is hardcoded in
+more than one place is driven from this single module. The fork takes its
+own name everywhere a user can see it; the internal ``voculinux`` Python
+package name is retained (see :data:`RETAINED_SURFACES`) and unrelated to
+these values.
-Retained internal names (the ``vocalinux`` Python package, upstream URLs, and
-changelog history) are recorded in :data:`RETAINED_SURFACES`, not renamed.
+One-time legacy import of a previous Voculinux install lives in
+:mod:`vocalinux.legacy_import` and keys off :data:`LEGACY_APP_DIR_NAME`.
"""
-APP_NAME: str = "Vocalinux"
-APP_ID: str = "vocalinux"
-APP_DIR_NAME: str = "vocalinux"
-CLI_PROG: str = "vocalinux"
+APP_NAME: str = "Voculinux"
+APP_ID: str = "voculinux"
+APP_DIR_NAME: str = "voculinux"
+CLI_PROG: str = "voculinux"
-BUS_NAME: str = "com.vocalinux.Vocalinux"
-OBJECT_PATH: str = "/com/vocalinux/Vocalinux"
-INTERFACE_NAME: str = "com.vocalinux.Vocalinux"
+BUS_NAME: str = "com.voculinux.Voculinux"
+OBJECT_PATH: str = "/com/voculinux/Voculinux"
+INTERFACE_NAME: str = "com.voculinux.Voculinux"
-DESKTOP_FILENAME: str = "vocalinux.desktop"
-DESKTOP_ICON_NAME: str = "vocalinux"
+DESKTOP_FILENAME: str = "voculinux.desktop"
+DESKTOP_ICON_NAME: str = "voculinux"
TRAY_TITLE: str = APP_NAME
-ICON_DEFAULT: str = "vocalinux-microphone-off"
-ICON_ACTIVE: str = "vocalinux-microphone"
-ICON_PROCESSING: str = "vocalinux-microphone-process"
+ICON_DEFAULT: str = "voculinux-microphone-off"
+ICON_ACTIVE: str = "voculinux-microphone"
+ICON_PROCESSING: str = "voculinux-microphone-process"
ICON_BASE_NAMES: tuple[str, ...] = (
- "vocalinux",
+ "voculinux",
ICON_ACTIVE,
ICON_DEFAULT,
ICON_PROCESSING,
)
-ENGINE_NAME: str = "vocalinux"
-ENGINE_LONGNAME: str = "Vocalinux"
-ENGINE_DESCRIPTION: str = "Vocalinux voice dictation (use as default input method)"
-COMPONENT_NAME: str = "org.freedesktop.IBus.Vocalinux"
-IBUS_DIR_NAME: str = "vocalinux-ibus"
-IBUS_TEXTDOMAIN: str = "vocalinux"
+ENGINE_NAME: str = "voculinux"
+ENGINE_LONGNAME: str = "Voculinux"
+ENGINE_DESCRIPTION: str = "Voculinux voice dictation (use as default input method)"
+COMPONENT_NAME: str = "org.freedesktop.IBus.Voculinux"
+IBUS_DIR_NAME: str = "voculinux-ibus"
+IBUS_TEXTDOMAIN: str = "voculinux"
-UPDATE_CHECKER_USER_AGENT: str = "Vocalinux-UpdateChecker"
+UPDATE_CHECKER_USER_AGENT: str = "Voculinux-UpdateChecker"
-RESOURCE_DIR_NAME: str = "vocalinux"
+RESOURCE_DIR_NAME: str = "voculinux"
-VERIFICATION_STAMP_NAME: str = ".vocalinux_verified"
-LOG_FILE_PREFIX: str = "vocalinux_logs_"
-PORTAL_TOKEN_PREFIX: str = "vocalinux_"
+VERIFICATION_STAMP_NAME: str = ".voculinux_verified"
+LOG_FILE_PREFIX: str = "voculinux_logs_"
+PORTAL_TOKEN_PREFIX: str = "voculinux_"
-ENV_FORCE_BACKEND: str = "VOCALINUX_FORCE_BACKEND"
-ENV_INJECT_MODIFIER_WAIT: str = "VOCALINUX_INJECT_MODIFIER_WAIT"
-ENV_YDOTOOL_KEY_DELAY: str = "VOCALINUX_YDOTOOL_KEY_DELAY"
+ENV_FORCE_BACKEND: str = "VOCULINUX_FORCE_BACKEND"
+ENV_INJECT_MODIFIER_WAIT: str = "VOCULINUX_INJECT_MODIFIER_WAIT"
+ENV_YDOTOOL_KEY_DELAY: str = "VOCULINUX_YDOTOOL_KEY_DELAY"
-SITE_URL: str = "https://vocalinux.com"
+SITE_URL: str = "https://voculinux.com"
-#: Files the rename ticket (#18) must flip. Checked by
+#: Previous install locations read once by the legacy importer. Never written.
+LEGACY_APP_DIR_NAME: str = "vocalinux"
+LEGACY_BUS_NAME: str = "com.vocalinux.Vocalinux"
+
+#: Files the rename ticket (#18) flipped. Checked by
#: ``tests/test_app_identity.py`` so the list cannot drift silently.
RENAME_SURFACES: tuple[str, ...] = (
"pyproject.toml",
- "vocalinux.desktop",
- "snap/gui/vocalinux.desktop",
+ "voculinux.desktop",
+ "snap/gui/voculinux.desktop",
"snap/snapcraft.yaml",
- "packaging/flatpak/com.vocalinux.Vocalinux.desktop",
- "packaging/flatpak/com.vocalinux.Vocalinux.metainfo.xml",
- "packaging/flatpak/com.vocalinux.Vocalinux.yml",
- "packaging/aur/vocalinux-bin/vocalinux.desktop",
+ "packaging/flatpak/com.voculinux.Voculinux.desktop",
+ "packaging/flatpak/com.voculinux.Voculinux.metainfo.xml",
+ "packaging/flatpak/com.voculinux.Voculinux.yml",
+ "packaging/aur/voculinux-bin/voculinux.desktop",
"web/src/app/page.tsx",
"web/package.json",
"README.md",
diff --git a/src/vocalinux/audio/capture.py b/src/vocalinux/audio/capture.py
index 1e539d1..db7c69c 100644
--- a/src/vocalinux/audio/capture.py
+++ b/src/vocalinux/audio/capture.py
@@ -494,7 +494,7 @@ def _open_capture_stream(audio: Any, device_index: Optional[int] = None) -> tupl
"""
Negotiate a working (channels, sample_rate) and return the opened stream.
- Historically Vocalinux probed channels and sample rates separately, each
+ Historically Voculinux probed channels and sample rates separately, each
opening and closing PortAudio streams, then opened the real capture stream
on top — three open/close cycles in under a second. Bluetooth headset
capture (SCO/HFP / PipeWire "Bluetooth internal capture stream") is
diff --git a/src/vocalinux/dbus_service.py b/src/vocalinux/dbus_service.py
index 0632340..faa3e80 100644
--- a/src/vocalinux/dbus_service.py
+++ b/src/vocalinux/dbus_service.py
@@ -1,9 +1,9 @@
"""
-Session-bus D-Bus service for Vocalinux.
+Session-bus D-Bus service for Voculinux.
-Exposes ``com.vocalinux.Vocalinux`` with ``Toggle``/``Start``/``Stop`` methods
+Exposes ``com.voculinux.Voculinux`` with ``Toggle``/``Start``/``Stop`` methods
so an external trigger (e.g. a KDE Plasma global shortcut running
-``vocalinux --toggle``) can control a running instance without the internal
+``voculinux --toggle``) can control a running instance without the internal
evdev/pynput hotkey listener reading ``/dev/input``.
Mirrors the GDBus usage already present in ``suspend_handler.py``.
@@ -37,7 +37,7 @@ _INTROSPECTION_XML = f"""
class VocalinuxDBusService:
- """Owns the Vocalinux session-bus name and dispatches control methods.
+ """Owns the Voculinux session-bus name and dispatches control methods.
Method calls are marshalled onto the GLib/GTK main thread via
:func:`GLib.idle_add` before the callbacks run, so recognition start/stop
diff --git a/src/vocalinux/gateway_embed/__init__.py b/src/vocalinux/gateway_embed/__init__.py
index fe49e9f..2885620 100644
--- a/src/vocalinux/gateway_embed/__init__.py
+++ b/src/vocalinux/gateway_embed/__init__.py
@@ -1,4 +1,4 @@
-"""Optional local VocaGateway lifecycle helpers for Vocalinux.
+"""Optional local VocaGateway lifecycle helpers for Voculinux.
This is an opt-in path for power users who want to run
https://github.com/VocaHQ/vocagateway on the same Linux box via podman
diff --git a/src/vocalinux/gateway_embed/manager.py b/src/vocalinux/gateway_embed/manager.py
index 154457f..6af3268 100644
--- a/src/vocalinux/gateway_embed/manager.py
+++ b/src/vocalinux/gateway_embed/manager.py
@@ -143,7 +143,7 @@ class GatewayEmbedManager:
return
threading.Thread(
target=_worker,
- name="vocalinux-gateway-runtime",
+ name="voculinux-gateway-runtime",
daemon=True,
).start()
@@ -163,7 +163,7 @@ class GatewayEmbedManager:
self.lan_publish = lan_publish
thread = threading.Thread(
target=self._start_worker,
- name="vocalinux-gateway-start",
+ name="voculinux-gateway-start",
daemon=True,
)
thread.start()
@@ -171,7 +171,7 @@ class GatewayEmbedManager:
def stop_async(self) -> None:
thread = threading.Thread(
target=self._stop_worker,
- name="vocalinux-gateway-stop",
+ name="voculinux-gateway-stop",
daemon=True,
)
thread.start()
@@ -201,7 +201,7 @@ class GatewayEmbedManager:
self._republish_started = True
thread = threading.Thread(
target=self._republish_worker,
- name="vocalinux-gateway-republish",
+ name="voculinux-gateway-republish",
daemon=True,
)
thread.start()
@@ -303,7 +303,7 @@ class GatewayEmbedManager:
logger.exception("gateway poll failed")
self._poll_thread = threading.Thread(
- target=_loop, name="vocalinux-gateway-poll", daemon=True
+ target=_loop, name="voculinux-gateway-poll", daemon=True
)
self._poll_thread.start()
diff --git a/src/vocalinux/gateway_embed/paths_embed.py b/src/vocalinux/gateway_embed/paths_embed.py
index 505df5e..e46eb9c 100644
--- a/src/vocalinux/gateway_embed/paths_embed.py
+++ b/src/vocalinux/gateway_embed/paths_embed.py
@@ -27,7 +27,7 @@ def xdg_cache_home() -> str:
def gateway_cache_dir() -> str:
- return os.path.join(xdg_cache_home(), "vocalinux", f"vocagateway-{GATEWAY_RELEASE_TAG}")
+ return os.path.join(xdg_cache_home(), "voculinux", f"vocagateway-{GATEWAY_RELEASE_TAG}")
def gateway_embed_config_dir() -> str:
diff --git a/src/vocalinux/gateway_embed/preset.py b/src/vocalinux/gateway_embed/preset.py
index 929df3a..eb21c07 100644
--- a/src/vocalinux/gateway_embed/preset.py
+++ b/src/vocalinux/gateway_embed/preset.py
@@ -1,4 +1,4 @@
-"""Map a paired local gateway onto Vocalinux remote_api settings."""
+"""Map a paired local gateway onto Voculinux remote_api settings."""
from __future__ import annotations
diff --git a/src/vocalinux/gateway_embed/runtime.py b/src/vocalinux/gateway_embed/runtime.py
index b2ef582..22d01d4 100644
--- a/src/vocalinux/gateway_embed/runtime.py
+++ b/src/vocalinux/gateway_embed/runtime.py
@@ -132,7 +132,7 @@ def detect_container_runtime(
binary=None,
hint=(
"Install podman (preferred) or docker to run a local VocaGateway. "
- "Vocalinux does not bundle a container engine in the AppImage."
+ "Voculinux does not bundle a container engine in the AppImage."
),
)
diff --git a/src/vocalinux/gateway_embed/sandbox.py b/src/vocalinux/gateway_embed/sandbox.py
index 17d7b3a..632cb54 100644
--- a/src/vocalinux/gateway_embed/sandbox.py
+++ b/src/vocalinux/gateway_embed/sandbox.py
@@ -34,8 +34,8 @@ def detect_sandbox(
blocked=True,
kind="flatpak",
hint=(
- "Vocalinux is running as a Flatpak and cannot reach the host "
- "podman/docker socket. Run Vocalinux from the native package or "
+ "Voculinux is running as a Flatpak and cannot reach the host "
+ "podman/docker socket. Run Voculinux from the native package or "
"AppImage, or start VocaGateway on the host and point Remote "
"Server at it. See docs/GATEWAY_EMBED.md."
),
diff --git a/src/vocalinux/legacy_import.py b/src/vocalinux/legacy_import.py
new file mode 100644
index 0000000..8e1d1b8
--- /dev/null
+++ b/src/vocalinux/legacy_import.py
@@ -0,0 +1,120 @@
+"""One-time legacy Vocalinux import for the Voculinux fork.
+
+Ticket #18: on first run, a previous Vocalinux install's user data is copied
+once into the new ``voculinux`` locations — ``config.json``, the custom
+dictionary (``dictionary.txt`` plus ``custom-dictionary-corrections.json``),
+and the RemoteDesktop portal restore token. After that the new configuration
+always wins: no merging, no write-back to the legacy location.
+
+Exactly-once falls out of existence checks — a copied file is never copied
+again, and a run that already has new locations imports nothing.
+"""
+
+import logging
+import os
+import shutil
+
+from .app_identity import APP_DIR_NAME, LEGACY_APP_DIR_NAME
+
+logger = logging.getLogger(__name__)
+
+#: Directory basenames, deliberately literal: the legacy name must keep
+#: resolving to the old install even after the rename.
+LEGACY_CONFIG_DIRNAME: str = LEGACY_APP_DIR_NAME
+NEW_CONFIG_DIRNAME: str = APP_DIR_NAME
+
+CONFIG_FILENAME: str = "config.json"
+TERMS_FILENAME: str = "dictionary.txt"
+CORRECTIONS_FILENAME: str = "custom-dictionary-corrections.json"
+RESTORE_TOKEN_FILENAME: str = "remote_desktop_restore_token"
+
+#: ``(subdirectory, filename)`` pairs copied ``config -> config`` or
+#: ``data -> data``. Models are deliberately absent: they re-resolve through
+#: the pinned-checksum download path instead of being migrated.
+CONFIG_PAYLOAD: tuple[tuple[str, str], ...] = (
+ ("", CONFIG_FILENAME),
+ ("", TERMS_FILENAME),
+ ("", CORRECTIONS_FILENAME),
+)
+DATA_PAYLOAD: tuple[tuple[str, str], ...] = (("", RESTORE_TOKEN_FILENAME),)
+
+
+def _xdg_dir(env_var: str, fallback: str) -> str:
+ """Return an XDG base directory (empty values treated as unset)."""
+ return os.environ.get(env_var) or os.path.expanduser(fallback)
+
+
+def legacy_config_dir() -> str:
+ """Return the previous Vocalinux configuration directory."""
+ return os.path.join(_xdg_dir("XDG_CONFIG_HOME", "~/.config"), LEGACY_CONFIG_DIRNAME)
+
+
+def new_config_dir() -> str:
+ """Return the Voculinux configuration directory."""
+ return os.path.join(_xdg_dir("XDG_CONFIG_HOME", "~/.config"), NEW_CONFIG_DIRNAME)
+
+
+def legacy_data_dir() -> str:
+ """Return the previous Vocalinux data directory."""
+ return os.path.join(_xdg_dir("XDG_DATA_HOME", "~/.local/share"), LEGACY_CONFIG_DIRNAME)
+
+
+def new_data_dir() -> str:
+ """Return the Voculinux data directory."""
+ return os.path.join(_xdg_dir("XDG_DATA_HOME", "~/.local/share"), NEW_CONFIG_DIRNAME)
+
+
+def _copy_once(src: str, dst: str) -> bool:
+ """Copy ``src`` to ``dst`` when the destination does not exist yet.
+
+ Returns True when a copy happened. Missing sources, existing
+ destinations, and I/O errors copy nothing and return False.
+ """
+ if os.path.exists(dst):
+ return False
+ if not os.path.isfile(src):
+ return False
+ try:
+ os.makedirs(os.path.dirname(dst) or ".", exist_ok=True)
+ shutil.copy2(src, dst)
+ except OSError as error:
+ logger.warning("Legacy import skipped %s: %s", src, error)
+ return False
+ logger.info("Imported legacy file %s to %s", src, dst)
+ return True
+
+
+def import_legacy_once() -> list[str]:
+ """Copy legacy Vocalinux user data into the new locations, once.
+
+ Preconditions (all must hold, otherwise nothing is imported):
+ - the new configuration directory has no ``config.json`` yet (an
+ existing new configuration always wins, with no merge and no
+ write-back to the legacy location);
+ - at least one legacy payload file exists.
+
+ Returns the list of destination paths that were created.
+ """
+ new_config = os.path.join(new_config_dir(), CONFIG_FILENAME)
+ if os.path.exists(new_config):
+ return []
+ legacy_config = legacy_config_dir()
+ if not os.path.isdir(legacy_config):
+ return []
+
+ imported: list[str] = []
+ for _subdir, filename in CONFIG_PAYLOAD:
+ src = os.path.join(legacy_config, filename)
+ dst = os.path.join(new_config_dir(), filename)
+ if _copy_once(src, dst):
+ imported.append(dst)
+ legacy_data = legacy_data_dir()
+ if os.path.isdir(legacy_data):
+ for _subdir, filename in DATA_PAYLOAD:
+ src = os.path.join(legacy_data, filename)
+ dst = os.path.join(new_data_dir(), filename)
+ if _copy_once(src, dst):
+ imported.append(dst)
+ if imported:
+ logger.info("Legacy Vocalinux import complete: %d file(s)", len(imported))
+ return imported
diff --git a/src/vocalinux/main.py b/src/vocalinux/main.py
index e7921b3..3fe74bf 100644
--- a/src/vocalinux/main.py
+++ b/src/vocalinux/main.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
"""
-Main entry point for Vocalinux application.
+Main entry point for Voculinux application.
"""
import argparse
@@ -157,11 +157,11 @@ def _dispatch_trigger(command: str) -> int:
from .dbus_service import send_command
if send_command(command):
- logger.info("Sent '%s' command to running Vocalinux instance", command)
+ logger.info("Sent '%s' command to running Voculinux instance", command)
return 0
logger.error(
- "Could not reach a running Vocalinux instance to '%s'. Is Vocalinux running?",
+ "Could not reach a running Voculinux instance to '%s'. Is Voculinux running?",
command,
)
return 1
@@ -257,7 +257,7 @@ def check_dependencies():
)
logger.error("")
logger.error(
- "For pipx users: Install system packages BEFORE running 'pipx install vocalinux'"
+ "For pipx users: Install system packages BEFORE running 'pipx install voculinux'"
)
logger.error("")
logger.error("For the best experience, use the recommended installer:")
@@ -304,12 +304,12 @@ def check_display_available():
display = Gdk.Display.get_default()
if display is None:
- logger.error("No display available. Vocalinux requires a graphical environment.")
+ logger.error("No display available. Voculinux requires a graphical environment.")
logger.error("")
logger.error("If running remotely, ensure DISPLAY is set:")
logger.error(" export DISPLAY=:0")
logger.error("")
- logger.error("If running in a headless environment, Vocalinux cannot run.")
+ logger.error("If running in a headless environment, Voculinux cannot run.")
return False
return True
except Exception as e:
@@ -394,9 +394,19 @@ def main():
# Register cleanup to release lock on exit
atexit.register(single_instance.release_lock)
+ # One-time legacy Voculinux import (ticket #18): copies a previous
+ # install's config, dictionary, and portal token into the new locations
+ # before anything reads them. No-op on every later run.
+ try:
+ from .legacy_import import import_legacy_once
+
+ import_legacy_once()
+ except Exception as error:
+ logger.debug("Legacy import skipped: %s", error)
+
# Check dependencies first (before importing GTK-dependent modules)
if not check_dependencies():
- logger.error("Cannot start Vocalinux due to missing dependencies")
+ logger.error("Cannot start Voculinux due to missing dependencies")
sys.exit(1)
# Identity for WM class / AppIndicator title (otherwise shows as main.py)
@@ -574,7 +584,7 @@ def main():
)
# Initialize main components
- logger.info("Initializing Vocalinux...")
+ logger.info("Initializing Voculinux...")
try:
# Initialize speech recognition engine with saved/configured settings
@@ -940,7 +950,7 @@ def main():
# script path mid-queue can never let a later segment overtake an
# earlier one still waiting behind a running script.
post_processing_executor = ThreadPoolExecutor(
- max_workers=1, thread_name_prefix="vocalinux-post-processing"
+ max_workers=1, thread_name_prefix="voculinux-post-processing"
)
# Cleared by the quit hook so a queued or in-flight job drops its
# segment instead of injecting while the injector is being stopped.
@@ -996,7 +1006,7 @@ def main():
logger.exception("Focus probe crashed unexpectedly: %s", exc)
probe_result.put(None)
- threading.Thread(target=probe, daemon=True, name="vocalinux-focus-probe").start()
+ threading.Thread(target=probe, daemon=True, name="voculinux-focus-probe").start()
return probe_result
def _probe_result(
@@ -1374,7 +1384,7 @@ def main():
indicator.run()
except Exception as e:
- logger.error(f"Failed to initialize Vocalinux: {e}")
+ logger.error(f"Failed to initialize Voculinux: {e}")
logger.error("Please check the logs above for more details")
sys.exit(1)
diff --git a/src/vocalinux/resources/__init__.py b/src/vocalinux/resources/__init__.py
index edc7523..4a6b488 100644
--- a/src/vocalinux/resources/__init__.py
+++ b/src/vocalinux/resources/__init__.py
@@ -1 +1 @@
-"""Bundled resources (icons, sounds) for Vocalinux."""
+"""Bundled resources (icons, sounds) for Voculinux."""
diff --git a/src/vocalinux/resources/icons/scalable/vocalinux-microphone-off.svg b/src/vocalinux/resources/icons/scalable/voculinux-microphone-off.svg
similarity index 93%
rename from src/vocalinux/resources/icons/scalable/vocalinux-microphone-off.svg
rename to src/vocalinux/resources/icons/scalable/voculinux-microphone-off.svg
index 826e120..7792b28 100644
--- a/src/vocalinux/resources/icons/scalable/vocalinux-microphone-off.svg
+++ b/src/vocalinux/resources/icons/scalable/voculinux-microphone-off.svg
@@ -1,4 +1,4 @@
-
+
diff --git a/resources/icons/scalable/vocalinux-microphone-process.svg b/src/vocalinux/resources/icons/scalable/voculinux-microphone-process.svg
similarity index 93%
rename from resources/icons/scalable/vocalinux-microphone-process.svg
rename to src/vocalinux/resources/icons/scalable/voculinux-microphone-process.svg
index 7b9d9c3..9f11044 100644
--- a/resources/icons/scalable/vocalinux-microphone-process.svg
+++ b/src/vocalinux/resources/icons/scalable/voculinux-microphone-process.svg
@@ -1,4 +1,4 @@
-
+
diff --git a/resources/icons/scalable/vocalinux-microphone.svg b/src/vocalinux/resources/icons/scalable/voculinux-microphone.svg
similarity index 93%
rename from resources/icons/scalable/vocalinux-microphone.svg
rename to src/vocalinux/resources/icons/scalable/voculinux-microphone.svg
index 4a9a4dd..48e136d 100644
--- a/resources/icons/scalable/vocalinux-microphone.svg
+++ b/src/vocalinux/resources/icons/scalable/voculinux-microphone.svg
@@ -1,4 +1,4 @@
-
+
diff --git a/packaging/aur/vocalinux-bin/vocalinux.svg b/src/vocalinux/resources/icons/scalable/voculinux.svg
similarity index 93%
rename from packaging/aur/vocalinux-bin/vocalinux.svg
rename to src/vocalinux/resources/icons/scalable/voculinux.svg
index 5b522ea..7f8ffb0 100644
--- a/packaging/aur/vocalinux-bin/vocalinux.svg
+++ b/src/vocalinux/resources/icons/scalable/voculinux.svg
@@ -1,4 +1,4 @@
-
+
diff --git a/src/vocalinux/single_instance.py b/src/vocalinux/single_instance.py
index 5b2a7e2..3dc0325 100644
--- a/src/vocalinux/single_instance.py
+++ b/src/vocalinux/single_instance.py
@@ -1,5 +1,5 @@
"""
-Single instance enforcement for Vocalinux.
+Single instance enforcement for Voculinux.
Uses file locking to ensure only one instance runs at a time.
Works across sessions and handles stale locks from crashed processes.
@@ -16,7 +16,7 @@ from .utils.paths import data_dir
logger = logging.getLogger(__name__)
-# Lock file location: $XDG_DATA_HOME/vocalinux/ (defaults to ~/.local/share/vocalinux/)
+# Lock file location: $XDG_DATA_HOME/voculinux/ (defaults to ~/.local/share/voculinux/)
LOCK_FILE_DIR = Path(data_dir())
LOCK_FILE_PATH = LOCK_FILE_DIR / "instance.lock"
@@ -61,8 +61,8 @@ def acquire_lock() -> bool:
fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
except (OSError, IOError):
# Lock is held by another process
- logger.warning("Another instance of Vocalinux is already running. Exiting.")
- print("Another instance of Vocalinux is already running.", file=sys.stderr)
+ logger.warning("Another instance of Voculinux is already running. Exiting.")
+ print("Another instance of Voculinux is already running.", file=sys.stderr)
print(
f"If you're sure no other instance is running, delete: {LOCK_FILE_PATH}",
file=sys.stderr,
diff --git a/src/vocalinux/speech_recognition/__init__.py b/src/vocalinux/speech_recognition/__init__.py
index 6181e97..b347067 100644
--- a/src/vocalinux/speech_recognition/__init__.py
+++ b/src/vocalinux/speech_recognition/__init__.py
@@ -1,5 +1,5 @@
"""
-Speech recognition module for Vocalinux
+Speech recognition module for Voculinux
"""
from . import command_processor, recognition_manager # noqa: F401
diff --git a/src/vocalinux/speech_recognition/command_processor.py b/src/vocalinux/speech_recognition/command_processor.py
index d8d61e0..f9e9ae2 100644
--- a/src/vocalinux/speech_recognition/command_processor.py
+++ b/src/vocalinux/speech_recognition/command_processor.py
@@ -1,5 +1,5 @@
"""
-Command processor for Vocalinux.
+Command processor for Voculinux.
This module processes text commands from speech recognition, such as
"new line", "period", etc.
diff --git a/src/vocalinux/speech_recognition/engines/__init__.py b/src/vocalinux/speech_recognition/engines/__init__.py
index 80f0c99..08fb9ad 100644
--- a/src/vocalinux/speech_recognition/engines/__init__.py
+++ b/src/vocalinux/speech_recognition/engines/__init__.py
@@ -1,4 +1,4 @@
-"""Speech recognition engine registry for Vocalinux.
+"""Speech recognition engine registry for Voculinux.
New engine implementations are registered here so the recognition manager can
discover them without hard-coding every backend.
diff --git a/src/vocalinux/speech_recognition/engines/faster_whisper_engine.py b/src/vocalinux/speech_recognition/engines/faster_whisper_engine.py
index 9941d4a..49e9d8c 100644
--- a/src/vocalinux/speech_recognition/engines/faster_whisper_engine.py
+++ b/src/vocalinux/speech_recognition/engines/faster_whisper_engine.py
@@ -1,4 +1,4 @@
-"""Faster-Whisper speech recognition engine for Vocalinux.
+"""Faster-Whisper speech recognition engine for Voculinux.
This module wraps `faster_whisper.WhisperModel` behind the Engine Protocol. It
reuses the same audio preprocessing used by the OpenAI Whisper backend and is
@@ -123,7 +123,7 @@ class FasterWhisperEngine:
self._model_initialized = False
def _normalize_language(self, language: Optional[str] = None) -> Optional[str]:
- """Map Vocalinux language codes to faster-whisper language codes."""
+ """Map Voculinux language codes to faster-whisper language codes."""
language = self.language if language is None else language
if language == "auto":
return None
diff --git a/src/vocalinux/speech_recognition/recognition_manager.py b/src/vocalinux/speech_recognition/recognition_manager.py
index 0fac4f8..facb095 100644
--- a/src/vocalinux/speech_recognition/recognition_manager.py
+++ b/src/vocalinux/speech_recognition/recognition_manager.py
@@ -1,5 +1,5 @@
"""
-Speech recognition manager module for Vocalinux.
+Speech recognition manager module for Voculinux.
This module provides a unified interface to different speech recognition engines,
currently supporting VOSK, Whisper, and whisper.cpp.
@@ -179,7 +179,7 @@ def _pywhispercpp_distribution_version() -> Optional[tuple[int, ...]]:
AUR ``python-pywhispercpp-{cpu,cuda,rocm}`` are still 1.4.x. Those wheels
advertise ``context_params`` on ``Model.__init__`` then setattr it onto
``whisper_full_params``, which raises AttributeError (AUR comments on
- vocalinux, GitHub #625).
+ voculinux, GitHub #625).
"""
try:
from importlib.metadata import version as pkg_version
@@ -585,7 +585,7 @@ class SpeechRecognitionManager:
if self._silero_vad is not None:
logger.info("Using Silero neural VAD")
else:
- logger.info("Using amplitude-based VAD (install vocalinux[vad] for neural VAD)")
+ logger.info("Using amplitude-based VAD (install voculinux[vad] for neural VAD)")
# Audio device selection (None means use system default)
self.audio_device_index = kwargs.get("audio_device_index", None)
@@ -951,7 +951,7 @@ class SpeechRecognitionManager:
play_error_sound()
_show_notification(
"Language Shortcut Unavailable",
- f"Vocalinux cannot dictate in {language} with the loaded model. "
+ f"Voculinux cannot dictate in {language} with the loaded model. "
"Choose a multilingual model in Settings to use this shortcut.",
"dialog-warning",
)
@@ -1078,7 +1078,7 @@ class SpeechRecognitionManager:
# Check if this is a pre-installed model
if any(self.vosk_model_path.startswith(sys_dir) for sys_dir in SYSTEM_MODELS_DIRS):
logger.info(f"Using pre-installed VOSK model from {self.vosk_model_path}")
- elif os.path.exists(os.path.join(self.vosk_model_path, ".vocalinux_preinstalled")):
+ elif os.path.exists(os.path.join(self.vosk_model_path, ".voculinux_preinstalled")):
logger.info(f"Using installer-provided VOSK model from {self.vosk_model_path}")
else:
logger.info(f"Using existing VOSK model from {self.vosk_model_path}")
@@ -1136,7 +1136,7 @@ class SpeechRecognitionManager:
available here is comparing the model's on-disk footprint against
currently available memory before calling into the native loader
(issue #676: this spike killed the process via the kernel OOM
- killer on a 16GB machine, with no exception Vocalinux could catch).
+ killer on a 16GB machine, with no exception Voculinux could catch).
"""
import psutil
@@ -1203,7 +1203,7 @@ class SpeechRecognitionManager:
self.model = None
# load_model() verifies the checkpoint against the sha256 in its URL,
- # for a file already on disk as well as a fresh download, so Vocalinux
+ # for a file already on disk as well as a fresh download, so Voculinux
# never hashes Whisper checkpoints itself.
self.model = whisper.load_model(
self.model_size, device=device, download_root=whisper_cache_dir
@@ -1858,7 +1858,7 @@ class SpeechRecognitionManager:
else:
logger.warning(
"pywhispercpp is Vulkan-backed but vulkaninfo found no devices. "
- "Install vulkan-tools so Vocalinux can pick a discrete GPU. "
+ "Install vulkan-tools so Voculinux can pick a discrete GPU. "
"whisper.cpp will default to GPU 0, which may be an iGPU on hybrid laptops."
)
elif host_backend != ComputeBackend.CPU:
@@ -1986,7 +1986,7 @@ class SpeechRecognitionManager:
logger.warning(f"Vulkan GPU initialization failed: {error}. Falling back to CPU backend.")
_show_notification(
- "Vocalinux: GPU Fallback",
+ "Voculinux: GPU Fallback",
"Your GPU doesn't support whisper.cpp Vulkan.\n" "Switched to CPU mode - still fast!",
"dialog-information",
)
@@ -2573,7 +2573,7 @@ class SpeechRecognitionManager:
"""Extract transcript text from OpenAI-compatible ASR responses.
FunASR/SenseVoice wrappers may include extra metadata or segment arrays.
- Vocalinux only injects the transcript text and ignores the metadata.
+ Voculinux only injects the transcript text and ignores the metadata.
"""
if payload is None:
return ""
@@ -2686,7 +2686,7 @@ class SpeechRecognitionManager:
url,
stream=True,
timeout=self._MODEL_DOWNLOAD_TIMEOUT,
- headers={"User-Agent": f"vocalinux/{__version__}"},
+ headers={"User-Agent": f"voculinux/{__version__}"},
proxies=requests_proxies(),
)
except requests.exceptions.RequestException as e:
@@ -3441,7 +3441,7 @@ class SpeechRecognitionManager:
play_error_sound()
_show_notification(
"Dictation Paused",
- "Vocalinux is paused because a listed game or app is running. "
+ "Voculinux is paused because a listed game or app is running. "
"Close that app or remove it from Auto-Pause settings to resume.",
"dialog-information",
)
@@ -3457,7 +3457,7 @@ class SpeechRecognitionManager:
play_error_sound()
_show_notification(
"Model Reload Failed",
- "Vocalinux could not reload the speech model. "
+ "Voculinux could not reload the speech model. "
"Open Settings to check your engine and try again.",
"dialog-warning",
)
diff --git a/src/vocalinux/speech_recognition/silero_vad.py b/src/vocalinux/speech_recognition/silero_vad.py
index 0d526af..b2ddbbb 100644
--- a/src/vocalinux/speech_recognition/silero_vad.py
+++ b/src/vocalinux/speech_recognition/silero_vad.py
@@ -1,5 +1,5 @@
"""
-Silero VAD wrapper for Vocalinux.
+Silero VAD wrapper for Voculinux.
Provides neural-network-based Voice Activity Detection using the Silero VAD
ONNX model. Falls back gracefully when onnxruntime is unavailable.
diff --git a/src/vocalinux/suspend_handler.py b/src/vocalinux/suspend_handler.py
index e8aac43..7901efb 100644
--- a/src/vocalinux/suspend_handler.py
+++ b/src/vocalinux/suspend_handler.py
@@ -1,5 +1,5 @@
"""
-Suspend/resume handler for Vocalinux.
+Suspend/resume handler for Voculinux.
Monitors systemd-logind via D-Bus for PrepareForSleep signals and
automatically reinitializes the audio pipeline and speech model
diff --git a/src/vocalinux/text_injection/__init__.py b/src/vocalinux/text_injection/__init__.py
index bb1ab09..c28f028 100644
--- a/src/vocalinux/text_injection/__init__.py
+++ b/src/vocalinux/text_injection/__init__.py
@@ -1,5 +1,5 @@
"""
-Text injection module for Vocalinux
+Text injection module for Voculinux
"""
from . import text_injector # noqa: F401
diff --git a/src/vocalinux/text_injection/focused_window.py b/src/vocalinux/text_injection/focused_window.py
index b0cdacf..7df14a2 100644
--- a/src/vocalinux/text_injection/focused_window.py
+++ b/src/vocalinux/text_injection/focused_window.py
@@ -330,9 +330,9 @@ def focused_xwayland_client_without_ibus() -> bool:
An X11 client only talks to IBus through an input method module that it
loads at startup from GTK_IM_MODULE (GTK), QT_IM_MODULE (Qt) or XMODIFIERS
(XIM). Its toolkit is read from the libraries it has mapped. Without
- one, IBus has no input context for it: the Vocalinux engine still commits
+ one, IBus has no input context for it: the Voculinux engine still commits
and reports success, and the text goes nowhere (#972). The client's own
- environment is read because it can differ from the one Vocalinux runs in.
+ environment is read because it can differ from the one Voculinux runs in.
While a native Wayland client holds focus, XWayland's active window is
unset or a placeholder with no pid and no WM_CLASS, so this returns False.
diff --git a/src/vocalinux/text_injection/ibus_engine.py b/src/vocalinux/text_injection/ibus_engine.py
index 25ad59a..7509e7b 100644
--- a/src/vocalinux/text_injection/ibus_engine.py
+++ b/src/vocalinux/text_injection/ibus_engine.py
@@ -1,8 +1,8 @@
"""
-IBus engine for Vocalinux text injection.
+IBus engine for Voculinux text injection.
This module provides an IBus input method engine that acts as a transparent
-proxy - it passes all keystrokes through normally while allowing Vocalinux
+proxy - it passes all keystrokes through normally while allowing Voculinux
to inject text directly via commit_text().
The engine should be set as the user's default input method. It will:
@@ -28,7 +28,7 @@ from pathlib import Path
from typing import Any, Callable, Mapping, Optional
# Package import when loaded normally; absolute / inline fallbacks when this
-# file is executed by path (Vocalinux start_engine_process / IBus component exec).
+# file is executed by path (Voculinux start_engine_process / IBus component exec).
try:
from ..app_identity import (
APP_NAME,
@@ -57,14 +57,14 @@ except ImportError: # pragma: no cover - exercised via script-path subprocess
except ImportError:
# Last resort: same semantics as the vocalinux.utils originals, except
# that host_env cannot strip a bundle it can no longer import.
- # Identity literals below keep in step with vocalinux/app_identity.py.
- APP_NAME = "Vocalinux"
- COMPONENT_NAME = "org.freedesktop.IBus.Vocalinux"
- ENGINE_DESCRIPTION = "Vocalinux voice dictation (use as default input method)"
- ENGINE_LONGNAME = "Vocalinux"
- ENGINE_NAME = "vocalinux"
- IBUS_DIR_NAME = "vocalinux-ibus"
- IBUS_TEXTDOMAIN = "vocalinux"
+ # Identity literals below keep in step with voculinux/app_identity.py.
+ APP_NAME = "Voculinux"
+ COMPONENT_NAME = "org.freedesktop.IBus.Voculinux"
+ ENGINE_DESCRIPTION = "Voculinux voice dictation (use as default input method)"
+ ENGINE_LONGNAME = "Voculinux"
+ ENGINE_NAME = "voculinux"
+ IBUS_DIR_NAME = "voculinux-ibus"
+ IBUS_TEXTDOMAIN = "voculinux"
def host_env(base: Optional[Mapping[str, str]] = None) -> dict[str, str]:
return dict(os.environ if base is None else base)
@@ -107,9 +107,9 @@ except (ImportError, ValueError) as e:
# File paths for communication ($XDG_DATA_HOME, defaults to ~/.local/share).
# Identity strings come from vocalinux/app_identity.py (see the import above);
# the homepage below is the retained upstream URL, never renamed.
-VOCALINUX_IBUS_DIR = Path(xdg_data_home()) / IBUS_DIR_NAME
-SOCKET_PATH = VOCALINUX_IBUS_DIR / "inject.sock"
-PID_FILE = VOCALINUX_IBUS_DIR / "engine.pid"
+VOCULINUX_IBUS_DIR = Path(xdg_data_home()) / IBUS_DIR_NAME
+SOCKET_PATH = VOCULINUX_IBUS_DIR / "inject.sock"
+PID_FILE = VOCULINUX_IBUS_DIR / "engine.pid"
# Shared metadata used by component XML, --xml output, and runtime registration.
# Kept in one place to prevent drift between the three consumers.
@@ -132,9 +132,9 @@ _COMPONENT_META = {
def ensure_ibus_dir() -> None:
"""Ensure the IBus data directory exists with secure permissions."""
- VOCALINUX_IBUS_DIR.mkdir(parents=True, exist_ok=True)
+ VOCULINUX_IBUS_DIR.mkdir(parents=True, exist_ok=True)
# Secure the directory - only owner can access (prevents socket hijacking)
- VOCALINUX_IBUS_DIR.chmod(0o700)
+ VOCULINUX_IBUS_DIR.chmod(0o700)
def verify_peer_credentials(conn: socket.socket) -> bool:
@@ -365,7 +365,7 @@ def _get_exec_command() -> str:
def is_engine_active() -> bool:
- """Check if the Vocalinux IBus engine is currently active."""
+ """Check if the Voculinux IBus engine is currently active."""
try:
import subprocess
@@ -494,7 +494,7 @@ def get_current_engine_gnome_fallback() -> Optional[str]:
Explicit IBus source IDs are returned directly. XKB source IDs are matched
against registered IBus engines; names such as ``xkb:cn::`` are never
- fabricated because a failed restoration can leave Vocalinux active.
+ fabricated because a failed restoration can leave Voculinux active.
Returns:
A verified IBus engine ID, or None if the current source cannot be
@@ -811,7 +811,7 @@ def sync_xwayland_layout_from_gnome() -> bool:
On GNOME Wayland, Mutter hands XWayland one keymap holding every
configured layout as a group plus all ``xkb-options``; input-source
- switches only move the active group inside it. The Vocalinux engine
+ switches only move the active group inside it. The Voculinux engine
round-trip (``ibus engine xkb:*`` applies a single-layout map) — and any
plain ``setxkbmap -layout X`` — leaves XWayland with a one-group map:
XKB group toggles like ``grp:alt_shift_toggle`` have no second group to
@@ -987,7 +987,7 @@ def switch_engine(engine_name: str) -> bool:
def is_engine_process_running() -> bool:
- """Check if the Vocalinux IBus engine process is running."""
+ """Check if the Voculinux IBus engine process is running."""
try:
if not PID_FILE.exists():
return False
@@ -999,7 +999,7 @@ def is_engine_process_running() -> bool:
cmdline_path = Path(f"/proc/{pid}/cmdline")
if cmdline_path.exists():
cmdline = cmdline_path.read_text()
- return "ibus_engine.py" in cmdline and "vocalinux" in cmdline
+ return "ibus_engine.py" in cmdline and "voculinux" in cmdline
return True # Process exists but can't verify cmdline
except (OSError, ValueError, FileNotFoundError):
# Process doesn't exist or PID file is invalid
@@ -1012,7 +1012,7 @@ def start_engine_process() -> bool:
"""
Start the IBus engine process in the background.
- This should be called by Vocalinux on startup to ensure the engine
+ This should be called by Voculinux on startup to ensure the engine
is running before attempting to switch to it.
Returns:
@@ -1042,7 +1042,7 @@ def start_engine_process() -> bool:
# keeps early import/startup failures visible without SIGPIPE risk if the
# engine keeps running and continues to log after we return.
ensure_ibus_dir()
- stderr_log = VOCALINUX_IBUS_DIR / "engine.stderr.log"
+ stderr_log = VOCULINUX_IBUS_DIR / "engine.stderr.log"
with open(stderr_log, "w", encoding="utf-8") as stderr_fh:
process = subprocess.Popen(
[sys.executable, str(engine_script)],
@@ -1121,7 +1121,7 @@ def stop_engine_process(wait_timeout: float = 2.0) -> None:
cmdline_path = Path(f"/proc/{pid}/cmdline")
if cmdline_path.exists():
cmdline = cmdline_path.read_text()
- if "ibus_engine.py" not in cmdline or "vocalinux" not in cmdline:
+ if "ibus_engine.py" not in cmdline or "voculinux" not in cmdline:
logger.warning(f"PID {pid} is not our engine process, skipping kill")
PID_FILE.unlink()
return
@@ -1163,7 +1163,7 @@ IBusEngineBase: Any = IBus.Engine if IBUS_AVAILABLE else object
class VocalinuxEngine(IBusEngineBase):
"""
- IBus proxy engine for Vocalinux text injection.
+ IBus proxy engine for Voculinux text injection.
This engine acts as a transparent proxy:
- All keyboard input passes through unchanged
@@ -1189,7 +1189,7 @@ class VocalinuxEngine(IBusEngineBase):
_FOCUS_WAIT_TIMEOUT_S: float = 1.0
def __init__(self):
- """Initialize the Vocalinux IBus engine."""
+ """Initialize the Voculinux IBus engine."""
if IBUS_AVAILABLE:
super().__init__()
logger.debug("VocalinuxEngine instance created")
@@ -1382,7 +1382,7 @@ class VocalinuxEngine(IBusEngineBase):
class VocalinuxEngineApplication:
"""
- Application wrapper for running the Vocalinux IBus engine.
+ Application wrapper for running the Voculinux IBus engine.
This is used when the engine is launched by IBus as a separate process.
"""
@@ -1392,7 +1392,7 @@ class VocalinuxEngineApplication:
Args:
exec_by_ibus: True when IBus launched this process (via --ibus flag).
- False when Vocalinux launched it directly.
+ False when Voculinux launched it directly.
"""
if not IBUS_AVAILABLE:
raise RuntimeError("IBus is not available")
@@ -1423,7 +1423,7 @@ class VocalinuxEngineApplication:
logger.error("bus.request_name() failed")
raise RuntimeError("Failed to acquire IBus D-Bus name")
else:
- # Launched by Vocalinux directly — register the full component
+ # Launched by Voculinux directly — register the full component
# so IBus discovers our engine without having launched us.
component = IBus.Component(
name=COMPONENT_NAME,
@@ -1444,10 +1444,10 @@ class VocalinuxEngineApplication:
raise RuntimeError("Failed to register IBus component")
logger.info("Registered component with IBus (standalone mode)")
- logger.info("Vocalinux IBus engine started")
+ logger.info("Voculinux IBus engine started")
# Start the socket server immediately so it's ready for connections
- # even before the engine is activated via `ibus engine vocalinux`
+ # even before the engine is activated via `ibus engine voculinux`
VocalinuxEngine._start_socket_server()
def _on_disconnected(self, bus: "IBus.Bus") -> None:
@@ -1465,10 +1465,10 @@ class IBusTextInjector:
"""
Text injector that uses IBus for text injection.
- This class connects to the Vocalinux IBus engine via Unix socket
+ This class connects to the Voculinux IBus engine via Unix socket
and sends text to be injected. The normal TextInjector warmup path starts
the engine process without selecting it as the user's active IBus engine.
- Each injection temporarily switches to the Vocalinux engine, commits the
+ Each injection temporarily switches to the Voculinux engine, commits the
text, and restores the user's previous engine.
The auto_activate=True path still performs the older eager activation flow
@@ -1499,14 +1499,14 @@ class IBusTextInjector:
"""
Start the IBus engine process without selecting it as the active engine.
- The Vocalinux engine is only needed while committing dictated text. Keeping
+ The Voculinux engine is only needed while committing dictated text. Keeping
the user's normal IBus/XKB engine active preserves dead-key composition and
layout-specific behavior during ordinary typing.
Captures the current engine for shutdown restore only. Injection still
resolves the restore target at commit time so a stale warmup value is not
used mid-session (see #623); shutdown needs a fallback when quit leaves
- Vocalinux selected after a failed inject restore (#558).
+ Voculinux selected after a failed inject restore (#558).
"""
if not is_engine_active():
captured = get_current_engine()
@@ -1538,28 +1538,28 @@ class IBusTextInjector:
f"variant: {self._previous_xkb_layout[1]}, option: {self._previous_xkb_layout[2]}"
)
- # Save current engine and switch to Vocalinux
+ # Save current engine and switch to Voculinux
if not is_engine_active():
self._previous_engine = get_current_engine()
if self._previous_engine:
logger.info(f"Saving current engine: {self._previous_engine}")
- logger.info("Activating Vocalinux IBus engine...")
+ logger.info("Activating Voculinux IBus engine...")
if switch_engine(ENGINE_NAME):
- logger.info("Vocalinux IBus engine activated")
+ logger.info("Voculinux IBus engine activated")
else:
raise IBusSetupError(
- "Failed to activate Vocalinux IBus engine. "
- "Try manually: ibus engine vocalinux"
+ "Failed to activate Voculinux IBus engine. "
+ "Try manually: ibus engine voculinux"
)
self._wait_for_engine_ready()
# Restore the user's XKB layout immediately after engine activation.
- # Switching to the Vocalinux IBus engine can override the system
+ # Switching to the Voculinux IBus engine can override the system
# keyboard layout (e.g. Spanish, French AZERTY) with the engine's
# default layout. Re-applying the captured XKB layout ensures the
- # user's keyboard keeps working correctly while Vocalinux is active.
+ # user's keyboard keeps working correctly while Voculinux is active.
# See issue #292.
if self._previous_xkb_layout:
layout, variant, option = self._previous_xkb_layout
@@ -1598,15 +1598,15 @@ class IBusTextInjector:
delay = min(delay * 2, 2.0)
raise IBusSetupError(
- "Vocalinux IBus engine did not become ready after startup. "
- "Try manually: ibus engine vocalinux"
+ "Voculinux IBus engine did not become ready after startup. "
+ "Try manually: ibus engine voculinux"
)
def stop(self) -> None:
"""
Stop the IBus text injector and restore previous engine and XKB layout.
- Call this when Vocalinux is shutting down. If no valid engine was
+ Call this when Voculinux is shutting down. If no valid engine was
captured before injection (e.g. on GNOME/Wayland with no global IBus
engine), restoration is skipped to avoid switching the user to a
wrong layout (see issue #497).
@@ -1616,12 +1616,12 @@ class IBusTextInjector:
``register_component`` makes IBus run ``check_global_engine()``, which
only searches ``register_engine_list`` and treats XML engines such as
``xkb:es::spa`` as missing, clearing the global engine even when
- Vocalinux was never selected (issue #558).
+ Voculinux was never selected (issue #558).
- Prefer the *live* engine at quit when it is a real non-Vocalinux
+ Prefer the *live* engine at quit when it is a real non-Voculinux
engine, so a user who changed input source after warmup is not
switched back to a stale cache. Fall back to ``_previous_engine`` only
- when the live engine is Vocalinux or unavailable (failed inject restore).
+ when the live engine is Voculinux or unavailable (failed inject restore).
"""
current = get_current_engine()
restore_engine: Optional[str]
@@ -1698,7 +1698,7 @@ class IBusTextInjector:
logger.info(f"Starting IBus text injection: '{text[:20]}...' (length: {len(text)})")
restore_engine: Optional[str] = None
- # Capture before any engine switch. Switching to Vocalinux can override
+ # Capture before any engine switch. Switching to Voculinux can override
# the system XKB map to us; scoped injection must restore it after
# switching back (#292, #664). Empty on Wayland (no-op restore).
captured_xkb = get_current_xkb_layout()
@@ -1716,10 +1716,10 @@ class IBusTextInjector:
# quit does not restore a stale warmup value (Bugbot on #643 / #558).
self._previous_engine = current_engine
logger.debug(
- f"Temporarily activating Vocalinux IBus engine (will restore {current_engine})"
+ f"Temporarily activating Voculinux IBus engine (will restore {current_engine})"
)
if not switch_engine(ENGINE_NAME):
- logger.error("Failed to activate Vocalinux IBus engine for injection")
+ logger.error("Failed to activate Voculinux IBus engine for injection")
return False
# Try injection with bounded retries for transient socket/engine races.
@@ -1752,7 +1752,7 @@ class IBusTextInjector:
logger.error(
"IBus engine socket not found. "
- "Make sure Vocalinux IBus engine is running."
+ "Make sure Voculinux IBus engine is running."
)
return False
diff --git a/src/vocalinux/text_injection/remote_desktop_portal.py b/src/vocalinux/text_injection/remote_desktop_portal.py
index 955def7..29f2889 100644
--- a/src/vocalinux/text_injection/remote_desktop_portal.py
+++ b/src/vocalinux/text_injection/remote_desktop_portal.py
@@ -1,5 +1,5 @@
"""
-RemoteDesktop portal text injection for Vocalinux.
+RemoteDesktop portal text injection for Voculinux.
``org.freedesktop.portal.RemoteDesktop`` is the only key-injection path
Wayland itself sanctions: the compositor's portal backend prompts the user
@@ -325,7 +325,7 @@ class RemoteDesktopPortal:
self._ready.clear()
self._connect_error = None
self._worker = threading.Thread(
- target=self._worker_main, name="vocalinux-portal", daemon=True
+ target=self._worker_main, name="voculinux-portal", daemon=True
)
self._worker.start()
if not self._ready.wait(10):
diff --git a/src/vocalinux/text_injection/text_injector.py b/src/vocalinux/text_injection/text_injector.py
index 23225ae..fc9f178 100644
--- a/src/vocalinux/text_injection/text_injector.py
+++ b/src/vocalinux/text_injection/text_injector.py
@@ -1,5 +1,5 @@
"""
-Text injection module for Vocalinux.
+Text injection module for Voculinux.
This module is responsible for injecting recognized text into the active
application, supporting both X11 and Wayland environments.
@@ -104,7 +104,7 @@ def _kde_wayland_ibus_hint() -> str:
"""Return the KDE Plasma Wayland IBus setup hint."""
return (
"Open System Settings -> Keyboard -> Virtual Keyboard, select "
- "'IBus Wayland', then restart Vocalinux or log out and back in."
+ "'IBus Wayland', then restart Voculinux or log out and back in."
)
@@ -245,7 +245,7 @@ class TextInjector:
"""
Clean up resources and restore previous state.
- Call this when shutting down Vocalinux.
+ Call this when shutting down Voculinux.
"""
with self._state_lock:
if self._ibus_injector:
@@ -318,7 +318,7 @@ class TextInjector:
"weston",
)
- # Backends a user may pin explicitly, via VOCALINUX_FORCE_BACKEND or the
+ # Backends a user may pin explicitly, via VOCULINUX_FORCE_BACKEND or the
# text_injection.backend setting. Named once so the two readers and the two
# "expected ..." messages cannot drift apart as values are added.
_SELECTABLE_BACKENDS = ("ibus", "portal", "wtype", "ydotool", "xdotool")
@@ -534,7 +534,7 @@ class TextInjector:
Host ydotool 0.1.x often works without a daemon; starting one is still
safe when ydotoold is installed. The CLI still needs a writable
/dev/uinput (the v0.18.x GitHub sideload Snap declares the plug:
- ``snap connect vocalinux:uinput``; the Store snap ships neither plug
+ ``snap connect voculinux:uinput``; the Store snap ships neither plug
nor ydotool).
"""
if self._is_ydotoold_running():
@@ -576,7 +576,7 @@ class TextInjector:
@staticmethod
def _forced_backend_setting() -> Optional[str]:
- """``VOCALINUX_FORCE_BACKEND`` as three distinct states.
+ """``VOCULINUX_FORCE_BACKEND`` as three distinct states.
``None`` when the variable is not set, ``"auto"`` when it is explicitly
set to auto, otherwise the backend name. The distinction matters:
@@ -599,7 +599,7 @@ class TextInjector:
if value in TextInjector._SELECTABLE_BACKENDS:
return value
logger.warning(
- "Ignoring unknown VOCALINUX_FORCE_BACKEND=%r (expected %s)",
+ "Ignoring unknown VOCULINUX_FORCE_BACKEND=%r (expected %s)",
value,
TextInjector._accepted_backends_help(),
)
@@ -624,7 +624,7 @@ class TextInjector:
return (
"ydotool cannot open /dev/uinput. The Store snap ships no "
"uinput plug; only the v0.18.x GitHub sideload declares it: "
- "sudo snap connect vocalinux:uinput"
+ "sudo snap connect voculinux:uinput"
)
return (
"ydotool cannot open /dev/uinput. "
@@ -645,7 +645,7 @@ class TextInjector:
@staticmethod
def _forced_backend() -> str:
- """Backend pinned via ``VOCALINUX_FORCE_BACKEND``, or ``"auto"``.
+ """Backend pinned via ``VOCULINUX_FORCE_BACKEND``, or ``"auto"``.
Autodetection has to infer whether IBus commits actually reach the
focused app, and it cannot verify that: ``commit_text()`` reports
@@ -780,7 +780,7 @@ class TextInjector:
used -- and so the environment is parsed once per construction, which
also means a malformed value is reported once rather than per caller.
- ``VOCALINUX_FORCE_BACKEND`` wins so a backend can still be A/B-tested
+ ``VOCULINUX_FORCE_BACKEND`` wins so a backend can still be A/B-tested
for one run without editing (or permanently changing) the user's config.
That includes an explicit ``auto``, which asks for autodetection this run
and so must short-circuit here rather than fall through to the saved pin.
@@ -918,7 +918,7 @@ class TextInjector:
)
)
# Bridging Wayland DEs (GNOME): inject_text() switches to the
- # real vocalinux engine for each commit, so a bare xkb:* baseline is
+ # real voculinux engine for each commit, so a bare xkb:* baseline is
# fine (#501, #504). KDE joins that set only when KWin's Virtual
# Keyboard is confirmed on: a confirmed VK bridge is what makes the
# commits reach apps, and it is also what keeps the #752
@@ -934,7 +934,7 @@ class TextInjector:
# Check if IBus is the active input method (not just installed)
# This is important because IBus may be installed but not being used,
# e.g., when the user has configured ydotool or Fcitx instead.
- # VOCALINUX_FORCE_BACKEND=ibus bypasses the reachability guards below
+ # VOCULINUX_FORCE_BACKEND=ibus bypasses the reachability guards below
# and goes straight to setup.
force_ibus = forced == "ibus"
if not force_ibus and not ibus_active and not wayland_scoped_ibus:
@@ -1278,7 +1278,7 @@ class TextInjector:
return
try:
- # Keep the Vocalinux IBus process warm without selecting it as the
+ # Keep the Voculinux IBus process warm without selecting it as the
# user's active keyboard engine. Activation is scoped to each text
# commit so normal typing keeps layout-specific compose/dead keys.
self._ibus_injector.prepare_engine()
@@ -2778,7 +2778,7 @@ class TextInjector:
def _injection_modifier_wait_seconds(self) -> float:
"""Return the sanitized max seconds to wait for modifiers to release.
- Reads VOCALINUX_INJECT_MODIFIER_WAIT and falls back to the default for
+ Reads VOCULINUX_INJECT_MODIFIER_WAIT and falls back to the default for
anything unusable: a non-numeric value, or a non-finite one. In
particular ``inf`` parses fine and is positive, so without this guard it
would make the wait deadline infinite and block injection forever while a
@@ -2793,7 +2793,7 @@ class TextInjector:
return self._DEFAULT_INJECT_MODIFIER_WAIT
if not math.isfinite(value):
logger.warning(
- "VOCALINUX_INJECT_MODIFIER_WAIT=%r is not a finite number; " "using default %.1fs",
+ "VOCULINUX_INJECT_MODIFIER_WAIT=%r is not a finite number; " "using default %.1fs",
raw,
self._DEFAULT_INJECT_MODIFIER_WAIT,
)
@@ -2805,7 +2805,7 @@ class TextInjector:
Returns immediately if no modifier is held (the common case), so this
adds no latency unless the user is still holding their toggle/PTT
- shortcut. Bounded by VOCALINUX_INJECT_MODIFIER_WAIT seconds (default 1.0;
+ shortcut. Bounded by VOCULINUX_INJECT_MODIFIER_WAIT seconds (default 1.0;
set to 0 to disable). Best-effort: if evdev/permissions are unavailable
it simply proceeds.
"""
diff --git a/src/vocalinux/ui/__init__.py b/src/vocalinux/ui/__init__.py
index 92bf91e..28fcac3 100644
--- a/src/vocalinux/ui/__init__.py
+++ b/src/vocalinux/ui/__init__.py
@@ -1,5 +1,5 @@
"""
-User interface module for Vocalinux
+User interface module for Voculinux
Note: GTK-dependent modules (tray_indicator) are imported lazily to allow
the package to be imported even when GTK/AppIndicator3 typelibs are not available.
diff --git a/src/vocalinux/ui/action_handler.py b/src/vocalinux/ui/action_handler.py
index fc3e477..3e8d1c3 100644
--- a/src/vocalinux/ui/action_handler.py
+++ b/src/vocalinux/ui/action_handler.py
@@ -1,5 +1,5 @@
"""
-Action handler for Vocalinux voice commands.
+Action handler for Voculinux voice commands.
This module handles special voice commands like "delete that", "undo", etc.
"""
diff --git a/src/vocalinux/ui/audio_feedback.py b/src/vocalinux/ui/audio_feedback.py
index 67a64cd..b826ea6 100644
--- a/src/vocalinux/ui/audio_feedback.py
+++ b/src/vocalinux/ui/audio_feedback.py
@@ -1,5 +1,5 @@
"""
-Audio feedback module for Vocalinux.
+Audio feedback module for Voculinux.
This module provides audio feedback for various recognition states.
"""
diff --git a/src/vocalinux/ui/autostart_manager.py b/src/vocalinux/ui/autostart_manager.py
index d660975..21f5fc1 100644
--- a/src/vocalinux/ui/autostart_manager.py
+++ b/src/vocalinux/ui/autostart_manager.py
@@ -1,8 +1,8 @@
"""
-Autostart manager for Vocalinux.
+Autostart manager for Voculinux.
This module handles the creation and removal of the XDG autostart desktop entry
-for automatically starting Vocalinux on login.
+for automatically starting Voculinux on login.
"""
import logging
diff --git a/src/vocalinux/ui/config_manager.py b/src/vocalinux/ui/config_manager.py
index d9f5423..e7e8156 100644
--- a/src/vocalinux/ui/config_manager.py
+++ b/src/vocalinux/ui/config_manager.py
@@ -1,5 +1,5 @@
"""
-Configuration manager for Vocalinux.
+Configuration manager for Voculinux.
This module handles loading, saving, and accessing user preferences.
"""
@@ -152,7 +152,7 @@ DEFAULT_CONFIG = {
"mode": "push_to_talk", # "toggle" or "push_to_talk"
# When True, the internal evdev/pynput listener is not started; activation
# comes in over D-Bus instead (e.g. a KDE Plasma global shortcut running
- # `vocalinux --toggle`). Avoids /dev/input access and the input group.
+ # `voculinux --toggle`). Avoids /dev/input access and the input group.
"disable_internal_hotkey": False,
# Opt-in: forward shortcut key events while still detecting gestures.
"pass_shortcut_to_apps": False,
@@ -201,7 +201,7 @@ DEFAULT_CONFIG = {
"paste_long_text": False, # Faster clipboard paste for long X11 dictations
# Text-injection backend: "auto" autodetects, or pin "ibus"/"wtype"/
# "ydotool"/"xdotool" when autodetection is wrong (#476).
- # VOCALINUX_FORCE_BACKEND overrides this for a single run.
+ # VOCULINUX_FORCE_BACKEND overrides this for a single run.
"backend": "auto",
# Route dictation into the in-app Dictation Pad window instead of
# injecting into other apps — the Wayland-safe fallback (#726).
@@ -210,7 +210,7 @@ DEFAULT_CONFIG = {
"history": {
"enabled": True, # Keep recent dictation snippets in the tray menu
"max_items": 10, # How many snippets to retain
- # Also save snippets to $XDG_DATA_HOME/vocalinux/history.jsonl so they
+ # Also save snippets to $XDG_DATA_HOME/voculinux/history.jsonl so they
# survive restarts. Off by default: dictated text must not silently
# accumulate on disk unless the user asks for it (#758).
"persist": False,
diff --git a/src/vocalinux/ui/dictation_overlay.py b/src/vocalinux/ui/dictation_overlay.py
index 5c5f974..df76250 100644
--- a/src/vocalinux/ui/dictation_overlay.py
+++ b/src/vocalinux/ui/dictation_overlay.py
@@ -1,5 +1,5 @@
"""
-Floating on-screen dictation overlay for Vocalinux.
+Floating on-screen dictation overlay for Voculinux.
Shows a compact glowing indicator while recognition is active so users get a
clear visual cue beyond the system tray icon (similar to SuperWhisper-style
@@ -286,7 +286,7 @@ class DictationOverlay:
Settings unmaps it instead.
The window stays, but the request is passed to ``on_close_request``
- so "Quit" from the dock quits Vocalinux like the tray's Quit (#1028).
+ so "Quit" from the dock quits Voculinux like the tray's Quit (#1028).
"""
if self._on_close_request is None:
logger.info(
diff --git a/src/vocalinux/ui/dictation_pad.py b/src/vocalinux/ui/dictation_pad.py
index 95efd69..08a857f 100644
--- a/src/vocalinux/ui/dictation_pad.py
+++ b/src/vocalinux/ui/dictation_pad.py
@@ -1,5 +1,5 @@
"""
-In-app dictation pad for Vocalinux.
+In-app dictation pad for Voculinux.
A small persistent window with an editable text view that receives dictated
text directly, bypassing cross-application text injection entirely. It is the
@@ -252,7 +252,7 @@ class DictationPad:
self._Gtk = Gtk
window = Gtk.Window(type=Gtk.WindowType.TOPLEVEL)
- window.set_title("Vocalinux Dictation Pad")
+ window.set_title("Voculinux Dictation Pad")
window.set_default_size(_PAD_WIDTH, _PAD_HEIGHT)
# Closing only hides: the pad keeps its buffer for the whole session
# and must not take the app down with it.
diff --git a/src/vocalinux/ui/first_run_dialog.py b/src/vocalinux/ui/first_run_dialog.py
index 4619f7d..9f0394f 100644
--- a/src/vocalinux/ui/first_run_dialog.py
+++ b/src/vocalinux/ui/first_run_dialog.py
@@ -1,5 +1,5 @@
"""
-First-run dialog for Vocalinux.
+First-run dialog for Voculinux.
This module shows a dialog on first run to ask the user about autostart preferences.
"""
@@ -25,7 +25,7 @@ class FirstRunDialog(Gtk.Dialog):
def __init__(self, parent: Optional[Gtk.Window] = None):
super().__init__(
- title="Welcome to Vocalinux",
+ title="Welcome to Voculinux",
transient_for=parent,
flags=Gtk.DialogFlags.MODAL,
)
@@ -52,12 +52,12 @@ class FirstRunDialog(Gtk.Dialog):
box.set_margin_top(24)
box.set_margin_bottom(20)
- title_label = Gtk.Label(label="Welcome to Vocalinux!", use_markup=True)
+ title_label = Gtk.Label(label="Welcome to Voculinux!", use_markup=True)
title_label.set_justify(Gtk.Justification.CENTER)
box.pack_start(title_label, False, False, 0)
description_label = Gtk.Label(
- label="Vocalinux runs from your system tray so you can start and stop voice typing anytime.",
+ label="Voculinux runs from your system tray so you can start and stop voice typing anytime.",
wrap=True,
justify=Gtk.Justification.CENTER,
)
@@ -77,7 +77,7 @@ class FirstRunDialog(Gtk.Dialog):
box.pack_start(quick_guide_label, False, False, 0)
subtitle_label = Gtk.Label(
- label="Would you like Vocalinux to start automatically when you log in?",
+ label="Would you like Voculinux to start automatically when you log in?",
wrap=True,
justify=Gtk.Justification.CENTER,
)
diff --git a/src/vocalinux/ui/keyboard_backends/__init__.py b/src/vocalinux/ui/keyboard_backends/__init__.py
index 1dbb2f6..04c4a92 100644
--- a/src/vocalinux/ui/keyboard_backends/__init__.py
+++ b/src/vocalinux/ui/keyboard_backends/__init__.py
@@ -1,5 +1,5 @@
"""
-Keyboard backend system for Vocalinux.
+Keyboard backend system for Voculinux.
This package provides a modular backend system for global keyboard shortcuts,
supporting multiple platforms and display servers (X11, Wayland).
diff --git a/src/vocalinux/ui/keyboard_backends/evdev_backend.py b/src/vocalinux/ui/keyboard_backends/evdev_backend.py
index cfb023a..bab4bd9 100644
--- a/src/vocalinux/ui/keyboard_backends/evdev_backend.py
+++ b/src/vocalinux/ui/keyboard_backends/evdev_backend.py
@@ -95,9 +95,9 @@ else:
_FORWARDED_EVENT_TYPES = frozenset()
# Suffix on every uinput clone name. ``_open_keyboard_device`` uses it to
-# skip clones (also ones created by other Vocalinux processes), so it must
+# skip clones (also ones created by other Voculinux processes), so it must
# survive the kernel's uinput name-length truncation.
-_CLONE_NAME_SUFFIX = " (vocalinux)"
+_CLONE_NAME_SUFFIX = " (voculinux)"
# Name fragments remapper-created keyboards are known to use. Only a
# fallback for systems where sysfs is unreadable (snap confinement): the
@@ -1234,16 +1234,16 @@ class EvdevDeviceHub:
logger.warning(f"Cannot open {device_path}: {e}")
return False
- # Only Vocalinux's own uinput clones are never monitored — reading
+ # Only Voculinux's own uinput clones are never monitored — reading
# them would loop the events we forwarded straight back in. Clones
- # are matched by their registered device path; the " (vocalinux)"
- # name suffix also covers clones of other Vocalinux processes whose
+ # are matched by their registered device path; the " (voculinux)"
+ # name suffix also covers clones of other Voculinux processes whose
# paths we never registered. Other virtual devices (key remappers,
# accessibility keyboards) ARE monitored: users can bind shortcuts
# to them.
device_name = str(getattr(device, "name", "") or "")
if device_path in self._clone_paths or device_name.endswith(_CLONE_NAME_SUFFIX):
- logger.debug(f"Skipping Vocalinux clone device: {device_path} ({device_name})")
+ logger.debug(f"Skipping Voculinux clone device: {device_path} ({device_name})")
try:
device.close()
except (OSError, IOError, RuntimeError) as e:
@@ -1953,8 +1953,8 @@ class EvdevKeyboardBackend(KeyboardBackend):
return (
"Snap is missing input-device access. "
"Connect once, then restart:\n"
- "sudo snap connect vocalinux:raw-input\n"
- "sudo snap connect vocalinux:hardware-observe"
+ "sudo snap connect voculinux:raw-input\n"
+ "sudo snap connect voculinux:hardware-observe"
)
return (
"Add your user to the 'input' group and log out/in:\n"
@@ -1967,8 +1967,8 @@ class EvdevKeyboardBackend(KeyboardBackend):
if in_snap:
return (
"Snap is missing input-device access. Connect once, then restart:\n"
- "sudo snap connect vocalinux:raw-input\n"
- "sudo snap connect vocalinux:hardware-observe"
+ "sudo snap connect voculinux:raw-input\n"
+ "sudo snap connect voculinux:hardware-observe"
)
try:
@@ -2034,7 +2034,7 @@ class EvdevKeyboardBackend(KeyboardBackend):
- Pure-modifier gestures (``right_alt+right_alt``, ``ctrl+ctrl``):
every event of the configured modifier side(s) is consumed — the
- modifier is reserved for Vocalinux while the listener runs.
+ modifier is reserved for Voculinux while the listener runs.
- Bare function-key shortcuts (``f11``): every event of that key.
- Modifier+key combos (``alt+r``): the main key is consumed only
while the combo owns it (press with all modifiers held, plus the
diff --git a/src/vocalinux/ui/keyboard_shortcuts.py b/src/vocalinux/ui/keyboard_shortcuts.py
index 785b1da..40320fe 100644
--- a/src/vocalinux/ui/keyboard_shortcuts.py
+++ b/src/vocalinux/ui/keyboard_shortcuts.py
@@ -1,5 +1,5 @@
"""
-Keyboard shortcut manager for Vocalinux.
+Keyboard shortcut manager for Voculinux.
This module provides global keyboard shortcut functionality to
start/stop speech recognition with configurable shortcuts.
@@ -101,9 +101,9 @@ class KeyboardShortcutManager:
logger.warning("Keyboard shortcuts need Snap input access")
logger.warning("=" * 60)
logger.warning("Global hotkeys read /dev/input (evdev). Connect once:")
- logger.warning(" sudo snap connect vocalinux:raw-input")
- logger.warning(" sudo snap connect vocalinux:hardware-observe")
- logger.warning("Then restart Vocalinux. Until then, use the system tray.")
+ logger.warning(" sudo snap connect voculinux:raw-input")
+ logger.warning(" sudo snap connect voculinux:hardware-observe")
+ logger.warning("Then restart Voculinux. Until then, use the system tray.")
logger.warning("=" * 60)
return
diff --git a/src/vocalinux/ui/logging_dialog.py b/src/vocalinux/ui/logging_dialog.py
index 7ee1c36..fc86ef5 100644
--- a/src/vocalinux/ui/logging_dialog.py
+++ b/src/vocalinux/ui/logging_dialog.py
@@ -1,5 +1,5 @@
"""
-Logging viewer dialog for VocaLinux.
+Logging viewer dialog for Voculinux.
This module provides a GTK dialog for viewing, filtering, and exporting
application logs for debugging purposes.
@@ -722,7 +722,7 @@ class LoggingDialog(Gtk.Dialog):
clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
# Create header for clipboard content
- header = f"VocaLinux Logs - Copied at {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n"
+ header = f"Voculinux Logs - Copied at {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n"
header += "=" * 80 + "\n\n"
# Combine header and content
diff --git a/src/vocalinux/ui/logging_manager.py b/src/vocalinux/ui/logging_manager.py
index 6a8d3bd..7524408 100644
--- a/src/vocalinux/ui/logging_manager.py
+++ b/src/vocalinux/ui/logging_manager.py
@@ -1,5 +1,5 @@
"""
-Logging manager for VocaLinux.
+Logging manager for Voculinux.
This module provides centralized logging functionality with UI integration,
allowing users to view, filter, and export application logs for debugging.
@@ -46,7 +46,7 @@ class LogRecord:
class LoggingManager:
"""
- Centralized logging manager for VocaLinux.
+ Centralized logging manager for Voculinux.
This class captures all application logs, stores them in memory,
and provides functionality for viewing, filtering, and exporting logs.
@@ -64,7 +64,7 @@ class LoggingManager:
self.log_callbacks: list[Callable[[LogRecord], None]] = []
self.lock = threading.Lock()
- # Create logs directory ($XDG_DATA_HOME/vocalinux/logs; Flatpak-safe)
+ # Create logs directory ($XDG_DATA_HOME/voculinux/logs; Flatpak-safe)
self.logs_dir = Path(data_dir()) / "logs"
self.logs_dir.mkdir(parents=True, exist_ok=True)
@@ -178,7 +178,7 @@ class LoggingManager:
records = self.get_logs(level_filter, module_filter)
with open(filepath, "w", encoding="utf-8") as f:
- f.write("VocaLinux Log Export\n")
+ f.write("Voculinux Log Export\n")
f.write(f"Generated: {datetime.now().isoformat()}\n")
f.write(f"Total Records: {len(records)}\n")
if level_filter:
diff --git a/src/vocalinux/ui/settings_about.py b/src/vocalinux/ui/settings_about.py
index e387a7c..d55a3a9 100644
--- a/src/vocalinux/ui/settings_about.py
+++ b/src/vocalinux/ui/settings_about.py
@@ -18,7 +18,7 @@ from ..version import __copyright__, __url__, __version__
logger = logging.getLogger(__name__)
-VOCALINUX_SITE_URL = "https://vocalinux.com"
+VOCULINUX_SITE_URL = "https://voculinux.com"
VOCAHQ_SITE_URL = "https://vocahq.com"
VOCAMAC_SITE_URL = "https://vocamac.com"
VOCAWIN_SITE_URL = "https://vocawin.com"
@@ -33,7 +33,7 @@ VOCAHQ_MAILTO_URL = "mailto:hello@vocahq.com"
# About page links that are not GitHub release URLs.
_ABOUT_OPEN_URLS = frozenset(
{
- VOCALINUX_SITE_URL,
+ VOCULINUX_SITE_URL,
VOCAHQ_SITE_URL,
VOCAMAC_SITE_URL,
VOCAWIN_SITE_URL,
@@ -130,11 +130,11 @@ _VOCAHQ_FAMILY_LINKS = (
"Open vocahq.com",
),
(
- VOCALINUX_SITE_URL,
- "Vocalinux",
+ VOCULINUX_SITE_URL,
+ "Voculinux",
"Linux, available now",
("platform-linux",),
- "Open vocalinux.com",
+ "Open voculinux.com",
),
(
VOCAMAC_SITE_URL,
@@ -306,7 +306,7 @@ class AboutSectionMixin(Gtk.Dialog):
dark = _about_surface_is_dark()
about_icon = None
- logo_path = ResourceManager().get_icon_path("vocalinux")
+ logo_path = ResourceManager().get_icon_path("voculinux")
if os.path.exists(logo_path):
try:
pixbuf = GdkPixbuf.Pixbuf.new_from_file(logo_path)
@@ -317,7 +317,7 @@ class AboutSectionMixin(Gtk.Dialog):
logger.warning("Failed to load About icon: %s", exc)
app_group = PreferencesGroup(
- title="Vocalinux",
+ title="Voculinux",
description=(
"Available now on Linux (X11 and Wayland). After a model is downloaded, "
"speech is processed on this PC."
@@ -331,7 +331,7 @@ class AboutSectionMixin(Gtk.Dialog):
self.about_version_label.get_style_context().add_class("preference-row-subtitle")
version_row = PreferenceRow(
title="Version",
- subtitle="Currently installed Vocalinux build",
+ subtitle="Currently installed Voculinux build",
widget=self.about_version_label,
keywords=("version", "build"),
)
@@ -340,8 +340,8 @@ class AboutSectionMixin(Gtk.Dialog):
link_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=8)
link_box.pack_start(
self._about_open_button(
- VOCALINUX_SITE_URL,
- "Open vocalinux.com website",
+ VOCULINUX_SITE_URL,
+ "Open voculinux.com website",
label="Website",
width=110,
dark=dark,
@@ -353,7 +353,7 @@ class AboutSectionMixin(Gtk.Dialog):
link_box.pack_start(
self._about_open_button(
GITHUB_REPO_URL,
- "Open the Vocalinux GitHub repository",
+ "Open the Voculinux GitHub repository",
label="Source code",
width=120,
dark=dark,
@@ -364,9 +364,9 @@ class AboutSectionMixin(Gtk.Dialog):
)
links_row = PreferenceRow(
title="Open source",
- subtitle="Product site at vocalinux.com, source on GitHub.",
+ subtitle="Product site at voculinux.com, source on GitHub.",
widget=link_box,
- keywords=("website", "vocalinux.com", "github", "source", "repo", "code", "agpl"),
+ keywords=("website", "voculinux.com", "github", "source", "repo", "code", "agpl"),
)
app_group.add_row(links_row)
diff --git a/src/vocalinux/ui/settings_dialog.py b/src/vocalinux/ui/settings_dialog.py
index c33eaf5..ab64f9f 100644
--- a/src/vocalinux/ui/settings_dialog.py
+++ b/src/vocalinux/ui/settings_dialog.py
@@ -1,5 +1,5 @@
"""
-Settings Dialog for Vocalinux.
+Settings Dialog for Voculinux.
Allows users to configure speech recognition engine, model size,
and other relevant parameters.
@@ -156,10 +156,10 @@ from .settings_about import ( # noqa: F401
VOCAHQ_MAILTO_URL,
VOCAHQ_SITE_URL,
VOCAHQ_X_URL,
- VOCALINUX_SITE_URL,
VOCAMAC_SITE_URL,
VOCAPHONE_SITE_URL,
VOCAWIN_SITE_URL,
+ VOCULINUX_SITE_URL,
AboutSectionMixin,
_about_ink_hex,
_about_surface_is_dark,
@@ -2515,7 +2515,7 @@ def _populate_gpu_device_choices(combo: Any, saved_device: Optional[int]) -> Non
class SettingsDialog(AboutSectionMixin):
- """Modern GTK Dialog for configuring Vocalinux settings."""
+ """Modern GTK Dialog for configuring Voculinux settings."""
def __init__(
self,
@@ -3281,7 +3281,7 @@ class SettingsDialog(AboutSectionMixin):
self.autostart_switch = _add_switch_row(
group,
title="Start on Login",
- subtitle="Automatically start Vocalinux when you log in",
+ subtitle="Automatically start Voculinux when you log in",
keywords=("autostart", "boot", "startup"),
)
@@ -3295,7 +3295,7 @@ class SettingsDialog(AboutSectionMixin):
self.missing_tray_warning_switch = Gtk.Switch()
missing_tray_warning_row = PreferenceRow(
title="Warn if tray support is not detected",
- subtitle="Show a warning when Vocalinux cannot detect AppIndicator support",
+ subtitle="Show a warning when Voculinux cannot detect AppIndicator support",
widget=self.missing_tray_warning_switch,
keywords=("tray", "appindicator", "warning"),
)
@@ -3315,7 +3315,7 @@ class SettingsDialog(AboutSectionMixin):
title="Transcription History",
description="Recent dictation snippets are kept in memory and shown "
"in the tray menu. History clears on quit unless Keep on Disk is on, "
- "which saves them to history.jsonl under the Vocalinux data directory.",
+ "which saves them to history.jsonl under the Voculinux data directory.",
)
self.history_enabled_switch = Gtk.Switch()
@@ -3425,7 +3425,7 @@ class SettingsDialog(AboutSectionMixin):
terms_path_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=6)
self.dictionary_terms_path_entry = Gtk.Entry()
self.dictionary_terms_path_entry.set_hexpand(True)
- self.dictionary_terms_path_entry.set_placeholder_text("~/.config/vocalinux/dictionary.txt")
+ self.dictionary_terms_path_entry.set_placeholder_text("~/.config/voculinux/dictionary.txt")
self.dictionary_terms_path_entry.set_tooltip_text(
"UTF-8 line file used for custom terms and the accessibility scanner"
)
@@ -5080,8 +5080,8 @@ class SettingsDialog(AboutSectionMixin):
vad_info_label = Gtk.Label(
label=(
"Neural VAD is more accurate at separating speech from background "
- "noise. To enable it, install onnxruntime and restart Vocalinux:\n"
- ' pip install "vocalinux[vad]"'
+ "noise. To enable it, install onnxruntime and restart Voculinux:\n"
+ ' pip install "voculinux[vad]"'
),
xalign=0,
wrap=True,
@@ -5106,12 +5106,12 @@ class SettingsDialog(AboutSectionMixin):
)
# External activation: drive start/stop from a desktop/compositor global
- # shortcut (bound to `vocalinux --toggle`) instead of the built-in key
+ # shortcut (bound to `voculinux --toggle`) instead of the built-in key
# listener. Avoids reading /dev/input (no keylogging, no `input` group).
self.disable_internal_hotkey_switch = Gtk.Switch()
self.disable_internal_hotkey_switch.set_tooltip_text(
"Turn off the built-in key listener and trigger voice typing from a "
- "desktop global shortcut bound to 'vocalinux --toggle'. Avoids reading "
+ "desktop global shortcut bound to 'voculinux --toggle'. Avoids reading "
"/dev/input (no keylogging, no 'input' group needed)."
)
external_row = PreferenceRow(
@@ -5287,7 +5287,7 @@ class SettingsDialog(AboutSectionMixin):
if disabled:
self.shortcut_info_label.set_text(
"External activation is on: the built-in key listener is off. "
- "Bind a desktop global shortcut to 'vocalinux --toggle' to start/stop."
+ "Bind a desktop global shortcut to 'voculinux --toggle' to start/stop."
)
else:
# Restore the mode-appropriate hint.
@@ -6258,7 +6258,7 @@ class SettingsDialog(AboutSectionMixin):
_style_combo(self.proxy_mode_combo)
_combo_chrome(
self.proxy_mode_combo,
- tooltip="How Vocalinux connects to model hosts and update checks",
+ tooltip="How Voculinux connects to model hosts and update checks",
)
self.proxy_mode_combo.append("off", "Off")
self.proxy_mode_combo.append("system", "System")
@@ -6611,7 +6611,7 @@ class SettingsDialog(AboutSectionMixin):
self.latest_release_row.set_title("Release notes")
self.latest_release_row.set_subtitle("Unavailable")
self.open_release_btn.set_sensitive(True)
- self.open_release_btn.set_tooltip_text("Open the Vocalinux project page")
+ self.open_release_btn.set_tooltip_text("Open the Voculinux project page")
self.open_release_btn.get_style_context().remove_class("suggested-action")
self.release_notes_group.hide()
# Clear dialog pending state so search restore cannot revive the New
@@ -6972,7 +6972,7 @@ class SettingsDialog(AboutSectionMixin):
self.gateway_embed_group.add_row(
PreferenceRow(
title="Remote API preset",
- subtitle="Points Vocalinux at the local gateway",
+ subtitle="Points Voculinux at the local gateway",
widget=self.gateway_use_btn,
)
)
@@ -9390,7 +9390,7 @@ class SettingsDialog(AboutSectionMixin):
threading.Thread(
target=cancel_test,
daemon=True,
- name="vocalinux-test-dictation-cancel",
+ name="voculinux-test-dictation-cancel",
).start()
def _finish_test_after_user_cancel(self) -> bool:
@@ -9464,7 +9464,7 @@ class SettingsDialog(AboutSectionMixin):
threading.Thread(
target=stop_test,
daemon=True,
- name="vocalinux-test-dictation-stop",
+ name="voculinux-test-dictation-stop",
).start()
self._test_idle_wait_ticks = 0
@@ -9526,7 +9526,7 @@ class SettingsDialog(AboutSectionMixin):
threading.Thread(
target=self._cancel_buffered_reload_then_restore,
daemon=True,
- name="vocalinux-test-dictation-cancel",
+ name="voculinux-test-dictation-cancel",
).start()
return False
diff --git a/src/vocalinux/ui/transcript_dialog.py b/src/vocalinux/ui/transcript_dialog.py
index 10709d4..08eb361 100644
--- a/src/vocalinux/ui/transcript_dialog.py
+++ b/src/vocalinux/ui/transcript_dialog.py
@@ -1,5 +1,5 @@
"""
-Diarized transcript dialog for VocaLinux.
+Diarized transcript dialog for Voculinux.
Shows the speaker-attributed transcript produced by the "Transcribe audio
file" flow (TinyDiarize tdrz output via diarization.py) with copy and
diff --git a/src/vocalinux/ui/transcription_history.py b/src/vocalinux/ui/transcription_history.py
index a062a91..0212853 100644
--- a/src/vocalinux/ui/transcription_history.py
+++ b/src/vocalinux/ui/transcription_history.py
@@ -1,4 +1,4 @@
-"""Recent-transcription history for Vocalinux.
+"""Recent-transcription history for Voculinux.
Keeps a bounded, newest-first list of recent dictation snippets so the user
can review and re-copy recent voice input from the tray menu.
@@ -11,7 +11,7 @@ in a file.
Users who want transcripts to survive restarts can opt in via
``history.persist`` in config.json. Each snippet is then stored as one JSON
-object per line in a ``history.jsonl`` file under the Vocalinux data
+object per line in a ``history.jsonl`` file under the Voculinux data
directory — timestamped, with the session's duration, language, and model
recorded when the pipeline reported them — and the file is rewritten on
every change so it always mirrors the in-memory list. Turning persistence
diff --git a/src/vocalinux/ui/tray_indicator.py b/src/vocalinux/ui/tray_indicator.py
index 19cdd59..134acda 100644
--- a/src/vocalinux/ui/tray_indicator.py
+++ b/src/vocalinux/ui/tray_indicator.py
@@ -1,5 +1,5 @@
"""
-System tray indicator module for Vocalinux.
+System tray indicator module for Voculinux.
This module provides a system tray indicator for controlling the speech
recognition process and displaying its status.
@@ -158,7 +158,7 @@ _FALLBACK_KEYBOARD_RESTART_SECONDS = 6
class TrayIndicator:
"""
- System tray indicator for Vocalinux.
+ System tray indicator for Voculinux.
This class provides a system tray icon with a menu for controlling
the speech recognition process.
@@ -258,7 +258,7 @@ class TrayIndicator:
# Prefer absolute icon paths outside Flatpak. StatusNotifier hosts often
# resolve IconName via the system hicolor theme and ignore IconThemePath,
- # so a stale ~/.local/share/icons copy of vocalinux-microphone-off.svg
+ # so a stale ~/.local/share/icons copy of voculinux-microphone-off.svg
# (the old red placeholder) would win over the AppImage's bundled icons.
self._icon_keys = {
"default": (self.icon_names["default"] if FLATPAK_ID else self.icon_paths["default"]),
@@ -340,7 +340,7 @@ class TrayIndicator:
self._setup_keyboard_shortcuts()
# Register the session-bus service so external triggers (e.g. a KDE
- # Plasma global shortcut running `vocalinux --toggle`) can control this
+ # Plasma global shortcut running `voculinux --toggle`) can control this
# running instance. Handlers marshal onto the GTK main thread.
self._dbus_service = VocalinuxDBusService(
on_toggle=self._toggle_recognition,
@@ -379,7 +379,7 @@ class TrayIndicator:
)
notifications.notify(
"External activation unavailable",
- "The D-Bus service could not start, so Vocalinux is using the "
+ "The D-Bus service could not start, so Voculinux is using the "
"internal keyboard shortcut instead. Check Settings -> Shortcuts.",
"dialog-warning",
)
@@ -721,7 +721,7 @@ class TrayIndicator:
text="System tray icon may not appear",
)
dialog.format_secondary_text(
- "Vocalinux could not detect AppIndicator support in your desktop environment.\n"
+ "Voculinux could not detect AppIndicator support in your desktop environment.\n"
"\n"
"If you are using GNOME Shell, install the AppIndicator extension:\n"
" sudo apt install gnome-shell-extension-appindicator\n"
@@ -861,7 +861,7 @@ class TrayIndicator:
"""Start recognition for an external (D-Bus) trigger.
Uses normal start semantics — not push-to-talk — so a single
- `vocalinux --start` transcribes immediately/with silence detection
+ `voculinux --start` transcribes immediately/with silence detection
rather than deferring until a Stop.
"""
with self._ptt_lock:
@@ -1071,7 +1071,7 @@ class TrayIndicator:
title = "Speech model downloaded"
body = (
f"{recommendation.display_name} is installed. "
- "Dictation will be available when Vocalinux resumes."
+ "Dictation will be available when Voculinux resumes."
)
else:
shortcut = self.config_manager.get_str(
diff --git a/src/vocalinux/utils/__init__.py b/src/vocalinux/utils/__init__.py
index b0be24e..f166609 100644
--- a/src/vocalinux/utils/__init__.py
+++ b/src/vocalinux/utils/__init__.py
@@ -1,5 +1,5 @@
"""
-Utility modules for Vocalinux.
+Utility modules for Voculinux.
"""
from .resource_manager import ResourceManager
diff --git a/src/vocalinux/utils/faster_whisper_model_info.py b/src/vocalinux/utils/faster_whisper_model_info.py
index 188f97a..414ff2e 100644
--- a/src/vocalinux/utils/faster_whisper_model_info.py
+++ b/src/vocalinux/utils/faster_whisper_model_info.py
@@ -1,4 +1,4 @@
-"""Faster-Whisper model information for Vocalinux.
+"""Faster-Whisper model information for Voculinux.
Metadata and checksum-gated download URLs for the optional faster-whisper
backend (CTranslate2). Bundles are stored under ``models_dir()/faster_whisper/``
diff --git a/src/vocalinux/utils/host_process.py b/src/vocalinux/utils/host_process.py
index 94e78ad..fee3059 100644
--- a/src/vocalinux/utils/host_process.py
+++ b/src/vocalinux/utils/host_process.py
@@ -1,4 +1,4 @@
-"""Environment for the host binaries Vocalinux shells out to.
+"""Environment for the host binaries Voculinux shells out to.
An AppImage puts its own libraries first on ``LD_LIBRARY_PATH``, and every child
process inherits that. A host tool linked against a newer GLib than the bundle
diff --git a/src/vocalinux/utils/model_checksums.py b/src/vocalinux/utils/model_checksums.py
index 6fa3a7e..3665776 100644
--- a/src/vocalinux/utils/model_checksums.py
+++ b/src/vocalinux/utils/model_checksums.py
@@ -1,6 +1,6 @@
"""Integrity verification for downloaded speech models.
-Vocalinux pulls 40MB-2GB model files from Hugging Face, Alphacephei and
+Voculinux pulls 40MB-2GB model files from Hugging Face, Alphacephei and
openaipublic.azureedge.net, then feeds them to native code -- whisper.cpp maps
its ggml files through ``ctypes.cdll``. A tampered or truncated model is
therefore not merely a bad transcription, so every download is checked against a
@@ -16,7 +16,7 @@ pins nothing they could not change alongside it). Regenerate it with
OpenAI Whisper ``.pt`` checkpoints are absent from it: ``openai-whisper``
downloads and verifies those itself, against the sha256 it reads out of the URL
-path, so Vocalinux neither fetches nor hashes them. ``install.sh`` does preinstall
+path, so Voculinux neither fetches nor hashes them. ``install.sh`` does preinstall
the tiny checkpoint, and verifies it there with its own bash implementation.
Verification fails closed: a file with no pinned digest is an error, not a
@@ -44,7 +44,7 @@ _MANIFEST_NAME = "model_checksums.txt"
# came out of. A directory has no hash of its own and the zip is deleted after
# unpacking, so this file is the only evidence the tree was ever verified.
# install.sh reads it under the same name; keep the two in step.
-# (Name itself lives in vocalinux/app_identity.py so the rename flips it once.)
+# (Name itself lives in voculinux/app_identity.py so the rename flips it once.)
# Hash of a 2GB model read in one go would sit in RAM; stream it instead.
_CHUNK_SIZE = 1024 * 1024
diff --git a/src/vocalinux/utils/model_checksums.txt b/src/vocalinux/utils/model_checksums.txt
index 459e4d2..1c566c1 100644
--- a/src/vocalinux/utils/model_checksums.txt
+++ b/src/vocalinux/utils/model_checksums.txt
@@ -1,4 +1,4 @@
-# Checksums for every speech model Vocalinux downloads.
+# Checksums for every speech model Voculinux downloads.
#
# Generated by scripts/generate-model-checksums.py -- do not edit by hand.
# Regenerate with `just model-checksums` after adding a model to
diff --git a/src/vocalinux/utils/parakeet_model_info.py b/src/vocalinux/utils/parakeet_model_info.py
index 40e0035..2894d0c 100644
--- a/src/vocalinux/utils/parakeet_model_info.py
+++ b/src/vocalinux/utils/parakeet_model_info.py
@@ -1,5 +1,5 @@
"""
-Parakeet model information for Vocalinux.
+Parakeet model information for Voculinux.
This module provides model metadata and download URLs for the Parakeet
engine, which runs NVIDIA NeMo ASR models through sherpa-onnx.
diff --git a/src/vocalinux/utils/paths.py b/src/vocalinux/utils/paths.py
index dcf09af..2415729 100644
--- a/src/vocalinux/utils/paths.py
+++ b/src/vocalinux/utils/paths.py
@@ -16,12 +16,12 @@ def xdg_data_home() -> str:
def config_dir() -> str:
- """Return the Vocalinux configuration directory."""
+ """Return the Voculinux configuration directory."""
return os.path.join(xdg_config_home(), APP_DIR_NAME)
def data_dir() -> str:
- """Return the Vocalinux data directory."""
+ """Return the Voculinux data directory."""
return os.path.join(xdg_data_home(), APP_DIR_NAME)
diff --git a/src/vocalinux/utils/proxy.py b/src/vocalinux/utils/proxy.py
index 07a4da3..671cf09 100644
--- a/src/vocalinux/utils/proxy.py
+++ b/src/vocalinux/utils/proxy.py
@@ -1,4 +1,4 @@
-"""Outbound-proxy configuration shared by Vocalinux network calls.
+"""Outbound-proxy configuration shared by Voculinux network calls.
Model downloads and update checks read the ``proxy`` section of config.json
through this module so every outbound path honors the same setting:
diff --git a/src/vocalinux/utils/resource_manager.py b/src/vocalinux/utils/resource_manager.py
index 566b3c1..f1a06bb 100644
--- a/src/vocalinux/utils/resource_manager.py
+++ b/src/vocalinux/utils/resource_manager.py
@@ -1,5 +1,5 @@
"""
-Centralized resource manager for Vocalinux.
+Centralized resource manager for Voculinux.
This module provides a unified way to locate and access application resources
like icons, sounds, and other assets regardless of how the application is installed.
diff --git a/src/vocalinux/utils/snap.py b/src/vocalinux/utils/snap.py
index 4c3245c..f7803a8 100644
--- a/src/vocalinux/utils/snap.py
+++ b/src/vocalinux/utils/snap.py
@@ -17,6 +17,6 @@ SNAP_GPU_NOTE = (
def running_in_snap(environ: Optional[Mapping[str, str]] = None) -> bool:
- """Whether this process runs inside the Vocalinux snap."""
+ """Whether this process runs inside the Voculinux snap."""
env = os.environ if environ is None else environ
return bool(env.get("SNAP_NAME") or env.get("SNAP"))
diff --git a/src/vocalinux/utils/update_checker.py b/src/vocalinux/utils/update_checker.py
index 5cb7816..38724f7 100644
--- a/src/vocalinux/utils/update_checker.py
+++ b/src/vocalinux/utils/update_checker.py
@@ -1,4 +1,4 @@
-"""Check GitHub Releases for newer Vocalinux versions."""
+"""Check GitHub Releases for newer Voculinux versions."""
import logging
import re
@@ -140,16 +140,16 @@ def is_update_available(
# github.com/jatinkrmalik/vocalinux redirects here after the org transfer.
-_VOCALINUX_GITHUB_OWNERS = frozenset({"VocaHQ", "jatinkrmalik"})
+_VOCULINUX_GITHUB_OWNERS = frozenset({"VocaHQ", "jatinkrmalik"})
def _trusted_path_prefixes(repo_url: str = __url__) -> tuple[str, ...]:
"""Return GitHub path prefixes that belong to this project."""
owner, repo = _repo_parts(repo_url)
prefixes = [f"/{owner}/{repo}"]
- known_owners = {name.casefold() for name in _VOCALINUX_GITHUB_OWNERS}
+ known_owners = {name.casefold() for name in _VOCULINUX_GITHUB_OWNERS}
if repo.casefold() == "vocalinux" and owner.casefold() in known_owners:
- prefixes.extend(f"/{name}/vocalinux" for name in sorted(_VOCALINUX_GITHUB_OWNERS))
+ prefixes.extend(f"/{name}/vocalinux" for name in sorted(_VOCULINUX_GITHUB_OWNERS))
seen: set[str] = set()
unique: list[str] = []
for prefix in prefixes:
diff --git a/src/vocalinux/utils/update_monitor.py b/src/vocalinux/utils/update_monitor.py
index c43a826..6663be3 100644
--- a/src/vocalinux/utils/update_monitor.py
+++ b/src/vocalinux/utils/update_monitor.py
@@ -1,4 +1,4 @@
-"""Background GitHub release checks for Vocalinux.
+"""Background GitHub release checks for Voculinux.
Schedules a delayed first check, then repeats on an interval. Networking runs on
a worker thread; the result callback is delivered on the GLib main loop.
@@ -132,7 +132,7 @@ class UpdateMonitor:
target=self._worker,
args=(channel, __version__, generation),
daemon=True,
- name="vocalinux-update-check",
+ name="voculinux-update-check",
).start()
def _worker(self, channel: str, current: str, generation: int) -> None:
diff --git a/src/vocalinux/utils/whisper_model_info.py b/src/vocalinux/utils/whisper_model_info.py
index 498b0f2..9556cd7 100644
--- a/src/vocalinux/utils/whisper_model_info.py
+++ b/src/vocalinux/utils/whisper_model_info.py
@@ -44,7 +44,7 @@ def whisper_model_file(model_size: str) -> str:
def migrate_legacy_checkpoint_names(cache_dir: str) -> list[str]:
"""Rename checkpoints saved under the old f"{size}.pt" name. Returns the new names.
- Vocalinux's own downloader used to name every checkpoint after the catalog
+ Voculinux's own downloader used to name every checkpoint after the catalog
entry, which is wrong wherever upstream publishes a versioned file: "large"
is stored as large-v3.pt. A file left under the old name is invisible three
times over. load_model() looks for the upstream name and refetches 2.9GB,
diff --git a/src/vocalinux/utils/whispercpp_model_info.py b/src/vocalinux/utils/whispercpp_model_info.py
index 4e59ec9..6b12ab2 100644
--- a/src/vocalinux/utils/whispercpp_model_info.py
+++ b/src/vocalinux/utils/whispercpp_model_info.py
@@ -1,5 +1,5 @@
"""
-Whisper.cpp model information and hardware detection for Vocalinux.
+Whisper.cpp model information and hardware detection for Voculinux.
This module provides model metadata and hardware acceleration detection
for whisper.cpp, supporting Vulkan, CUDA, and CPU backends.
diff --git a/src/vocalinux/version.py b/src/vocalinux/version.py
index 22e8e14..55e7a9b 100644
--- a/src/vocalinux/version.py
+++ b/src/vocalinux/version.py
@@ -1,5 +1,5 @@
"""
-Version information for Vocalinux.
+Version information for Voculinux.
"""
__version__ = "0.18.5"
diff --git a/tests/conftest.py b/tests/conftest.py
index 4d4d06e..b1f9d9c 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -19,11 +19,11 @@ import pytest
os.environ["PYTEST_RUNNING"] = "1"
# Isolate the whole test process from the developer's real desktop session
-# and Vocalinux state, mirroring a fresh CI runner:
+# and Voculinux state, mirroring a fresh CI runner:
# * XDG base dirs point at a throwaway directory, so locally downloaded
-# models (~/.local/share/vocalinux/models) and the real config file
+# models (~/.local/share/voculinux/models) and the real config file
# never leak into tests. This must happen at conftest import time:
-# vocalinux modules freeze paths like MODELS_DIR at first import during
+# voculinux modules freeze paths like MODELS_DIR at first import during
# collection, before any fixture could run. The directory is shared for
# the whole session on purpose — some tests rely on directories that
# earlier tests created, exactly as they do on CI with the runner's HOME.
@@ -31,7 +31,7 @@ os.environ["PYTEST_RUNNING"] = "1"
# session flips IBus/keyboard code paths (issue #478) that CI never sees.
# Tests that need specific values set them via patch.dict/monkeypatch, which
# layer on top of this.
-_XDG_ISOLATION_DIR = tempfile.mkdtemp(prefix="vocalinux-pytest-xdg-")
+_XDG_ISOLATION_DIR = tempfile.mkdtemp(prefix="voculinux-pytest-xdg-")
os.environ["XDG_DATA_HOME"] = os.path.join(_XDG_ISOLATION_DIR, "data")
os.environ["XDG_CONFIG_HOME"] = os.path.join(_XDG_ISOLATION_DIR, "config")
os.environ["XDG_CACHE_HOME"] = os.path.join(_XDG_ISOLATION_DIR, "cache")
@@ -53,7 +53,7 @@ try:
except ImportError:
_real_numpy = None
else:
- sys._vocalinux_real_numpy = _real_numpy
+ sys._voculinux_real_numpy = _real_numpy
# And the same for zipfile: test_recognition_manager.py and
# test_recognition_manager_download_buffer.py assign a MagicMock to
@@ -62,7 +62,7 @@ else:
# reachable for the ones that need it.
import zipfile as _real_zipfile # noqa: E402
-sys._vocalinux_real_zipfile = _real_zipfile
+sys._voculinux_real_zipfile = _real_zipfile
# Prevent specific known-blocking daemon threads from starting during tests.
# Source code in ibus_engine.py and evdev_backend.py spawns daemon threads
@@ -105,7 +105,7 @@ sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")
# Always mock GI/GTK modules before any test files are collected.
# On CI, real gi (PyGObject) is installed via "pip install PyGObject" and
-# module-level imports in vocalinux source files (ibus_engine, tray_indicator,
+# module-level imports in voculinux source files (ibus_engine, tray_indicator,
# settings_dialog, etc.) will trigger GTK initialization or IBus daemon
# connections that hang indefinitely in headless environments.
# pytest-timeout cannot interrupt these C-level blocking calls.
diff --git a/tests/distro-testing-checklist.md b/tests/distro-testing-checklist.md
index 5d19be4..59bc2df 100644
--- a/tests/distro-testing-checklist.md
+++ b/tests/distro-testing-checklist.md
@@ -1,6 +1,6 @@
# Distribution Testing Checklist
-Use this checklist when testing Vocalinux on a new Linux distribution.
+Use this checklist when testing Voculinux on a new Linux distribution.
## Pre-Installation
@@ -51,22 +51,22 @@ Use this checklist when testing Vocalinux on a new Linux distribution.
- [ ] Check for errors during installation
- [ ] Verify virtual environment was created
```bash
- ls -la ~/.local/share/vocalinux/venv/
+ ls -la ~/.local/share/voculinux/venv/
```
- [ ] Check wrapper scripts exist
```bash
- ls -la ~/.local/bin/vocalinux*
+ ls -la ~/.local/bin/voculinux*
```
- [ ] Check desktop entry was created
```bash
- ls -la ~/.local/share/applications/vocalinux.desktop
+ ls -la ~/.local/share/applications/voculinux.desktop
```
- [ ] Check icons were installed
```bash
- ls -la ~/.local/share/icons/hicolor/scalable/apps/vocalinux*
+ ls -la ~/.local/share/icons/hicolor/scalable/apps/voculinux*
```
## Post-Installation
@@ -74,7 +74,7 @@ Use this checklist when testing Vocalinux on a new Linux distribution.
### Launch from Terminal
- [ ] Launch from terminal
```bash
- ~/.local/bin/vocalinux-gui
+ ~/.local/bin/voculinux-gui
```
- [ ] Check for startup errors
@@ -154,7 +154,7 @@ Use this checklist when testing Vocalinux on a new Linux distribution.
- [ ] Settings persist after restart
- [ ] Config file is created correctly
```bash
- cat ~/.config/vocalinux/config.json
+ cat ~/.config/voculinux/config.json
```
### Model Download (if using Whisper)
@@ -162,7 +162,7 @@ Use this checklist when testing Vocalinux on a new Linux distribution.
- [ ] Download progress is shown
- [ ] Model is saved to correct location
```bash
- ls -la ~/.local/share/vocalinux/models/
+ ls -la ~/.local/share/voculinux/models/
```
### Error Handling
@@ -179,7 +179,7 @@ Use this checklist when testing Vocalinux on a new Linux distribution.
- [ ] Memory usage is reasonable
```bash
# Check memory usage
- ps aux | grep vocalinux
+ ps aux | grep voculinux
```
- [ ] CPU usage is reasonable during idle
@@ -190,17 +190,17 @@ Use this checklist when testing Vocalinux on a new Linux distribution.
- [ ] Application can be quit cleanly
- [ ] No processes left running
```bash
- ps aux | grep vocalinux
+ ps aux | grep voculinux
```
- [ ] Uninstallation works
```bash
- bash ~/.local/share/vocalinux/uninstall.sh # if exists
+ bash ~/.local/share/voculinux/uninstall.sh # if exists
# or manual cleanup
- rm -rf ~/.local/share/vocalinux
- rm -rf ~/.config/vocalinux
- rm ~/.local/share/applications/vocalinux.desktop
- rm ~/.local/bin/vocalinux*
+ rm -rf ~/.local/share/voculinux
+ rm -rf ~/.config/voculinux
+ rm ~/.local/share/applications/voculinux.desktop
+ rm ~/.local/bin/voculinux*
```
## Known Issues
@@ -262,7 +262,7 @@ After completing the checklist:
3. **Attach logs** if there were errors:
- Installer output
- Application output from terminal
- - Journal logs: `journalctl --user -u vocalinux -b`
+ - Journal logs: `journalctl --user -u voculinux -b`
4. **Mention any workarounds** you found
@@ -293,13 +293,13 @@ pactl list sources short # PulseAudio
arecord -l # ALSA
# Check for running processes
-ps aux | grep vocalinux
+ps aux | grep voculinux
# Check memory usage
-ps aux | grep vocalinux | awk '{print $6}'
+ps aux | grep voculinux | awk '{print $6}'
# Check logs
-journalctl --user -b | grep vocalinux
+journalctl --user -b | grep voculinux
# Run dependency checker
bash scripts/check-system-deps.sh
@@ -308,7 +308,7 @@ bash scripts/check-system-deps.sh
bash -n install.sh
# Verify installation
-ls -la ~/.local/bin/vocalinux*
-ls -la ~/.local/share/vocalinux/
-ls -la ~/.config/vocalinux/
+ls -la ~/.local/bin/voculinux*
+ls -la ~/.local/share/voculinux/
+ls -la ~/.config/voculinux/
```
diff --git a/tests/test_app_identity.py b/tests/test_app_identity.py
index ff0ded0..3edb2fb 100644
--- a/tests/test_app_identity.py
+++ b/tests/test_app_identity.py
@@ -7,7 +7,7 @@ Seams under test (per spec Testing Decisions):
the rename ticket must flip (or deliberately keep) without network access.
No user-visible behaviour, name, path, or string changes: all asserted values
-are the pre-rename Vocalinux/vocalinux literals.
+are the pre-rename Voculinux/voculinux literals.
"""
import ast
@@ -26,27 +26,27 @@ def _load_identity():
def test_central_values_are_current_names():
"""Shared definition still carries the pre-rename literals."""
identity = _load_identity()
- assert identity.APP_NAME == "Vocalinux"
- assert identity.APP_ID == "vocalinux"
- assert identity.APP_DIR_NAME == "vocalinux"
- assert identity.CLI_PROG == "vocalinux"
- assert identity.BUS_NAME == "com.vocalinux.Vocalinux"
- assert identity.OBJECT_PATH == "/com/vocalinux/Vocalinux"
- assert identity.INTERFACE_NAME == "com.vocalinux.Vocalinux"
- assert identity.DESKTOP_FILENAME == "vocalinux.desktop"
- assert identity.DESKTOP_ICON_NAME == "vocalinux"
- assert identity.ENGINE_NAME == "vocalinux"
- assert identity.ENGINE_LONGNAME == "Vocalinux"
- assert identity.COMPONENT_NAME == "org.freedesktop.IBus.Vocalinux"
- assert identity.IBUS_DIR_NAME == "vocalinux-ibus"
- assert identity.UPDATE_CHECKER_USER_AGENT == "Vocalinux-UpdateChecker"
- assert identity.RESOURCE_DIR_NAME == "vocalinux"
- assert identity.VERIFICATION_STAMP_NAME == ".vocalinux_verified"
- assert identity.LOG_FILE_PREFIX == "vocalinux_logs_"
- assert identity.PORTAL_TOKEN_PREFIX == "vocalinux_"
- assert identity.ENV_FORCE_BACKEND == "VOCALINUX_FORCE_BACKEND"
- assert identity.ENV_INJECT_MODIFIER_WAIT == "VOCALINUX_INJECT_MODIFIER_WAIT"
- assert identity.ENV_YDOTOOL_KEY_DELAY == "VOCALINUX_YDOTOOL_KEY_DELAY"
+ assert identity.APP_NAME == "Voculinux"
+ assert identity.APP_ID == "voculinux"
+ assert identity.APP_DIR_NAME == "voculinux"
+ assert identity.CLI_PROG == "voculinux"
+ assert identity.BUS_NAME == "com.voculinux.Voculinux"
+ assert identity.OBJECT_PATH == "/com/voculinux/Voculinux"
+ assert identity.INTERFACE_NAME == "com.voculinux.Voculinux"
+ assert identity.DESKTOP_FILENAME == "voculinux.desktop"
+ assert identity.DESKTOP_ICON_NAME == "voculinux"
+ assert identity.ENGINE_NAME == "voculinux"
+ assert identity.ENGINE_LONGNAME == "Voculinux"
+ assert identity.COMPONENT_NAME == "org.freedesktop.IBus.Voculinux"
+ assert identity.IBUS_DIR_NAME == "voculinux-ibus"
+ assert identity.UPDATE_CHECKER_USER_AGENT == "Voculinux-UpdateChecker"
+ assert identity.RESOURCE_DIR_NAME == "voculinux"
+ assert identity.VERIFICATION_STAMP_NAME == ".voculinux_verified"
+ assert identity.LOG_FILE_PREFIX == "voculinux_logs_"
+ assert identity.PORTAL_TOKEN_PREFIX == "voculinux_"
+ assert identity.ENV_FORCE_BACKEND == "VOCULINUX_FORCE_BACKEND"
+ assert identity.ENV_INJECT_MODIFIER_WAIT == "VOCULINUX_INJECT_MODIFIER_WAIT"
+ assert identity.ENV_YDOTOOL_KEY_DELAY == "VOCULINUX_YDOTOOL_KEY_DELAY"
def _imports_app_identity(path: Path) -> bool:
@@ -108,13 +108,13 @@ def test_source_pinned_literals_reserved_for_rename():
"""
about = (SRC_ROOT / "ui" / "settings_about.py").read_text(encoding="utf-8")
for literal in (
- 'VOCALINUX_SITE_URL = "https://vocalinux.com"',
- 'title="Vocalinux"',
- 'get_icon_path("vocalinux")',
+ 'VOCULINUX_SITE_URL = "https://voculinux.com"',
+ 'title="Voculinux"',
+ 'get_icon_path("voculinux")',
):
assert literal in about, literal
pad = (SRC_ROOT / "ui" / "dictation_pad.py").read_text(encoding="utf-8")
- assert 'window.set_title("Vocalinux Dictation Pad")' in pad
+ assert 'window.set_title("Voculinux Dictation Pad")' in pad
def test_rename_inventory_files_exist():
@@ -134,3 +134,18 @@ def test_retained_inventory_records_internal_names():
import vocalinux
assert vocalinux.__name__ == "vocalinux"
+
+
+def test_legacy_names_recorded_and_unclaimed():
+ """The old install identity is recorded for the one-time import only.
+
+ No compatibility alias: the legacy D-Bus name differs from the claimed
+ one, and no source claims it.
+ """
+ identity = _load_identity()
+ assert identity.LEGACY_APP_DIR_NAME == "vocalinux"
+ assert identity.LEGACY_APP_DIR_NAME != identity.APP_DIR_NAME
+ assert identity.LEGACY_BUS_NAME == "com.vocalinux.Vocalinux"
+ assert identity.LEGACY_BUS_NAME != identity.BUS_NAME
+ service = (SRC_ROOT / "dbus_service.py").read_text(encoding="utf-8")
+ assert identity.LEGACY_BUS_NAME not in service
diff --git a/tests/test_appimage_native_cache.py b/tests/test_appimage_native_cache.py
index 9c0f797..aa894ed 100644
--- a/tests/test_appimage_native_cache.py
+++ b/tests/test_appimage_native_cache.py
@@ -1,6 +1,6 @@
"""The AppImage reuses its pywhispercpp Vulkan build only when the pins match.
-The compile does not depend on the Vocalinux commit. The cache id is the base
+The compile does not depend on the Voculinux commit. The cache id is the base
image, tool_checksums.txt, the pinned cmake and ninja, the Vulkan flags, and
the pywhispercpp pin. It is not the git SHA and not the Actions run id. A tree
without libggml-vulkan.so is a CPU wheel and is not cached.
@@ -39,8 +39,8 @@ def _run(args: list[str], env: dict[str, str] | None = None) -> subprocess.Compl
def _cache_id(pins: Path, install: Path, extra: dict[str, str] | None = None) -> str:
env = os.environ.copy()
- env["VOCALINUX_PINS"] = str(pins)
- env["VOCALINUX_INSTALL_SH"] = str(install)
+ env["VOCULINUX_PINS"] = str(pins)
+ env["VOCULINUX_INSTALL_SH"] = str(install)
if extra:
env.update(extra)
result = _run(["bash", str(ID_SCRIPT)], env=env)
@@ -103,7 +103,7 @@ def test_native_cache_id_tracks_build_tools_and_compile_flags(tmp_path: Path) ->
tools = tmp_path / "appimage-tools.txt"
tools_text = TOOLS.read_text(encoding="utf-8")
tools.write_text(tools_text.replace("cmake", "cmake-other", 1), encoding="utf-8")
- changed_tools = _cache_id(PINS, INSTALL_SH, extra={"VOCALINUX_APPIMAGE_TOOLS": str(tools)})
+ changed_tools = _cache_id(PINS, INSTALL_SH, extra={"VOCULINUX_APPIMAGE_TOOLS": str(tools)})
assert changed_tools != baseline
commented = tmp_path / "build-comment.sh"
@@ -111,7 +111,7 @@ def test_native_cache_id_tracks_build_tools_and_compile_flags(tmp_path: Path) ->
commented.write_text(
build_text.replace("# GPU:", "# GPU: unchanged flags\n# GPU:", 1), encoding="utf-8"
)
- assert _cache_id(PINS, INSTALL_SH, extra={"VOCALINUX_BUILD_SH": str(commented)}) == baseline
+ assert _cache_id(PINS, INSTALL_SH, extra={"VOCULINUX_BUILD_SH": str(commented)}) == baseline
flagged = tmp_path / "build-flags.sh"
flagged.write_text(
@@ -122,7 +122,7 @@ def test_native_cache_id_tracks_build_tools_and_compile_flags(tmp_path: Path) ->
),
encoding="utf-8",
)
- assert _cache_id(PINS, INSTALL_SH, extra={"VOCALINUX_BUILD_SH": str(flagged)}) != baseline
+ assert _cache_id(PINS, INSTALL_SH, extra={"VOCULINUX_BUILD_SH": str(flagged)}) != baseline
def test_native_cache_id_does_not_read_the_commit_or_the_run() -> None:
@@ -307,11 +307,11 @@ def test_a_failed_restore_runs_the_compile_command(tmp_path: Path) -> None:
def test_native_cache_dir_binds_the_arch_to_that_id(tmp_path: Path) -> None:
env = os.environ.copy()
- env["VOCALINUX_APPIMAGE_CACHE"] = str(tmp_path / "cache")
- env.pop("VOCALINUX_PINS", None)
- env.pop("VOCALINUX_INSTALL_SH", None)
- env.pop("VOCALINUX_APPIMAGE_TOOLS", None)
- env.pop("VOCALINUX_BUILD_SH", None)
+ env["VOCULINUX_APPIMAGE_CACHE"] = str(tmp_path / "cache")
+ env.pop("VOCULINUX_PINS", None)
+ env.pop("VOCULINUX_INSTALL_SH", None)
+ env.pop("VOCULINUX_APPIMAGE_TOOLS", None)
+ env.pop("VOCULINUX_BUILD_SH", None)
result = _source("pywhispercpp_native_cache_dir x86_64", env=env)
assert result.returncode == 0, result.stderr
expected = _cache_id(PINS, INSTALL_SH)
@@ -331,7 +331,7 @@ def test_build_reuses_the_cached_vulkan_tree_before_compiling() -> None:
match = re.search(r"\nrebuild_pywhispercpp_vulkan\(\) \{(.+?)\n\}\n", text, re.S)
assert match, "rebuild_pywhispercpp_vulkan disappeared"
body = match.group(1)
- assert body.index("VOCALINUX_APPIMAGE_SKIP_VULKAN") < body.index("pywhispercpp_restore_or_run")
+ assert body.index("VOCULINUX_APPIMAGE_SKIP_VULKAN") < body.index("pywhispercpp_restore_or_run")
assert "GGML_VULKAN=1" not in body
assert "_compile_pywhispercpp_vulkan" in body
compile_fn = re.search(r"\n_compile_pywhispercpp_vulkan\(\) \{(.+?)\n\}\n", text, re.S)
@@ -349,7 +349,7 @@ def test_appimage_workflows_share_one_native_cache_key() -> None:
keys = []
for name in APPIMAGE_WORKFLOWS:
text = (WORKFLOWS / name).read_text(encoding="utf-8")
- found = re.findall(r"path: ~/.cache/vocalinux-appimage\n\s+key: (.+)\n", text)
+ found = re.findall(r"path: ~/.cache/voculinux-appimage\n\s+key: (.+)\n", text)
assert found, name
assert all(key == NATIVE_KEY for key in found), found
for token in ("github.sha", "github.run_id", "github.run_number", "github.run_attempt"):
@@ -366,7 +366,7 @@ def test_appimage_workflows_share_one_native_cache_key() -> None:
for token in ("github.sha", "github.run_id", "github.run_number", "github.run_attempt"):
assert token not in step, step
assert "packaging/appimage/docker-build.sh" in text
- assert 'VOCALINUX_APPIMAGE_REQUIRE_VULKAN: "1"' in text
+ assert 'VOCULINUX_APPIMAGE_REQUIRE_VULKAN: "1"' in text
assert "aarch64" in text
keys.extend(found)
assert len(keys) == 5
diff --git a/tests/test_appimage_packaging.py b/tests/test_appimage_packaging.py
index 6cbdfd4..f422cf7 100644
--- a/tests/test_appimage_packaging.py
+++ b/tests/test_appimage_packaging.py
@@ -113,7 +113,7 @@ def test_running_from_appimage_follows_appdir(monkeypatch):
monkeypatch.delenv("APPDIR", raising=False)
assert not running_from_appimage()
- monkeypatch.setenv("APPDIR", "/tmp/.mount_vocalinux")
+ monkeypatch.setenv("APPDIR", "/tmp/.mount_voculinux")
assert running_from_appimage()
@@ -185,8 +185,8 @@ def test_appimage_build_rebuilds_pywhispercpp_with_vulkan():
text = BUILD_SH.read_text()
assert "GGML_VULKAN=1" in text
assert "libggml-vulkan" in text
- assert "VOCALINUX_APPIMAGE_REQUIRE_VULKAN" in text
- assert "VOCALINUX_APPIMAGE_SKIP_VULKAN" in text
+ assert "VOCULINUX_APPIMAGE_REQUIRE_VULKAN" in text
+ assert "VOCULINUX_APPIMAGE_SKIP_VULKAN" in text
assert "rebuild_pywhispercpp_vulkan" in text
assert 'CC="${CC:-gcc}"' in text
assert 'CXX="${CXX:-g++}"' in text
@@ -345,7 +345,7 @@ def test_vulkan_shaders_get_the_compiler_the_base_image_lacks():
for workflow in APPIMAGE_WORKFLOWS:
content = (WORKFLOWS / workflow).read_text(encoding="utf-8")
assert (
- "vocalinux-appimage" in content
+ "voculinux-appimage" in content
), f"{workflow} does not cache the built glslc; every run rebuilds it"
diff --git a/tests/test_aur_gate.py b/tests/test_aur_gate.py
index b25bd0c..8ddc59f 100644
--- a/tests/test_aur_gate.py
+++ b/tests/test_aur_gate.py
@@ -44,9 +44,9 @@ def test_local_gate_isolates_outputs_and_retains_failed_diagnostics(
checkout = tmp_path / "checkout"
scripts = checkout / "scripts"
scripts.mkdir(parents=True)
- template = checkout / "packaging/aur/vocalinux"
+ template = checkout / "packaging/aur/voculinux"
template.mkdir(parents=True)
- shutil.copy2(ROOT / "packaging/aur/vocalinux/PKGBUILD", template / "PKGBUILD")
+ shutil.copy2(ROOT / "packaging/aur/voculinux/PKGBUILD", template / "PKGBUILD")
shutil.copy2(ROOT / "scripts/prepare_aur_source.py", scripts / "prepare_aur_source.py")
# Keep the real cleanup policy: shared dist/ would reject these outputs.
@@ -78,22 +78,22 @@ def test_local_gate_isolates_outputs_and_retains_failed_diagnostics(
if os.environ['AUR_GATE_TEST_FAILURE'] == 'build':
sys.exit(31)
args.output.mkdir(parents=True, exist_ok=True)
- with tarfile.open(args.output / 'vocalinux-0.18.4.tar.gz', 'w:gz') as archive:
- metadata = b'Name: vocalinux\\nVersion: 0.18.4\\n'
- member = tarfile.TarInfo('vocalinux-0.18.4/PKG-INFO')
+ with tarfile.open(args.output / 'voculinux-0.18.4.tar.gz', 'w:gz') as archive:
+ metadata = b'Name: voculinux\\nVersion: 0.18.4\\n'
+ member = tarfile.TarInfo('voculinux-0.18.4/PKG-INFO')
member.size = len(metadata)
archive.addfile(member, io.BytesIO(metadata))
- (args.output / 'vocalinux-0.18.4-py3-none-any.whl').write_text('new wheel')
+ (args.output / 'voculinux-0.18.4-py3-none-any.whl').write_text('new wheel')
"""))
# Existing packaging outputs, wheel diagnostics and dev tooling are not ours.
protected = {}
for name in (
- "dist/vocalinux-0.18.4-py3-none-any.whl",
- "dist/vocalinux-0.18.4.tar.gz",
- "dist/Vocalinux-0.18.4-x86_64.AppImage",
- "dist/vocalinux_0.18.4_amd64.deb",
- "dist/vocalinux-0.18.4.x86_64.rpm",
+ "dist/voculinux-0.18.4-py3-none-any.whl",
+ "dist/voculinux-0.18.4.tar.gz",
+ "dist/Voculinux-0.18.4-x86_64.AppImage",
+ "dist/voculinux_0.18.4_amd64.deb",
+ "dist/voculinux-0.18.4.x86_64.rpm",
"build/reproducible-wheel/canonical.log",
".venv/keep.txt",
):
@@ -133,7 +133,7 @@ def test_local_gate_isolates_outputs_and_retains_failed_diagnostics(
source = next(arg.removesuffix(':/aur-source:ro') for arg in sys.argv
if arg.endswith(':/aur-source:ro'))
assert (Path(source) / 'PKGBUILD').is_file()
- assert (Path(source) / 'vocalinux-0.18.4.tar.gz').is_file()
+ assert (Path(source) / 'voculinux-0.18.4.tar.gz').is_file()
assert 'AUR_SOURCE=/aur-source' in sys.argv
with open(os.environ['AUR_GATE_TEST_LOG'], 'a') as log:
log.write(json.dumps(['arch', source]) + '\\n')
diff --git a/tests/test_aur_packaging.py b/tests/test_aur_packaging.py
index 68f7c06..6c53396 100644
--- a/tests/test_aur_packaging.py
+++ b/tests/test_aur_packaging.py
@@ -11,8 +11,8 @@ from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parents[1]
AUR = REPO_ROOT / "packaging" / "aur"
-PKGBUILD = AUR / "vocalinux" / "PKGBUILD"
-BIN_DIR = AUR / "vocalinux-bin"
+PKGBUILD = AUR / "voculinux" / "PKGBUILD"
+BIN_DIR = AUR / "voculinux-bin"
BIN_PKGBUILD = BIN_DIR / "PKGBUILD"
GATE_SH = AUR / "build-test.sh"
WORKFLOWS = REPO_ROOT / ".github" / "workflows"
@@ -190,7 +190,7 @@ def test_the_smoke_walks_the_pinned_deps():
assert "requirements/runtime.txt" in script
assert "--require-hashes" in script
- assert "pacman -U" in script and "vocalinux --version" in script
+ assert "pacman -U" in script and "voculinux --version" in script
# Arch name -> PyPI name for the export the gate installs from.
pypi_names = {"python-pywhispercpp": "pywhispercpp", "python-pynput": "pynput"}
for arch_name, pypi_name in pypi_names.items():
@@ -369,7 +369,7 @@ def test_bin_package_ships_the_release_appimage_per_arch() -> None:
text = _bin_pkgbuild()
assert "arch=('x86_64' 'aarch64')" in text
for arch in ("x86_64", "aarch64"):
- asset = f"Vocalinux-${{_tag}}-{arch}.AppImage"
+ asset = f"Voculinux-${{_tag}}-{arch}.AppImage"
assert (
f'"{asset}::https://github.com/VocaHQ/vocalinux/releases/download/'
f"v${{_tag}}/{asset}" in text
@@ -383,19 +383,19 @@ def test_bin_package_installs_the_appimage_intact_and_runnable() -> None:
text = _bin_pkgbuild()
assert "options=('!strip')" in text
assert "'fuse2'" in text
- assert 'install -Dm755 "Vocalinux-${_tag}-${CARCH}.AppImage"' in text
+ assert 'install -Dm755 "Voculinux-${_tag}-${CARCH}.AppImage"' in text
assert '"/opt/${pkgname}/' in text
- assert "ln -s" in text and '"${pkgdir}/usr/bin/vocalinux"' in text
+ assert "ln -s" in text and '"${pkgdir}/usr/bin/voculinux"' in text
def test_bin_package_conflicts_with_the_source_and_git_packages() -> None:
- """All three packages ship /usr/bin/vocalinux; provides= lets a depends on
- 'vocalinux' resolve to the -bin install."""
+ """All three packages ship /usr/bin/voculinux; provides= lets a depends on
+ 'voculinux' resolve to the -bin install."""
text = _bin_pkgbuild()
- assert "provides=('vocalinux')" in text
+ assert "provides=('voculinux')" in text
conflicts = re.search(r"conflicts=\(([^)]*)\)", text)
- assert conflicts, "vocalinux-bin has no conflicts=()"
- for name in ("'vocalinux'", "'vocalinux-git'"):
+ assert conflicts, "voculinux-bin has no conflicts=()"
+ for name in ("'voculinux'", "'voculinux-git'"):
assert name in conflicts.group(1)
@@ -405,8 +405,8 @@ def test_bin_pkgbuild_bundled_files_match_the_repo_copies() -> None:
outside the bundle). Guarded byte-for-byte so a fix to a canonical file
cannot leave the -bin package shipping the stale one."""
for name, canonical in (
- ("vocalinux.desktop", REPO_ROOT / "vocalinux.desktop"),
- ("vocalinux.svg", REPO_ROOT / "resources" / "icons" / "scalable" / "vocalinux.svg"),
+ ("voculinux.desktop", REPO_ROOT / "voculinux.desktop"),
+ ("voculinux.svg", REPO_ROOT / "resources" / "icons" / "scalable" / "voculinux.svg"),
("LICENSE", REPO_ROOT / "LICENSE"),
):
bundled = BIN_DIR / name
@@ -415,10 +415,10 @@ def test_bin_pkgbuild_bundled_files_match_the_repo_copies() -> None:
f"{name} drifted from {canonical.relative_to(REPO_ROOT)};" " sync the bundled copy"
)
assert f"'{name}'" in _bin_pkgbuild(), f"{name} not in source=()"
- desktop = (BIN_DIR / "vocalinux.desktop").read_text(encoding="utf-8")
+ desktop = (BIN_DIR / "voculinux.desktop").read_text(encoding="utf-8")
# The names package() links into /usr/bin and installs under hicolor.
- assert re.search(r"^Exec=vocalinux$", desktop, re.M)
- assert re.search(r"^Icon=vocalinux$", desktop, re.M)
+ assert re.search(r"^Exec=voculinux$", desktop, re.M)
+ assert re.search(r"^Icon=voculinux$", desktop, re.M)
def test_bin_package_asks_the_host_only_for_what_the_bundle_lacks() -> None:
@@ -436,7 +436,7 @@ def test_bin_package_asks_the_host_only_for_what_the_bundle_lacks() -> None:
assert "'wtype'" in depends.group(1)
lines = text.splitlines()
start = next((i for i, line in enumerate(lines) if line.startswith("optdepends=(")), None)
- assert start is not None, "vocalinux-bin has no optdepends=()"
+ assert start is not None, "voculinux-bin has no optdepends=()"
end = next(i for i in range(start + 1, len(lines)) if lines[i].strip() == ")")
optdepends = "\n".join(lines[start + 1 : end])
for tool in ("ibus", "xclip", "wl-clipboard", "ydotool"):
@@ -445,7 +445,7 @@ def test_bin_package_asks_the_host_only_for_what_the_bundle_lacks() -> None:
def test_bin_pkgbuild_tracks_the_release_tag_like_the_source_one() -> None:
- """Same pkgver/_tag split as packaging/aur/vocalinux, real digests for
+ """Same pkgver/_tag split as packaging/aur/voculinux, real digests for
the published AppImages, and the release workflow must bump and publish
both — a -bin left on the last tag would serve the previous release's
AppImage."""
@@ -455,14 +455,14 @@ def test_bin_pkgbuild_tracks_the_release_tag_like_the_source_one() -> None:
# Local builds must verify payloads against real sums, not SKIP.
assert "'SKIP'" not in text
release = RELEASE.read_text(encoding="utf-8")
- assert "packaging/aur/vocalinux-bin/PKGBUILD" in release, (
+ assert "packaging/aur/voculinux-bin/PKGBUILD" in release, (
"release.yml bumps the source PKGBUILD only; the -bin package would"
" keep installing the previous release's AppImage"
)
# The publish step's own updpkgsums only refreshes the x86_64 array, so
# release.yml pins both per-arch digests itself right before publishing.
assert re.search(r"for arch in x86_64 aarch64[\s\S]*sha256sums_\$\{arch\}", release), (
- "release.yml must pin per-arch AppImage digests for vocalinux-bin — "
+ "release.yml must pin per-arch AppImage digests for voculinux-bin — "
"the publish action's updpkgsums only covers the runner's arch"
)
# The aarch64 AppImage lands in a later job; the -bin publish must wait
@@ -472,12 +472,12 @@ def test_bin_pkgbuild_tracks_the_release_tag_like_the_source_one() -> None:
), "publish-aur-bin must need build-appimage-arm64 so the aarch64 asset exists"
# The -bin PKGBUILD names local sources; a lone-PKGBUILD publish leaves
# users unable to build. asset_dir mirrors the whole directory to AUR.
- assert "asset_dir: packaging/aur/vocalinux-bin" in release
+ assert "asset_dir: packaging/aur/voculinux-bin" in release
def test_the_gate_builds_the_bin_package_too() -> None:
"""The -bin package needs build validation as much as the source one:
the gate stubs the release AppImage and runs makepkg on it."""
script = GATE_SH.read_text(encoding="utf-8")
- assert "vocalinux-bin" in script
+ assert "voculinux-bin" in script
assert "--skipchecksums" in script
diff --git a/tests/test_auto_pause_monitor.py b/tests/test_auto_pause_monitor.py
index 89011c0..e846709 100644
--- a/tests/test_auto_pause_monitor.py
+++ b/tests/test_auto_pause_monitor.py
@@ -678,7 +678,7 @@ class TestAutoPauseConfigDefaults(unittest.TestCase):
from vocalinux.ui.config_manager import ConfigManager
with tempfile.TemporaryDirectory() as tmp:
- config_dir = os.path.join(tmp, "vocalinux")
+ config_dir = os.path.join(tmp, "voculinux")
config_file = os.path.join(config_dir, "config.json")
os.makedirs(config_dir, exist_ok=True)
diff --git a/tests/test_autostart_manager.py b/tests/test_autostart_manager.py
index 07630e5..eefddad 100644
--- a/tests/test_autostart_manager.py
+++ b/tests/test_autostart_manager.py
@@ -15,10 +15,10 @@ class TestAutostartManager(unittest.TestCase):
def test_get_exec_command_prefers_installed_command(self):
with patch(
"vocalinux.ui.autostart_manager.shutil.which",
- return_value="/usr/bin/vocalinux",
+ return_value="/usr/bin/voculinux",
):
command = autostart_manager.get_exec_command()
- self.assertEqual(command, "/usr/bin/vocalinux --start-minimized")
+ self.assertEqual(command, "/usr/bin/voculinux --start-minimized")
def test_get_exec_command_falls_back_to_python_module(self):
with (
@@ -31,22 +31,22 @@ class TestAutostartManager(unittest.TestCase):
def test_get_exec_command_flatpak_uses_flatpak_run(self):
# Inside a Flatpak the host session manager must use the flatpak launcher,
- # which is always on PATH, rather than /app/bin/vocalinux.
- with patch.dict("os.environ", {"FLATPAK_ID": "com.vocalinux.Vocalinux"}, clear=False):
+ # which is always on PATH, rather than /app/bin/voculinux.
+ with patch.dict("os.environ", {"FLATPAK_ID": "com.voculinux.Voculinux"}, clear=False):
command = autostart_manager.get_exec_command()
- self.assertEqual(command, "flatpak run com.vocalinux.Vocalinux --start-minimized")
+ self.assertEqual(command, "flatpak run com.voculinux.Voculinux --start-minimized")
def test_enable_autostart_flatpak_writes_flatpak_run_exec(self):
with tempfile.TemporaryDirectory() as tmp_dir:
with patch.dict(
"os.environ",
- {"XDG_CONFIG_HOME": tmp_dir, "FLATPAK_ID": "com.vocalinux.Vocalinux"},
+ {"XDG_CONFIG_HOME": tmp_dir, "FLATPAK_ID": "com.voculinux.Voculinux"},
clear=False,
):
self.assertTrue(autostart_manager.enable_autostart())
- desktop_file = Path(tmp_dir) / "autostart" / "vocalinux.desktop"
+ desktop_file = Path(tmp_dir) / "autostart" / "voculinux.desktop"
content = desktop_file.read_text(encoding="utf-8")
- self.assertIn("Exec=flatpak run com.vocalinux.Vocalinux --start-minimized", content)
+ self.assertIn("Exec=flatpak run com.voculinux.Voculinux --start-minimized", content)
def test_enable_disable_autostart_creates_and_removes_entry(self):
with tempfile.TemporaryDirectory() as tmp_dir:
@@ -54,16 +54,16 @@ class TestAutostartManager(unittest.TestCase):
patch.dict("os.environ", {"XDG_CONFIG_HOME": tmp_dir}, clear=False),
patch(
"vocalinux.ui.autostart_manager.shutil.which",
- return_value="/usr/bin/vocalinux",
+ return_value="/usr/bin/voculinux",
),
):
enabled = autostart_manager.enable_autostart()
self.assertTrue(enabled)
- desktop_file = Path(tmp_dir) / "autostart" / "vocalinux.desktop"
+ desktop_file = Path(tmp_dir) / "autostart" / "voculinux.desktop"
self.assertTrue(desktop_file.exists())
content = desktop_file.read_text(encoding="utf-8")
- self.assertIn("Exec=/usr/bin/vocalinux --start-minimized", content)
+ self.assertIn("Exec=/usr/bin/voculinux --start-minimized", content)
disabled = autostart_manager.disable_autostart()
self.assertTrue(disabled)
diff --git a/tests/test_autostart_manager_ext.py b/tests/test_autostart_manager_ext.py
index 51ece35..4dc4280 100644
--- a/tests/test_autostart_manager_ext.py
+++ b/tests/test_autostart_manager_ext.py
@@ -34,8 +34,8 @@ class TestAutostartManagerExtra:
from vocalinux.ui import autostart_manager
with tempfile.TemporaryDirectory() as tmp_dir:
- autostart_file = Path(tmp_dir) / "vocalinux.desktop"
- autostart_file.write_text("[Desktop Entry]\nName=Vocalinux")
+ autostart_file = Path(tmp_dir) / "voculinux.desktop"
+ autostart_file.write_text("[Desktop Entry]\nName=Voculinux")
with patch.object(autostart_manager, "get_autostart_file", return_value=autostart_file):
assert autostart_manager.is_autostart_enabled() is True
@@ -45,7 +45,7 @@ class TestAutostartManagerExtra:
from vocalinux.ui import autostart_manager
with tempfile.TemporaryDirectory() as tmp_dir:
- autostart_file = Path(tmp_dir) / "vocalinux.desktop"
+ autostart_file = Path(tmp_dir) / "voculinux.desktop"
with patch.object(autostart_manager, "get_autostart_file", return_value=autostart_file):
assert autostart_manager.is_autostart_enabled() is False
@@ -59,7 +59,7 @@ class TestAutostartManagerExtra:
readonly_dir = Path(tmp_dir) / "readonly"
readonly_dir.mkdir()
- autostart_file = readonly_dir / "vocalinux.desktop"
+ autostart_file = readonly_dir / "voculinux.desktop"
readonly_dir.chmod(0o444) # Remove write permission
try:
@@ -72,7 +72,7 @@ class TestAutostartManagerExtra:
with patch.object(
autostart_manager,
"get_exec_command",
- return_value="vocalinux --start-minimized",
+ return_value="voculinux --start-minimized",
):
result = autostart_manager.enable_autostart()
assert result is False
@@ -87,23 +87,23 @@ class TestAutostartManagerExtra:
with tempfile.TemporaryDirectory() as tmp_dir:
with patch.dict(os.environ, {"XDG_CONFIG_HOME": tmp_dir}, clear=False):
with patch(
- "vocalinux.ui.autostart_manager.shutil.which", return_value="/usr/bin/vocalinux"
+ "vocalinux.ui.autostart_manager.shutil.which", return_value="/usr/bin/voculinux"
):
result = autostart_manager.enable_autostart()
assert result is True
- autostart_file = Path(tmp_dir) / "autostart" / "vocalinux.desktop"
+ autostart_file = Path(tmp_dir) / "autostart" / "voculinux.desktop"
assert autostart_file.exists()
content = autostart_file.read_text(encoding="utf-8")
assert "[Desktop Entry]" in content
- assert "vocalinux" in content
+ assert "voculinux" in content
def test_disable_autostart_file_not_found(self):
"""Test disable_autostart succeeds even if file doesn't exist."""
from vocalinux.ui import autostart_manager
with tempfile.TemporaryDirectory() as tmp_dir:
- autostart_file = Path(tmp_dir) / "vocalinux.desktop"
+ autostart_file = Path(tmp_dir) / "voculinux.desktop"
with patch.object(autostart_manager, "get_autostart_file", return_value=autostart_file):
result = autostart_manager.disable_autostart()
@@ -114,8 +114,8 @@ class TestAutostartManagerExtra:
from vocalinux.ui import autostart_manager
with tempfile.TemporaryDirectory() as tmp_dir:
- autostart_file = Path(tmp_dir) / "vocalinux.desktop"
- autostart_file.write_text("[Desktop Entry]\nName=Vocalinux")
+ autostart_file = Path(tmp_dir) / "voculinux.desktop"
+ autostart_file.write_text("[Desktop Entry]\nName=Voculinux")
# Create a mock that will raise a permission error on unlink()
mock_file = MagicMock()
@@ -133,12 +133,12 @@ class TestAutostartManagerExtra:
with tempfile.TemporaryDirectory() as tmp_dir:
with patch.dict(os.environ, {"XDG_CONFIG_HOME": tmp_dir}, clear=False):
with patch(
- "vocalinux.ui.autostart_manager.shutil.which", return_value="/usr/bin/vocalinux"
+ "vocalinux.ui.autostart_manager.shutil.which", return_value="/usr/bin/voculinux"
):
result = autostart_manager.set_autostart(True)
assert result is True
- autostart_file = Path(tmp_dir) / "autostart" / "vocalinux.desktop"
+ autostart_file = Path(tmp_dir) / "autostart" / "voculinux.desktop"
assert autostart_file.exists()
def test_set_autostart_enabled_false(self):
@@ -149,8 +149,8 @@ class TestAutostartManagerExtra:
# First create the file
autostart_dir = Path(tmp_dir) / "autostart"
autostart_dir.mkdir(parents=True)
- autostart_file = autostart_dir / "vocalinux.desktop"
- autostart_file.write_text("[Desktop Entry]\nName=Vocalinux")
+ autostart_file = autostart_dir / "voculinux.desktop"
+ autostart_file.write_text("[Desktop Entry]\nName=Voculinux")
with patch.dict(os.environ, {"XDG_CONFIG_HOME": tmp_dir}, clear=False):
result = autostart_manager.set_autostart(False)
@@ -164,10 +164,10 @@ class TestAutostartManagerExtra:
with patch("vocalinux.ui.autostart_manager.shutil.which", return_value=None):
with patch("vocalinux.ui.autostart_manager.sys.frozen", True, create=True):
with patch(
- "vocalinux.ui.autostart_manager.sys.executable", "/usr/local/bin/vocalinux-bin"
+ "vocalinux.ui.autostart_manager.sys.executable", "/usr/local/bin/voculinux-bin"
):
command = autostart_manager.get_exec_command()
- assert "/usr/local/bin/vocalinux-bin --start-minimized" in command
+ assert "/usr/local/bin/voculinux-bin --start-minimized" in command
def test_get_autostart_dir_without_xdg_config_home(self):
"""Test get_autostart_dir uses default location when XDG_CONFIG_HOME is not set."""
@@ -186,5 +186,5 @@ class TestAutostartManagerExtra:
with tempfile.TemporaryDirectory() as tmp_dir:
with patch.dict(os.environ, {"XDG_CONFIG_HOME": tmp_dir}, clear=False):
autostart_file = autostart_manager.get_autostart_file()
- expected = Path(tmp_dir) / "autostart" / "vocalinux.desktop"
+ expected = Path(tmp_dir) / "autostart" / "voculinux.desktop"
assert autostart_file == expected
diff --git a/tests/test_capture_cancellation.py b/tests/test_capture_cancellation.py
index 908b8a8..ead1d7f 100644
--- a/tests/test_capture_cancellation.py
+++ b/tests/test_capture_cancellation.py
@@ -116,7 +116,7 @@ def test_overflow_does_not_reset_deadline(stream: MagicMock, clock: SimpleNamesp
def test_portaudio_chunk_preserves_normalization(
stream: MagicMock, monkeypatch: pytest.MonkeyPatch
) -> None:
- monkeypatch.setitem(sys.modules, "numpy", sys._vocalinux_real_numpy)
+ monkeypatch.setitem(sys.modules, "numpy", sys._voculinux_real_numpy)
stream.read.return_value = b"\x64\x00\x64\x00" * 1024
source = capture.PortAudioCaptureSource()
source.stream = stream
@@ -133,7 +133,7 @@ def audio_test(monkeypatch: pytest.MonkeyPatch, stream: MagicMock) -> tuple[Magi
"""Supply one negotiated stream without touching PortAudio or the desktop."""
audio = MagicMock()
audio.get_default_input_device_info.return_value = {"name": "Test Mic", "index": 3}
- monkeypatch.setitem(sys.modules, "numpy", sys._vocalinux_real_numpy)
+ monkeypatch.setitem(sys.modules, "numpy", sys._voculinux_real_numpy)
monkeypatch.setitem(sys.modules, "pyaudio", MagicMock(PyAudio=lambda: audio, paInt16=8))
monkeypatch.setattr(capture, "_open_capture_stream", lambda *_args: (1, 16000, stream))
return audio, stream
@@ -246,7 +246,7 @@ def test_pipewire_select_is_sliced_and_cancellable(monkeypatch: pytest.MonkeyPat
def test_pipewire_test_partial_failure_cleans_up(
monkeypatch: pytest.MonkeyPatch, failure: str
) -> None:
- monkeypatch.setitem(sys.modules, "numpy", sys._vocalinux_real_numpy)
+ monkeypatch.setitem(sys.modules, "numpy", sys._voculinux_real_numpy)
source = MagicMock(sample_rate=16000, _CHUNK_FRAMES=1024)
source.read_chunk.side_effect = [
b"\x01\x00" * 1024,
diff --git a/tests/test_capture_recovery.py b/tests/test_capture_recovery.py
index ce0bf3b..3e884a6 100644
--- a/tests/test_capture_recovery.py
+++ b/tests/test_capture_recovery.py
@@ -17,7 +17,7 @@ from vocalinux.speech_recognition import recognition_manager as rm
def manager(monkeypatch: pytest.MonkeyPatch) -> Generator[rm.SpeechRecognitionManager, None, None]:
monkeypatch.setattr(rm.SpeechRecognitionManager, "_init_vosk", lambda self: None)
monkeypatch.setattr(rm, "load_silero_vad", lambda: None)
- monkeypatch.setitem(sys.modules, "numpy", sys._vocalinux_real_numpy)
+ monkeypatch.setitem(sys.modules, "numpy", sys._voculinux_real_numpy)
for name in ("play_start_sound", "play_stop_sound", "play_error_sound"):
monkeypatch.setattr(rm, name, Mock())
# Close this patch before the autouse notification patch exits.
diff --git a/tests/test_capture_shutdown.py b/tests/test_capture_shutdown.py
index 8239ee2..5c7f9fa 100644
--- a/tests/test_capture_shutdown.py
+++ b/tests/test_capture_shutdown.py
@@ -26,7 +26,7 @@ def manager(monkeypatch: pytest.MonkeyPatch) -> Generator[rm.SpeechRecognitionMa
monkeypatch.setattr(rm.SpeechRecognitionManager, "_init_vosk", lambda self: None)
monkeypatch.setattr(rm, "load_silero_vad", lambda: None)
monkeypatch.setattr(rm.SpeechRecognitionManager, "_download_selected_model_if_missing", Mock())
- monkeypatch.setitem(sys.modules, "numpy", sys._vocalinux_real_numpy)
+ monkeypatch.setitem(sys.modules, "numpy", sys._voculinux_real_numpy)
for name in ("play_start_sound", "play_stop_sound", "play_error_sound"):
monkeypatch.setattr(rm, name, Mock())
monkeypatch.setattr(rm, "_CAPTURE_JOIN_SECONDS", 0.02)
diff --git a/tests/test_config_manager.py b/tests/test_config_manager.py
index 3e53ee1..dc59ed4 100644
--- a/tests/test_config_manager.py
+++ b/tests/test_config_manager.py
@@ -32,7 +32,7 @@ class TestConfigManager(unittest.TestCase):
"""Set up test environment."""
# Create a temporary directory for configuration
self.temp_dir = tempfile.TemporaryDirectory()
- self.temp_config_dir = os.path.join(self.temp_dir.name, ".config/vocalinux")
+ self.temp_config_dir = os.path.join(self.temp_dir.name, ".config/voculinux")
_ensure_test_config_dir(self.temp_config_dir)
self.temp_config_file = os.path.join(self.temp_config_dir, "config.json")
@@ -891,7 +891,7 @@ class TestTypedAccessors(unittest.TestCase):
def test_whispercpp_advanced_persistence(self):
# This class skips ConfigManager.__init__, so unlike TestConfigManager
# nothing has redirected CONFIG_FILE: without the patches below this
- # save_config() overwrites the developer's real ~/.config/vocalinux/
+ # save_config() overwrites the developer's real ~/.config/voculinux/
# config.json with the synthetic fixture from setUp.
with tempfile.TemporaryDirectory() as temp_dir:
temp_file = os.path.join(temp_dir, "config.json")
diff --git a/tests/test_cross_distro_compatibility.py b/tests/test_cross_distro_compatibility.py
index 82b7b90..0144835 100644
--- a/tests/test_cross_distro_compatibility.py
+++ b/tests/test_cross_distro_compatibility.py
@@ -21,9 +21,11 @@ def get_repo_root() -> Path:
# Check for common repo indicators
if (parent / ".git").exists() or (parent / "install.sh").exists():
return parent
- # Also check if we're in a 'vocalinux' subdirectory (CI structure)
- if parent.name == "vocalinux" and (parent.parent / "vocalinux" / "install.sh").exists():
- return parent.parent / "vocalinux"
+ # Also check if we're in a checkout-named subdirectory (CI structure)
+ if parent.name in {"vocalinux", "voculinux"}:
+ for sibling in ("voculinux", "vocalinux"):
+ if (parent.parent / sibling / "install.sh").exists():
+ return parent.parent / sibling
# Fallback: use parent of tests directory
return current.parent.parent.parent
@@ -98,10 +100,10 @@ class TestCrossDistroCompatibility:
if desktop_start == -1:
pytest.skip("install_desktop_entry function not found")
desktop_section = install_sh_content[desktop_start : desktop_start + 1000]
- if "sed -i" in desktop_section and "vocalinux.desktop" in desktop_section:
+ if "sed -i" in desktop_section and "voculinux.desktop" in desktop_section:
assert (
"/usr/lib/girepository-1.0"
- not in desktop_section.split("sed -i")[1].split("vocalinux.desktop")[0]
+ not in desktop_section.split("sed -i")[1].split("voculinux.desktop")[0]
), "Desktop entry should not hardcode /usr/lib/girepository-1.0 path"
def test_detect_typelib_path_with_pkgconfig(self, install_sh_content):
diff --git a/tests/test_custom_dictionary.py b/tests/test_custom_dictionary.py
index 6cba739..b334bad 100644
--- a/tests/test_custom_dictionary.py
+++ b/tests/test_custom_dictionary.py
@@ -91,10 +91,10 @@ def test_terms_are_live_reloaded_and_scanner_friendly(tmp_path: Path, monkeypatc
"""The UTF-8 line file accepts comments and applies an external replacement."""
manager = manager_at(tmp_path, monkeypatch, FakeConfig({"dictionary": {"enabled": True}}))
terms_file = tmp_path / TERMS_FILENAME
- terms_file.write_text("# scanner comment\nVocaLinux\nvocalinux\nSupabase\n", encoding="utf-8")
+ terms_file.write_text("# scanner comment\nVoculinux\nvoculinux\nSupabase\n", encoding="utf-8")
- assert manager.get_terms() == ["VocaLinux", "Supabase"]
- assert manager.build_initial_prompt() == "VocaLinux Supabase"
+ assert manager.get_terms() == ["Voculinux", "Supabase"]
+ assert manager.build_initial_prompt() == "Voculinux Supabase"
terms_file.write_text("PyGObject\n", encoding="utf-8")
assert manager.build_initial_prompt() == "PyGObject"
@@ -105,8 +105,8 @@ def test_terms_save_is_atomic_shape_and_transient_override_is_not_written(
) -> None:
"""UI saves standard terms safely while CLI terms remain session-only."""
manager = manager_at(tmp_path, monkeypatch)
- assert manager.save_terms(["VocaLinux", "vocalinux", "# ignored", " PyGObject "])
- assert (tmp_path / TERMS_FILENAME).read_text(encoding="utf-8") == "VocaLinux\nPyGObject\n"
+ assert manager.save_terms(["Voculinux", "voculinux", "# ignored", " PyGObject "])
+ assert (tmp_path / TERMS_FILENAME).read_text(encoding="utf-8") == "Voculinux\nPyGObject\n"
override = tmp_path / "override.txt"
override.write_text("Override\n", encoding="utf-8")
@@ -122,15 +122,15 @@ def test_incremental_term_edits_preserve_comments_and_blank_lines(
"""GTK add/remove operations retain unrelated scanner-managed source lines."""
manager = manager_at(tmp_path, monkeypatch)
terms_file = tmp_path / TERMS_FILENAME
- terms_file.write_text("# scanner note\n\nVocaLinux\n# retain me\nPyGObject\n", encoding="utf-8")
+ terms_file.write_text("# scanner note\n\nVoculinux\n# retain me\nPyGObject\n", encoding="utf-8")
assert manager.add_term("Supabase")
assert terms_file.read_text(encoding="utf-8") == (
- "# scanner note\n\nVocaLinux\n# retain me\nPyGObject\nSupabase\n"
+ "# scanner note\n\nVoculinux\n# retain me\nPyGObject\nSupabase\n"
)
assert manager.remove_term("PyGObject")
assert terms_file.read_text(encoding="utf-8") == (
- "# scanner note\n\nVocaLinux\n# retain me\nSupabase\n"
+ "# scanner note\n\nVoculinux\n# retain me\nSupabase\n"
)
@@ -278,7 +278,7 @@ def test_pr_767_dictionary_configuration_keys_and_contract_are_preserved(
) -> None:
"""Existing enabled, file_path, and max_words settings remain effective."""
configured_path = tmp_path / TERMS_FILENAME
- configured_path.write_text("VocaLinux\nPyGObject\n", encoding="utf-8")
+ configured_path.write_text("Voculinux\nPyGObject\n", encoding="utf-8")
config = FakeConfig(
{
"dictionary": {
@@ -294,7 +294,7 @@ def test_pr_767_dictionary_configuration_keys_and_contract_are_preserved(
assert Path(DEFAULT_TERMS_PATH).name == TERMS_FILENAME
assert manager.terms_enabled()
assert manager.terms_path() == configured_path
- assert manager.build_initial_prompt() == "VocaLinux"
+ assert manager.build_initial_prompt() == "Voculinux"
def test_default_terms_path_follows_xdg_config_home(tmp_path: Path, monkeypatch) -> None:
@@ -306,10 +306,10 @@ def test_default_terms_path_follows_xdg_config_home(tmp_path: Path, monkeypatch)
assert manager.corrections_path() == tmp_path / CORRECTIONS_FILENAME
-def test_legacy_vocalinux_terms_root_keeps_corrections_at_config_dir(
+def test_legacy_voculinux_terms_root_keeps_corrections_at_config_dir(
tmp_path: Path, monkeypatch
) -> None:
- """Persisted ~/.config/vocalinux terms do not move the corrections file."""
+ """Legacy ~/.config/vocalinux terms do not move the corrections file."""
monkeypatch.setattr("vocalinux.custom_dictionary.config_dir", lambda: str(tmp_path))
legacy_corrections = Path.home() / ".config" / "vocalinux" / CORRECTIONS_FILENAME
expanded_legacy = str(Path.home() / ".config" / "vocalinux" / TERMS_FILENAME)
@@ -434,7 +434,7 @@ def test_corrections_fallback_survives_copy_failure(tmp_path: Path, monkeypatch)
def test_corrections_stay_at_config_dir_with_arbitrary_terms_parent(
tmp_path: Path, monkeypatch
) -> None:
- """Corrections ignore the terms file location outside a vocalinux directory."""
+ """Corrections ignore the terms file location outside a voculinux directory."""
xdg_dir = tmp_path / "xdg-config"
xdg_dir.mkdir()
monkeypatch.setattr("vocalinux.custom_dictionary.config_dir", lambda: str(xdg_dir))
@@ -568,7 +568,7 @@ def test_invalid_or_unreadable_configured_terms_path_is_not_persisted(
config = FakeConfig({"dictionary": {"file_path": previous_path}})
manager = manager_at(tmp_path, monkeypatch, config)
- assert not manager.set_terms_path("~vocalinux-user-does-not-exist/dictionary.txt")
+ assert not manager.set_terms_path("~voculinux-user-does-not-exist/dictionary.txt")
assert config.get("dictionary", "file_path") == previous_path
assert not manager.set_terms_path(str(tmp_path))
@@ -581,7 +581,7 @@ def test_invalid_saved_terms_path_is_safe_to_read_and_report(tmp_path: Path, mon
{
"dictionary": {
"enabled": True,
- "file_path": "~vocalinux-user-does-not-exist/dictionary.txt",
+ "file_path": "~voculinux-user-does-not-exist/dictionary.txt",
}
}
)
@@ -609,7 +609,7 @@ def test_terms_path_save_failure_preserves_the_previous_configured_path(
def test_invalid_transient_terms_path_does_not_crash(tmp_path: Path, monkeypatch) -> None:
"""An unresolved CLI tilde path disables only its session's terms safely."""
manager_at(tmp_path, monkeypatch)
- manager = CustomDictionaryManager(FakeConfig(), "~vocalinux-user-does-not-exist/dictionary.txt")
+ manager = CustomDictionaryManager(FakeConfig(), "~voculinux-user-does-not-exist/dictionary.txt")
assert manager.terms_enabled()
assert manager.terms_path() is None
@@ -638,7 +638,7 @@ def test_file_edits_preserve_existing_permissions(tmp_path: Path, monkeypatch) -
manager = manager_at(tmp_path, monkeypatch)
terms_file = tmp_path / TERMS_FILENAME
- terms_file.write_text("VocaLinux\n", encoding="utf-8")
+ terms_file.write_text("Voculinux\n", encoding="utf-8")
terms_file.chmod(0o600)
assert manager.save_terms(["Supabase"])
assert stat.S_IMODE(terms_file.stat().st_mode) == 0o600
@@ -652,7 +652,7 @@ def test_file_edits_preserve_existing_permissions(tmp_path: Path, monkeypatch) -
def test_dictionary_file_argument_is_available_for_a_session_override(monkeypatch) -> None:
"""The retained CLI option accepts a terms file without changing config."""
- monkeypatch.setattr("sys.argv", ["vocalinux", "--dictionary-file", "/tmp/terms.txt"])
+ monkeypatch.setattr("sys.argv", ["voculinux", "--dictionary-file", "/tmp/terms.txt"])
assert parse_arguments().dictionary_file == "/tmp/terms.txt"
@@ -961,7 +961,7 @@ def test_invalid_terms_file_is_ignored_and_explained(tmp_path: Path, monkeypatch
def test_whisper_receives_the_live_custom_terms_prompt(tmp_path: Path, monkeypatch) -> None:
"""Whisper gets the current file contents as initial_prompt at transcription time."""
dictionary = manager_at(tmp_path, monkeypatch, FakeConfig({"dictionary": {"enabled": True}}))
- (tmp_path / TERMS_FILENAME).write_text("VocaLinux\n", encoding="utf-8")
+ (tmp_path / TERMS_FILENAME).write_text("Voculinux\n", encoding="utf-8")
manager = recognition_manager("whisper", dictionary)
manager.model = MagicMock()
manager.model.transcribe.return_value = {"text": "ok"}
@@ -970,13 +970,13 @@ def test_whisper_receives_the_live_custom_terms_prompt(tmp_path: Path, monkeypat
with patch.dict("sys.modules", {"numpy": mock_numpy(), "torch": MagicMock()}):
assert manager._transcribe_with_whisper([b"\x00\x00"]) == "ok"
- assert manager.model.transcribe.call_args.kwargs["initial_prompt"] == "VocaLinux"
+ assert manager.model.transcribe.call_args.kwargs["initial_prompt"] == "Voculinux"
def test_faster_whisper_receives_the_live_custom_terms_prompt(tmp_path: Path, monkeypatch) -> None:
"""Faster Whisper receives the same live vocabulary bias as OpenAI Whisper."""
dictionary = manager_at(tmp_path, monkeypatch, FakeConfig({"dictionary": {"enabled": True}}))
- (tmp_path / TERMS_FILENAME).write_text("VocaLinux\n", encoding="utf-8")
+ (tmp_path / TERMS_FILENAME).write_text("Voculinux\n", encoding="utf-8")
manager = object.__new__(SpeechRecognitionManager)
manager.dictionary_manager = dictionary
manager._faster_whisper_engine = MagicMock()
@@ -985,7 +985,7 @@ def test_faster_whisper_receives_the_live_custom_terms_prompt(tmp_path: Path, mo
assert manager._transcribe_with_faster_whisper([b"\x00\x00"]) == "ok"
manager._faster_whisper_engine.transcribe.assert_called_once_with(
- [b"\x00\x00"], language="auto", initial_prompt="VocaLinux"
+ [b"\x00\x00"], language="auto", initial_prompt="Voculinux"
)
@@ -994,7 +994,7 @@ def test_whispercpp_composes_and_clears_live_terms_prompt(tmp_path: Path, monkey
config = FakeConfig({"dictionary": {"enabled": True}})
dictionary = manager_at(tmp_path, monkeypatch, config)
terms_file = tmp_path / TERMS_FILENAME
- terms_file.write_text("VocaLinux\n", encoding="utf-8")
+ terms_file.write_text("Voculinux\n", encoding="utf-8")
manager = recognition_manager("whisper_cpp", dictionary, advanced_prompt="Explicit context")
manager._model_lock = threading.Lock()
manager.model = MagicMock()
@@ -1008,7 +1008,7 @@ def test_whispercpp_composes_and_clears_live_terms_prompt(tmp_path: Path, monkey
assert manager._transcribe_with_whispercpp([b"\x00\x00"]) == "ok"
prompts = [call.kwargs["initial_prompt"] for call in manager.model.transcribe.call_args_list]
- assert prompts == ["Explicit context VocaLinux", "Explicit context", ""]
+ assert prompts == ["Explicit context Voculinux", "Explicit context", ""]
def test_vosk_warns_once_for_bias_while_corrections_remain_available(
@@ -1016,7 +1016,7 @@ def test_vosk_warns_once_for_bias_while_corrections_remain_available(
) -> None:
"""VOSK rejects vocabulary bias only; its transcript can still be corrected."""
dictionary = manager_at(tmp_path, monkeypatch, FakeConfig({"dictionary": {"enabled": True}}))
- (tmp_path / TERMS_FILENAME).write_text("VocaLinux\n", encoding="utf-8")
+ (tmp_path / TERMS_FILENAME).write_text("Voculinux\n", encoding="utf-8")
manager = recognition_manager("vosk", dictionary)
manager._get_vosk_model_path = MagicMock(return_value="/models/vosk")
vosk = MagicMock()
@@ -1041,11 +1041,11 @@ def test_whispercpp_prompt_composes_advanced_and_terms() -> None:
recognition_manager = object.__new__(SpeechRecognitionManager)
recognition_manager.whispercpp_initial_prompt = "Write product names accurately."
recognition_manager.dictionary_manager = type(
- "Dictionary", (), {"build_initial_prompt": lambda self: "VocaLinux"}
+ "Dictionary", (), {"build_initial_prompt": lambda self: "Voculinux"}
)()
assert (
- recognition_manager._get_whispercpp_prompt() == "Write product names accurately. VocaLinux"
+ recognition_manager._get_whispercpp_prompt() == "Write product names accurately. Voculinux"
)
recognition_manager.dictionary_manager = type(
"Dictionary", (), {"build_initial_prompt": lambda self: None}
diff --git a/tests/test_dbus_activation.py b/tests/test_dbus_activation.py
index 122d01e..59b0f65 100644
--- a/tests/test_dbus_activation.py
+++ b/tests/test_dbus_activation.py
@@ -16,7 +16,7 @@ import pytest
if TYPE_CHECKING:
from vocalinux.dbus_service import VocalinuxDBusService
-# gi is mocked globally by conftest. All vocalinux imports are done lazily
+# gi is mocked globally by conftest. All voculinux imports are done lazily
# inside the individual tests. Importing them at module level would bind their
# `gi.repository` references at collection time and clash with test_main.py,
# which replaces sys.modules["gi"] / sys.modules["gi.repository"] wholesale --
@@ -35,7 +35,7 @@ def test_cli_flag_sends_matching_command(flag, command):
from vocalinux.main import main
with patch("vocalinux.dbus_service.send_command", return_value=True) as mock_send:
- with patch.object(sys, "argv", ["vocalinux", flag]):
+ with patch.object(sys, "argv", ["voculinux", flag]):
with pytest.raises(SystemExit) as exc_info:
main()
assert exc_info.value.code == 0
@@ -47,7 +47,7 @@ def test_cli_flag_exits_nonzero_when_no_instance():
from vocalinux.main import main
with patch("vocalinux.dbus_service.send_command", return_value=False):
- with patch.object(sys, "argv", ["vocalinux", "--toggle"]):
+ with patch.object(sys, "argv", ["voculinux", "--toggle"]):
with pytest.raises(SystemExit) as exc_info:
main()
assert exc_info.value.code == 1
@@ -58,7 +58,7 @@ def test_no_trigger_flag_does_not_dispatch():
from vocalinux.main import main
# Mock single_instance via sys.modules (not patch("...acquire_lock")) so we
- # don't import the real module and set it as a vocalinux package attribute,
+ # don't import the real module and set it as a voculinux package attribute,
# which would defeat patch.dict-based single-instance tests elsewhere.
mock_single_instance = MagicMock()
mock_single_instance.acquire_lock.return_value = True
@@ -66,7 +66,7 @@ def test_no_trigger_flag_does_not_dispatch():
# check_dependencies returns False so main() exits early after dispatch.
with patch.dict(sys.modules, {"vocalinux.single_instance": mock_single_instance}):
with patch("vocalinux.main.check_dependencies", return_value=False):
- with patch.object(sys, "argv", ["vocalinux"]):
+ with patch.object(sys, "argv", ["voculinux"]):
with pytest.raises(SystemExit):
main()
mock_send.assert_not_called()
@@ -269,7 +269,7 @@ def test_on_bus_acquired_handles_register_failure():
# Patch GLib.Error to a real class so both the raise and the `except` clause
# reference the same type and the GLib.Error branch is exercised.
with patch.object(dbus_service.GLib, "Error", RuntimeError):
- service._on_bus_acquired(connection, "com.vocalinux.Vocalinux")
+ service._on_bus_acquired(connection, "com.voculinux.Voculinux")
assert service._registration_id == 0
@@ -278,8 +278,8 @@ def test_name_acquired_and_lost_are_safe_to_call():
"""The name-acquired/lost callbacks only log and never raise."""
service = _make_service()
connection = MagicMock()
- service._on_name_acquired(connection, "com.vocalinux.Vocalinux")
- service._on_name_lost(connection, "com.vocalinux.Vocalinux")
+ service._on_name_acquired(connection, "com.voculinux.Voculinux")
+ service._on_name_lost(connection, "com.voculinux.Voculinux")
def test_invoke_swallows_callback_errors():
diff --git a/tests/test_dictation_overlay.py b/tests/test_dictation_overlay.py
index b16f4e1..8190a04 100644
--- a/tests/test_dictation_overlay.py
+++ b/tests/test_dictation_overlay.py
@@ -136,7 +136,7 @@ class TestOverlayConfig(unittest.TestCase):
def setUp(self):
self.temp_dir = tempfile.TemporaryDirectory()
- self.temp_config_dir = os.path.join(self.temp_dir.name, ".config/vocalinux")
+ self.temp_config_dir = os.path.join(self.temp_dir.name, ".config/voculinux")
_ensure_test_config_dir(self.temp_config_dir)
self.temp_config_file = os.path.join(self.temp_config_dir, "config.json")
@@ -1199,7 +1199,7 @@ class TestOverlayConfigMissingUiSection(unittest.TestCase):
def setUp(self):
self.temp_dir = tempfile.TemporaryDirectory()
- self.temp_config_dir = os.path.join(self.temp_dir.name, ".config/vocalinux")
+ self.temp_config_dir = os.path.join(self.temp_dir.name, ".config/voculinux")
_ensure_test_config_dir(self.temp_config_dir)
self.temp_config_file = os.path.join(self.temp_config_dir, "config.json")
self.config_dir_patcher = patch(
diff --git a/tests/test_dictation_pad.py b/tests/test_dictation_pad.py
index 934c272..476c7c0 100644
--- a/tests/test_dictation_pad.py
+++ b/tests/test_dictation_pad.py
@@ -190,7 +190,7 @@ class TestDictationPadConfig(unittest.TestCase):
def setUp(self) -> None:
self.temp_dir = tempfile.TemporaryDirectory()
- self.temp_config_dir = os.path.join(self.temp_dir.name, ".config/vocalinux")
+ self.temp_config_dir = os.path.join(self.temp_dir.name, ".config/voculinux")
_ensure_test_config_dir(self.temp_config_dir)
self.temp_config_file = os.path.join(self.temp_config_dir, "config.json")
diff --git a/tests/test_evdev_backend_ext.py b/tests/test_evdev_backend_ext.py
index dfa0d5f..0aab413 100644
--- a/tests/test_evdev_backend_ext.py
+++ b/tests/test_evdev_backend_ext.py
@@ -790,7 +790,7 @@ class TestEvdevKeyboardBackendPermissionHint:
result = backend.get_permission_hint()
assert result is None
- @patch.dict("os.environ", {"SNAP": "/snap/vocalinux/x1"}, clear=False)
+ @patch.dict("os.environ", {"SNAP": "/snap/voculinux/x1"}, clear=False)
@patch("vocalinux.ui.keyboard_backends.evdev_backend.EVDEV_AVAILABLE", True)
@patch("vocalinux.ui.keyboard_backends.evdev_backend.find_keyboard_devices")
def test_permission_hint_snap_no_devices(self, mock_find_devices):
@@ -802,7 +802,7 @@ class TestEvdevKeyboardBackendPermissionHint:
assert "raw-input" in result
assert "hardware-observe" in result
- @patch.dict("os.environ", {"SNAP": "/snap/vocalinux/x1"}, clear=False)
+ @patch.dict("os.environ", {"SNAP": "/snap/voculinux/x1"}, clear=False)
@patch("vocalinux.ui.keyboard_backends.evdev_backend.EVDEV_AVAILABLE", True)
@patch("vocalinux.ui.keyboard_backends.evdev_backend.find_keyboard_devices")
@patch("vocalinux.ui.keyboard_backends.evdev_backend.InputDevice")
@@ -1804,7 +1804,7 @@ class TestEvdevGrabAndForwarding:
device = MagicMock()
device.fileno.return_value = 10
device.info.bustype = 0x06 # BUS_VIRTUAL
- device.name = "AT Translated Set 2 keyboard (vocalinux)"
+ device.name = "AT Translated Set 2 keyboard (voculinux)"
mock_input_device.return_value = device
backend = EvdevKeyboardBackend()
@@ -3192,7 +3192,7 @@ class TestWriteOnlyUInput:
patch.object(eb._WriteOnlyUInput, "_find_device", return_value=device),
patch.object(eb._uinput, "write") as write,
):
- uinput = eb._WriteOnlyUInput(events={1: [30]}, name="kbd (vocalinux)", bustype=0x06)
+ uinput = eb._WriteOnlyUInput(events={1: [30]}, name="kbd (voculinux)", bustype=0x06)
yield uinput, mock_open, set_phys, enable, setup, create, write, device
def test_opens_wronly_and_runs_setup(self) -> None:
@@ -3243,7 +3243,7 @@ class TestWriteOnlyUInput:
),
):
with pytest.raises(TypeError):
- eb._WriteOnlyUInput(events=None, name="kbd (vocalinux)", bustype=0x06)
+ eb._WriteOnlyUInput(events=None, name="kbd (voculinux)", bustype=0x06)
mock_close.assert_called_once_with(42)
@@ -3254,7 +3254,7 @@ class TestWriteOnlyUInput:
name = _clone_device_name(device)
- assert name.endswith(" (vocalinux)")
+ assert name.endswith(" (voculinux)")
assert len(name.encode("utf-8")) <= 79
def test_clone_device_name_keeps_short_names(self) -> None:
@@ -3262,7 +3262,7 @@ class TestWriteOnlyUInput:
device = MagicMock()
device.name = "AT Translated Set 2 keyboard"
- assert _clone_device_name(device) == "AT Translated Set 2 keyboard (vocalinux)"
+ assert _clone_device_name(device) == "AT Translated Set 2 keyboard (voculinux)"
class TestSharedEvdevDeviceLayer:
diff --git a/tests/test_faster_whisper_engine.py b/tests/test_faster_whisper_engine.py
index 137984e..b85f565 100644
--- a/tests/test_faster_whisper_engine.py
+++ b/tests/test_faster_whisper_engine.py
@@ -326,17 +326,17 @@ class TestFasterWhisperEngine:
def test_transcribe_passes_initial_prompt(self) -> None:
"""Test that vocabulary bias is forwarded to faster-whisper."""
- whisper_mock = self._mock_whisper_model([MagicMock(text="VocaLinux")])
+ whisper_mock = self._mock_whisper_model([MagicMock(text="Voculinux")])
with patch.dict(sys.modules, {"faster_whisper": whisper_mock}):
engine = FasterWhisperEngine(model_size="tiny", device="cpu")
engine.init()
audio = np.array([0, 1000, -1000, 0], dtype=np.int16)
- engine.transcribe([audio.tobytes()], initial_prompt="VocaLinux")
+ engine.transcribe([audio.tobytes()], initial_prompt="Voculinux")
assert (
whisper_mock.WhisperModel.return_value.transcribe.call_args.kwargs["initial_prompt"]
- == "VocaLinux"
+ == "Voculinux"
)
def test_transcribe_empty_audio(self):
@@ -429,7 +429,7 @@ class TestFasterWhisperEngine:
assert text == ""
def test_language_mapping(self):
- """Test that Vocalinux language codes are mapped correctly."""
+ """Test that Voculinux language codes are mapped correctly."""
engine = FasterWhisperEngine(language="en-us")
assert engine._normalize_language() == "en"
diff --git a/tests/test_first_run_dialog_ext.py b/tests/test_first_run_dialog_ext.py
index 08c914e..5d50179 100644
--- a/tests/test_first_run_dialog_ext.py
+++ b/tests/test_first_run_dialog_ext.py
@@ -47,7 +47,7 @@ class _FakeGtkDialog:
pass
-_ISOLATED_MODULE_NAME = "vocalinux_test_first_run_dialog_isolated"
+_ISOLATED_MODULE_NAME = "voculinux_test_first_run_dialog_isolated"
def _load_first_run_dialog_with_fake_gtk():
diff --git a/tests/test_flatpak_packaging.py b/tests/test_flatpak_packaging.py
index 7852fb5..3a22556 100644
--- a/tests/test_flatpak_packaging.py
+++ b/tests/test_flatpak_packaging.py
@@ -47,7 +47,7 @@ PYPROJECT = REPO_ROOT / "pyproject.toml"
EXPORT = REPO_ROOT / "requirements" / "vad.txt"
FLATPAK_DIR = REPO_ROOT / "packaging" / "flatpak"
DEPS_YAML = FLATPAK_DIR / "python3-dependencies.yaml"
-MANIFEST = FLATPAK_DIR / "com.vocalinux.Vocalinux.yml"
+MANIFEST = FLATPAK_DIR / "com.voculinux.Voculinux.yml"
WORKFLOW = REPO_ROOT / ".github" / "workflows" / "flatpak.yml"
#: Kept in step with scripts/sync_flatpak_deps.py, which resolves the same
diff --git a/tests/test_gateway_embed.py b/tests/test_gateway_embed.py
index c2ec224..85ae0d8 100644
--- a/tests/test_gateway_embed.py
+++ b/tests/test_gateway_embed.py
@@ -266,7 +266,7 @@ class TestPairingDecode(unittest.TestCase):
class TestSandbox(unittest.TestCase):
def test_flatpak_fails_closed(self):
- state = detect_sandbox({"FLATPAK_ID": "com.vocahq.Vocalinux"})
+ state = detect_sandbox({"FLATPAK_ID": "com.vocahq.Voculinux"})
self.assertTrue(state.blocked)
self.assertEqual(state.kind, "flatpak")
self.assertIn("Flatpak", state.hint)
@@ -704,7 +704,7 @@ class TestOrphanComposeDetect(unittest.TestCase):
manager.stop_async()
fake_thread.assert_called_once()
kwargs = fake_thread.call_args.kwargs
- self.assertEqual(kwargs.get("name"), "vocalinux-gateway-stop")
+ self.assertEqual(kwargs.get("name"), "voculinux-gateway-stop")
self.assertEqual(kwargs.get("target").__func__, manager._stop_worker.__func__)
started.start.assert_called_once()
diff --git a/tests/test_host_process.py b/tests/test_host_process.py
index 2c59ecf..705c980 100644
--- a/tests/test_host_process.py
+++ b/tests/test_host_process.py
@@ -1,4 +1,4 @@
-"""Guards for the environment Vocalinux hands to host binaries.
+"""Guards for the environment Voculinux hands to host binaries.
An AppImage exports its own `LD_LIBRARY_PATH`, `GI_TYPELIB_PATH` and
`PYTHONHOME`, and every child process inherits them. A host `ibus` linked
diff --git a/tests/test_ibus_active_engine_guard.py b/tests/test_ibus_active_engine_guard.py
index cb9af49..ce9ce19 100644
--- a/tests/test_ibus_active_engine_guard.py
+++ b/tests/test_ibus_active_engine_guard.py
@@ -29,7 +29,7 @@ sys.modules["gi"] = _mock_gi
sys.modules["gi.repository"] = _mock_gi_repo
for _key in list(sys.modules.keys()):
- if "vocalinux" in _key and "ibus_engine" in _key:
+ if "voculinux" in _key and "ibus_engine" in _key:
del sys.modules[_key]
import vocalinux.text_injection.ibus_engine as ibus_engine # noqa: E402
diff --git a/tests/test_ibus_engine.py b/tests/test_ibus_engine.py
index a9c3e2b..6960c10 100644
--- a/tests/test_ibus_engine.py
+++ b/tests/test_ibus_engine.py
@@ -94,7 +94,7 @@ class TestIBusTextInjectorSetupFailures(unittest.TestCase):
with self.assertRaises(IBusSetupError) as context:
IBusTextInjector(auto_activate=True)
- self.assertIn("Failed to activate Vocalinux IBus engine", str(context.exception))
+ self.assertIn("Failed to activate Voculinux IBus engine", str(context.exception))
@patch("vocalinux.text_injection.ibus_engine.IBUS_AVAILABLE", True)
@patch("vocalinux.text_injection.ibus_engine.ensure_ibus_dir")
@@ -137,7 +137,7 @@ class TestIBusEngineHelpers(unittest.TestCase):
def test_ensure_ibus_dir_creates_directory(self):
"""Test that ensure_ibus_dir creates the directory."""
- with patch("vocalinux.text_injection.ibus_engine.VOCALINUX_IBUS_DIR") as mock_dir:
+ with patch("vocalinux.text_injection.ibus_engine.VOCULINUX_IBUS_DIR") as mock_dir:
mock_dir.mkdir = MagicMock()
from vocalinux.text_injection.ibus_engine import ensure_ibus_dir
@@ -157,7 +157,7 @@ class TestIsEngineActive(unittest.TestCase):
@patch("subprocess.run")
def test_engine_active(self, mock_run):
"""Test detection when engine is active."""
- mock_run.return_value = MagicMock(stdout="vocalinux", returncode=0)
+ mock_run.return_value = MagicMock(stdout="voculinux", returncode=0)
from vocalinux.text_injection.ibus_engine import is_engine_active
@@ -589,12 +589,12 @@ class TestSwitchEngine(unittest.TestCase):
# First call: ibus engine (switch)
# Second call: ibus engine (get current) - for verification
switch_result = MagicMock(returncode=0)
- verify_result = MagicMock(returncode=0, stdout="vocalinux\n")
+ verify_result = MagicMock(returncode=0, stdout="voculinux\n")
mock_run.side_effect = [switch_result, verify_result]
from vocalinux.text_injection.ibus_engine import switch_engine
- result = switch_engine("vocalinux")
+ result = switch_engine("voculinux")
self.assertTrue(result)
self.assertEqual(mock_run.call_count, 2)
@@ -621,7 +621,7 @@ class TestSwitchEngine(unittest.TestCase):
from vocalinux.text_injection.ibus_engine import switch_engine
- result = switch_engine("vocalinux")
+ result = switch_engine("voculinux")
self.assertFalse(result)
@@ -674,8 +674,8 @@ class TestIBusTextInjector(unittest.TestCase):
self.assertGreaterEqual(mock_ensure_dir.call_count, 1)
# Engine should be started
mock_start_engine.assert_called_once()
- # Should switch to vocalinux engine
- mock_switch.assert_called_once_with("vocalinux")
+ # Should switch to voculinux engine
+ mock_switch.assert_called_once_with("voculinux")
mock_wait_ready.assert_called_once_with()
self.assertEqual(injector._previous_engine, "xkb:us::eng")
@@ -1003,20 +1003,20 @@ class TestIBusTextInjector(unittest.TestCase):
@patch(
"vocalinux.text_injection.ibus_engine._query_active_engine",
- return_value="vocalinux",
+ return_value="voculinux",
)
@patch("vocalinux.text_injection.ibus_engine.stop_engine_process")
@patch(
"vocalinux.text_injection.ibus_engine.get_current_engine",
- return_value="vocalinux",
+ return_value="voculinux",
)
@patch("vocalinux.text_injection.ibus_engine.switch_engine", return_value=True)
@patch("vocalinux.text_injection.ibus_engine.IBUS_AVAILABLE", True)
@patch("vocalinux.text_injection.ibus_engine.ensure_ibus_dir")
- def test_stop_uses_cached_engine_when_stuck_on_vocalinux(
+ def test_stop_uses_cached_engine_when_stuck_on_voculinux(
self, mock_ensure_dir, mock_switch, mock_get_current, mock_stop_proc, mock_live
):
- """If quit finds vocalinux selected, fall back to the warmup-captured engine (#558)."""
+ """If quit finds voculinux selected, fall back to the warmup-captured engine (#558)."""
from vocalinux.text_injection.ibus_engine import IBusTextInjector
injector = IBusTextInjector(auto_activate=False)
@@ -1031,15 +1031,15 @@ class TestIBusTextInjector(unittest.TestCase):
@patch("vocalinux.text_injection.ibus_engine.stop_engine_process")
@patch(
"vocalinux.text_injection.ibus_engine.get_current_engine",
- return_value="vocalinux",
+ return_value="voculinux",
)
@patch("vocalinux.text_injection.ibus_engine.switch_engine")
@patch("vocalinux.text_injection.ibus_engine.IBUS_AVAILABLE", True)
@patch("vocalinux.text_injection.ibus_engine.ensure_ibus_dir")
- def test_stop_skips_restore_when_only_vocalinux_active(
+ def test_stop_skips_restore_when_only_voculinux_active(
self, mock_ensure_dir, mock_switch, mock_get_current, mock_stop_proc
):
- """Do not try to reselect vocalinux after its process has been torn down."""
+ """Do not try to reselect voculinux after its process has been torn down."""
from vocalinux.text_injection.ibus_engine import IBusTextInjector
injector = IBusTextInjector(auto_activate=False)
@@ -1091,7 +1091,7 @@ class TestIBusTextInjector(unittest.TestCase):
@patch("vocalinux.text_injection.ibus_engine.start_engine_process", return_value=True)
@patch("vocalinux.text_injection.ibus_engine.IBusTextInjector._wait_for_engine_ready")
@patch("vocalinux.text_injection.ibus_engine.switch_engine")
- def test_prepare_engine_does_not_activate_vocalinux_engine(
+ def test_prepare_engine_does_not_activate_voculinux_engine(
self,
mock_switch,
mock_wait_ready,
@@ -1124,7 +1124,7 @@ class TestIBusTextInjector(unittest.TestCase):
mock_is_active,
mock_get_current,
):
- """Warmup caches the live engine so quit can restore after a stuck vocalinux (#558)."""
+ """Warmup caches the live engine so quit can restore after a stuck voculinux (#558)."""
from vocalinux.text_injection.ibus_engine import IBusTextInjector
injector = IBusTextInjector(auto_activate=False)
@@ -1194,7 +1194,7 @@ class TestIBusTextInjector(unittest.TestCase):
mock_get_xkb,
mock_restore_xkb,
):
- """Scoped injection must restore XKB after the Vocalinux engine switch (#664)."""
+ """Scoped injection must restore XKB after the Voculinux engine switch (#664)."""
from vocalinux.text_injection.ibus_engine import ENGINE_NAME, IBusTextInjector
mock_socket_path.exists.return_value = True
@@ -1615,14 +1615,14 @@ class TestIBusTextInjector(unittest.TestCase):
mock_is_active,
mock_get_current,
):
- """Test inject_text returns False when switch to Vocalinux engine fails."""
+ """Test inject_text returns False when switch to Voculinux engine fails."""
from vocalinux.text_injection.ibus_engine import IBusTextInjector
injector = IBusTextInjector(auto_activate=False)
result = injector.inject_text("Hello")
self.assertFalse(result)
- mock_switch.assert_called_once_with("vocalinux")
+ mock_switch.assert_called_once_with("voculinux")
@patch("vocalinux.text_injection.ibus_engine.get_current_engine", return_value=None)
@patch("vocalinux.text_injection.ibus_engine.is_engine_active", return_value=False)
diff --git a/tests/test_ibus_engine_core.py b/tests/test_ibus_engine_core.py
index b2df534..16e4c5f 100644
--- a/tests/test_ibus_engine_core.py
+++ b/tests/test_ibus_engine_core.py
@@ -194,7 +194,7 @@ class TestIBusEngineModuleFunctions(unittest.TestCase):
@patch("subprocess.run")
def test_is_engine_active_success(self, mock_run):
"""Test when engine is active."""
- mock_run.return_value = MagicMock(returncode=0, stdout="vocalinux")
+ mock_run.return_value = MagicMock(returncode=0, stdout="voculinux")
from vocalinux.text_injection.ibus_engine import is_engine_active
result = is_engine_active()
@@ -231,10 +231,10 @@ class TestIBusEngineModuleFunctions(unittest.TestCase):
@patch("vocalinux.text_injection.ibus_engine.get_current_engine")
def test_switch_engine_success(self, mock_get_current, mock_run):
"""Test switching engine successfully."""
- mock_get_current.return_value = "vocalinux"
+ mock_get_current.return_value = "voculinux"
from vocalinux.text_injection.ibus_engine import switch_engine
- result = switch_engine("vocalinux")
+ result = switch_engine("voculinux")
self.assertTrue(result)
@patch("subprocess.run")
@@ -244,7 +244,7 @@ class TestIBusEngineModuleFunctions(unittest.TestCase):
mock_get_current.return_value = "other-engine"
from vocalinux.text_injection.ibus_engine import switch_engine
- result = switch_engine("vocalinux")
+ result = switch_engine("voculinux")
self.assertFalse(result)
@patch("vocalinux.text_injection.ibus_engine.PID_FILE")
@@ -380,7 +380,7 @@ class TestVocalinuxEngine(unittest.TestCase):
VocalinuxEngine._server_socket = None
VocalinuxEngine._server_running = False
- def test_vocalinux_engine_init(self):
+ def test_voculinux_engine_init(self):
"""Test VocalinuxEngine initialization."""
from vocalinux.text_injection.ibus_engine import VocalinuxEngine
@@ -394,7 +394,7 @@ class TestVocalinuxEngine(unittest.TestCase):
self.assertIsNone(VocalinuxEngine._server_socket)
self.assertFalse(VocalinuxEngine._server_running)
- def test_vocalinux_engine_do_enable(self):
+ def test_voculinux_engine_do_enable(self):
"""Test engine enable signal handler."""
from vocalinux.text_injection.ibus_engine import VocalinuxEngine
@@ -404,7 +404,7 @@ class TestVocalinuxEngine(unittest.TestCase):
# Verify active instance is set
self.assertEqual(VocalinuxEngine._active_instance, engine)
- def test_vocalinux_engine_do_disable(self):
+ def test_voculinux_engine_do_disable(self):
"""Test engine disable signal handler."""
from vocalinux.text_injection.ibus_engine import VocalinuxEngine
@@ -414,7 +414,7 @@ class TestVocalinuxEngine(unittest.TestCase):
# Instance should still be active (not cleared on disable)
self.assertEqual(VocalinuxEngine._active_instance, engine)
- def test_vocalinux_engine_do_focus_in(self):
+ def test_voculinux_engine_do_focus_in(self):
"""Test engine focus in signal handler."""
from vocalinux.text_injection.ibus_engine import VocalinuxEngine
@@ -423,7 +423,7 @@ class TestVocalinuxEngine(unittest.TestCase):
self.assertEqual(VocalinuxEngine._active_instance, engine)
self.assertTrue(VocalinuxEngine._focus_event.is_set())
- def test_vocalinux_engine_do_focus_out(self):
+ def test_voculinux_engine_do_focus_out(self):
"""Test engine focus out signal handler."""
from vocalinux.text_injection.ibus_engine import VocalinuxEngine
@@ -508,7 +508,7 @@ class TestVocalinuxEngine(unittest.TestCase):
self.assertIsNone(VocalinuxEngine._active_instance)
self.assertFalse(VocalinuxEngine._focus_event.is_set())
- def test_vocalinux_engine_do_process_key_event(self):
+ def test_voculinux_engine_do_process_key_event(self):
"""Test engine key event processing."""
from vocalinux.text_injection.ibus_engine import VocalinuxEngine
@@ -517,7 +517,7 @@ class TestVocalinuxEngine(unittest.TestCase):
# Should return False to pass through all keys
self.assertFalse(result)
- def test_vocalinux_engine_inject_text_empty(self):
+ def test_voculinux_engine_inject_text_empty(self):
"""Test text injection with empty text."""
from vocalinux.text_injection.ibus_engine import VocalinuxEngine
@@ -526,7 +526,7 @@ class TestVocalinuxEngine(unittest.TestCase):
# Empty text should return True (no-op)
self.assertTrue(result)
- def test_vocalinux_engine_inject_text_success(self):
+ def test_voculinux_engine_inject_text_success(self):
"""Test successful text injection."""
from vocalinux.text_injection.ibus_engine import VocalinuxEngine
@@ -540,7 +540,7 @@ class TestVocalinuxEngine(unittest.TestCase):
self.assertTrue(result)
engine.commit_text.assert_called_once()
- def test_vocalinux_engine_inject_text_failure(self):
+ def test_voculinux_engine_inject_text_failure(self):
"""Test text injection error handling."""
from vocalinux.text_injection.ibus_engine import VocalinuxEngine
@@ -733,7 +733,7 @@ class TestVocalinuxEngineApplication(unittest.TestCase):
pass
@patch("vocalinux.text_injection.ibus_engine.VocalinuxEngine._start_socket_server")
- def test_vocalinux_engine_application_init(self, mock_start_server):
+ def test_voculinux_engine_application_init(self, mock_start_server):
"""Test VocalinuxEngineApplication initialization."""
from vocalinux.text_injection.ibus_engine import VocalinuxEngineApplication
@@ -748,7 +748,7 @@ class TestVocalinuxEngineApplication(unittest.TestCase):
self.assertEqual(type(app.mainloop).__name__, "MagicMock")
@patch("vocalinux.text_injection.ibus_engine.VocalinuxEngine._start_socket_server")
- def test_vocalinux_engine_application_on_disconnected(self, mock_start_server):
+ def test_voculinux_engine_application_on_disconnected(self, mock_start_server):
"""Test IBus disconnection handler."""
from vocalinux.text_injection.ibus_engine import VocalinuxEngineApplication
@@ -760,7 +760,7 @@ class TestVocalinuxEngineApplication(unittest.TestCase):
app.mainloop.quit.assert_called_once()
@patch("vocalinux.text_injection.ibus_engine.VocalinuxEngine._start_socket_server")
- def test_vocalinux_engine_application_run(self, mock_start_server):
+ def test_voculinux_engine_application_run(self, mock_start_server):
"""Test engine application main loop."""
from vocalinux.text_injection.ibus_engine import VocalinuxEngineApplication
@@ -774,7 +774,7 @@ class TestVocalinuxEngineApplication(unittest.TestCase):
@patch("vocalinux.text_injection.ibus_engine.IBus.Component")
@patch("vocalinux.text_injection.ibus_engine.IBus.Factory.new")
@patch("vocalinux.text_injection.ibus_engine.IBus.Bus")
- def test_vocalinux_engine_application_standalone_registers_component(
+ def test_voculinux_engine_application_standalone_registers_component(
self,
mock_bus_cls,
mock_factory_new,
@@ -810,7 +810,7 @@ class TestVocalinuxEngineApplication(unittest.TestCase):
@patch("vocalinux.text_injection.ibus_engine.VocalinuxEngine._start_socket_server")
@patch("vocalinux.text_injection.ibus_engine.IBus.Factory.new")
@patch("vocalinux.text_injection.ibus_engine.IBus.Bus")
- def test_vocalinux_engine_application_ibus_exec_requests_name(
+ def test_voculinux_engine_application_ibus_exec_requests_name(
self,
mock_bus_cls,
mock_factory_new,
@@ -835,7 +835,7 @@ class TestVocalinuxEngineApplication(unittest.TestCase):
@patch("vocalinux.text_injection.ibus_engine.VocalinuxEngine._start_socket_server")
@patch("vocalinux.text_injection.ibus_engine.IBus.Factory.new")
@patch("vocalinux.text_injection.ibus_engine.IBus.Bus")
- def test_vocalinux_engine_application_request_name_failure_raises(
+ def test_voculinux_engine_application_request_name_failure_raises(
self,
mock_bus_cls,
mock_factory_new,
@@ -858,7 +858,7 @@ class TestVocalinuxEngineApplication(unittest.TestCase):
@patch("vocalinux.text_injection.ibus_engine.VocalinuxEngine._start_socket_server")
@patch("vocalinux.text_injection.ibus_engine.IBus.Factory.new")
@patch("vocalinux.text_injection.ibus_engine.IBus.Bus")
- def test_vocalinux_engine_application_register_component_failure_raises(
+ def test_voculinux_engine_application_register_component_failure_raises(
self,
mock_bus_cls,
mock_factory_new,
@@ -880,7 +880,7 @@ class TestVocalinuxEngineApplication(unittest.TestCase):
@patch("vocalinux.text_injection.ibus_engine.VocalinuxEngine._start_socket_server")
@patch("vocalinux.text_injection.ibus_engine.IBus.Bus")
- def test_vocalinux_engine_application_disconnected_bus_raises(
+ def test_voculinux_engine_application_disconnected_bus_raises(
self,
mock_bus_cls,
mock_start_server,
@@ -898,7 +898,7 @@ class TestVocalinuxEngineApplication(unittest.TestCase):
@patch("vocalinux.text_injection.ibus_engine.VocalinuxEngine._start_socket_server")
@patch("vocalinux.text_injection.ibus_engine.IBus.Factory.new")
@patch("vocalinux.text_injection.ibus_engine.IBus.Bus")
- def test_vocalinux_engine_application_none_connection_raises(
+ def test_voculinux_engine_application_none_connection_raises(
self,
mock_bus_cls,
mock_factory_new,
@@ -962,7 +962,7 @@ class TestIBusEngineMainEntrypoint(unittest.TestCase):
msg=f"stdout={result.stdout!r} stderr={result.stderr!r}",
)
self.assertIn("", result.stdout)
- self.assertIn("vocalinux", result.stdout)
+ self.assertIn("voculinux", result.stdout)
self.assertNotIn("attempted relative import", result.stderr)
def test_main_passes_ibus_flag_to_application(self):
@@ -1008,7 +1008,7 @@ class TestStartEngineProcess(unittest.TestCase):
patch.object(ibus_engine, "is_engine_process_running", side_effect=running_states),
patch.object(ibus_engine, "ensure_ibus_dir"),
patch.object(ibus_engine, "PID_FILE") as mock_pid,
- patch.object(ibus_engine, "VOCALINUX_IBUS_DIR", Path(tempfile.mkdtemp())),
+ patch.object(ibus_engine, "VOCULINUX_IBUS_DIR", Path(tempfile.mkdtemp())),
patch.object(ibus_engine.subprocess, "Popen", return_value=mock_proc) as mock_popen,
patch.object(ibus_engine.time, "sleep"),
patch.object(ibus_engine.sys, "prefix", "/venv"),
@@ -1040,7 +1040,7 @@ class TestStartEngineProcess(unittest.TestCase):
patch.object(ibus_engine, "is_engine_process_running", side_effect=iter([False, True])),
patch.object(ibus_engine, "ensure_ibus_dir"),
patch.object(ibus_engine, "PID_FILE"),
- patch.object(ibus_engine, "VOCALINUX_IBUS_DIR", Path(tempfile.mkdtemp())),
+ patch.object(ibus_engine, "VOCULINUX_IBUS_DIR", Path(tempfile.mkdtemp())),
patch.object(ibus_engine.subprocess, "Popen", return_value=mock_proc) as mock_popen,
patch.object(ibus_engine.time, "sleep"),
):
@@ -1077,7 +1077,7 @@ class TestStartEngineProcess(unittest.TestCase):
patch.object(ibus_engine, "is_engine_process_running", return_value=False),
patch.object(ibus_engine, "ensure_ibus_dir"),
patch.object(ibus_engine, "PID_FILE") as mock_pid,
- patch.object(ibus_engine, "VOCALINUX_IBUS_DIR", tmp),
+ patch.object(ibus_engine, "VOCULINUX_IBUS_DIR", tmp),
patch.object(ibus_engine.subprocess, "Popen", side_effect=popen_side_effect),
patch.object(ibus_engine.time, "sleep"),
patch.object(ibus_engine.logger, "error") as mock_error,
@@ -1110,7 +1110,7 @@ class TestStartEngineProcess(unittest.TestCase):
patch.object(ibus_engine, "is_engine_process_running", return_value=False),
patch.object(ibus_engine, "ensure_ibus_dir"),
patch.object(ibus_engine, "PID_FILE") as mock_pid,
- patch.object(ibus_engine, "VOCALINUX_IBUS_DIR", tmp),
+ patch.object(ibus_engine, "VOCULINUX_IBUS_DIR", tmp),
patch.object(ibus_engine.subprocess, "Popen", return_value=mock_proc),
patch.object(ibus_engine.time, "sleep"),
patch.object(ibus_engine.logger, "error") as mock_error,
@@ -1137,7 +1137,7 @@ class TestStartEngineProcess(unittest.TestCase):
patch.object(ibus_engine, "is_engine_process_running", return_value=False),
patch.object(ibus_engine, "ensure_ibus_dir"),
patch.object(ibus_engine, "PID_FILE") as mock_pid,
- patch.object(ibus_engine, "VOCALINUX_IBUS_DIR", tmp),
+ patch.object(ibus_engine, "VOCULINUX_IBUS_DIR", tmp),
patch.object(ibus_engine.subprocess, "Popen", return_value=mock_proc),
patch.object(ibus_engine.time, "sleep"),
patch.object(ibus_engine.logger, "error") as mock_error,
@@ -1173,7 +1173,7 @@ class TestStartEngineProcess(unittest.TestCase):
patch.object(ibus_engine, "is_engine_process_running", return_value=False),
patch.object(ibus_engine, "ensure_ibus_dir"),
patch.object(ibus_engine, "PID_FILE") as mock_pid,
- patch.object(ibus_engine, "VOCALINUX_IBUS_DIR", tmp),
+ patch.object(ibus_engine, "VOCULINUX_IBUS_DIR", tmp),
patch.object(ibus_engine.subprocess, "Popen", return_value=mock_proc),
patch.object(ibus_engine.time, "sleep"),
):
@@ -1198,7 +1198,7 @@ class TestStartEngineProcess(unittest.TestCase):
patch.object(ibus_engine, "is_engine_process_running", return_value=False),
patch.object(ibus_engine, "ensure_ibus_dir"),
patch.object(ibus_engine, "PID_FILE") as mock_pid,
- patch.object(ibus_engine, "VOCALINUX_IBUS_DIR", tmp),
+ patch.object(ibus_engine, "VOCULINUX_IBUS_DIR", tmp),
patch.object(ibus_engine.subprocess, "Popen", return_value=mock_proc),
patch.object(ibus_engine.time, "sleep"),
):
@@ -1230,7 +1230,7 @@ class TestStartEngineProcess(unittest.TestCase):
patch.object(ibus_engine, "is_engine_process_running", return_value=False),
patch.object(ibus_engine, "ensure_ibus_dir"),
patch.object(ibus_engine, "PID_FILE") as mock_pid,
- patch.object(ibus_engine, "VOCALINUX_IBUS_DIR", tmp),
+ patch.object(ibus_engine, "VOCULINUX_IBUS_DIR", tmp),
patch.object(ibus_engine.subprocess, "Popen", return_value=mock_proc),
patch.object(ibus_engine.time, "sleep"),
patch.object(ibus_engine.logger, "error") as mock_error,
@@ -1249,7 +1249,7 @@ class TestStartEngineProcess(unittest.TestCase):
with (
patch.object(ibus_engine, "is_engine_process_running", return_value=False),
patch.object(ibus_engine, "ensure_ibus_dir"),
- patch.object(ibus_engine, "VOCALINUX_IBUS_DIR", Path(tempfile.mkdtemp())),
+ patch.object(ibus_engine, "VOCULINUX_IBUS_DIR", Path(tempfile.mkdtemp())),
patch.object(ibus_engine.subprocess, "Popen", side_effect=OSError("cannot exec")),
patch.object(ibus_engine.logger, "error") as mock_error,
):
diff --git a/tests/test_ibus_engine_utils.py b/tests/test_ibus_engine_utils.py
index 4bc7b53..3829931 100644
--- a/tests/test_ibus_engine_utils.py
+++ b/tests/test_ibus_engine_utils.py
@@ -10,7 +10,7 @@ import sys
import unittest
from unittest.mock import MagicMock, patch
-# Mock GI imports before importing any vocalinux modules that use gi.
+# Mock GI imports before importing any voculinux modules that use gi.
# On CI, real gi/IBus may be installed; importing ibus_engine without mocks
# would set IBUS_AVAILABLE=True and VocalinuxEngine would inherit from real
# IBus.Engine, causing hangs when super().__init__() tries to connect to IBus.
@@ -31,7 +31,7 @@ sys.modules["gi.repository"] = _mock_gi_repo
# Force reload ibus_engine so it picks up mocks (in case it was already imported)
for _key in list(sys.modules.keys()):
- if "vocalinux" in _key and "ibus_engine" in _key:
+ if "voculinux" in _key and "ibus_engine" in _key:
del sys.modules[_key]
@@ -323,8 +323,8 @@ class TestSwitchEngine(unittest.TestCase):
"""Test successfully switching engines."""
from vocalinux.text_injection.ibus_engine import switch_engine
- mock_get_engine.return_value = "vocalinux"
- result = switch_engine("vocalinux")
+ mock_get_engine.return_value = "voculinux"
+ result = switch_engine("voculinux")
self.assertTrue(result)
@patch("vocalinux.text_injection.ibus_engine.get_current_engine")
@@ -335,7 +335,7 @@ class TestSwitchEngine(unittest.TestCase):
from vocalinux.text_injection.ibus_engine import switch_engine
mock_get_engine.return_value = "other"
- result = switch_engine("vocalinux")
+ result = switch_engine("voculinux")
self.assertFalse(result)
@@ -381,7 +381,7 @@ class TestStopEngineProcess(unittest.TestCase):
cmdline = MagicMock()
cmdline.exists.return_value = True
- cmdline.read_text.return_value = "python /x/vocalinux/text_injection/ibus_engine.py --ibus"
+ cmdline.read_text.return_value = "python /x/voculinux/text_injection/ibus_engine.py --ibus"
mock_path_cls.return_value = cmdline
# SIGTERM succeeds; first liveness check still alive; second gone.
@@ -409,7 +409,7 @@ class TestStopEngineProcess(unittest.TestCase):
cmdline = MagicMock()
cmdline.exists.return_value = True
- cmdline.read_text.return_value = "python /x/vocalinux/text_injection/ibus_engine.py --ibus"
+ cmdline.read_text.return_value = "python /x/voculinux/text_injection/ibus_engine.py --ibus"
mock_path_cls.return_value = cmdline
# SIGTERM, then keep reporting alive until wait timeout, then SIGKILL succeeds.
diff --git a/tests/test_ibus_xkb_wayland.py b/tests/test_ibus_xkb_wayland.py
index c443262..49d637d 100644
--- a/tests/test_ibus_xkb_wayland.py
+++ b/tests/test_ibus_xkb_wayland.py
@@ -30,7 +30,7 @@ sys.modules["gi"] = _mock_gi
sys.modules["gi.repository"] = _mock_gi_repo
for _key in list(sys.modules.keys()):
- if "vocalinux" in _key and "ibus_engine" in _key:
+ if "voculinux" in _key and "ibus_engine" in _key:
del sys.modules[_key]
from vocalinux.text_injection.ibus_engine import restore_xkb_layout # noqa: E402
diff --git a/tests/test_injection_modifier_wait.py b/tests/test_injection_modifier_wait.py
index 99f3a96..7b9ac73 100644
--- a/tests/test_injection_modifier_wait.py
+++ b/tests/test_injection_modifier_wait.py
@@ -84,14 +84,14 @@ class TestWaitForModifiersReleased:
def test_disabled_via_env(self, monkeypatch):
inj = _bare_injector()
- monkeypatch.setenv("VOCALINUX_INJECT_MODIFIER_WAIT", "0")
+ monkeypatch.setenv("VOCULINUX_INJECT_MODIFIER_WAIT", "0")
with patch.object(inj, "_held_modifier_keycodes") as held:
inj._wait_for_modifiers_released()
held.assert_not_called()
def test_gives_up_after_timeout(self, monkeypatch):
inj = _bare_injector()
- monkeypatch.setenv("VOCALINUX_INJECT_MODIFIER_WAIT", "0.05")
+ monkeypatch.setenv("VOCULINUX_INJECT_MODIFIER_WAIT", "0.05")
# Always held -> must still return (best-effort) rather than hang.
with patch.object(inj, "_held_modifier_keycodes", return_value={56}), patch("time.sleep"):
inj._wait_for_modifiers_released() # should return within the timeout
@@ -227,30 +227,30 @@ class TestInjectionModifierWaitSeconds:
@pytest.mark.parametrize("raw,expected", [("2.5", 2.5), ("0", 0.0), ("0.5", 0.5)])
def test_valid_values(self, raw, expected, monkeypatch):
inj = _bare_injector()
- monkeypatch.setenv("VOCALINUX_INJECT_MODIFIER_WAIT", raw)
+ monkeypatch.setenv("VOCULINUX_INJECT_MODIFIER_WAIT", raw)
assert inj._injection_modifier_wait_seconds() == expected
@pytest.mark.parametrize("raw", ["inf", "-inf", "nan", "Infinity", "NaN"])
def test_non_finite_falls_back_to_default(self, raw, monkeypatch):
inj = _bare_injector()
- monkeypatch.setenv("VOCALINUX_INJECT_MODIFIER_WAIT", raw)
+ monkeypatch.setenv("VOCULINUX_INJECT_MODIFIER_WAIT", raw)
assert inj._injection_modifier_wait_seconds() == 1.0
def test_non_numeric_falls_back_to_default(self, monkeypatch):
inj = _bare_injector()
- monkeypatch.setenv("VOCALINUX_INJECT_MODIFIER_WAIT", "abc")
+ monkeypatch.setenv("VOCULINUX_INJECT_MODIFIER_WAIT", "abc")
assert inj._injection_modifier_wait_seconds() == 1.0
def test_unset_uses_default(self, monkeypatch):
inj = _bare_injector()
- monkeypatch.delenv("VOCALINUX_INJECT_MODIFIER_WAIT", raising=False)
+ monkeypatch.delenv("VOCULINUX_INJECT_MODIFIER_WAIT", raising=False)
assert inj._injection_modifier_wait_seconds() == 1.0
def test_inf_does_not_block_forever(self, monkeypatch):
# Regression: with 'inf', the wait must still terminate (bounded by the
# finite default) instead of looping forever while a modifier is held.
inj = _bare_injector()
- monkeypatch.setenv("VOCALINUX_INJECT_MODIFIER_WAIT", "inf")
+ monkeypatch.setenv("VOCULINUX_INJECT_MODIFIER_WAIT", "inf")
# Simulate the clock crossing the finite default deadline in a few steps.
clock = iter([0.0, 0.5, 1.5])
monkeypatch.setattr("time.monotonic", lambda: next(clock, 2.0))
diff --git a/tests/test_installer_engine_config.py b/tests/test_installer_engine_config.py
index 5ff2a67..fe0748c 100644
--- a/tests/test_installer_engine_config.py
+++ b/tests/test_installer_engine_config.py
@@ -1,7 +1,7 @@
"""Behavioral tests for the installer's speech-engine sanity check.
config.json survives reinstalls, so it can name an engine the current venv
-cannot import — vosk is an optional extra since #705. Vocalinux then dies at
+cannot import — vosk is an optional extra since #705. Voculinux then dies at
startup with "No module named 'vosk'" instead of the installer saying so.
"""
diff --git a/tests/test_installer_gate.py b/tests/test_installer_gate.py
index 9dcdcd2..a543afa 100644
--- a/tests/test_installer_gate.py
+++ b/tests/test_installer_gate.py
@@ -174,7 +174,7 @@ def test_the_gate_takes_this_commit_from_git_not_the_working_directory():
), "the gate no longer extracts the tree from git"
installer = INSTALLER.read_text(encoding="utf-8").splitlines()
assert any(
- "grep" in line and "pyproject.toml" in line and "vocalinux" in line for line in installer
+ "grep" in line and "pyproject.toml" in line and "voculinux" in line for line in installer
), (
"local mode is no longer detected from pyproject.toml in the working"
" directory; the gate may now be testing a downloaded tag instead of"
@@ -206,9 +206,9 @@ def test_the_smoke_checks_what_the_installer_claims_to_have_created():
gate = _gate_text()
for construct in (
r'\[ -x "\$VENV/bin/python" \]',
- r'\[ -x "\$INSTALL_HOME/\.local/bin/vocalinux" \]',
- r'\[ -f "\$INSTALL_HOME/\.local/share/applications/vocalinux\.desktop" \]',
- r"'\$INSTALL_HOME/\.local/bin/vocalinux' --version",
+ r'\[ -x "\$INSTALL_HOME/\.local/bin/voculinux" \]',
+ r'\[ -f "\$INSTALL_HOME/\.local/share/applications/voculinux\.desktop" \]',
+ r"'\$INSTALL_HOME/\.local/bin/voculinux' --version",
):
assert re.search(construct, gate), f"the smoke no longer asserts {construct}"
@@ -306,13 +306,13 @@ def test_the_remote_gate_bootstraps_outside_a_checkout():
checkout exists. Overriding the clone source is what keeps the run on this
commit instead of the public repo's last release."""
gate = _without_comments(_remote_gate_text())
- assert "VOCALINUX_REPO_URL" in gate, (
+ assert "VOCULINUX_REPO_URL" in gate, (
"the remote gate no longer redirects the clone source; it would"
" install the public repo's tag rather than this commit"
)
installer = _without_comments(INSTALLER.read_text(encoding="utf-8"))
- assert re.search(r"VOCALINUX_REPO_URL:-https://github\.com/VocaHQ/vocalinux\.git", installer), (
- "install.sh no longer honors VOCALINUX_REPO_URL; the gate's mirror"
+ assert re.search(r"VOCULINUX_REPO_URL:-https://github\.com/VocaHQ/vocalinux\.git", installer), (
+ "install.sh no longer honors VOCULINUX_REPO_URL; the gate's mirror"
" cannot reach it and the clone falls back to the public repo"
)
@@ -346,7 +346,7 @@ def test_the_remote_gate_checks_handoff_artifacts():
gate = _without_comments(_remote_gate_text())
for construct in (
r'\[ -x "\$REMOTE_VENV/bin/python" \]',
- r'\[ -f "\$INSTALL_HOME/\.local/bin/activate-vocalinux\.sh" \]',
+ r'\[ -f "\$INSTALL_HOME/\.local/bin/activate-voculinux\.sh" \]',
):
assert re.search(construct, gate), f"the remote gate no longer asserts {construct}"
@@ -355,9 +355,9 @@ def test_the_remote_gate_smoke_tests_the_installed_app():
"""Same standard as the local gate: the app binary answers --version
through the wrapper the user's PATH carries."""
gate = _without_comments(_remote_gate_text())
- assert re.search(r"'\$INSTALL_HOME/\.local/bin/vocalinux' --version", gate)
+ assert re.search(r"'\$INSTALL_HOME/\.local/bin/voculinux' --version", gate)
assert re.search(
- r'\[ -x "\$INSTALL_HOME/\.local/bin/vocalinux" \]', gate
+ r'\[ -x "\$INSTALL_HOME/\.local/bin/voculinux" \]', gate
), "the remote gate no longer asserts the user-facing wrapper exists"
diff --git a/tests/test_installer_pinned_dependencies.py b/tests/test_installer_pinned_dependencies.py
index 6d95c9e..78af906 100644
--- a/tests/test_installer_pinned_dependencies.py
+++ b/tests/test_installer_pinned_dependencies.py
@@ -67,7 +67,7 @@ print_info() {{ :; }}
require_distro_gi() {{ :; }}
VENV_DIR={shlex.quote(str(venv))}
INSTALL_DIR={shlex.quote(str(ROOT))}
-VOCALINUX_TMP_DIR={shlex.quote(str(tmp_path))}
+VOCULINUX_TMP_DIR={shlex.quote(str(tmp_path))}
{source}
{command}
"""
@@ -188,15 +188,15 @@ def test_remote_handoff_preserves_tagged_behavior(tmp_path: Path, remote_aware:
"""A main bootstrap must preserve remote behavior for every tag."""
clone = tmp_path / "old tagged tree"
clone.mkdir()
- marker = 'CLEANUP_ON_EXIT="${VOCALINUX_REMOTE_INSTALL:-no}"\n' if remote_aware else ""
+ marker = 'CLEANUP_ON_EXIT="${VOCULINUX_REMOTE_INSTALL:-no}"\n' if remote_aware else ""
(clone / "install.sh").write_text(
"#!/bin/bash\n"
+ marker
- + 'printf "%s\\n" "${VOCALINUX_REMOTE_INSTALL:-no}" "$PWD" "$@"\n'
- + "helper=activate-vocalinux.sh\n"
- + 'if [ "${VOCALINUX_REMOTE_INSTALL:-no}" = yes ]; then\n'
+ + 'printf "%s\\n" "${VOCULINUX_REMOTE_INSTALL:-no}" "$PWD" "$@"\n'
+ + "helper=activate-voculinux.sh\n"
+ + 'if [ "${VOCULINUX_REMOTE_INSTALL:-no}" = yes ]; then\n'
+ ' mkdir -p "$HOME/.local/bin"\n'
- + ' helper="$HOME/.local/bin/activate-vocalinux.sh"\n'
+ + ' helper="$HOME/.local/bin/activate-voculinux.sh"\n'
+ "fi\n"
+ 'printf helper > "$helper"\n'
)
@@ -214,7 +214,7 @@ def test_remote_handoff_preserves_tagged_behavior(tmp_path: Path, remote_aware:
"-c",
f"set -eu\n{handoff}\ncd {shlex.quote(str(clone))}\n"
f"INSTALL_DIR={shlex.quote(str(clone))}\n"
- f"VOCALINUX_TMP_DIR={shlex.quote(str(scratch))}\n"
+ f"VOCULINUX_TMP_DIR={shlex.quote(str(scratch))}\n"
"INSTALLER_ARGS=(--auto --tag=v0.17.0 --engine=remote_api)\n"
'print_error() { echo "$*" >&2; }\n'
"handoff_to_tagged_installer",
@@ -231,12 +231,12 @@ def test_remote_handoff_preserves_tagged_behavior(tmp_path: Path, remote_aware:
"--auto",
"--tag=v0.17.0",
"--engine=remote_api",
- f"--venv-dir={home}/.local/share/vocalinux/venv",
+ f"--venv-dir={home}/.local/share/voculinux/venv",
]
assert scratch.exists() != remote_aware
- helper = home / ".local/bin/activate-vocalinux.sh"
+ helper = home / ".local/bin/activate-voculinux.sh"
assert helper.read_text() == "helper"
- assert not (clone / "activate-vocalinux.sh").exists()
+ assert not (clone / "activate-voculinux.sh").exists()
def test_every_pip_install_has_an_explicit_resolution_boundary() -> None:
diff --git a/tests/test_installer_review_notes.py b/tests/test_installer_review_notes.py
index fd80f57..31f8a55 100644
--- a/tests/test_installer_review_notes.py
+++ b/tests/test_installer_review_notes.py
@@ -43,16 +43,16 @@ def test_help_does_not_create_install_log_or_scratch_dir(tmp_path, monkeypatch)
)
assert result.returncode == 0
assert not list((tmp_path / "state").rglob("install-*.log"))
- assert not list((tmp_path / "tmp").glob("vocalinux-install.*"))
+ assert not list((tmp_path / "tmp").glob("voculinux-install.*"))
def test_scratch_dir_owns_pip_logs_and_model_temps() -> None:
source = _installer_source()
- assert 'PIP_LOG_DIR="$VOCALINUX_TMP_DIR/pip"' in source
- assert 'export TMPDIR="$VOCALINUX_TMP_DIR"' in source
- assert 'TEMP_FILE="$VOCALINUX_TMP_DIR/tiny.pt"' in source
- assert 'TEMP_FILE="$VOCALINUX_TMP_DIR/ggml-tiny.bin"' in source
- assert 'TEMP_ZIP="$VOCALINUX_TMP_DIR/$(basename $SMALL_MODEL_URL)"' in source
+ assert 'PIP_LOG_DIR="$VOCULINUX_TMP_DIR/pip"' in source
+ assert 'export TMPDIR="$VOCULINUX_TMP_DIR"' in source
+ assert 'TEMP_FILE="$VOCULINUX_TMP_DIR/tiny.pt"' in source
+ assert 'TEMP_FILE="$VOCULINUX_TMP_DIR/ggml-tiny.bin"' in source
+ assert 'TEMP_ZIP="$VOCULINUX_TMP_DIR/$(basename $SMALL_MODEL_URL)"' in source
def test_system_dep_and_venv_failures_use_structured_exit_codes() -> None:
@@ -67,10 +67,10 @@ def test_system_dep_and_venv_failures_use_structured_exit_codes() -> None:
bootstrap_failure = source.split("install_pinned_build_tools || {", 1)[1].split("}", 1)[0]
assert 'exit "$EXIT_NETWORK"' in bootstrap_failure
assert (
- 'print_error "Failed to install Vocalinux package. Installation cannot continue."' in source
+ 'print_error "Failed to install Voculinux package. Installation cannot continue."' in source
)
assert 'exit "$EXIT_NETWORK"' in source
- assert "Could not terminate all Vocalinux processes" in source
+ assert "Could not terminate all Voculinux processes" in source
assert 'exit "$EXIT_USER_ABORT"' in source
diff --git a/tests/test_installer_tty_prompts.py b/tests/test_installer_tty_prompts.py
index e97b148..ec54cbc 100644
--- a/tests/test_installer_tty_prompts.py
+++ b/tests/test_installer_tty_prompts.py
@@ -108,7 +108,7 @@ def test_piped_installer_reaches_past_the_stdin_probe(tmp_path: Path) -> None:
check=False,
)
output = transcript.read_text(encoding="utf-8", errors="replace")
- assert "Vocalinux Installer" in output
+ assert "Voculinux Installer" in output
assert "Usage:" in output
diff --git a/tests/test_installer_upgrade.py b/tests/test_installer_upgrade.py
index 296a36c..068c42d 100644
--- a/tests/test_installer_upgrade.py
+++ b/tests/test_installer_upgrade.py
@@ -359,7 +359,7 @@ run_interactive_install
echo "U=$UPGRADE_MODE N=$NON_INTERACTIVE I=$INTERACTIVE_MODE"
""")
- assert "existing Vocalinux installation was detected" in result.stdout
+ assert "existing Voculinux installation was detected" in result.stdout
assert "REACHED_GUIDED_SETUP" not in result.stdout
assert "U=yes N=yes I=no" in result.stdout
@@ -407,7 +407,7 @@ def test_piped_installer_defaults_to_upgrade_on_existing_install(tmp_path: Path)
venv = tmp_path / "venv"
(venv / "bin").mkdir(parents=True)
(venv / "bin" / "activate").touch()
- config_dir = tmp_path / ".config" / "vocalinux"
+ config_dir = tmp_path / ".config" / "voculinux"
config_dir.mkdir(parents=True)
(config_dir / "config.json").write_text(json.dumps({"speech_recognition": {"engine": "vosk"}}))
@@ -432,7 +432,7 @@ def test_piped_installer_defaults_to_upgrade_on_existing_install(tmp_path: Path)
env = os.environ.copy()
env["HOME"] = str(tmp_path)
# conftest points XDG_CONFIG_HOME at an isolation dir; the installer reads
- # config.json from $XDG_CONFIG_HOME/vocalinux, not straight from $HOME.
+ # config.json from $XDG_CONFIG_HOME/voculinux, not straight from $HOME.
env["XDG_CONFIG_HOME"] = str(tmp_path / ".config")
env["XDG_STATE_HOME"] = str(tmp_path / ".local" / "state")
env["TMPDIR"] = str(tmp_path)
diff --git a/tests/test_integration_branches.py b/tests/test_integration_branches.py
index 15d1287..9598afc 100644
--- a/tests/test_integration_branches.py
+++ b/tests/test_integration_branches.py
@@ -1,5 +1,5 @@
"""
-Branch coverage tests for Vocalinux.
+Branch coverage tests for Voculinux.
This module tests uncovered branches in:
- recognition_manager.py
@@ -533,7 +533,7 @@ class TestRecognitionManagerModelReady:
class TestParseArguments:
"""Test parse_arguments function."""
- @patch("sys.argv", ["vocalinux", "--debug"])
+ @patch("sys.argv", ["voculinux", "--debug"])
def test_parse_arguments_debug(self):
"""Test parse_arguments with --debug flag."""
from vocalinux.main import parse_arguments
@@ -541,7 +541,7 @@ class TestParseArguments:
args = parse_arguments()
assert args.debug is True
- @patch("sys.argv", ["vocalinux", "--engine", "whisper"])
+ @patch("sys.argv", ["voculinux", "--engine", "whisper"])
def test_parse_arguments_engine(self):
"""Test parse_arguments with --engine flag."""
from vocalinux.main import parse_arguments
@@ -549,7 +549,7 @@ class TestParseArguments:
args = parse_arguments()
assert args.engine == "whisper"
- @patch("sys.argv", ["vocalinux", "--model", "large"])
+ @patch("sys.argv", ["voculinux", "--model", "large"])
def test_parse_arguments_model(self):
"""Test parse_arguments with --model flag."""
from vocalinux.main import parse_arguments
@@ -557,7 +557,7 @@ class TestParseArguments:
args = parse_arguments()
assert args.model == "large"
- @patch("sys.argv", ["vocalinux", "--language", "en-us"])
+ @patch("sys.argv", ["voculinux", "--language", "en-us"])
def test_parse_arguments_language(self):
"""Test parse_arguments with --language flag."""
from vocalinux.main import parse_arguments
@@ -565,7 +565,7 @@ class TestParseArguments:
args = parse_arguments()
assert args.language == "en-us"
- @patch("sys.argv", ["vocalinux", "--wayland"])
+ @patch("sys.argv", ["voculinux", "--wayland"])
def test_parse_arguments_wayland(self):
"""Test parse_arguments with --wayland flag."""
from vocalinux.main import parse_arguments
@@ -573,7 +573,7 @@ class TestParseArguments:
args = parse_arguments()
assert args.wayland is True
- @patch("sys.argv", ["vocalinux", "--start-minimized"])
+ @patch("sys.argv", ["voculinux", "--start-minimized"])
def test_parse_arguments_start_minimized(self):
"""Test parse_arguments with --start-minimized flag."""
from vocalinux.main import parse_arguments
@@ -898,7 +898,7 @@ class TestRecognitionManagerUpdateState:
class TestParseArgumentsCombinations:
"""Test parse_arguments with various flag combinations."""
- @patch("sys.argv", ["vocalinux", "--debug", "--engine", "vosk", "--wayland"])
+ @patch("sys.argv", ["voculinux", "--debug", "--engine", "vosk", "--wayland"])
def test_parse_arguments_multiple_flags(self):
"""Test parse_arguments with multiple flags."""
from vocalinux.main import parse_arguments
@@ -908,7 +908,7 @@ class TestParseArgumentsCombinations:
assert args.engine == "vosk"
assert args.wayland is True
- @patch("sys.argv", ["vocalinux"])
+ @patch("sys.argv", ["voculinux"])
def test_parse_arguments_no_flags(self):
"""Test parse_arguments with no flags."""
from vocalinux.main import parse_arguments
@@ -1306,7 +1306,7 @@ class TestCallbackManagement:
class TestParseArgumentsAllCombos:
"""Test all argument combinations."""
- @patch("sys.argv", ["vocalinux", "--model", "small"])
+ @patch("sys.argv", ["voculinux", "--model", "small"])
def test_parse_arguments_model_small(self):
"""Test parse_arguments with small model."""
from vocalinux.main import parse_arguments
@@ -1314,7 +1314,7 @@ class TestParseArgumentsAllCombos:
args = parse_arguments()
assert args.model == "small"
- @patch("sys.argv", ["vocalinux", "--model", "medium"])
+ @patch("sys.argv", ["voculinux", "--model", "medium"])
def test_parse_arguments_model_medium(self):
"""Test parse_arguments with medium model."""
from vocalinux.main import parse_arguments
@@ -1322,7 +1322,7 @@ class TestParseArgumentsAllCombos:
args = parse_arguments()
assert args.model == "medium"
- @patch("sys.argv", ["vocalinux", "--language", "hi"])
+ @patch("sys.argv", ["voculinux", "--language", "hi"])
def test_parse_arguments_language_hi(self):
"""Test parse_arguments with Hindi language."""
from vocalinux.main import parse_arguments
@@ -1330,7 +1330,7 @@ class TestParseArgumentsAllCombos:
args = parse_arguments()
assert args.language == "hi"
- @patch("sys.argv", ["vocalinux", "--language", "es"])
+ @patch("sys.argv", ["voculinux", "--language", "es"])
def test_parse_arguments_language_es(self):
"""Test parse_arguments with Spanish language."""
from vocalinux.main import parse_arguments
@@ -1338,7 +1338,7 @@ class TestParseArgumentsAllCombos:
args = parse_arguments()
assert args.language == "es"
- @patch("sys.argv", ["vocalinux", "--engine", "vosk"])
+ @patch("sys.argv", ["voculinux", "--engine", "vosk"])
def test_parse_arguments_engine_vosk(self):
"""Test parse_arguments with vosk engine."""
from vocalinux.main import parse_arguments
@@ -1346,7 +1346,7 @@ class TestParseArgumentsAllCombos:
args = parse_arguments()
assert args.engine == "vosk"
- @patch("sys.argv", ["vocalinux", "--engine", "whisper_cpp"])
+ @patch("sys.argv", ["voculinux", "--engine", "whisper_cpp"])
def test_parse_arguments_engine_whisper_cpp(self):
"""Test parse_arguments with whisper_cpp engine."""
from vocalinux.main import parse_arguments
diff --git a/tests/test_keyboard_init_ext.py b/tests/test_keyboard_init_ext.py
index 3e0ba65..e45c7ee 100644
--- a/tests/test_keyboard_init_ext.py
+++ b/tests/test_keyboard_init_ext.py
@@ -56,7 +56,7 @@ class TestDesktopEnvironmentDetect:
is set — pynput over XWayland is not truly global.
"""
env = {
- "FLATPAK_ID": "com.vocalinux.Vocalinux",
+ "FLATPAK_ID": "com.voculinux.Voculinux",
"XDG_SESSION_TYPE": "wayland",
"DISPLAY": ":0",
}
@@ -66,7 +66,7 @@ class TestDesktopEnvironmentDetect:
def test_detect_flatpak_wayland_with_socket_stays_wayland(self):
"""With a Wayland socket exposed, detection still reports Wayland."""
env = {
- "FLATPAK_ID": "com.vocalinux.Vocalinux",
+ "FLATPAK_ID": "com.voculinux.Voculinux",
"XDG_SESSION_TYPE": "wayland",
"WAYLAND_DISPLAY": "wayland-0",
}
@@ -81,7 +81,7 @@ class TestDesktopEnvironmentDetect:
fake.is_available.return_value = True
env = {
- "FLATPAK_ID": "com.vocalinux.Vocalinux",
+ "FLATPAK_ID": "com.voculinux.Voculinux",
"XDG_SESSION_TYPE": "wayland",
"DISPLAY": ":0",
}
@@ -119,7 +119,7 @@ class TestDesktopEnvironmentDetect:
def test_create_backend_flatpak_native_x11_prefers_pynput(self) -> None:
"""Flatpak on native X11 uses pynput outside GNOME."""
env = {
- "FLATPAK_ID": "com.vocalinux.Vocalinux",
+ "FLATPAK_ID": "com.voculinux.Voculinux",
"XDG_SESSION_TYPE": "x11",
"XDG_CURRENT_DESKTOP": "X-Cinnamon",
"DISPLAY": ":0",
@@ -140,7 +140,7 @@ class TestDesktopEnvironmentDetect:
def test_create_backend_flatpak_gnome_native_x11_prefers_evdev(self) -> None:
"""Flatpak on GNOME X11 prefers evdev."""
env = {
- "FLATPAK_ID": "com.vocalinux.Vocalinux",
+ "FLATPAK_ID": "com.voculinux.Voculinux",
"XDG_SESSION_TYPE": "x11",
"XDG_CURRENT_DESKTOP": "GNOME",
"DISPLAY": ":0",
@@ -162,7 +162,7 @@ class TestDesktopEnvironmentDetect:
def test_create_backend_flatpak_gnome_native_x11_falls_back_to_pynput(self) -> None:
"""Flatpak on GNOME X11 falls back when evdev cannot read /dev/input."""
env = {
- "FLATPAK_ID": "com.vocalinux.Vocalinux",
+ "FLATPAK_ID": "com.voculinux.Voculinux",
"XDG_SESSION_TYPE": "x11",
"XDG_CURRENT_DESKTOP": "GNOME",
"DISPLAY": ":0",
@@ -187,7 +187,7 @@ class TestDesktopEnvironmentDetect:
def test_create_backend_flatpak_x11_with_wayland_display_prefers_evdev(self) -> None:
"""A Wayland socket keeps Flatpak on the evdev path."""
env = {
- "FLATPAK_ID": "com.vocalinux.Vocalinux",
+ "FLATPAK_ID": "com.voculinux.Voculinux",
"XDG_SESSION_TYPE": "x11",
"WAYLAND_DISPLAY": "wayland-0",
"DISPLAY": ":0",
@@ -209,7 +209,7 @@ class TestDesktopEnvironmentDetect:
def test_create_backend_flatpak_xwayland_without_evdev_returns_none(self) -> None:
"""A Flatpak on a Wayland session without input access needs evdev."""
env = {
- "FLATPAK_ID": "com.vocalinux.Vocalinux",
+ "FLATPAK_ID": "com.voculinux.Voculinux",
"XDG_SESSION_TYPE": "wayland",
"DISPLAY": ":0",
}
@@ -231,7 +231,7 @@ class TestDesktopEnvironmentDetect:
def test_create_backend_flatpak_unknown_session_prefers_evdev(self) -> None:
"""Unknown Flatpak sessions conservatively prefer evdev."""
env = {
- "FLATPAK_ID": "com.vocalinux.Vocalinux",
+ "FLATPAK_ID": "com.voculinux.Voculinux",
"DISPLAY": ":0",
}
fake = MagicMock()
diff --git a/tests/test_keyboard_shortcuts.py b/tests/test_keyboard_shortcuts.py
index 5927603..6811a84 100644
--- a/tests/test_keyboard_shortcuts.py
+++ b/tests/test_keyboard_shortcuts.py
@@ -375,7 +375,7 @@ class TestKeyboardShortcuts(unittest.TestCase):
def test_unavailable_hints_snap_lists_both_connects(self):
"""Snap log banner should list both raw-input and hardware-observe."""
self.mock_create_backend.return_value = None
- with patch.dict("os.environ", {"SNAP": "/snap/vocalinux/x1"}, clear=False):
+ with patch.dict("os.environ", {"SNAP": "/snap/voculinux/x1"}, clear=False):
with patch("vocalinux.ui.keyboard_shortcuts.logger") as mock_logger:
KeyboardShortcutManager()
diff --git a/tests/test_language_shortcuts.py b/tests/test_language_shortcuts.py
index e53edd1..18f325e 100644
--- a/tests/test_language_shortcuts.py
+++ b/tests/test_language_shortcuts.py
@@ -106,7 +106,7 @@ def test_normalize_language_shortcuts_dedupes_by_shortcut() -> None:
def test_language_shortcuts_roundtrip_through_config(tmp_path: Any) -> None:
- config_dir = tmp_path / "vocalinux"
+ config_dir = tmp_path / "voculinux"
config_dir.mkdir()
config_file = config_dir / "config.json"
with (
@@ -137,7 +137,7 @@ def test_language_shortcuts_roundtrip_through_config(tmp_path: Any) -> None:
def test_get_language_shortcuts_survives_a_broken_shortcuts_section() -> None:
"""A hand-edited config replacing the section with a scalar reads as empty."""
with tempfile.TemporaryDirectory() as temp_dir:
- config_dir = os.path.join(temp_dir, "vocalinux")
+ config_dir = os.path.join(temp_dir, "voculinux")
config_file = os.path.join(config_dir, "config.json")
os.makedirs(config_dir, exist_ok=True)
with open(config_file, "w") as handle:
@@ -1062,7 +1062,7 @@ def test_slovenian_shortcut_row_persists_through_config(
dialog_class: type[Any], tmp_path: Any
) -> None:
"""A row picked as Slovenian is saved and read back, not dropped (#970)."""
- config_dir = tmp_path / "vocalinux"
+ config_dir = tmp_path / "voculinux"
config_dir.mkdir()
with (
patch("vocalinux.ui.config_manager.CONFIG_DIR", str(config_dir)),
diff --git a/tests/test_legacy_import.py b/tests/test_legacy_import.py
new file mode 100644
index 0000000..6e99ced
--- /dev/null
+++ b/tests/test_legacy_import.py
@@ -0,0 +1,147 @@
+"""Ticket #18: one-time legacy Vocalinux import into the Voculinux locations.
+
+Seams under test (all offline, no hardware):
+- A fresh run with a legacy install present imports ``config.json``, the
+ custom dictionary, and the portal restore token exactly once and logs it;
+ a second run imports nothing.
+- A fresh run with an existing new configuration never imports, merges, or
+ writes to the legacy location.
+- A fresh run with no legacy install starts from defaults (nothing imported).
+- Models are not migrated.
+"""
+
+import json
+from pathlib import Path
+
+from vocalinux import legacy_import
+from vocalinux.legacy_import import import_legacy_once
+
+
+def _isolate(monkeypatch, tmp_path: Path) -> tuple[Path, Path]:
+ """Point XDG roots at scratch dirs; return (config_root, data_root)."""
+ config_root = tmp_path / "config"
+ data_root = tmp_path / "data"
+ monkeypatch.setenv("XDG_CONFIG_HOME", str(config_root))
+ monkeypatch.setenv("XDG_DATA_HOME", str(data_root))
+ return config_root, data_root
+
+
+def _seed_legacy(config_root: Path, data_root: Path) -> dict[str, Path]:
+ """Create a legacy install's payload; return the created files."""
+ legacy_config = config_root / "vocalinux"
+ legacy_data = data_root / "vocalinux"
+ legacy_config.mkdir(parents=True)
+ legacy_data.mkdir(parents=True)
+ created = {}
+ for name, content in (
+ ("config.json", '{"general": {"first_run": false}}'),
+ ("dictionary.txt", "Supabase\n"),
+ ("custom-dictionary-corrections.json", json.dumps({"version": 1, "corrections": []})),
+ ):
+ target = legacy_config / name
+ target.write_text(content, encoding="utf-8")
+ created[name] = target
+ token = legacy_data / "remote_desktop_restore_token"
+ token.write_text("legacy-token\n", encoding="utf-8")
+ created["remote_desktop_restore_token"] = token
+ return created
+
+
+def test_fresh_run_with_legacy_install_imports_once(monkeypatch, tmp_path, caplog) -> None:
+ """Legacy config, dictionary, and restore token copy over exactly once."""
+ config_root, data_root = _isolate(monkeypatch, tmp_path)
+ _seed_legacy(config_root, data_root)
+
+ with caplog.at_level("INFO", logger="vocalinux.legacy_import"):
+ imported = import_legacy_once()
+
+ assert len(imported) == 4
+ assert (
+ config_root / "voculinux" / "config.json"
+ ).read_text() == '{"general": {"first_run": false}}'
+ assert (config_root / "voculinux" / "dictionary.txt").read_text() == "Supabase\n"
+ assert json.loads(
+ (config_root / "voculinux" / "custom-dictionary-corrections.json").read_text()
+ ) == {
+ "version": 1,
+ "corrections": [],
+ }
+ assert (
+ data_root / "voculinux" / "remote_desktop_restore_token"
+ ).read_text() == "legacy-token\n"
+ assert any("Legacy Vocalinux import complete" in r.message for r in caplog.records)
+
+ # A second run imports nothing.
+ assert import_legacy_once() == []
+
+
+def test_existing_new_config_never_imports_or_touches_legacy(monkeypatch, tmp_path) -> None:
+ """An existing new configuration always wins: no merge, no write-back."""
+ config_root, data_root = _isolate(monkeypatch, tmp_path)
+ seeded = _seed_legacy(config_root, data_root)
+ before = {name: path.read_bytes() for name, path in seeded.items()}
+
+ new_config = config_root / "voculinux"
+ new_config.mkdir(parents=True)
+ (new_config / "config.json").write_text('{"general": {"first_run": true}}', encoding="utf-8")
+
+ assert import_legacy_once() == []
+ assert (new_config / "config.json").read_text() == '{"general": {"first_run": true}}'
+ assert not (new_config / "dictionary.txt").exists()
+ assert not (data_root / "voculinux").exists()
+ for name, path in seeded.items():
+ assert path.read_bytes() == before[name], name
+
+
+def test_no_legacy_install_starts_from_defaults(monkeypatch, tmp_path) -> None:
+ """No legacy directories means nothing is imported."""
+ _isolate(monkeypatch, tmp_path)
+ assert import_legacy_once() == []
+
+
+def test_models_are_not_migrated(monkeypatch, tmp_path) -> None:
+ """A legacy models directory is left alone; rung files re-download."""
+ config_root, data_root = _isolate(monkeypatch, tmp_path)
+ _seed_legacy(config_root, data_root)
+ legacy_models = data_root / "vocalinux" / "models"
+ legacy_models.mkdir(parents=True)
+ (legacy_models / "ggml-large-v3-turbo-q8_0.bin").write_bytes(b"fake-model")
+
+ imported = import_legacy_once()
+
+ assert not (data_root / "voculinux" / "models").exists()
+ assert {Path(p).name for p in imported} == {
+ "config.json",
+ "dictionary.txt",
+ "custom-dictionary-corrections.json",
+ "remote_desktop_restore_token",
+ }
+
+
+def test_partial_legacy_payload_imports_what_exists(monkeypatch, tmp_path) -> None:
+ """A legacy install with only a config still imports just that file."""
+ config_root, _data_root = _isolate(monkeypatch, tmp_path)
+ legacy_config = config_root / "vocalinux"
+ legacy_config.mkdir(parents=True)
+ (legacy_config / "config.json").write_text("{}", encoding="utf-8")
+
+ imported = import_legacy_once()
+
+ assert imported == [str(config_root / "voculinux" / "config.json")]
+ assert import_legacy_once() == []
+
+
+def test_new_dictionary_never_overwritten_by_legacy(monkeypatch, tmp_path) -> None:
+ """A new dictionary file is never clobbered even when config is absent."""
+ config_root, data_root = _isolate(monkeypatch, tmp_path)
+ _seed_legacy(config_root, data_root)
+ new_config = config_root / "voculinux"
+ new_config.mkdir(parents=True)
+ (new_config / "dictionary.txt").write_text("Mine\n", encoding="utf-8")
+
+ import_legacy_once()
+
+ # No new config.json exists, so the import ran — but the existing new
+ # dictionary file must survive untouched.
+ assert (new_config / "dictionary.txt").read_text() == "Mine\n"
+ assert legacy_import.CONFIG_FILENAME == "config.json"
diff --git a/tests/test_logging_manager.py b/tests/test_logging_manager.py
index 7314c51..f8f1647 100644
--- a/tests/test_logging_manager.py
+++ b/tests/test_logging_manager.py
@@ -129,7 +129,7 @@ class TestLoggingManager:
manager = lm.LoggingManager(max_records=10)
try:
- assert manager.logs_dir == tmp_path / "vocalinux" / "logs"
+ assert manager.logs_dir == tmp_path / "voculinux" / "logs"
assert manager.logs_dir.is_dir()
finally:
root_logger.removeHandler(manager.handler)
@@ -296,7 +296,7 @@ class TestLoggingManager:
record2 = LogRecord(
timestamp=datetime.now(),
level="INFO",
- logger_name="vocalinux.speech.test",
+ logger_name="voculinux.speech.test",
message="Speech message",
)
logging_manager.add_log_record(record1)
@@ -353,7 +353,7 @@ class TestLoggingManager:
with open(filepath, "r") as f:
content = f.read()
- assert "VocaLinux Log Export" in content
+ assert "Voculinux Log Export" in content
assert "Export test message" in content
finally:
if os.path.exists(filepath):
@@ -451,7 +451,7 @@ class TestLoggingManager:
record2 = LogRecord(
timestamp=timestamp2,
level="ERROR",
- logger_name="vocalinux.speech.test",
+ logger_name="voculinux.speech.test",
message="Message 2",
)
logging_manager.add_log_record(record1)
@@ -462,7 +462,7 @@ class TestLoggingManager:
assert stats["total"] == 2
assert stats["by_level"]["INFO"] == 1
assert stats["by_level"]["ERROR"] == 1
- assert "vocalinux" in stats["by_module"]
+ assert "voculinux" in stats["by_module"]
assert stats["oldest"] == timestamp1
assert stats["newest"] == timestamp2
diff --git a/tests/test_main.py b/tests/test_main.py
index 0609ad7..a092b9e 100644
--- a/tests/test_main.py
+++ b/tests/test_main.py
@@ -29,7 +29,7 @@ class TestMainModule(unittest.TestCase):
def test_parse_arguments_defaults(self):
"""Test argument parsing with defaults."""
# Test with no arguments (model/engine/language will be None without defaults)
- with patch("sys.argv", ["vocalinux"]):
+ with patch("sys.argv", ["voculinux"]):
args = parse_arguments()
self.assertFalse(args.debug)
self.assertIsNone(args.model) # No default set, loaded from config instead
@@ -45,7 +45,7 @@ class TestMainModule(unittest.TestCase):
with patch(
"sys.argv",
[
- "vocalinux",
+ "voculinux",
"--debug",
"--model",
"large",
@@ -67,33 +67,33 @@ class TestMainModule(unittest.TestCase):
def test_parse_arguments_model_values(self):
"""Test model parsing for base and exact whisper.cpp model IDs."""
- with patch("sys.argv", ["vocalinux", "--model", "small"]):
+ with patch("sys.argv", ["voculinux", "--model", "small"]):
args = parse_arguments()
self.assertEqual(args.model, "small")
- with patch("sys.argv", ["vocalinux", "--model", "medium"]):
+ with patch("sys.argv", ["voculinux", "--model", "medium"]):
args = parse_arguments()
self.assertEqual(args.model, "medium")
- with patch("sys.argv", ["vocalinux", "--model", "large"]):
+ with patch("sys.argv", ["voculinux", "--model", "large"]):
args = parse_arguments()
self.assertEqual(args.model, "large")
- with patch("sys.argv", ["vocalinux", "--model", "medium.en-q5_0"]):
+ with patch("sys.argv", ["voculinux", "--model", "medium.en-q5_0"]):
args = parse_arguments()
self.assertEqual(args.model, "medium.en-q5_0")
- with patch("sys.argv", ["vocalinux", "--model", "large-v3-turbo"]):
+ with patch("sys.argv", ["voculinux", "--model", "large-v3-turbo"]):
args = parse_arguments()
self.assertEqual(args.model, "large-v3-turbo")
def test_parse_arguments_engine_choices(self):
"""Test that engine only accepts valid choices."""
- with patch("sys.argv", ["vocalinux", "--engine", "vosk"]):
+ with patch("sys.argv", ["voculinux", "--engine", "vosk"]):
args = parse_arguments()
self.assertEqual(args.engine, "vosk")
- with patch("sys.argv", ["vocalinux", "--engine", "whisper"]):
+ with patch("sys.argv", ["voculinux", "--engine", "whisper"]):
args = parse_arguments()
self.assertEqual(args.engine, "whisper")
@@ -106,7 +106,7 @@ class TestMainModule(unittest.TestCase):
# Spot-check newly exposed languages (issue #565 and catalog expansion).
for lang in ["auto", "en-us", "hu", "ja", "ko", "ar", "nl", "pl", "sl", "uk"]:
self.assertIn(lang, LANGUAGE_CHOICES)
- with patch("sys.argv", ["vocalinux", "--language", lang]):
+ with patch("sys.argv", ["voculinux", "--language", lang]):
args = parse_arguments()
self.assertEqual(args.language, lang)
@@ -399,7 +399,7 @@ class TestMainModule(unittest.TestCase):
mock_args.start_minimized = False
mock_parse.return_value = mock_args
- with patch("sys.argv", ["vocalinux", "--engine", engine]):
+ with patch("sys.argv", ["voculinux", "--engine", engine]):
main()
text_callback = mock_speech_instance.register_text_callback.call_args.args[0]
@@ -923,7 +923,7 @@ class TestMainConfigPrecedence(unittest.TestCase):
with patch(
"sys.argv",
[
- "vocalinux",
+ "voculinux",
"--engine",
"whisper",
"--model",
@@ -989,7 +989,7 @@ class TestMainConfigPrecedence(unittest.TestCase):
mock_action_handler.return_value = mock_action_instance
# No CLI args for engine/model/language
- with patch("sys.argv", ["vocalinux"]):
+ with patch("sys.argv", ["voculinux"]):
with patch("vocalinux.main.logger"):
main()
@@ -1040,7 +1040,7 @@ class TestMainConfigPrecedence(unittest.TestCase):
with patch(
"sys.argv",
[
- "vocalinux",
+ "voculinux",
"--engine",
"parakeet",
"--model",
@@ -1094,7 +1094,7 @@ class TestMainConfigPrecedence(unittest.TestCase):
mock_tray.return_value = MagicMock()
mock_action_handler.return_value = MagicMock()
- with patch("sys.argv", ["vocalinux"]):
+ with patch("sys.argv", ["voculinux"]):
with patch("vocalinux.main.logger"):
main()
@@ -1151,7 +1151,7 @@ class TestMainConfigPrecedence(unittest.TestCase):
mock_tray.return_value = MagicMock()
mock_action_handler.return_value = MagicMock()
- with patch("sys.argv", ["vocalinux"]):
+ with patch("sys.argv", ["voculinux"]):
with patch("vocalinux.main.logger"):
main()
@@ -1368,7 +1368,7 @@ def _boot_main_callbacks(
)
)
mock_parse = stack.enter_context(patch("vocalinux.main.parse_arguments"))
- stack.enter_context(patch("sys.argv", ["vocalinux"]))
+ stack.enter_context(patch("sys.argv", ["voculinux"]))
mock_args = MagicMock()
mock_args.debug = False
@@ -2144,7 +2144,7 @@ class TestSessionHistoryRecording(unittest.TestCase):
stack.enter_context(patch("vocalinux.ui.logging_manager.initialize_logging"))
mock_parse = stack.enter_context(patch("vocalinux.main.parse_arguments"))
- stack.enter_context(patch("sys.argv", ["vocalinux"]))
+ stack.enter_context(patch("sys.argv", ["voculinux"]))
mock_args = MagicMock()
mock_args.debug = False
diff --git a/tests/test_main_args_deps.py b/tests/test_main_args_deps.py
index 8d3e3ba..3e0d46a 100644
--- a/tests/test_main_args_deps.py
+++ b/tests/test_main_args_deps.py
@@ -1,7 +1,7 @@
"""
Additional coverage tests for main.py module.
-Tests for parse_args(), main(), and VocalinuxApp class (if present).
+Tests for parse_args(), main(), and VoculinuxApp class (if present).
Covers normal startup, debug mode, version flag, keyboard interrupt, and exception handling.
"""
@@ -41,7 +41,7 @@ class TestParseArguments(unittest.TestCase):
def test_parse_args_defaults(self):
"""Test parsing arguments with defaults."""
- with patch.object(sys, "argv", ["vocalinux"]):
+ with patch.object(sys, "argv", ["voculinux"]):
from vocalinux.main import parse_arguments
args = parse_arguments()
@@ -55,7 +55,7 @@ class TestParseArguments(unittest.TestCase):
def test_parse_args_debug_flag(self):
"""Test parsing with debug flag."""
- with patch.object(sys, "argv", ["vocalinux", "--debug"]):
+ with patch.object(sys, "argv", ["voculinux", "--debug"]):
from vocalinux.main import parse_arguments
args = parse_arguments()
@@ -66,18 +66,18 @@ class TestParseArguments(unittest.TestCase):
from vocalinux.version import __version__
output = StringIO()
- with patch.object(sys, "argv", ["vocalinux", "--version"]):
+ with patch.object(sys, "argv", ["voculinux", "--version"]):
from vocalinux.main import parse_arguments
with redirect_stdout(output), self.assertRaises(SystemExit) as exit_context:
parse_arguments()
assert exit_context.exception.code == 0
- assert output.getvalue() == f"vocalinux {__version__}\n"
+ assert output.getvalue() == f"voculinux {__version__}\n"
def test_parse_args_model_argument(self):
"""Test parsing with model argument."""
- with patch.object(sys, "argv", ["vocalinux", "--model", "small"]):
+ with patch.object(sys, "argv", ["voculinux", "--model", "small"]):
from vocalinux.main import parse_arguments
args = parse_arguments()
@@ -85,7 +85,7 @@ class TestParseArguments(unittest.TestCase):
def test_parse_args_language_argument(self):
"""Test parsing with language argument."""
- with patch.object(sys, "argv", ["vocalinux", "--language", "en-us"]):
+ with patch.object(sys, "argv", ["voculinux", "--language", "en-us"]):
from vocalinux.main import parse_arguments
args = parse_arguments()
@@ -93,7 +93,7 @@ class TestParseArguments(unittest.TestCase):
def test_parse_args_engine_argument(self):
"""Test parsing with engine argument."""
- with patch.object(sys, "argv", ["vocalinux", "--engine", "whisper_cpp"]):
+ with patch.object(sys, "argv", ["voculinux", "--engine", "whisper_cpp"]):
from vocalinux.main import parse_arguments
args = parse_arguments()
@@ -101,7 +101,7 @@ class TestParseArguments(unittest.TestCase):
def test_parse_args_wayland_flag(self):
"""Test parsing with wayland flag."""
- with patch.object(sys, "argv", ["vocalinux", "--wayland"]):
+ with patch.object(sys, "argv", ["voculinux", "--wayland"]):
from vocalinux.main import parse_arguments
args = parse_arguments()
@@ -109,7 +109,7 @@ class TestParseArguments(unittest.TestCase):
def test_parse_args_start_minimized_flag(self):
"""Test parsing with start-minimized flag."""
- with patch.object(sys, "argv", ["vocalinux", "--start-minimized"]):
+ with patch.object(sys, "argv", ["voculinux", "--start-minimized"]):
from vocalinux.main import parse_arguments
args = parse_arguments()
@@ -117,7 +117,7 @@ class TestParseArguments(unittest.TestCase):
def test_parse_args_transcribe_file(self):
"""Test parsing with the headless --transcribe-file flag."""
- with patch.object(sys, "argv", ["vocalinux", "--transcribe-file", "/tmp/a.wav"]):
+ with patch.object(sys, "argv", ["voculinux", "--transcribe-file", "/tmp/a.wav"]):
from vocalinux.main import parse_arguments
args = parse_arguments()
@@ -157,7 +157,7 @@ class TestParseArguments(unittest.TestCase):
sys,
"argv",
[
- "vocalinux",
+ "voculinux",
"--debug",
"--model",
"large",
@@ -353,13 +353,13 @@ class TestMainFunction(unittest.TestCase):
output = StringIO()
with patch.dict(sys.modules, {"vocalinux.single_instance": mock_single_instance}):
- with patch.object(sys, "argv", ["vocalinux", "--version"]):
+ with patch.object(sys, "argv", ["voculinux", "--version"]):
with redirect_stdout(output):
with pytest.raises(SystemExit) as exc_info:
main()
assert exc_info.value.code == 0
- assert output.getvalue() == f"vocalinux {__version__}\n"
+ assert output.getvalue() == f"voculinux {__version__}\n"
mock_single_instance.acquire_lock.assert_not_called()
@patch("vocalinux.main.check_display_available")
diff --git a/tests/test_main_edge_cases.py b/tests/test_main_edge_cases.py
index 70f56ee..1c6146c 100644
--- a/tests/test_main_edge_cases.py
+++ b/tests/test_main_edge_cases.py
@@ -341,7 +341,7 @@ class TestMainFunctionExtra:
with patch.object(
sys,
"argv",
- ["vocalinux", "--engine", "vosk", "--model", "medium", "--language", "es"],
+ ["voculinux", "--engine", "vosk", "--model", "medium", "--language", "es"],
):
with pytest.raises(SystemExit) as exc_info:
main()
diff --git a/tests/test_model_checksums.py b/tests/test_model_checksums.py
index e9e5fd1..4dcb8be 100644
--- a/tests/test_model_checksums.py
+++ b/tests/test_model_checksums.py
@@ -140,7 +140,7 @@ class TestManifestCoverage(unittest.TestCase):
class TestVerifyFile(unittest.TestCase):
def setUp(self):
self.tmp = Path(self.enterContext(__import__("tempfile").TemporaryDirectory()))
- self.payload = b"vocalinux model payload"
+ self.payload = b"voculinux model payload"
self.path = self.tmp / "model.bin"
self.path.write_bytes(self.payload)
self.digest = hashlib.sha256(self.payload).hexdigest()
@@ -416,7 +416,7 @@ class TestExistingModelsAreVerified(unittest.TestCase):
for name, checker in (
("install_whisper_model", "verify_openai_model_checksum"),
("install_whispercpp_model", "verify_model_checksum"),
- ("install_vosk_models", ".vocalinux_verified"),
+ ("install_vosk_models", ".voculinux_verified"),
):
guard = self._exists_guard(name)
self.assertLess(
@@ -484,9 +484,9 @@ print_error() { echo "ERROR: $*"; }
print_success() { echo "SUCCESS: $*"; }
command_exists() { command -v "$1" >/dev/null 2>&1; }
DATA_DIR="$ROOT/data"
-VOCALINUX_TMP_DIR="$ROOT/tmp"
+VOCULINUX_TMP_DIR="$ROOT/tmp"
MODEL_CHECKSUMS_FILE="$ROOT/model_checksums.txt"
-mkdir -p "$VOCALINUX_TMP_DIR"
+mkdir -p "$VOCULINUX_TMP_DIR"
# The installer only probes for these; the download itself is stubbed out.
check_connectivity() { return 0; }
@@ -663,8 +663,8 @@ download_model_file() { echo "DOWNLOAD ATTEMPTED"; return 1; }
"""The 40MB fetch must not happen when nothing can verify it."""
with TemporaryDirectory() as tmp:
result = self._run(
- f'DATA_DIR="{tmp}/data"; VOCALINUX_TMP_DIR="{tmp}/tmp"; '
- f'mkdir -p "$DATA_DIR" "$VOCALINUX_TMP_DIR"; '
+ f'DATA_DIR="{tmp}/data"; VOCULINUX_TMP_DIR="{tmp}/tmp"; '
+ f'mkdir -p "$DATA_DIR" "$VOCULINUX_TMP_DIR"; '
f'MODEL_CHECKSUMS_FILE="{tmp}/nope.txt"; '
"install_vosk_models; echo RC=$?",
functions=("pinned_digest_for", "install_vosk_models"),
diff --git a/tests/test_native_packaging.py b/tests/test_native_packaging.py
index 1d614a0..89430f4 100644
--- a/tests/test_native_packaging.py
+++ b/tests/test_native_packaging.py
@@ -26,7 +26,7 @@ RELEASE_YML = WORKFLOWS / "release.yml"
PIPELINE_YML = WORKFLOWS / "unified-pipeline.yml"
#: Runtime dependencies no distro packages; build.sh vendors their wheels
-#: under /usr/lib/vocalinux/vendor instead of declaring distro deps.
+#: under /usr/lib/voculinux/vendor instead of declaring distro deps.
VENDORED = ("pywhispercpp", "pynput")
#: pip name -> the Debian/Ubuntu package that Provides it. pywhispercpp's own
@@ -267,9 +267,9 @@ def test_nfpm_contents_and_launcher_env_agree() -> None:
text = BUILD_SH.read_text(encoding="utf-8")
smoke = SMOKE_SH.read_text(encoding="utf-8")
for where in (text, smoke):
- assert "/usr/lib/vocalinux/app" in where
- assert "/usr/lib/vocalinux/vendor" in where
- assert "/usr/bin/vocalinux" in text and "/usr/bin/vocalinux-gui" in text
+ assert "/usr/lib/voculinux/app" in where
+ assert "/usr/lib/voculinux/vendor" in where
+ assert "/usr/bin/voculinux" in text and "/usr/bin/voculinux-gui" in text
assert "pywhispercpp.libs" in text and "pywhispercpp.libs" in smoke
# Arguments keep their boundaries: $* into an unquoted exec re-splits a
# path like "Meeting notes.wav" before argparse sees it (PR #913).
@@ -286,8 +286,8 @@ def test_smoke_gate_covers_both_formats() -> None:
smoke = SMOKE_SH.read_text(encoding="utf-8")
assert "debian|ubuntu)" in smoke, "smoke must install the .deb on Debian-family images"
assert "fedora)" in smoke, "smoke must install the .rpm on Fedora"
- assert "vocalinux --version" in smoke
- assert "vocalinux-gui --version" in smoke
+ assert "voculinux --version" in smoke
+ assert "voculinux-gui --version" in smoke
assert "pywhispercpp.model" in smoke, "the smoke must prove the vendored extension loads"
assert (
'find_spec("pynput")' in smoke
diff --git a/tests/test_paste_shortcut.py b/tests/test_paste_shortcut.py
index 91ad03a..e3e9069 100644
--- a/tests/test_paste_shortcut.py
+++ b/tests/test_paste_shortcut.py
@@ -139,7 +139,7 @@ class TestYdotoolTerminalPasteCommand(unittest.TestCase):
def test_flatpak_uses_shift_keycodes(self, mock_which, _mock_map):
mock_which.return_value = "/app/bin/ydotool"
injector = _make_injector()
- with patch.dict("os.environ", {"FLATPAK_ID": "com.vocalinux.Vocalinux"}):
+ with patch.dict("os.environ", {"FLATPAK_ID": "com.voculinux.Voculinux"}):
self.assertEqual(
injector._ydotool_ctrl_v_command(terminal=True),
["ydotool", "key", "29:1", "42:1", "47:1", "47:0", "42:0", "29:0"],
diff --git a/tests/test_paths.py b/tests/test_paths.py
index b541c4d..fec7a75 100644
--- a/tests/test_paths.py
+++ b/tests/test_paths.py
@@ -11,9 +11,9 @@ class TestXdgHelpers:
with patch.dict(os.environ, {}, clear=True):
assert paths.xdg_config_home() == os.path.expanduser("~/.config")
assert paths.xdg_data_home() == os.path.expanduser("~/.local/share")
- assert paths.config_dir() == os.path.expanduser("~/.config/vocalinux")
- assert paths.data_dir() == os.path.expanduser("~/.local/share/vocalinux")
- assert paths.models_dir() == os.path.expanduser("~/.local/share/vocalinux/models")
+ assert paths.config_dir() == os.path.expanduser("~/.config/voculinux")
+ assert paths.data_dir() == os.path.expanduser("~/.local/share/voculinux")
+ assert paths.models_dir() == os.path.expanduser("~/.local/share/voculinux/models")
def test_honours_xdg_environment(self):
env = {
@@ -21,9 +21,9 @@ class TestXdgHelpers:
"XDG_DATA_HOME": "/run/user/1000/data",
}
with patch.dict(os.environ, env, clear=True):
- assert paths.config_dir() == "/run/user/1000/cfg/vocalinux"
- assert paths.data_dir() == "/run/user/1000/data/vocalinux"
- assert paths.models_dir() == "/run/user/1000/data/vocalinux/models"
+ assert paths.config_dir() == "/run/user/1000/cfg/voculinux"
+ assert paths.data_dir() == "/run/user/1000/data/voculinux"
+ assert paths.models_dir() == "/run/user/1000/data/voculinux/models"
def test_empty_env_falls_back_to_default(self):
# The XDG spec says empty values must be treated as unset.
@@ -33,9 +33,9 @@ class TestXdgHelpers:
def test_flatpak_style_data_home(self):
# Flatpak points XDG_DATA_HOME at ~/.var/app//data.
- flatpak_data = "/home/user/.var/app/com.vocalinux.Vocalinux/data"
+ flatpak_data = "/home/user/.var/app/com.voculinux.Voculinux/data"
with patch.dict(os.environ, {"XDG_DATA_HOME": flatpak_data}, clear=True):
- assert paths.models_dir() == os.path.join(flatpak_data, "vocalinux", "models")
+ assert paths.models_dir() == os.path.join(flatpak_data, "voculinux", "models")
def test_is_within_directory(self, tmp_path):
nested = tmp_path / "models" / "ggml-tiny.bin"
diff --git a/tests/test_perf_baseline_protocol.py b/tests/test_perf_baseline_protocol.py
index d005e9d..c09bfa2 100644
--- a/tests/test_perf_baseline_protocol.py
+++ b/tests/test_perf_baseline_protocol.py
@@ -21,9 +21,9 @@ SPEC.loader.exec_module(PROTOCOL)
def test_parse_vmrss_kb_reads_kilobytes() -> None:
"""VmRSS lines parse to kilobytes; anything else yields None."""
- status = "Name:\tvocalinux\nVmRSS:\t 412336 kB\nVmSwap:\t0 kB\n"
+ status = "Name:\tvoculinux\nVmRSS:\t 412336 kB\nVmSwap:\t0 kB\n"
assert PROTOCOL.parse_vmrss_kb(status) == 412336
- assert PROTOCOL.parse_vmrss_kb("Name:\tvocalinux\n") is None
+ assert PROTOCOL.parse_vmrss_kb("Name:\tvoculinux\n") is None
def test_describe_reports_count_mean_min_max() -> None:
diff --git a/tests/test_pipewire_capture.py b/tests/test_pipewire_capture.py
index b9e0308..c2b1d01 100644
--- a/tests/test_pipewire_capture.py
+++ b/tests/test_pipewire_capture.py
@@ -635,7 +635,7 @@ class TestManagerPipeWireIntegration(unittest.TestCase):
if isinstance(sys.modules.get("numpy"), MagicMock):
# Restore the stashed real module — re-importing it would
# leave sys.modules["numpy.*"] bound to an orphan.
- real_numpy = getattr(sys, "_vocalinux_real_numpy", None)
+ real_numpy = getattr(sys, "_voculinux_real_numpy", None)
if real_numpy is not None:
sys.modules["numpy"] = real_numpy
else:
diff --git a/tests/test_playback_ducker.py b/tests/test_playback_ducker.py
index 813c78d..7aecc81 100644
--- a/tests/test_playback_ducker.py
+++ b/tests/test_playback_ducker.py
@@ -36,7 +36,7 @@ def _numpy_is_real_while_comparing() -> Iterator[None]:
``isinstance(value, numpy.bool_)`` and raises TypeError.
"""
current = sys.modules.get("numpy")
- real = getattr(sys, "_vocalinux_real_numpy", None)
+ real = getattr(sys, "_voculinux_real_numpy", None)
if isinstance(current, MagicMock) and real is not None:
sys.modules["numpy"] = real
try:
@@ -620,7 +620,7 @@ def test_pactl_restores_each_channel(tmp_path: Path) -> None:
def test_playback_duck_percent_clamps_and_round_trips(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
- config_dir = tmp_path / "vocalinux"
+ config_dir = tmp_path / "voculinux"
config_dir.mkdir()
config_file = config_dir / "config.json"
monkeypatch.setattr("vocalinux.ui.config_manager.CONFIG_DIR", str(config_dir))
diff --git a/tests/test_prepare_aur_source.py b/tests/test_prepare_aur_source.py
index f89bce6..e680545 100644
--- a/tests/test_prepare_aur_source.py
+++ b/tests/test_prepare_aur_source.py
@@ -35,10 +35,10 @@ def sdist(
extra: tuple[str, ...] = (),
) -> Path:
"""Write a small real sdist with independently controllable metadata/members."""
- path = directory / f"vocalinux-{version}.tar.gz"
- info = metadata if metadata is not None else f"Name: vocalinux\nVersion: {version}\n"
+ path = directory / f"voculinux-{version}.tar.gz"
+ info = metadata if metadata is not None else f"Name: voculinux\nVersion: {version}\n"
with tarfile.open(path, "w:gz") as archive:
- for name, text in [(f"vocalinux-{version}/PKG-INFO", info)] + [
+ for name, text in [(f"voculinux-{version}/PKG-INFO", info)] + [
(name, "payload") for name in extra
]:
member = tarfile.TarInfo(name)
@@ -208,11 +208,11 @@ def test_release_verification_cannot_be_silently_skipped(
"metadata,extra",
[
("Name: other\nVersion: 0.18.4\n", ()),
- ("Name: vocalinux\nVersion: 0.18.3\n", ()),
- ("Name: vocalinux\nVersion: 0.18.4\nVersion: 0.18.3\n", ()),
+ ("Name: voculinux\nVersion: 0.18.3\n", ()),
+ ("Name: voculinux\nVersion: 0.18.4\nVersion: 0.18.3\n", ()),
(None, ("other-root/file",)),
- (None, ("vocalinux-0.18.4/../unsafe",)),
- (None, ("vocalinux-0.18.4/PKG-INFO",)),
+ (None, ("voculinux-0.18.4/../unsafe",)),
+ (None, ("voculinux-0.18.4/PKG-INFO",)),
],
)
def test_wrong_or_ambiguous_archive_metadata_is_rejected(
diff --git a/tests/test_pulse_sources.py b/tests/test_pulse_sources.py
index 98197a0..35a91aa 100644
--- a/tests/test_pulse_sources.py
+++ b/tests/test_pulse_sources.py
@@ -38,7 +38,7 @@ from vocalinux.audio.pulse_sources import (
from vocalinux.utils import whispercpp_model_info
from vocalinux.utils.snap import SNAP_GPU_NOTE, running_in_snap
-SNAP_ENV = {"SNAP": "/snap/vocalinux/42", "SNAP_NAME": "vocalinux"}
+SNAP_ENV = {"SNAP": "/snap/voculinux/42", "SNAP_NAME": "voculinux"}
PACTL_JSON = [
{
@@ -108,7 +108,7 @@ def _runner(
def _have_pactl(name: str) -> Optional[str]:
- return "/snap/vocalinux/42/usr/bin/pactl" if name == "pactl" else None
+ return "/snap/voculinux/42/usr/bin/pactl" if name == "pactl" else None
class TestPactlParsing:
@@ -503,7 +503,7 @@ class TestSnapGpuReporting:
def test_running_in_snap(self) -> None:
assert running_in_snap(SNAP_ENV)
- assert running_in_snap({"SNAP": "/snap/vocalinux/42"})
+ assert running_in_snap({"SNAP": "/snap/voculinux/42"})
assert not running_in_snap({})
def test_snap_reports_cpu_without_probing_host_gpu_tools(
diff --git a/tests/test_python_version_policy.py b/tests/test_python_version_policy.py
index b77a4f5..6e5cbf6 100644
--- a/tests/test_python_version_policy.py
+++ b/tests/test_python_version_policy.py
@@ -14,7 +14,7 @@ REPO_ROOT = Path(__file__).resolve().parents[1]
PYPROJECT = REPO_ROOT / "pyproject.toml"
INSTALL_SH = REPO_ROOT / "install.sh"
PIPELINE = REPO_ROOT / ".github" / "workflows" / "unified-pipeline.yml"
-PKGBUILD = REPO_ROOT / "packaging" / "aur" / "vocalinux" / "PKGBUILD"
+PKGBUILD = REPO_ROOT / "packaging" / "aur" / "voculinux" / "PKGBUILD"
# Everything user-facing that could state the floor. Scanned as trees rather than
# a fixed list: docs and the website drifted to "3.9+" for a full release cycle
diff --git a/tests/test_recognition_manager.py b/tests/test_recognition_manager.py
index 4422dd7..095f97e 100644
--- a/tests/test_recognition_manager.py
+++ b/tests/test_recognition_manager.py
@@ -1022,7 +1022,7 @@ class TestInitializationEdgeCases(unittest.TestCase):
with patch("os.path.exists") as mock_exists:
def exists_check(path):
- if ".vocalinux_preinstalled" in path:
+ if ".voculinux_preinstalled" in path:
return True
return True
diff --git a/tests/test_recognition_manager_device_config.py b/tests/test_recognition_manager_device_config.py
index e2f8ae3..f570697 100644
--- a/tests/test_recognition_manager_device_config.py
+++ b/tests/test_recognition_manager_device_config.py
@@ -817,7 +817,7 @@ class TestDownmixToMono(unittest.TestCase):
def setUpClass(cls):
# Other test modules may have left sys.modules["numpy"] as MagicMock.
if isinstance(sys.modules.get("numpy"), MagicMock):
- real = getattr(sys, "_vocalinux_real_numpy", None)
+ real = getattr(sys, "_voculinux_real_numpy", None)
if real is not None:
sys.modules["numpy"] = real
else:
@@ -1092,10 +1092,10 @@ class TestVoskInitialization(unittest.TestCase):
):
with patch(
"vocalinux.speech_recognition.recognition_manager.SYSTEM_MODELS_DIRS",
- ["/usr/share/vocalinux"],
+ ["/usr/share/voculinux"],
):
with patch.object(
- manager, "_get_vosk_model_path", return_value="/usr/share/vocalinux/model"
+ manager, "_get_vosk_model_path", return_value="/usr/share/voculinux/model"
):
with patch("os.path.exists", return_value=True):
with patch.dict("sys.modules", {"vosk": mock_vosk}):
diff --git a/tests/test_recognition_manager_downloads.py b/tests/test_recognition_manager_downloads.py
index 7524ed8..9200abf 100644
--- a/tests/test_recognition_manager_downloads.py
+++ b/tests/test_recognition_manager_downloads.py
@@ -18,7 +18,7 @@ from unittest.mock import MagicMock, patch
import pytest
-# Mock GI imports before importing any vocalinux modules that use gi.
+# Mock GI imports before importing any voculinux modules that use gi.
# On CI, real gi/IBus packages are installed; without mocks, importing
# ibus_engine would connect to a real IBus daemon and hang.
if "gi" not in sys.modules:
@@ -463,7 +463,7 @@ class TestDownloadWhispercppModel:
class TestDownloadWhisperModel:
"""OpenAI Whisper downloads run through the shared streaming helper.
- Vocalinux fetches the checkpoint only to give the UI progress and a working
+ Voculinux fetches the checkpoint only to give the UI progress and a working
cancel; whisper.load_model() is what verifies it. Both were briefly lost when
the downloader was removed altogether, so they are pinned here.
"""
@@ -534,7 +534,7 @@ class TestDownloadVoskModel:
# Extraction has to really happen here — the stamp lands in the tree it
# creates — and other modules leave a MagicMock in sys.modules["zipfile"].
- real_zipfile = getattr(sys, "_vocalinux_real_zipfile", None) or __import__("zipfile")
+ real_zipfile = getattr(sys, "_voculinux_real_zipfile", None) or __import__("zipfile")
with patch.dict("sys.modules", {"requests": mock_requests, "zipfile": real_zipfile}):
with patch(
diff --git a/tests/test_recognition_manager_helpers.py b/tests/test_recognition_manager_helpers.py
index 1e39ed5..37c39bb 100644
--- a/tests/test_recognition_manager_helpers.py
+++ b/tests/test_recognition_manager_helpers.py
@@ -167,8 +167,8 @@ class TestGetSystemModelPaths(unittest.TestCase):
mock_open.return_value.read.return_value = mock_os_release
paths = _get_system_model_paths()
self.assertIsInstance(paths, list)
- self.assertNotIn("/usr/local/share/vocalinux/models", paths)
- self.assertIn("/usr/share/vocalinux/models", paths)
+ self.assertNotIn("/usr/local/share/voculinux/models", paths)
+ self.assertIn("/usr/share/voculinux/models", paths)
def test_arch_paths_custom_xdg_dirs(self):
# Regression test: custom XDG_DATA_DIRS + Arch os-release used to
diff --git a/tests/test_recognition_manager_silero.py b/tests/test_recognition_manager_silero.py
index c29a566..4ef4f53 100644
--- a/tests/test_recognition_manager_silero.py
+++ b/tests/test_recognition_manager_silero.py
@@ -22,7 +22,7 @@ from unittest.mock import MagicMock, patch # noqa: E402
# load and don't restore it. Reuse the real module cached by conftest instead
# of unloading/re-importing NumPy's compiled extensions.
if isinstance(sys.modules.get("numpy"), MagicMock):
- _real_numpy = getattr(sys, "_vocalinux_real_numpy", None)
+ _real_numpy = getattr(sys, "_voculinux_real_numpy", None)
if _real_numpy is not None:
sys.modules["numpy"] = _real_numpy
diff --git a/tests/test_release_integrity.py b/tests/test_release_integrity.py
index 40ce194..4548d67 100644
--- a/tests/test_release_integrity.py
+++ b/tests/test_release_integrity.py
@@ -249,7 +249,7 @@ def test_flatpak_release_jobs_reuse_ci_builder_pins():
"action's restore-keys prefix matches after it appends -${arch}"
)
assert f"runs-on: {runner}" in block
- assert f"Vocalinux-${{{{ steps.get_version.outputs.VERSION }}}}-{arch}.flatpak" in block
+ assert f"Voculinux-${{{{ steps.get_version.outputs.VERSION }}}}-{arch}.flatpak" in block
assert "actions/upload-artifact" in block, f"{name} does not upload a workflow artifact"
assert "gh release upload" not in block, f"{name} cannot run gh in the builder image"
assert "python -m build" not in _without_comments(block)
@@ -273,7 +273,7 @@ def test_the_release_notes_document_flatpak_bundles():
assert "org.gnome.Platform//50" in body
assert "no auto-update" in body
assert "not on Flathub" in body
- assert "Vocalinux-__VERSION__-x86_64.flatpak" in body
+ assert "Voculinux-__VERSION__-x86_64.flatpak" in body
def test_the_remote_install_guidance_only_runs_when_the_remote_publishes():
diff --git a/tests/test_remote_desktop_portal.py b/tests/test_remote_desktop_portal.py
index 1564ff2..7bf8ee0 100644
--- a/tests/test_remote_desktop_portal.py
+++ b/tests/test_remote_desktop_portal.py
@@ -657,7 +657,7 @@ def _wayland_injector(
}
env.update(extra_env or {})
if forced:
- env["VOCALINUX_FORCE_BACKEND"] = forced
+ env["VOCULINUX_FORCE_BACKEND"] = forced
for key, value in env.items():
if value is None:
monkeypatch.delenv(key, raising=False)
@@ -767,7 +767,7 @@ class TestPortalBackendSelection:
portal=cls,
extra_env={
"WAYLAND_DISPLAY": None,
- "FLATPAK_ID": "com.vocalinux.Vocalinux",
+ "FLATPAK_ID": "com.voculinux.Voculinux",
"DISPLAY": ":99",
},
)
@@ -872,7 +872,7 @@ class TestPortalInjectionPaths:
with (
patch.dict(
os.environ,
- {"FLATPAK_ID": "com.vocalinux.Vocalinux"},
+ {"FLATPAK_ID": "com.voculinux.Voculinux"},
clear=True,
),
patch.object(injector, "_wait_for_modifiers_released"),
@@ -899,7 +899,7 @@ class TestPortalInjectionPaths:
with patch.dict(
os.environ,
- {"FLATPAK_ID": "com.vocalinux.Vocalinux"},
+ {"FLATPAK_ID": "com.voculinux.Voculinux"},
clear=True,
):
assert injector._demote_portal_backend() is False
@@ -921,7 +921,7 @@ class TestPortalInjectionPaths:
with patch.dict(
os.environ,
- {"FLATPAK_ID": "com.vocalinux.Vocalinux"},
+ {"FLATPAK_ID": "com.voculinux.Voculinux"},
clear=True,
):
assert injector._demote_portal_backend() is True
@@ -947,7 +947,7 @@ class TestPortalInjectionPaths:
with (
patch.dict(
os.environ,
- {"FLATPAK_ID": "com.vocalinux.Vocalinux"},
+ {"FLATPAK_ID": "com.voculinux.Voculinux"},
clear=True,
),
patch.object(injector, "_wait_for_modifiers_released"),
@@ -970,7 +970,7 @@ class TestPortalInjectionPaths:
with patch.dict(
os.environ,
- {"FLATPAK_ID": "com.vocalinux.Vocalinux"},
+ {"FLATPAK_ID": "com.voculinux.Voculinux"},
clear=True,
):
assert injector.inject_text("hello world") is False
@@ -989,7 +989,7 @@ class TestPortalInjectionPaths:
with patch.dict(
os.environ,
- {"FLATPAK_ID": "com.vocalinux.Vocalinux"},
+ {"FLATPAK_ID": "com.voculinux.Voculinux"},
clear=True,
):
assert injector.inject_text("hello world") is False
@@ -1008,7 +1008,7 @@ class TestPortalInjectionPaths:
with patch.dict(
os.environ,
- {"FLATPAK_ID": "com.vocalinux.Vocalinux"},
+ {"FLATPAK_ID": "com.voculinux.Voculinux"},
clear=True,
):
assert injector.inject_text("hello world") is True
diff --git a/tests/test_rename_sweep.py b/tests/test_rename_sweep.py
new file mode 100644
index 0000000..f3b88ec
--- /dev/null
+++ b/tests/test_rename_sweep.py
@@ -0,0 +1,158 @@
+"""Ticket #18: offline naming-sweep — no old-name strings on user-visible surfaces.
+
+The fork takes its own name everywhere a user can see it. Anything still
+spelling the old name must be on the allowlist below:
+
+- upstream provenance (``VocaHQ/vocalinux`` URLs),
+- the retained internal Python module name (``src/vocalinux`` paths,
+ ``vocalinux.*`` imports/attributes, ``-m vocalinux.main``),
+- retained internal class names (``VocalinuxEngine*``, ``VocalinuxDBusService``),
+- one-time-legacy import sources (old config/dictionary/bus literals),
+- generated or historical files (``uv.lock``, ``requirements/*.txt``,
+ ``CHANGELOG.md``),
+- the rest of ``web/`` (owned by ticket #24; only ``page.tsx`` and
+ ``package.json`` belong to this ticket).
+"""
+
+import os
+import re
+
+REPO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+
+OLD_NAME = re.compile(r"vocalinux", re.IGNORECASE)
+
+SKIP_DIRS = {".git", "__pycache__", ".venv", "venv", "node_modules", ".next", "build", "dist"}
+SKIP_SUFFIXES = (".egg-info",)
+SKIP_FILES = {"uv.lock", "CHANGELOG.md"}
+SKIP_PREFIXES = ("requirements/",)
+BINARY_EXTS = (
+ ".wav",
+ ".mp3",
+ ".ogg",
+ ".png",
+ ".svg",
+ ".ico",
+ ".icns",
+ ".bin",
+ ".onnx",
+ ".pt",
+ ".zip",
+ ".tar",
+ ".gz",
+ ".whl",
+ ".AppImage",
+ ".zsync",
+ ".pyc",
+)
+
+#: web/ belongs to ticket #24 except the two rename-inventory files.
+WEB_OWNED = {"web/src/app/page.tsx", "web/package.json"}
+
+
+def _allowed(path: str, line: str) -> bool:
+ """Return True when an old-name match is an allowlisted surface."""
+ low = line.lower()
+ if "vocahq/" in low or "jatinkrmalik/vocalinux" in low:
+ return True
+ if "vocalinux" in low and "voculinux" in low:
+ # Migration-compat shims that name both installs at once.
+ return True
+ if "/{name}/vocalinux" in line:
+ # Upstream repo-name template (retained provenance).
+ return True
+ if path == "snap/local/check_runtime.py" and '"vocalinux"' in line:
+ # Smoke imports resolve the retained import package.
+ return True
+ if re.search(r'vocalinux\.["a-z_]', line):
+ return True
+ if line.strip().rstrip(",").lstrip("/ ") == '"vocalinux"':
+ # Retained module-dir path segment element in tests and tooling
+ # (single-line and os.path.join element forms).
+ return True
+ if 'site / "vocalinux"' in line or '"platform/vocalinux"' in line:
+ # Fixture module trees named after the retained import package.
+ return True
+ if '"vocalinux/' in line:
+ # Fixture module file paths under the retained package name.
+ return True
+ if "/vocalinux/" in line or "src/vocalinux" in line:
+ return True
+ if "-m vocalinux" in line or "import vocalinux" in line:
+ return True
+ if "VocalinuxEngine" in line or "VocalinuxDBusService" in line:
+ return True
+ if "cmdline" in line:
+ return True
+ if " - vocalinux" in line:
+ # Log logger names keep the retained module path.
+ return True
+ if path in (
+ "src/vocalinux/legacy_import.py",
+ "tests/test_legacy_import.py",
+ ):
+ return True
+ if "LEGACY" in line or "legacy" in line:
+ return True
+ if "~/.config/vocalinux" in line or '".config" / "vocalinux"' in line:
+ # Documented one-time-import source (ticket #18).
+ return True
+ if "from vocalinux" in line:
+ return True
+ if '"src"' in line and '"vocalinux"' in line:
+ # Retained module-dir path segments in tests and tooling.
+ return True
+ if path == "tests/test_rename_sweep.py":
+ return True
+ if path == "pyproject.toml" and re.search(r'"vocalinux[."\'\]]', line):
+ return True
+ if path == "pyproject.toml" and "vocalinux.version" in line:
+ return True
+ if 'PKG_NAME="vocalinux"' in line:
+ # Installer probes the retained import package, not the distribution.
+ return True
+ if '== "vocalinux"' in line or '.startswith("vocalinux' in line:
+ # Retained module identity comparisons in test isolation helpers.
+ return True
+ return False
+
+
+def _iter_files():
+ for root, dirs, files in os.walk(REPO_ROOT):
+ dirs[:] = [d for d in sorted(dirs) if d not in SKIP_DIRS]
+ for name in sorted(files):
+ if name in SKIP_FILES or name.endswith(BINARY_EXTS):
+ continue
+ full = os.path.join(root, name)
+ rel = os.path.relpath(full, REPO_ROOT)
+ if rel.startswith(SKIP_PREFIXES):
+ continue
+ if rel.startswith("web/") and rel not in WEB_OWNED:
+ continue
+ yield rel, full
+
+
+def test_naming_sweep_no_old_name_outside_allowlist() -> None:
+ """Every old-name hit must be an allowlisted retained surface."""
+ offenders: list[str] = []
+ for rel, full in _iter_files():
+ if any(part.endswith(SKIP_SUFFIXES) for part in rel.split("/")):
+ continue
+ try:
+ with open(full, encoding="utf-8") as handle:
+ text = handle.read()
+ except (UnicodeDecodeError, ValueError):
+ continue
+ for number, line in enumerate(text.splitlines(), 1):
+ if OLD_NAME.search(line) and not _allowed(rel, line):
+ offenders.append(f"{rel}:{number}:{line.strip()[:160]}")
+ assert (
+ offenders == []
+ ), f"{len(offenders)} old-name string(s) outside the allowlist:\n" + "\n".join(offenders[:60])
+
+
+def test_owned_web_files_carry_new_name() -> None:
+ """The two web rename surfaces name the fork (URLs aside)."""
+ for rel in sorted(WEB_OWNED):
+ with open(os.path.join(REPO_ROOT, rel), encoding="utf-8") as handle:
+ text = handle.read()
+ assert "Voculinux" in text or "voculinux" in text, rel
diff --git a/tests/test_reproducible_wheel.py b/tests/test_reproducible_wheel.py
index 4b8487d..b63611b 100644
--- a/tests/test_reproducible_wheel.py
+++ b/tests/test_reproducible_wheel.py
@@ -11,13 +11,13 @@ from types import ModuleType
import pytest
# Other legacy tests replace zipfile in sys.modules during collection.
-ZIPFILE = getattr(sys, "_vocalinux_real_zipfile", __import__("zipfile"))
+ZIPFILE = getattr(sys, "_voculinux_real_zipfile", __import__("zipfile"))
SCRIPT = Path(__file__).resolve().parents[1] / "scripts/build_reproducible_wheel.py"
@pytest.fixture
def gate(monkeypatch: pytest.MonkeyPatch) -> ModuleType:
- """Load the standalone build tool without importing Vocalinux/GTK."""
+ """Load the standalone build tool without importing Voculinux/GTK."""
spec = importlib.util.spec_from_file_location("reproducible_wheel", SCRIPT)
assert spec and spec.loader
module = importlib.util.module_from_spec(spec)
@@ -29,7 +29,7 @@ def gate(monkeypatch: pytest.MonkeyPatch) -> ModuleType:
def wheel(path: Path, content: str = "payload", year: int = 2020) -> Path:
"""Make a tiny real archive, including independently controllable ZIP metadata."""
path.parent.mkdir(parents=True, exist_ok=True)
- info = ZIPFILE.ZipInfo("vocalinux/__init__.py", date_time=(year, 1, 1, 0, 0, 0))
+ info = ZIPFILE.ZipInfo("voculinux/__init__.py", date_time=(year, 1, 1, 0, 0, 0))
with ZIPFILE.ZipFile(path, "w") as archive:
archive.writestr(info, content)
return path
@@ -59,7 +59,7 @@ def test_mismatches_fail_without_normalizing_archives(
gate.compare_wheels(first, second, report)
assert "FAIL" in report.read_text()
if difference == "payload":
- assert "member content differs: vocalinux/__init__.py" in report.read_text()
+ assert "member content differs: voculinux/__init__.py" in report.read_text()
def test_snapshot_uses_working_source_without_ignored_build_state(
diff --git a/tests/test_resource_manager_ext.py b/tests/test_resource_manager_ext.py
index 78b47df..d05be52 100644
--- a/tests/test_resource_manager_ext.py
+++ b/tests/test_resource_manager_ext.py
@@ -162,10 +162,10 @@ class TestResourceManagerCandidateSelection:
(full_candidate / "sounds").mkdir(parents=True, exist_ok=True)
for icon in [
- "vocalinux",
- "vocalinux-microphone",
- "vocalinux-microphone-off",
- "vocalinux-microphone-process",
+ "voculinux",
+ "voculinux-microphone",
+ "voculinux-microphone-off",
+ "voculinux-microphone-process",
]:
(full_candidate / "icons" / "scalable" / f"{icon}.svg").write_text("x")
@@ -183,7 +183,7 @@ class TestResourceManagerCandidateSelection:
ResourceManager._resources_dir = None
manager = ResourceManager()
- missing = Path("/tmp/this-path-should-not-exist-vocalinux-resource-manager")
+ missing = Path("/tmp/this-path-should-not-exist-voculinux-resource-manager")
candidate_score = getattr(manager, "_candidate_score")
score = candidate_score(missing)
assert score == -1
diff --git a/tests/test_settings_dialog.py b/tests/test_settings_dialog.py
index 59ef164..36f9706 100644
--- a/tests/test_settings_dialog.py
+++ b/tests/test_settings_dialog.py
@@ -1265,7 +1265,7 @@ class TestSettingsNavigation(unittest.TestCase):
"""Finalization keeps the Cancel button usable while recognition stops."""
finalize_body = self.source_code.split("def _finalize_test")[1].split("\n def ")[0]
self.assertIn("def stop_test", finalize_body)
- self.assertIn('name="vocalinux-test-dictation-stop"', finalize_body)
+ self.assertIn('name="voculinux-test-dictation-stop"', finalize_body)
self.assertIn(
"GLib.timeout_add(100, self._wait_for_idle_then_restore_callbacks)",
finalize_body,
@@ -1342,7 +1342,7 @@ class TestAboutPage(unittest.TestCase):
cls.about = cls.about_source.split("def _build_about_section")[1].split("\n def ")[0]
def test_three_groups_keep_updater(self) -> None:
- self.assertIn('title="Vocalinux"', self.about)
+ self.assertIn('title="Voculinux"', self.about)
self.assertIn('title="Part of VocaHQ"', self.about)
self.assertIn('title="Talk to us"', self.about)
self.assertIn('title="Updates"', self.about)
@@ -1369,7 +1369,7 @@ class TestAboutPage(unittest.TestCase):
def test_family_and_talk_urls(self):
for url in (
- "https://vocalinux.com",
+ "https://voculinux.com",
"https://vocahq.com",
"https://vocamac.com",
"https://vocawin.com",
@@ -1395,29 +1395,29 @@ class TestAboutPage(unittest.TestCase):
self.assertIn("_set_accessible_name(button, tooltip)", helper)
self.assertIn('if label == "Open"', helper)
for name in (
- "Open vocalinux.com website",
+ "Open voculinux.com website",
"Open vocahq.com",
- "Open vocalinux.com",
+ "Open voculinux.com",
"Open vocamac.com",
"Open vocawin.com",
"Open vocaphone.vocahq.com",
"Open vocagateway.vocahq.com",
- "Open the Vocalinux GitHub repository",
+ "Open the Voculinux GitHub repository",
"Open the latest release page",
):
self.assertIn(name, self.source)
self.assertIn("_set_accessible_name", self.about)
def test_website_is_product_site_not_only_github(self):
- self.assertIn("VOCALINUX_SITE_URL", self.about)
- self.assertIn("Product site at vocalinux.com", self.about)
- self.assertNotIn("Open the Vocalinux GitHub page", self.about)
+ self.assertIn("VOCULINUX_SITE_URL", self.about)
+ self.assertIn("Product site at voculinux.com", self.about)
+ self.assertNotIn("Open the Voculinux GitHub page", self.about)
def test_source_code_row_sits_beside_website(self):
self.assertIn('label="Website"', self.about)
self.assertIn('label="Source code"', self.about)
self.assertIn("GITHUB_REPO_URL", self.about)
- self.assertIn("Open the Vocalinux GitHub repository", self.about)
+ self.assertIn("Open the Voculinux GitHub repository", self.about)
self.assertLess(self.about.find('label="Website"'), self.about.find('label="Source code"'))
def test_talk_to_us_sits_above_updates(self):
@@ -1457,15 +1457,15 @@ class TestAboutPage(unittest.TestCase):
VOCAHQ_MAILTO_URL,
VOCAHQ_SITE_URL,
VOCAHQ_X_URL,
- VOCALINUX_SITE_URL,
VOCAMAC_SITE_URL,
VOCAPHONE_SITE_URL,
VOCAWIN_SITE_URL,
+ VOCULINUX_SITE_URL,
_can_open_url,
)
for url in (
- VOCALINUX_SITE_URL,
+ VOCULINUX_SITE_URL,
VOCAHQ_SITE_URL,
VOCAMAC_SITE_URL,
VOCAWIN_SITE_URL,
@@ -1542,22 +1542,22 @@ class TestAboutPage(unittest.TestCase):
/ "resources"
/ "icons"
/ "scalable"
- / "vocalinux.svg"
+ / "voculinux.svg"
)
shipped = (
Path(__file__).resolve().parents[1]
/ "resources"
/ "icons"
/ "scalable"
- / "vocalinux.svg"
+ / "voculinux.svg"
)
packaged_svg = packaged.read_text(encoding="utf-8")
shipped_svg = shipped.read_text(encoding="utf-8")
self.assertEqual(packaged_svg, shipped_svg)
self.assertIn('', packaged_svg)
- self.assertIn('aria-label="Vocalinux"', packaged_svg)
+ self.assertIn('aria-label="Voculinux"', packaged_svg)
self.assertNotIn(" None:
dialog.test_button.set_label.assert_called_with("Cancelling…")
thread_cls.assert_called_once()
assert thread_cls.call_args.kwargs["daemon"] is True
- assert thread_cls.call_args.kwargs["name"] == "vocalinux-test-dictation-cancel"
+ assert thread_cls.call_args.kwargs["name"] == "voculinux-test-dictation-cancel"
with patch.object(settings_dialog, "GLib") as glib:
thread_cls.call_args.kwargs["target"]()
@@ -443,7 +443,7 @@ def test_finalize_test_buffered_reload_waits_for_idle_before_restore() -> None:
dialog.speech_engine.stop_recognition.assert_not_called()
thread_cls.assert_called_once()
assert thread_cls.call_args.kwargs["daemon"] is True
- assert thread_cls.call_args.kwargs["name"] == "vocalinux-test-dictation-stop"
+ assert thread_cls.call_args.kwargs["name"] == "voculinux-test-dictation-stop"
thread_cls.call_args.kwargs["target"]()
dialog.speech_engine.stop_recognition.assert_called_once()
# Must not restore live injector yet — worker still holds the utterance.
@@ -518,7 +518,7 @@ def test_cancel_during_processing_restores_once_without_result_check() -> None:
):
SettingsDialog._finalize_test(dialog)
- assert thread_cls.call_args.kwargs["name"] == "vocalinux-test-dictation-stop"
+ assert thread_cls.call_args.kwargs["name"] == "voculinux-test-dictation-stop"
dialog._test_cancelled = True
assert SettingsDialog._finish_test_after_user_cancel(dialog) is False
assert dialog.test_buffer._text == "(Test cancelled)"
diff --git a/tests/test_silero_vad.py b/tests/test_silero_vad.py
index 8d0380f..f999675 100644
--- a/tests/test_silero_vad.py
+++ b/tests/test_silero_vad.py
@@ -15,7 +15,7 @@ from unittest.mock import MagicMock, patch # noqa: E402
# load and don't restore it. Reuse the real module cached by conftest instead
# of unloading/re-importing NumPy's compiled extensions.
if isinstance(sys.modules.get("numpy"), MagicMock):
- _real_numpy = getattr(sys, "_vocalinux_real_numpy", None)
+ _real_numpy = getattr(sys, "_voculinux_real_numpy", None)
if _real_numpy is not None:
sys.modules["numpy"] = _real_numpy
diff --git a/tests/test_single_instance_ext.py b/tests/test_single_instance_ext.py
index ec0b880..205ece7 100644
--- a/tests/test_single_instance_ext.py
+++ b/tests/test_single_instance_ext.py
@@ -183,7 +183,7 @@ class TestLockFileConstants(unittest.TestCase):
"""Tests for lock file constants."""
def test_lock_file_path_is_in_data_home(self):
- """Test that lock file lives under $XDG_DATA_HOME/vocalinux/."""
+ """Test that lock file lives under $XDG_DATA_HOME/voculinux/."""
expected_dir = Path(data_dir())
self.assertEqual(single_instance_module.LOCK_FILE_DIR, expected_dir)
self.assertEqual(single_instance_module.LOCK_FILE_PATH, expected_dir / "instance.lock")
diff --git a/tests/test_snap_build.py b/tests/test_snap_build.py
index 04d5116..a7807bf 100644
--- a/tests/test_snap_build.py
+++ b/tests/test_snap_build.py
@@ -116,10 +116,10 @@ def test_record_audits_payload_and_preserves_export_digests(tmp_path: Path) -> N
(source / "src/vocalinux/version.py").write_text('__version__ = "0.18.5"\n')
root = tmp_path / "install"
distribution(root, "demo", "1.0")
- distribution(root, "vocalinux", "0.18.5")
+ distribution(root, "voculinux", "0.18.5")
CHECK.record(root, source)
manifest = json.loads((root / CHECK.MANIFEST).read_text())
- assert manifest["packages"] == {"demo": "1.0", "vocalinux": "0.18.5"}
+ assert manifest["packages"] == {"demo": "1.0", "voculinux": "0.18.5"}
assert manifest["python"] == list(sys.version_info[:2])
for name, digest in manifest["exports"].items():
assert digest == hashlib.sha256((source / "requirements" / name).read_bytes()).hexdigest()
@@ -154,12 +154,12 @@ def test_launchers_are_relocatable_and_keep_locked_packages_first(
header = (
f"#!/bin/sh\n'''exec' {python} \"$0\" \"$@\"\n' '''\n" if long_shebang else f"#!{python}\n"
)
- for name in ("vocalinux", "vocalinux-gui", "pwcpp"):
+ for name in ("voculinux", "voculinux-gui", "pwcpp"):
path = binary / name
path.write_text(header + "print('entry point')\n")
path.chmod(0o755)
(binary / "python3").symlink_to(sys.executable)
- site = distribution(install, "vocalinux", "0.18.5")
+ site = distribution(install, "voculinux", "0.18.5")
package = site / "vocalinux"
package.mkdir()
(package / "__init__.py").write_text("")
@@ -169,13 +169,13 @@ def test_launchers_are_relocatable_and_keep_locked_packages_first(
platform.mkdir(parents=True)
(platform / "__init__.py").write_text("raise RuntimeError('wrong runtime')\n")
BUILD.relocate_scripts(install, tooling)
- for name in ("vocalinux", "vocalinux-gui", "pwcpp"):
+ for name in ("voculinux", "voculinux-gui", "pwcpp"):
text = (binary / name).read_text()
assert text.startswith("#!/usr/bin/env python3\n")
assert str(tooling) not in text
assert os.access(binary / name, os.X_OK)
result = subprocess.run(
- [str(binary / "vocalinux")],
+ [str(binary / "voculinux")],
env={
**os.environ,
"PATH": f"{binary}{os.pathsep}{os.environ['PATH']}",
@@ -211,7 +211,7 @@ def test_build_orchestration_uses_hashes_and_separates_tooling(
def run(argv: list[str], cwd: Path, env: dict[str, str]) -> None:
calls.append((argv, cwd, env.copy()))
if str(source) == argv[-1]:
- for name in ("vocalinux", "vocalinux-gui"):
+ for name in ("voculinux", "voculinux-gui"):
(install / "bin" / name).write_text(f"#!{argv[0]}\n")
monkeypatch.setattr(BUILD.venv.EnvBuilder, "create", create)
@@ -309,7 +309,7 @@ def test_runtime_pip_flags_reject_corrupt_artifact_offline(tmp_path: Path) -> No
environment = tmp_path / "tooling"
venv.EnvBuilder(with_pip=True).create(environment)
wheel = tmp_path / "demo-1.0-py3-none-any.whl"
- real_zipfile = getattr(sys, "_vocalinux_real_zipfile", zipfile)
+ real_zipfile = getattr(sys, "_voculinux_real_zipfile", zipfile)
with real_zipfile.ZipFile(wheel, "w") as archive:
archive.writestr("demo.py", "VALUE = 1\n")
archive.writestr(
@@ -369,7 +369,7 @@ def test_full_python_payload_build_is_offline_and_keeps_project_metadata(tmp_pat
(source / "src/vocalinux/version.py").write_text('__version__ = "0.18.5"\n')
wheelhouse = tmp_path / "wheels"
wheelhouse.mkdir()
- real_zipfile = getattr(sys, "_vocalinux_real_zipfile", zipfile)
+ real_zipfile = getattr(sys, "_voculinux_real_zipfile", zipfile)
def wheel(name: str, version: str, files: dict[str, str]) -> Path:
path = wheelhouse / f"{name}-{version}-py3-none-any.whl"
@@ -399,13 +399,13 @@ def test_full_python_payload_build_is_offline_and_keeps_project_metadata(tmp_pat
)
runtime = wheel("demo", "1.0", {"demo.py": "VALUE = 1\n"})
app = wheel(
- "vocalinux",
+ "voculinux",
"0.18.5",
{
"vocalinux/__init__.py": "",
"vocalinux/main.py": "def main():\n print('fixture app')\n",
- "vocalinux-0.18.5.dist-info/entry_points.txt": "[console_scripts]\nvocalinux = vocalinux.main:main\n"
- "[gui_scripts]\nvocalinux-gui = vocalinux.main:main\n",
+ "voculinux-0.18.5.dist-info/entry_points.txt": "[console_scripts]\nvoculinux = vocalinux.main:main\n"
+ "[gui_scripts]\nvoculinux-gui = vocalinux.main:main\n",
},
)
for filename, name, version, artifact in (
@@ -421,7 +421,7 @@ def test_full_python_payload_build_is_offline_and_keeps_project_metadata(tmp_pat
metadata = source / "pyproject.toml"
metadata.write_text(
'[build-system]\nrequires = []\nbuild-backend = "backend"\nbackend-path = ["."]\n'
- '[project]\nname = "vocalinux"\nversion = "0.18.5"\ndependencies = ["PyGObject"]\n'
+ '[project]\nname = "voculinux"\nversion = "0.18.5"\ndependencies = ["PyGObject"]\n'
)
(source / "backend.py").write_text(
"import shutil\nfrom pathlib import Path\n"
@@ -434,11 +434,11 @@ def test_full_python_payload_build_is_offline_and_keeps_project_metadata(tmp_pat
install = tmp_path / "install"
BUILD.build(source, install, tmp_path / "work")
assert metadata.read_bytes() == before
- CHECK.audit(install, {"demo": "1.0", "vocalinux": "0.18.5"})
+ CHECK.audit(install, {"demo": "1.0", "voculinux": "0.18.5"})
assert not list((tmp_path / "work").iterdir())
assert not (install / "bin/pip").exists()
result = subprocess.run(
- [str(install / "bin/python3"), str(install / "bin/vocalinux")],
+ [str(install / "bin/python3"), str(install / "bin/voculinux")],
capture_output=True,
text=True,
timeout=5,
@@ -464,7 +464,7 @@ def test_artifact_smoke_refuses_user_install_and_checks_the_supplied_file(
"with open(os.environ['SNAP_TEST_LOG'], 'a') as stream:\n"
" stream.write(json.dumps([Path(sys.argv[0]).name, sys.argv[1:], "
"os.environ.get('PYNPUT_BACKEND')]) + '\\n')\n"
- "if sys.argv[1:3] == ['list', 'vocalinux']:\n"
+ "if sys.argv[1:3] == ['list', 'voculinux']:\n"
" sys.exit(0 if os.environ['SNAP_TEST_EXISTING'] == '1' else 1)\n"
)
path.chmod(0o755)
@@ -490,8 +490,8 @@ def test_artifact_smoke_refuses_user_install_and_checks_the_supplied_file(
else:
assert result.returncode == 0, result.stderr
assert calls[1][:2] == ["sudo", ["snap", "install", "--dangerous", str(artifact)]]
- assert calls[2][:2] == ["snap", ["run", "vocalinux", "--version"]]
- assert calls[3][1][:4] == ["run", "--shell", "vocalinux", "-c"]
+ assert calls[2][:2] == ["snap", ["run", "voculinux", "--version"]]
+ assert calls[3][1][:4] == ["run", "--shell", "voculinux", "-c"]
assert '"$SNAP/snap/command-chain/desktop-launch"' in calls[3][1][4]
- assert '"$SNAP/usr/lib/vocalinux/check_runtime.py"' in calls[3][1][4]
+ assert '"$SNAP/usr/lib/voculinux/check_runtime.py"' in calls[3][1][4]
assert calls[3][2] == "dummy"
diff --git a/tests/test_snap_packaging.py b/tests/test_snap_packaging.py
index 1c8c906..451f200 100644
--- a/tests/test_snap_packaging.py
+++ b/tests/test_snap_packaging.py
@@ -6,35 +6,35 @@ import yaml
REPO_ROOT = Path(__file__).resolve().parents[1]
SNAPCRAFT_YAML = REPO_ROOT / "snap" / "snapcraft.yaml"
-DESKTOP_FILE = REPO_ROOT / "snap" / "gui" / "vocalinux.desktop"
-SNAP_PNG = REPO_ROOT / "snap" / "gui" / "vocalinux.png"
+DESKTOP_FILE = REPO_ROOT / "snap" / "gui" / "voculinux.desktop"
+SNAP_PNG = REPO_ROOT / "snap" / "gui" / "voculinux.png"
def test_snapcraft_recipe_and_gui_assets() -> None:
assert SNAPCRAFT_YAML.is_file()
doc = yaml.safe_load(SNAPCRAFT_YAML.read_text(encoding="utf-8"))
- assert doc["name"] == "vocalinux"
+ assert doc["name"] == "voculinux"
assert doc["base"] == "core24"
assert doc["summary"] == "Free offline voice dictation for Linux"
assert doc["license"] == "AGPL-3.0-only"
- assert doc["icon"] == "snap/gui/vocalinux.png"
- assert doc["website"] == "https://vocalinux.com"
+ assert doc["icon"] == "snap/gui/voculinux.png"
+ assert doc["website"] == "https://voculinux.com"
assert doc["confinement"] == "strict"
assert doc["grade"] == "stable"
- plugs = set((doc.get("apps") or {}).get("vocalinux", {}).get("plugs") or [])
+ plugs = set((doc.get("apps") or {}).get("voculinux", {}).get("plugs") or [])
assert "raw-input" in plugs
assert "hardware-observe" in plugs
assert "audio-record" in plugs
# The Store denied the super-privileged uinput grant; the plug (and the
# uinput-only ydotool) must stay out or every revision is held in review.
assert "uinput" not in plugs
- stage = doc["parts"]["vocalinux"].get("stage-packages") or []
+ stage = doc["parts"]["voculinux"].get("stage-packages") or []
assert "ydotool" not in stage
recipe_text = SNAPCRAFT_YAML.read_text(encoding="utf-8")
- assert "sudo snap connect vocalinux:raw-input" in recipe_text
- assert "sudo snap connect vocalinux:hardware-observe" in recipe_text
+ assert "sudo snap connect voculinux:raw-input" in recipe_text
+ assert "sudo snap connect voculinux:hardware-observe" in recipe_text
assert DESKTOP_FILE.is_file()
assert SNAP_PNG.is_file()
@@ -50,7 +50,7 @@ def test_snap_puts_gnome_platform_first_on_ld_library_path() -> None:
come first or About-page SVGs fail with "Image type svg is not supported".
"""
doc = yaml.safe_load(SNAPCRAFT_YAML.read_text(encoding="utf-8"))
- env = (doc.get("apps") or {}).get("vocalinux", {}).get("environment") or {}
+ env = (doc.get("apps") or {}).get("voculinux", {}).get("environment") or {}
ld_path = env.get("LD_LIBRARY_PATH")
assert isinstance(ld_path, str)
assert ld_path.startswith("$SNAP/gnome-platform/usr/lib/$CRAFT_ARCH_TRIPLET:")
@@ -63,8 +63,8 @@ def test_snap_docs_tell_users_to_connect_hardware_observe() -> None:
install = (REPO_ROOT / "docs" / "INSTALL.md").read_text(encoding="utf-8")
snapcraft = SNAPCRAFT_YAML.read_text(encoding="utf-8")
for text in (readme, install, snapcraft):
- assert "sudo snap connect vocalinux:raw-input" in text
- assert "sudo snap connect vocalinux:hardware-observe" in text
+ assert "sudo snap connect voculinux:raw-input" in text
+ assert "sudo snap connect voculinux:hardware-observe" in text
def test_snap_docs_explain_typing_without_uinput_plug() -> None:
@@ -88,13 +88,13 @@ def test_snap_preserves_metadata_and_uses_gnome_gi() -> None:
"""GI comes from GNOME without rewriting project dependencies."""
text = SNAPCRAFT_YAML.read_text(encoding="utf-8")
doc = yaml.safe_load(text)
- part = doc["parts"]["vocalinux"]
+ part = doc["parts"]["voculinux"]
assert part["plugin"] == "nil"
assert "python-packages" not in part
assert "sed -i" not in part["override-pull"]
assert "snap/local/build.py" in part["override-build"]
assert "craftctl default" not in part["override-build"]
- stage = doc["parts"]["vocalinux"].get("stage-packages") or []
+ stage = doc["parts"]["voculinux"].get("stage-packages") or []
assert "python3-gi" not in stage
assert "python3-gi-cairo" not in stage
@@ -143,7 +143,7 @@ def test_release_notes_document_snap_sideload() -> None:
assert "snap install --dangerous" in body
assert "RemoteDesktop portal" in body
assert "no `uinput` plug" in body
- assert "vocalinux_${{ steps.get_version.outputs.VERSION }}_amd64.snap" in body
+ assert "voculinux_${{ steps.get_version.outputs.VERSION }}_amd64.snap" in body
def test_snap_backfill_workflow_attests_only_the_snap() -> None:
@@ -179,11 +179,11 @@ def test_snap_promote_dispatch_gates_stable_on_candidate() -> None:
"""stable is the gated option of #783: a manual dispatch releasing the candidate revision."""
text = (REPO_ROOT / ".github" / "workflows" / "snap-promote.yml").read_text(encoding="utf-8")
assert "workflow_dispatch:" in text
- assert 'snapcraft release vocalinux "$REVISION" latest/stable' in text
+ assert 'snapcraft release voculinux "$REVISION" latest/stable' in text
assert "SNAPCRAFT_STORE_CREDENTIALS is unset; cannot promote the snap" in text
assert "environment:" in text
# The promote must prove the candidate revision carries the tag's version.
- assert "snapcraft status vocalinux" in text
+ assert "snapcraft status voculinux" in text
assert 'if [ "$seen_version" != "$VERSION" ]' in text
@@ -222,7 +222,7 @@ def test_snap_builds_pywhispercpp_at_the_portable_baseline() -> None:
alone leaves them all on."""
doc = yaml.safe_load(SNAPCRAFT_YAML.read_text(encoding="utf-8"))
env: dict = {}
- for entry in doc["parts"]["vocalinux"].get("build-environment") or []:
+ for entry in doc["parts"]["voculinux"].get("build-environment") or []:
env.update(entry)
build = (REPO_ROOT / "snap/local/build.py").read_text()
assert '"--no-binary=pywhispercpp"' in build
diff --git a/tests/test_start_stop_race.py b/tests/test_start_stop_race.py
index 406f312..ad35e56 100644
--- a/tests/test_start_stop_race.py
+++ b/tests/test_start_stop_race.py
@@ -32,7 +32,7 @@ def _numpy_is_real_while_capturing() -> Iterator[None]:
stalled read this file depends on.
"""
current = sys.modules.get("numpy")
- real = getattr(sys, "_vocalinux_real_numpy", None)
+ real = getattr(sys, "_voculinux_real_numpy", None)
if isinstance(current, MagicMock) and real is not None:
sys.modules["numpy"] = real
try:
diff --git a/tests/test_system_default_capture.py b/tests/test_system_default_capture.py
index 06ee3a7..1f6f56b 100644
--- a/tests/test_system_default_capture.py
+++ b/tests/test_system_default_capture.py
@@ -31,7 +31,7 @@ def audio(monkeypatch: pytest.MonkeyPatch) -> Mock:
audio.open.return_value.get_read_available.return_value = 1024
audio.open.return_value.read.return_value = b"\x00\x01" * 1024
monkeypatch.setitem(sys.modules, "pyaudio", SimpleNamespace(PyAudio=lambda: audio, paInt16=8))
- monkeypatch.setitem(sys.modules, "numpy", sys._vocalinux_real_numpy)
+ monkeypatch.setitem(sys.modules, "numpy", sys._voculinux_real_numpy)
return audio
diff --git a/tests/test_text_injector.py b/tests/test_text_injector.py
index 553f560..fc0fce9 100644
--- a/tests/test_text_injector.py
+++ b/tests/test_text_injector.py
@@ -197,7 +197,7 @@ class TestTextInjector(unittest.TestCase):
def test_wayland_wtype_fail_xdotool_when_uinput_blocked(self) -> None:
"""ydotool in PATH without /dev/uinput still cannot rescue a wtype miss."""
with patch.dict(
- "os.environ", {"XDG_SESSION_TYPE": "wayland", "SNAP": "/snap/vocalinux/x1"}
+ "os.environ", {"XDG_SESSION_TYPE": "wayland", "SNAP": "/snap/voculinux/x1"}
):
self.mock_which.side_effect = lambda cmd: {
"wtype": "/usr/bin/wtype",
@@ -298,7 +298,7 @@ class TestTextInjector(unittest.TestCase):
injector.inject_text("Hello world")
# Clipboard paste fails (no wl-copy/xclip/xsel in this mock); type fallback.
- # Default key-delay is 2 (overridable via VOCALINUX_YDOTOOL_KEY_DELAY).
+ # Default key-delay is 2 (overridable via VOCULINUX_YDOTOOL_KEY_DELAY).
self.mock_subprocess.assert_any_call(
["ydotool", "type", "--key-delay", "2", "--", "Hello world"],
check=True,
@@ -891,7 +891,7 @@ class TestTextInjector(unittest.TestCase):
"""Flatpak pins ydotool 1.0.4; always use keycode:value form."""
mock_which.return_value = "/app/bin/ydotool"
injector = TextInjector.__new__(TextInjector)
- with patch.dict("os.environ", {"FLATPAK_ID": "com.vocalinux.Vocalinux"}):
+ with patch.dict("os.environ", {"FLATPAK_ID": "com.voculinux.Voculinux"}):
cmd = injector._ydotool_ctrl_v_command()
self.assertEqual(cmd, ["ydotool", "key", "29:1", "47:1", "47:0", "29:0"])
@@ -3516,7 +3516,7 @@ class TestBackendPreference(unittest.TestCase):
def test_environment_overrides_config(self):
"""A one-off experiment must not require editing the user's config."""
with _fake_config({"text_injection": {"backend": "ibus"}}):
- with patch.dict("os.environ", {"VOCALINUX_FORCE_BACKEND": "wtype"}):
+ with patch.dict("os.environ", {"VOCULINUX_FORCE_BACKEND": "wtype"}):
self.assertEqual(TextInjector._backend_preference(), "wtype")
def test_config_used_when_environment_unset(self):
@@ -3530,14 +3530,14 @@ class TestBackendPreference(unittest.TestCase):
self.assertEqual(TextInjector._backend_preference(), "auto")
def test_explicit_auto_overrides_a_saved_pin(self):
- """``VOCALINUX_FORCE_BACKEND=auto`` asks for autodetection *this run*.
+ """``VOCULINUX_FORCE_BACKEND=auto`` asks for autodetection *this run*.
It must not be read as "nothing was set" and fall through to the saved
pin, or the variable cannot undo a pin for a single run -- which is the
one-off A/B test it exists for.
"""
with _fake_config({"text_injection": {"backend": "wtype"}}):
- with patch.dict("os.environ", {"VOCALINUX_FORCE_BACKEND": "auto"}):
+ with patch.dict("os.environ", {"VOCULINUX_FORCE_BACKEND": "auto"}):
self.assertEqual(TextInjector._backend_preference(), "auto")
def test_unset_environment_uses_the_saved_pin(self):
@@ -3554,7 +3554,7 @@ class TestBackendPreference(unittest.TestCase):
``test_explicit_auto_overrides_a_saved_pin``, where they did ask.
"""
with _fake_config({"text_injection": {"backend": "wtype"}}):
- with patch.dict("os.environ", {"VOCALINUX_FORCE_BACKEND": "wtpye"}):
+ with patch.dict("os.environ", {"VOCULINUX_FORCE_BACKEND": "wtpye"}):
self.assertEqual(TextInjector._backend_preference(), "wtype")
@@ -3562,7 +3562,7 @@ class TestSelectableBackends(unittest.TestCase):
"""xdotool is a pinnable value, and both readers accept the same set."""
def test_xdotool_is_accepted_from_the_environment(self):
- with patch.dict("os.environ", {"VOCALINUX_FORCE_BACKEND": "xdotool"}):
+ with patch.dict("os.environ", {"VOCULINUX_FORCE_BACKEND": "xdotool"}):
self.assertEqual(TextInjector._forced_backend_setting(), "xdotool")
def test_xdotool_is_accepted_from_config(self):
@@ -3572,7 +3572,7 @@ class TestSelectableBackends(unittest.TestCase):
def test_both_readers_accept_the_same_values(self):
"""A value valid in one source must be valid in the other."""
for value in TextInjector._SELECTABLE_BACKENDS:
- with patch.dict("os.environ", {"VOCALINUX_FORCE_BACKEND": value}):
+ with patch.dict("os.environ", {"VOCULINUX_FORCE_BACKEND": value}):
self.assertEqual(TextInjector._forced_backend_setting(), value)
with _fake_config({"text_injection": {"backend": value}}):
self.assertEqual(TextInjector._configured_backend(), value)
@@ -3586,7 +3586,7 @@ class TestSelectableBackends(unittest.TestCase):
class TestForcedBackendSetting(unittest.TestCase):
- """The raw three-state reading of VOCALINUX_FORCE_BACKEND.
+ """The raw three-state reading of VOCULINUX_FORCE_BACKEND.
``_forced_backend()`` collapses unset and explicit ``auto`` together, which
is fine for its own callers but loses the distinction ``_backend_preference()``
@@ -3599,40 +3599,40 @@ class TestForcedBackendSetting(unittest.TestCase):
def test_explicit_auto_is_the_string_not_none(self):
for value in ("auto", " AUTO "):
- with patch.dict("os.environ", {"VOCALINUX_FORCE_BACKEND": value}):
+ with patch.dict("os.environ", {"VOCULINUX_FORCE_BACKEND": value}):
self.assertEqual(TextInjector._forced_backend_setting(), "auto")
def test_empty_value_counts_as_unset(self):
- with patch.dict("os.environ", {"VOCALINUX_FORCE_BACKEND": " "}):
+ with patch.dict("os.environ", {"VOCULINUX_FORCE_BACKEND": " "}):
self.assertIsNone(TextInjector._forced_backend_setting())
def test_recognised_backends_are_returned(self):
for value in ("ibus", "wtype", "ydotool", "xdotool"):
- with patch.dict("os.environ", {"VOCALINUX_FORCE_BACKEND": value.upper()}):
+ with patch.dict("os.environ", {"VOCULINUX_FORCE_BACKEND": value.upper()}):
self.assertEqual(TextInjector._forced_backend_setting(), value)
def test_unknown_value_is_unset_rather_than_auto(self):
"""See ``test_typo_in_environment_is_treated_as_unset_not_as_auto``."""
- with patch.dict("os.environ", {"VOCALINUX_FORCE_BACKEND": "ibsu"}):
+ with patch.dict("os.environ", {"VOCULINUX_FORCE_BACKEND": "ibsu"}):
self.assertIsNone(TextInjector._forced_backend_setting())
class TestForcedBackend(unittest.TestCase):
- """VOCALINUX_FORCE_BACKEND overrides backend autodetection."""
+ """VOCULINUX_FORCE_BACKEND overrides backend autodetection."""
def test_unset_or_auto_means_auto(self):
for value in ("", "auto", " AUTO "):
- with patch.dict("os.environ", {"VOCALINUX_FORCE_BACKEND": value}):
+ with patch.dict("os.environ", {"VOCULINUX_FORCE_BACKEND": value}):
self.assertEqual(TextInjector._forced_backend(), "auto")
def test_recognised_backends(self):
for value in ("ibus", "wtype", "ydotool", "xdotool"):
- with patch.dict("os.environ", {"VOCALINUX_FORCE_BACKEND": value.upper()}):
+ with patch.dict("os.environ", {"VOCULINUX_FORCE_BACKEND": value.upper()}):
self.assertEqual(TextInjector._forced_backend(), value)
def test_unknown_value_falls_back_to_auto(self):
"""A typo must not silently pin the wrong backend."""
- with patch.dict("os.environ", {"VOCALINUX_FORCE_BACKEND": "ibsu"}):
+ with patch.dict("os.environ", {"VOCULINUX_FORCE_BACKEND": "ibsu"}):
self.assertEqual(TextInjector._forced_backend(), "auto")
def test_missing_variable_means_auto(self):
diff --git a/tests/test_text_injector_ext.py b/tests/test_text_injector_ext.py
index f976947..edc218a 100644
--- a/tests/test_text_injector_ext.py
+++ b/tests/test_text_injector_ext.py
@@ -111,7 +111,7 @@ class TestDetectEnvironment(unittest.TestCase):
obj = _make_injector(DesktopEnvironment.X11)
env = {
- "FLATPAK_ID": "com.vocalinux.Vocalinux",
+ "FLATPAK_ID": "com.voculinux.Voculinux",
"XDG_SESSION_TYPE": "wayland",
"DISPLAY": ":0",
}
@@ -126,7 +126,7 @@ class TestDetectEnvironment(unittest.TestCase):
obj = _make_injector(DesktopEnvironment.X11)
env = {
- "FLATPAK_ID": "com.vocalinux.Vocalinux",
+ "FLATPAK_ID": "com.voculinux.Voculinux",
"XDG_SESSION_TYPE": "wayland",
"DISPLAY": ":0",
}
@@ -140,7 +140,7 @@ class TestDetectEnvironment(unittest.TestCase):
obj = _make_injector(DesktopEnvironment.WAYLAND)
env = {
- "FLATPAK_ID": "com.vocalinux.Vocalinux",
+ "FLATPAK_ID": "com.voculinux.Voculinux",
"XDG_SESSION_TYPE": "wayland",
"WAYLAND_DISPLAY": "wayland-0",
"DISPLAY": ":0",
@@ -346,7 +346,7 @@ class TestCheckDependencies(unittest.TestCase):
mock_ibus_class.assert_called_once()
def test_force_backend_wtype_skips_ibus(self):
- """VOCALINUX_FORCE_BACKEND=wtype pins wtype even where IBus would be chosen."""
+ """VOCULINUX_FORCE_BACKEND=wtype pins wtype even where IBus would be chosen."""
from vocalinux.text_injection.text_injector import DesktopEnvironment
obj = _make_injector(DesktopEnvironment.WAYLAND)
@@ -354,7 +354,7 @@ class TestCheckDependencies(unittest.TestCase):
with (
patch.dict(
os.environ,
- {"XDG_SESSION_TYPE": "wayland", "VOCALINUX_FORCE_BACKEND": "wtype"},
+ {"XDG_SESSION_TYPE": "wayland", "VOCULINUX_FORCE_BACKEND": "wtype"},
clear=True,
),
patch("vocalinux.text_injection.text_injector.is_ibus_available", return_value=True),
@@ -450,7 +450,7 @@ class TestCheckDependencies(unittest.TestCase):
run(pinned).assert_not_called()
def test_explicit_auto_environment_ignores_the_saved_config_pin(self):
- """VOCALINUX_FORCE_BACKEND=auto is how you get one run of plain autodetection.
+ """VOCULINUX_FORCE_BACKEND=auto is how you get one run of plain autodetection.
The resolver already knows an explicit auto from an unset variable; this
drives the whole of _check_dependencies to show the saved pin really is
@@ -467,7 +467,7 @@ class TestCheckDependencies(unittest.TestCase):
with (
patch.dict(
os.environ,
- {"XDG_SESSION_TYPE": "wayland", "VOCALINUX_FORCE_BACKEND": "auto"},
+ {"XDG_SESSION_TYPE": "wayland", "VOCULINUX_FORCE_BACKEND": "auto"},
clear=True,
),
patch("vocalinux.text_injection.text_injector.config_dir", return_value="/fake/config"),
@@ -512,7 +512,7 @@ class TestCheckDependencies(unittest.TestCase):
"XDG_CURRENT_DESKTOP": desktop,
}
if not config_pin:
- environ["VOCALINUX_FORCE_BACKEND"] = "ibus"
+ environ["VOCULINUX_FORCE_BACKEND"] = "ibus"
with (
patch.dict(
@@ -628,7 +628,7 @@ class TestCheckDependencies(unittest.TestCase):
"XDG_CURRENT_DESKTOP": "Hyprland",
}
if pin:
- environ["VOCALINUX_FORCE_BACKEND"] = pin
+ environ["VOCULINUX_FORCE_BACKEND"] = pin
with (
patch.dict(os.environ, environ, clear=True),
patch(
@@ -716,7 +716,7 @@ class TestCheckDependencies(unittest.TestCase):
self.assertFalse(self._not_applied(output))
def test_pinned_log_line_names_the_config_source_not_the_variable(self):
- """A config-sourced pin must not be reported as VOCALINUX_FORCE_BACKEND."""
+ """A config-sourced pin must not be reported as VOCULINUX_FORCE_BACKEND."""
from vocalinux.text_injection.text_injector import DesktopEnvironment, TextInjector
obj = _make_injector(DesktopEnvironment.WAYLAND)
@@ -736,7 +736,7 @@ class TestCheckDependencies(unittest.TestCase):
pinned_lines = [line for line in logs.output if "wtype" in line and "=" in line]
self.assertTrue(pinned_lines)
self.assertFalse(
- [line for line in pinned_lines if "VOCALINUX_FORCE_BACKEND" in line],
+ [line for line in pinned_lines if "VOCULINUX_FORCE_BACKEND" in line],
f"config-sourced pin reported as the env var: {pinned_lines}",
)
@@ -764,7 +764,7 @@ class TestCheckDependencies(unittest.TestCase):
with (
patch.dict(
os.environ,
- {"XDG_SESSION_TYPE": "wayland", "VOCALINUX_FORCE_BACKEND": "ibus"},
+ {"XDG_SESSION_TYPE": "wayland", "VOCULINUX_FORCE_BACKEND": "ibus"},
clear=True,
),
patch("vocalinux.text_injection.text_injector.is_ibus_available", return_value=True),
@@ -864,7 +864,7 @@ class TestCheckDependencies(unittest.TestCase):
)
def test_force_backend_ydotool_skips_ibus_and_wtype(self):
- """VOCALINUX_FORCE_BACKEND=ydotool pins ydotool even when wtype is available."""
+ """VOCULINUX_FORCE_BACKEND=ydotool pins ydotool even when wtype is available."""
from vocalinux.text_injection.text_injector import DesktopEnvironment
obj = _make_injector(DesktopEnvironment.WAYLAND)
@@ -872,7 +872,7 @@ class TestCheckDependencies(unittest.TestCase):
with (
patch.dict(
os.environ,
- {"XDG_SESSION_TYPE": "wayland", "VOCALINUX_FORCE_BACKEND": "ydotool"},
+ {"XDG_SESSION_TYPE": "wayland", "VOCULINUX_FORCE_BACKEND": "ydotool"},
clear=True,
),
patch("vocalinux.text_injection.text_injector.is_ibus_available", return_value=True),
@@ -890,7 +890,7 @@ class TestCheckDependencies(unittest.TestCase):
mock_ibus_class.assert_not_called()
def test_force_backend_ibus_bypasses_reachability_guards(self):
- """VOCALINUX_FORCE_BACKEND=ibus selects IBus even on an unbridged compositor."""
+ """VOCULINUX_FORCE_BACKEND=ibus selects IBus even on an unbridged compositor."""
from vocalinux.text_injection.text_injector import DesktopEnvironment, TextInjector
obj = _make_injector(DesktopEnvironment.WAYLAND)
@@ -901,7 +901,7 @@ class TestCheckDependencies(unittest.TestCase):
{
"XDG_SESSION_TYPE": "wayland",
"XDG_CURRENT_DESKTOP": "Hyprland",
- "VOCALINUX_FORCE_BACKEND": "ibus",
+ "VOCULINUX_FORCE_BACKEND": "ibus",
},
clear=True,
),
@@ -1596,7 +1596,7 @@ class TestPressBackspace(unittest.TestCase):
def test_ydotool_v1_uses_keycode_14(self):
obj = _make_backspace_injector("WAYLAND", tool="ydotool", legacy=False)
- with patch.dict(os.environ, {"VOCALINUX_YDOTOOL_KEY_DELAY": "2"}):
+ with patch.dict(os.environ, {"VOCULINUX_YDOTOOL_KEY_DELAY": "2"}):
with patch("subprocess.run") as mock_run:
self.assertTrue(obj.press_backspace(2))
self.assertEqual(
@@ -1788,7 +1788,7 @@ class TestBackgroundIBusInitialization(unittest.TestCase):
with (
patch.dict(
os.environ,
- {"XDG_SESSION_TYPE": "x11", "VOCALINUX_FORCE_BACKEND": "ibus"},
+ {"XDG_SESSION_TYPE": "x11", "VOCULINUX_FORCE_BACKEND": "ibus"},
clear=True,
),
patch("vocalinux.text_injection.text_injector.is_ibus_available", return_value=True),
@@ -1832,7 +1832,7 @@ class TestBackgroundIBusInitialization(unittest.TestCase):
with (
patch.dict(
os.environ,
- {"XDG_SESSION_TYPE": "wayland", "VOCALINUX_FORCE_BACKEND": "ibus"},
+ {"XDG_SESSION_TYPE": "wayland", "VOCULINUX_FORCE_BACKEND": "ibus"},
clear=True,
),
patch("vocalinux.text_injection.text_injector.is_ibus_available", return_value=True),
@@ -1872,7 +1872,7 @@ class TestBackgroundIBusInitialization(unittest.TestCase):
with (
patch.dict(
os.environ,
- {"XDG_SESSION_TYPE": "x11", "VOCALINUX_FORCE_BACKEND": "ibus"},
+ {"XDG_SESSION_TYPE": "x11", "VOCULINUX_FORCE_BACKEND": "ibus"},
clear=True,
),
patch("vocalinux.text_injection.text_injector.is_ibus_available", return_value=True),
@@ -1905,7 +1905,7 @@ class TestBackgroundIBusInitialization(unittest.TestCase):
with (
patch.dict(
os.environ,
- {"XDG_SESSION_TYPE": "x11", "VOCALINUX_FORCE_BACKEND": "ibus"},
+ {"XDG_SESSION_TYPE": "x11", "VOCULINUX_FORCE_BACKEND": "ibus"},
clear=True,
),
patch("vocalinux.text_injection.text_injector.is_ibus_available", return_value=True),
@@ -1939,7 +1939,7 @@ class TestBackgroundIBusInitialization(unittest.TestCase):
obj._ibus_injector = MagicMock()
obj.wayland_tool = "ydotool"
obj._ibus_injector.prepare_engine.side_effect = RuntimeError("late failure")
- obj._backend_pin = ("ibus", "VOCALINUX_FORCE_BACKEND")
+ obj._backend_pin = ("ibus", "VOCULINUX_FORCE_BACKEND")
with self.assertLogs("vocalinux.text_injection.text_injector", level="DEBUG") as logs:
obj._warn_if_pin_not_honoured(*obj._backend_pin)
diff --git a/tests/test_tray_indicator.py b/tests/test_tray_indicator.py
index da82d81..4d02d57 100644
--- a/tests/test_tray_indicator.py
+++ b/tests/test_tray_indicator.py
@@ -120,10 +120,10 @@ class TestTrayIndicator(unittest.TestCase):
self.patcher_listdir = patch(
"os.listdir",
return_value=[
- "vocalinux.svg",
- "vocalinux-microphone-off.svg",
- "vocalinux-microphone.svg",
- "vocalinux-microphone-process.svg",
+ "voculinux.svg",
+ "voculinux-microphone-off.svg",
+ "voculinux-microphone.svg",
+ "voculinux-microphone-process.svg",
],
)
self.mock_listdir = self.patcher_listdir.start()
@@ -350,7 +350,7 @@ class TestTrayIndicator(unittest.TestCase):
self.tray_indicator._cancel_menu_item.set_sensitive.assert_called_with(False)
self.tray_indicator._cancel_menu_item.set_visible.assert_called_with(False)
- self.tray_indicator.indicator.set_title.assert_called_with("Vocalinux")
+ self.tray_indicator.indicator.set_title.assert_called_with("Voculinux")
def test_cancel_tooltip_uses_fallback_without_shortcut_name(self) -> None:
self.tray_indicator.indicator = MagicMock()
@@ -728,7 +728,7 @@ class TestTrayIndicator(unittest.TestCase):
with patch.object(_resource_manager, "validate_resources") as mock_validate:
mock_validate.return_value = {
"resources_dir_exists": True,
- "missing_icons": ["vocalinux.svg"],
+ "missing_icons": ["voculinux.svg"],
"missing_sounds": [],
}
self.tray_indicator._validate_resources()
@@ -1220,7 +1220,7 @@ class TestTrayIndicator(unittest.TestCase):
)
def test_overlay_close_request_quits_app(self):
- """A dock/taskbar close of the overlay window quits Vocalinux (#1028)."""
+ """A dock/taskbar close of the overlay window quits Voculinux (#1028)."""
self.assertEqual(self.tray_indicator.overlay._on_close_request, self.tray_indicator._quit)
def test_quit_destroys_overlay(self):
@@ -1355,7 +1355,7 @@ class TestTrayIndicatorFlatpakIcons(unittest.TestCase):
Inside a Flatpak the StatusNotifier host runs outside the sandbox and resolves
icons from the exported ``-*`` theme, so the indicator must reference
- those names rather than the bundled ``vocalinux-*`` names.
+ those names rather than the bundled ``voculinux-*`` names.
"""
def setUp(self):
@@ -1369,18 +1369,18 @@ class TestTrayIndicatorFlatpakIcons(unittest.TestCase):
with patch.object(tray, "FLATPAK_ID", None):
names = tray._themed_icon_names()
- self.assertEqual(names["default"], "vocalinux-microphone-off")
- self.assertEqual(names["active"], "vocalinux-microphone")
- self.assertEqual(names["processing"], "vocalinux-microphone-process")
+ self.assertEqual(names["default"], "voculinux-microphone-off")
+ self.assertEqual(names["active"], "voculinux-microphone")
+ self.assertEqual(names["processing"], "voculinux-microphone-process")
def test_themed_icon_names_inside_flatpak(self):
import vocalinux.ui.tray_indicator as tray
- with patch.object(tray, "FLATPAK_ID", "com.vocalinux.Vocalinux"):
+ with patch.object(tray, "FLATPAK_ID", "com.voculinux.Voculinux"):
names = tray._themed_icon_names()
- self.assertEqual(names["default"], "com.vocalinux.Vocalinux-microphone-off")
- self.assertEqual(names["active"], "com.vocalinux.Vocalinux-microphone")
- self.assertEqual(names["processing"], "com.vocalinux.Vocalinux-microphone-process")
+ self.assertEqual(names["default"], "com.voculinux.Voculinux-microphone-off")
+ self.assertEqual(names["active"], "com.voculinux.Voculinux-microphone")
+ self.assertEqual(names["processing"], "com.voculinux.Voculinux-microphone-process")
class TestAppIndicatorImportFallback(unittest.TestCase):
@@ -1447,7 +1447,7 @@ class TestAppIndicatorImportFallback(unittest.TestCase):
AyatanaAppIndicator3=sentinel,
)
- with patch.dict(os.environ, {"APPDIR": "/tmp/.mount_vocalinux"}):
+ with patch.dict(os.environ, {"APPDIR": "/tmp/.mount_voculinux"}):
import vocalinux.ui.tray_indicator as tray
self.assertIs(tray.AppIndicator, sentinel)
@@ -1519,7 +1519,7 @@ class TestIndicatorBackendWiring(TestTrayIndicator):
patch(
"vocalinux.ui.tray_indicator.AppIndicator.Indicator.new", return_value=raw
) as new,
- patch("vocalinux.ui.tray_indicator.FLATPAK_ID", "com.vocalinux.Vocalinux"),
+ patch("vocalinux.ui.tray_indicator.FLATPAK_ID", "com.voculinux.Voculinux"),
):
self.tray_indicator._init_indicator()
diff --git a/tests/test_tray_indicator_ext.py b/tests/test_tray_indicator_ext.py
index f91ed04..761ecd8 100644
--- a/tests/test_tray_indicator_ext.py
+++ b/tests/test_tray_indicator_ext.py
@@ -669,7 +669,7 @@ class TestExternalTriggerHandlers(unittest.TestCase):
"""Tests for the D-Bus external Start/Stop handlers on TrayIndicator.
These use normal (non push-to-talk) start semantics and guard on the
- current recognition state, so repeated `vocalinux --start`/`--stop` calls
+ current recognition state, so repeated `voculinux --start`/`--stop` calls
are idempotent.
"""
diff --git a/tests/test_tray_menu_model.py b/tests/test_tray_menu_model.py
index 4d4fbd9..010b1d9 100644
--- a/tests/test_tray_menu_model.py
+++ b/tests/test_tray_menu_model.py
@@ -218,11 +218,11 @@ def test_gmenu_indicator_adapts_gtk3_calls():
exported = raw.set_menu.call_args[0][0]
assert _labels(exported) == [["Start"]]
- indicator.set_icon_full("vocalinux-microphone", "Microphone on")
- raw.set_icon.assert_called_once_with("vocalinux-microphone", "Microphone on")
+ indicator.set_icon_full("voculinux-microphone", "Microphone on")
+ raw.set_icon.assert_called_once_with("voculinux-microphone", "Microphone on")
- indicator.set_title("Vocalinux")
- raw.set_title.assert_called_once_with("Vocalinux")
+ indicator.set_title("Voculinux")
+ raw.set_title.assert_called_once_with("Voculinux")
def test_refresh_before_set_menu_is_a_no_op():
diff --git a/tests/test_uninstall_cwd_safety.py b/tests/test_uninstall_cwd_safety.py
index 7654649..455d1e9 100644
--- a/tests/test_uninstall_cwd_safety.py
+++ b/tests/test_uninstall_cwd_safety.py
@@ -2,7 +2,7 @@
The website runs ``bash /tmp/vul.sh`` from whatever directory the terminal is
in. ``venv/``, ``build/``, ``dist/``, and Python bytecode are removed only when
-the script itself lives in a Vocalinux source checkout, and only inside that
+the script itself lives in a Voculinux source checkout, and only inside that
checkout.
"""
@@ -40,8 +40,8 @@ def _decoy_tree(root: Path) -> None:
(root / ".pytest_cache").mkdir()
(root / ".coverage").write_text("cov", encoding="utf-8")
(root / "src" / "pkg.egg-info").mkdir(parents=True)
- (root / "activate-vocalinux.sh").write_text("echo hi\n", encoding="utf-8")
- (root / "vocalinux-run.py").write_text("print(1)\n", encoding="utf-8")
+ (root / "activate-voculinux.sh").write_text("echo hi\n", encoding="utf-8")
+ (root / "voculinux-run.py").write_text("print(1)\n", encoding="utf-8")
def _assert_decoy_intact(root: Path) -> None:
@@ -56,15 +56,15 @@ def _assert_decoy_intact(root: Path) -> None:
assert (root / ".pytest_cache").is_dir()
assert (root / ".coverage").is_file()
assert (root / "src" / "pkg.egg-info").is_dir()
- assert (root / "activate-vocalinux.sh").is_file()
- assert (root / "vocalinux-run.py").is_file()
+ assert (root / "activate-voculinux.sh").is_file()
+ assert (root / "voculinux-run.py").is_file()
def _make_checkout(root: Path) -> Path:
- checkout = root / "vocalinux"
+ checkout = root / "voculinux"
(checkout / "src" / "vocalinux").mkdir(parents=True)
(checkout / "pyproject.toml").write_text(
- '[project]\nname = "vocalinux"\n',
+ '[project]\nname = "voculinux"\n',
encoding="utf-8",
)
(checkout / "src" / "vocalinux" / "__init__.py").write_text("", encoding="utf-8")
@@ -81,7 +81,7 @@ def _run(script: Path, cwd: Path, home: Path, *args: str) -> subprocess.Complete
"""Run uninstall.sh against a fake home, without the host's pgrep or kill.
The uninstaller looks up this uid's processes and can TERM then KILL a
- running Vocalinux. A stub earlier on PATH records the call and matches
+ running Voculinux. A stub earlier on PATH records the call and matches
nothing, so the suite cannot stop the app a developer has open.
"""
bin_dir = home.parent / "uninstall-test-bin"
@@ -90,17 +90,17 @@ def _run(script: Path, cwd: Path, home: Path, *args: str) -> subprocess.Complete
kill_log = home.parent / "kill.log"
_write_stub(
bin_dir / "pgrep",
- "#!/bin/sh\n" 'printf \'%s\\n\' "$*" >> "$VOCALINUX_TEST_PGREP_LOG"\n' "exit 1\n",
+ "#!/bin/sh\n" 'printf \'%s\\n\' "$*" >> "$VOCULINUX_TEST_PGREP_LOG"\n' "exit 1\n",
)
_write_stub(
bin_dir / "kill",
- "#!/bin/sh\n" 'printf \'%s\\n\' "$*" >> "$VOCALINUX_TEST_KILL_LOG"\n' "exit 0\n",
+ "#!/bin/sh\n" 'printf \'%s\\n\' "$*" >> "$VOCULINUX_TEST_KILL_LOG"\n' "exit 0\n",
)
env = os.environ.copy()
env["HOME"] = str(home)
env["PATH"] = os.pathsep.join((str(bin_dir), env.get("PATH", "")))
- env["VOCALINUX_TEST_PGREP_LOG"] = str(pgrep_log)
- env["VOCALINUX_TEST_KILL_LOG"] = str(kill_log)
+ env["VOCULINUX_TEST_PGREP_LOG"] = str(pgrep_log)
+ env["VOCULINUX_TEST_KILL_LOG"] = str(kill_log)
env.pop("XDG_DATA_HOME", None)
env.pop("XDG_CONFIG_HOME", None)
env.pop("VIRTUAL_ENV", None)
@@ -114,9 +114,9 @@ def _run(script: Path, cwd: Path, home: Path, *args: str) -> subprocess.Complete
stdin=subprocess.DEVNULL,
check=False,
)
- if "Checking for running Vocalinux processes" in result.stdout:
+ if "Checking for running Voculinux processes" in result.stdout:
logged = pgrep_log.read_text(encoding="utf-8") if pgrep_log.is_file() else ""
- assert "vocalinux" in logged, "uninstall.sh did not use the test pgrep stub"
+ assert "voculinux" in logged, "uninstall.sh did not use the test pgrep stub"
if kill_log.is_file():
assert kill_log.read_text(encoding="utf-8").strip() == ""
return result
@@ -136,8 +136,8 @@ def test_curl_style_run_leaves_the_callers_directory_alone(tmp_path: Path) -> No
script = tmp_path / "vul.sh"
_write_script(script)
- data = home / ".local" / "share" / "vocalinux"
- config = home / ".config" / "vocalinux"
+ data = home / ".local" / "share" / "voculinux"
+ config = home / ".config" / "voculinux"
data.mkdir(parents=True)
(data / "marker").write_text("data", encoding="utf-8")
(data / "venv").mkdir()
@@ -146,12 +146,12 @@ def test_curl_style_run_leaves_the_callers_directory_alone(tmp_path: Path) -> No
(config / "config.json").write_text("{}\n", encoding="utf-8")
bindir = home / ".local" / "bin"
bindir.mkdir(parents=True)
- (bindir / "vocalinux").write_text("#!/bin/sh\n", encoding="utf-8")
- (bindir / "vocalinux-gui").symlink_to("vocalinux")
- (bindir / "activate-vocalinux.sh").write_text("echo\n", encoding="utf-8")
+ (bindir / "voculinux").write_text("#!/bin/sh\n", encoding="utf-8")
+ (bindir / "voculinux-gui").symlink_to("voculinux")
+ (bindir / "activate-voculinux.sh").write_text("echo\n", encoding="utf-8")
desktop = home / ".local" / "share" / "applications"
desktop.mkdir(parents=True)
- (desktop / "vocalinux.desktop").write_text("[Desktop Entry]\n", encoding="utf-8")
+ (desktop / "voculinux.desktop").write_text("[Desktop Entry]\n", encoding="utf-8")
result = _run(script, cwd, home)
@@ -161,10 +161,10 @@ def test_curl_style_run_leaves_the_callers_directory_alone(tmp_path: Path) -> No
_assert_decoy_intact(cwd)
assert not data.exists()
assert not config.exists()
- assert not (bindir / "vocalinux").exists()
- assert not (bindir / "vocalinux-gui").exists()
- assert not (bindir / "activate-vocalinux.sh").exists()
- assert not (desktop / "vocalinux.desktop").exists()
+ assert not (bindir / "voculinux").exists()
+ assert not (bindir / "voculinux-gui").exists()
+ assert not (bindir / "activate-voculinux.sh").exists()
+ assert not (desktop / "voculinux.desktop").exists()
def test_keep_flags_still_do_not_touch_the_working_directory(tmp_path: Path) -> None:
@@ -175,8 +175,8 @@ def test_keep_flags_still_do_not_touch_the_working_directory(tmp_path: Path) ->
_decoy_tree(cwd)
script = tmp_path / "vul.sh"
_write_script(script)
- config = home / ".config" / "vocalinux"
- data = home / ".local" / "share" / "vocalinux"
+ config = home / ".config" / "voculinux"
+ data = home / ".local" / "share" / "voculinux"
config.mkdir(parents=True)
data.mkdir(parents=True)
(config / "config.json").write_text("{}\n", encoding="utf-8")
@@ -217,8 +217,8 @@ def test_source_checkout_cleans_itself_and_leaves_the_caller_alone(tmp_path: Pat
assert not (checkout / ".pytest_cache").exists()
assert not (checkout / "proj" / "pkg" / "__pycache__").exists()
assert not (checkout / "src" / "pkg.egg-info").exists()
- assert not (checkout / "activate-vocalinux.sh").exists()
- assert not (checkout / "vocalinux-run.py").exists()
+ assert not (checkout / "activate-voculinux.sh").exists()
+ assert not (checkout / "voculinux-run.py").exists()
def test_dev_venv_records_survive_checkout_cleanup(tmp_path: Path) -> None:
@@ -234,8 +234,8 @@ def test_dev_venv_records_survive_checkout_cleanup(tmp_path: Path) -> None:
dev_cache.mkdir(parents=True)
(dev_cache / "mod.cpython-312.pyc").write_bytes(b"pyc")
(checkout / ".venv" / ".coverage").write_text("keep", encoding="utf-8")
- (checkout / "vocalinux.egg-info").mkdir()
- (checkout / "vocalinux.egg-info" / "PKG-INFO").write_text("name\n", encoding="utf-8")
+ (checkout / "voculinux.egg-info").mkdir()
+ (checkout / "voculinux.egg-info" / "PKG-INFO").write_text("name\n", encoding="utf-8")
result = _run(checkout / "uninstall.sh", tmp_path, home)
@@ -245,7 +245,7 @@ def test_dev_venv_records_survive_checkout_cleanup(tmp_path: Path) -> None:
assert (dev_cache / "mod.cpython-312.pyc").is_file()
assert (checkout / ".venv" / ".coverage").is_file()
assert not (checkout / "src" / "pkg.egg-info").exists()
- assert not (checkout / "vocalinux.egg-info").exists()
+ assert not (checkout / "voculinux.egg-info").exists()
assert not (checkout / "proj" / "pkg" / "__pycache__").exists()
assert not (checkout / ".coverage").exists()
@@ -257,11 +257,11 @@ def test_curl_clone_uninstall_does_not_print_a_cleanup_error(tmp_path: Path) ->
home.mkdir()
cwd.mkdir()
(cwd / "notes.txt").write_text("keep", encoding="utf-8")
- clone = home / ".local" / "share" / "vocalinux-install"
+ clone = home / ".local" / "share" / "voculinux-install"
(clone / "src" / "vocalinux").mkdir(parents=True)
- (clone / "pyproject.toml").write_text('[project]\nname = "vocalinux"\n', encoding="utf-8")
+ (clone / "pyproject.toml").write_text('[project]\nname = "voculinux"\n', encoding="utf-8")
(clone / "src" / "vocalinux" / "__init__.py").write_text("", encoding="utf-8")
- (clone / "src" / "vocalinux.egg-info").mkdir()
+ (clone / "src" / "voculinux.egg-info").mkdir()
(clone / "build").mkdir()
(clone / "build" / "out").write_text("build", encoding="utf-8")
_write_script(clone / "uninstall.sh")
@@ -298,7 +298,7 @@ def test_another_projects_tree_is_not_treated_as_a_checkout(tmp_path: Path) -> N
home.mkdir()
project = tmp_path / "other"
(project / "src" / "vocalinux").mkdir(parents=True)
- (project / "pyproject.toml").write_text('name = "not-vocalinux"\n', encoding="utf-8")
+ (project / "pyproject.toml").write_text('name = "not-voculinux"\n', encoding="utf-8")
_write_script(project / "uninstall.sh")
_decoy_tree(project)
@@ -399,7 +399,7 @@ def test_uninstaller_is_valid_bash() -> None:
"pyproject",
[
"",
- 'name = "vocalinux"\n',
+ 'name = "voculinux"\n',
],
)
def test_checkout_detection_needs_both_the_name_and_the_package_dir(
diff --git a/tests/test_update_checker.py b/tests/test_update_checker.py
index 694a851..90607c5 100644
--- a/tests/test_update_checker.py
+++ b/tests/test_update_checker.py
@@ -114,7 +114,7 @@ class TestTrustedUrls:
def test_rejects_untrusted_urls(self):
assert not is_trusted_release_url("https://evil.example/payload")
assert not is_trusted_release_url("http://github.com/VocaHQ/vocalinux")
- assert not is_trusted_release_url("https://github.com/evil/vocalinux")
+ assert not is_trusted_release_url("https://github.com/evil/voculinux")
assert not is_trusted_release_url("")
@@ -315,7 +315,7 @@ class TestFetchLatestRelease:
def test_evil_update_url_does_not_become_html_url(self, caplog):
tag_url = "https://github.com/VocaHQ/vocalinux/releases/tag/v0.17.0"
evil_paths = [
- "/evil/vocalinux/releases/tag/v9",
+ "/evil/voculinux/releases/tag/v9",
"https://evil.example/x",
"/VocaHQ/vocalinux/releases/../evil",
]
@@ -343,7 +343,7 @@ class TestFetchLatestRelease:
}
untrusted_urls = (
"https://evil.example/VocaHQ/vocalinux/releases/tag/v0.17.0",
- "https://github.com/evil/vocalinux/releases/tag/v0.17.0",
+ "https://github.com/evil/voculinux/releases/tag/v0.17.0",
"http://github.com/VocaHQ/vocalinux/releases/tag/v0.17.0",
)
caplog.set_level(logging.WARNING, logger="vocalinux.utils.update_checker")
@@ -392,11 +392,11 @@ class TestFetchLatestRelease:
first, second = mock_requests.get.call_args_list
assert first[0][0] == "https://api.github.com/repos/VocaHQ/vocalinux/releases/latest"
assert first.kwargs["headers"]["Accept"] == "application/vnd.github+json"
- assert first.kwargs["headers"]["User-Agent"] == "Vocalinux-UpdateChecker"
+ assert first.kwargs["headers"]["User-Agent"] == "Voculinux-UpdateChecker"
assert "Authorization" not in first.kwargs["headers"]
assert second[0][0] == "https://github.com/VocaHQ/vocalinux/releases/latest"
assert second.kwargs["headers"]["Accept"] == "application/json"
- assert second.kwargs["headers"]["User-Agent"] == "Vocalinux-UpdateChecker"
+ assert second.kwargs["headers"]["User-Agent"] == "Voculinux-UpdateChecker"
assert "Authorization" not in second.kwargs["headers"]
assert fallback.url == tag_url
assert _checker_warnings(caplog) == []
diff --git a/tests/test_upstream_intake_policy.py b/tests/test_upstream_intake_policy.py
index cb672df..7a21b7a 100644
--- a/tests/test_upstream_intake_policy.py
+++ b/tests/test_upstream_intake_policy.py
@@ -52,7 +52,7 @@ def test_policy_states_qualification_rule() -> None:
def test_policy_names_retained_internal_module_name() -> None:
policy = _policy()
- assert "vocalinux" in policy
+ assert "voculinux" in policy
assert "internal" in policy.lower()
diff --git a/tests/test_verify_release.py b/tests/test_verify_release.py
index a2ee30f..55c4817 100644
--- a/tests/test_verify_release.py
+++ b/tests/test_verify_release.py
@@ -35,11 +35,11 @@ def test_the_dispatch_input_never_reaches_the_shell():
def test_the_manifest_parses_as_sha256sum_writes_it():
parsed = verify.parse_manifest(
- "0ee0d8e6 Vocalinux-0.16.2-x86_64.AppImage\n22deb51a *vocalinux-0.16.2.whl\n\n"
+ "0ee0d8e6 Voculinux-0.16.2-x86_64.AppImage\n22deb51a *voculinux-0.16.2.whl\n\n"
)
assert parsed == {
- "Vocalinux-0.16.2-x86_64.AppImage": "0ee0d8e6",
- "vocalinux-0.16.2.whl": "22deb51a",
+ "Voculinux-0.16.2-x86_64.AppImage": "0ee0d8e6",
+ "voculinux-0.16.2.whl": "22deb51a",
}
@@ -108,7 +108,7 @@ def test_provenance_asks_only_for_slsa_build_provenance(monkeypatch):
def test_a_release_missing_a_distribution_names_it():
"""Comparing only what is left would pass while PyPI serves an unchecked file."""
- assert verify.check_pypi("0.16.2", {"Vocalinux-0.16.2-x86_64.AppImage": "aa"}) == [
+ assert verify.check_pypi("0.16.2", {"Voculinux-0.16.2-x86_64.AppImage": "aa"}) == [
"the release carries no .whl to compare against PyPI",
"the release carries no .tar.gz to compare against PyPI",
]
@@ -130,9 +130,9 @@ def test_an_extra_pypi_distribution_fails(monkeypatch):
import urllib.request
- wheel = "vocalinux-0.16.2-py3-none-any.whl"
- sdist = "vocalinux-0.16.2.tar.gz"
- extra = "vocalinux-0.16.2-extra.whl"
+ wheel = "voculinux-0.16.2-py3-none-any.whl"
+ sdist = "voculinux-0.16.2.tar.gz"
+ extra = "voculinux-0.16.2-extra.whl"
payload = {
"urls": [
{"filename": wheel, "digests": {"sha256": "aa"}},
diff --git a/tests/test_whisper_support.py b/tests/test_whisper_support.py
index 65b022b..743226c 100644
--- a/tests/test_whisper_support.py
+++ b/tests/test_whisper_support.py
@@ -7,7 +7,7 @@ import sys
import types
from unittest.mock import MagicMock, patch # noqa: F401
-# Mock GTK and other dependencies before importing vocalinux
+# Mock GTK and other dependencies before importing voculinux
sys.modules["gi"] = MagicMock()
sys.modules["gi.repository"] = MagicMock()
sys.modules["vosk"] = MagicMock()
diff --git a/tests/test_whispercpp_model_info_ext.py b/tests/test_whispercpp_model_info_ext.py
index 45cf9f3..6613e06 100644
--- a/tests/test_whispercpp_model_info_ext.py
+++ b/tests/test_whispercpp_model_info_ext.py
@@ -210,7 +210,7 @@ class TestModelInfo(unittest.TestCase):
"large-v2",
"large-v2-q5_0",
"large-v2-q8_0",
- "large", # Vocalinux alias for upstream large-v3
+ "large", # Voculinux alias for upstream large-v3
"large-v3-q5_0",
"large-v3-turbo",
"large-v3-turbo-q5_0",
diff --git a/uninstall.sh b/uninstall.sh
index 3b71deb..4eaf9f5 100755
--- a/uninstall.sh
+++ b/uninstall.sh
@@ -1,6 +1,6 @@
#!/bin/bash
-# Vocalinux Uninstaller
-# This script removes Vocalinux and cleans up the environment
+# Voculinux Uninstaller
+# This script removes Voculinux and cleans up the environment
# Don't exit on error to allow for more robust cleanup
# set -e
@@ -39,9 +39,9 @@ read_pid_file() {
fi
}
-# True only for the Vocalinux app / IBus engine — not editors, shells, or tests
-# whose argv merely contains the string "vocalinux" (e.g. cwd under the repo).
-is_vocalinux_process() {
+# True only for the Voculinux app / IBus engine — not editors, shells, or tests
+# whose argv merely contains the string "voculinux" (e.g. cwd under the repo).
+is_voculinux_process() {
local pid="$1"
if [ "$pid" = "$$" ] || [ "$pid" = "$PPID" ]; then
@@ -69,18 +69,18 @@ is_vocalinux_process() {
return 0
fi
- # IBus engine: .../vocalinux/.../ibus_engine.py
- if [[ "$cmdline" == *"ibus_engine.py"* && "$cmdline" == *"vocalinux"* ]]; then
+ # IBus engine: .../voculinux/.../ibus_engine.py
+ if [[ "$cmdline" == *"ibus_engine.py"* && "$cmdline" == *"voculinux"* ]]; then
return 0
fi
# Console-script entrypoints. Setuptools scripts are executed as
- # `python …/bin/vocalinux`, so argv0 is python — scan every arg for the
- # script path (require …/bin/vocalinux to avoid matching a repo directory).
+ # `python …/bin/voculinux`, so argv0 is python — scan every arg for the
+ # script path (require …/bin/voculinux to avoid matching a repo directory).
local arg
while IFS= read -r -d '' arg; do
case "$arg" in
- vocalinux|vocalinux-gui|*/bin/vocalinux|*/bin/vocalinux-gui)
+ voculinux|voculinux-gui|*/bin/voculinux|*/bin/voculinux-gui)
return 0
;;
esac
@@ -90,16 +90,16 @@ is_vocalinux_process() {
}
# Prefer the PIDs the app writes; fall back to narrow entrypoint patterns only.
-# Deliberately does NOT use `pgrep -f vocalinux` (matches editors/shells/cwd paths).
-get_vocalinux_pids() {
+# Deliberately does NOT use `pgrep -f voculinux` (matches editors/shells/cwd paths).
+get_voculinux_pids() {
local data_home="${XDG_DATA_HOME:-$HOME/.local/share}"
local -A seen=()
local pid candidate
local -a candidates=()
for candidate in \
- "$(read_pid_file "$data_home/vocalinux/instance.lock")" \
- "$(read_pid_file "$data_home/vocalinux-ibus/engine.pid")"
+ "$(read_pid_file "$data_home/voculinux/instance.lock")" \
+ "$(read_pid_file "$data_home/voculinux-ibus/engine.pid")"
do
[ -n "$candidate" ] && candidates+=("$candidate")
done
@@ -108,16 +108,16 @@ get_vocalinux_pids() {
while read -r candidate; do
[ -n "$candidate" ] && candidates+=("$candidate")
done < <(
- pgrep -u "$(id -u)" -x vocalinux 2>/dev/null || true
- pgrep -u "$(id -u)" -x vocalinux-gui 2>/dev/null || true
- pgrep -u "$(id -u)" -f -- '-m vocalinux\.main' 2>/dev/null || true
- pgrep -u "$(id -u)" -f -- 'vocalinux/.*/ibus_engine\.py' 2>/dev/null || true
+ pgrep -u "$(id -u)" -x voculinux 2>/dev/null || true
+ pgrep -u "$(id -u)" -x voculinux-gui 2>/dev/null || true
+ pgrep -u "$(id -u)" -f -- '-m voculinux\.main' 2>/dev/null || true
+ pgrep -u "$(id -u)" -f -- 'voculinux/.*/ibus_engine\.py' 2>/dev/null || true
)
for pid in "${candidates[@]}"; do
[ -n "${seen[$pid]:-}" ] && continue
seen[$pid]=1
- if is_vocalinux_process "$pid"; then
+ if is_voculinux_process "$pid"; then
echo "$pid"
fi
done
@@ -145,15 +145,15 @@ safe_remove() {
fi
}
-# Function to kill running Vocalinux processes
-kill_vocalinux_processes() {
- print_info "Checking for running Vocalinux processes..."
+# Function to kill running Voculinux processes
+kill_voculinux_processes() {
+ print_info "Checking for running Voculinux processes..."
local PIDS
- PIDS=$(get_vocalinux_pids || true)
+ PIDS=$(get_voculinux_pids || true)
if [ -n "$PIDS" ]; then
- print_warning "Found running Vocalinux process(es):"
+ print_warning "Found running Voculinux process(es):"
local pid
for pid in $PIDS; do
local cmd
@@ -162,7 +162,7 @@ kill_vocalinux_processes() {
done
if [[ "$NON_INTERACTIVE" != "yes" ]]; then
- read -p "Kill running Vocalinux process(es)? (Y/n) " -n 1 -r
+ read -p "Kill running Voculinux process(es)? (Y/n) " -n 1 -r
echo
if [[ $REPLY =~ ^[Nn]$ ]]; then
print_warning "Processes not killed. Uninstallation may be incomplete."
@@ -170,13 +170,13 @@ kill_vocalinux_processes() {
fi
fi
- print_info "Stopping Vocalinux..."
+ print_info "Stopping Voculinux..."
# shellcheck disable=SC2086
echo $PIDS | xargs -r kill -TERM 2>/dev/null || true
sleep 2
local REMAINING_PIDS
- REMAINING_PIDS=$(get_vocalinux_pids || true)
+ REMAINING_PIDS=$(get_voculinux_pids || true)
if [ -n "$REMAINING_PIDS" ]; then
print_warning "Some processes still running, forcing termination..."
@@ -186,19 +186,19 @@ kill_vocalinux_processes() {
fi
local FINAL_PIDS
- FINAL_PIDS=$(get_vocalinux_pids || true)
+ FINAL_PIDS=$(get_voculinux_pids || true)
if [ -n "$FINAL_PIDS" ]; then
- print_error "Warning: Could not terminate all Vocalinux processes: $FINAL_PIDS"
+ print_error "Warning: Could not terminate all Voculinux processes: $FINAL_PIDS"
print_error "You may need to manually kill these processes before continuing."
else
- print_success "All Vocalinux processes stopped"
+ print_success "All Voculinux processes stopped"
fi
else
- print_info "No running Vocalinux processes found"
+ print_info "No running Voculinux processes found"
fi
}
-print_info "Vocalinux Uninstaller"
+print_info "Voculinux Uninstaller"
print_info "=============================="
echo ""
@@ -214,7 +214,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SOURCE_CHECKOUT=""
VENV_DIR=""
if [[ -f "$SCRIPT_DIR/pyproject.toml" && -d "$SCRIPT_DIR/src/vocalinux" ]] \
- && grep -q 'name = "vocalinux"' "$SCRIPT_DIR/pyproject.toml" 2>/dev/null; then
+ && grep -q 'name = "voculinux"' "$SCRIPT_DIR/pyproject.toml" 2>/dev/null; then
SOURCE_CHECKOUT="$SCRIPT_DIR"
VENV_DIR="$SCRIPT_DIR/venv"
fi
@@ -243,15 +243,15 @@ while [[ $# -gt 0 ]]; do
shift
;;
--help)
- echo "Vocalinux Uninstaller"
+ echo "Voculinux Uninstaller"
echo "Usage: $0 [options]"
echo "Options:"
echo " --keep-config Keep configuration files"
echo " --keep-data Keep application data (models, etc.)"
echo " --venv-dir=PATH Virtual environment to remove. Absolute, or relative to a"
echo " source checkout. Default: /venv when this script"
- echo " lives in a Vocalinux tree; otherwise only the curl install"
- echo " at ~/.local/share/vocalinux/venv is removed."
+ echo " lives in a Voculinux tree; otherwise only the curl install"
+ echo " at ~/.local/share/voculinux/venv is removed."
echo " -y, --yes Non-interactive mode (no confirmation prompts)"
echo " --help Show this help message"
exit 0
@@ -271,22 +271,22 @@ if [[ -n "$VENV_DIR" && "$VENV_DIR" != /* ]]; then
VENV_DIR="$SOURCE_CHECKOUT/$VENV_DIR"
else
print_error "Refusing relative --venv-dir outside a source checkout: $VENV_DIR"
- print_error "Pass an absolute path. A curl uninstall already removes ~/.local/share/vocalinux/venv."
+ print_error "Pass an absolute path. A curl uninstall already removes ~/.local/share/voculinux/venv."
exit 1
fi
fi
# Define XDG directories
-CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/vocalinux"
-DATA_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/vocalinux"
-IBUS_DATA_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/vocalinux-ibus"
+CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/voculinux"
+DATA_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/voculinux"
+IBUS_DATA_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/voculinux-ibus"
DESKTOP_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/applications"
AUTOSTART_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/autostart"
ICON_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/icons/hicolor/scalable/apps"
# Directories created by curl-based installation
-CURL_INSTALL_DIR="$HOME/.local/share/vocalinux-install"
-CURL_VENV_DIR="$HOME/.local/share/vocalinux/venv"
+CURL_INSTALL_DIR="$HOME/.local/share/voculinux-install"
+CURL_VENV_DIR="$HOME/.local/share/voculinux/venv"
CURL_BIN_DIR="$HOME/.local/bin"
echo "Uninstallation options:"
@@ -302,7 +302,7 @@ echo
if [[ "$NON_INTERACTIVE" == "yes" ]]; then
print_info "Non-interactive mode: proceeding with uninstallation..."
else
- read -p "This will remove Vocalinux from your system. Continue? (y/n) " -n 1 -r
+ read -p "This will remove Voculinux from your system. Continue? (y/n) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
print_info "Uninstallation cancelled."
@@ -346,10 +346,10 @@ remove_virtual_environment() {
safe_remove "$CURL_VENV_DIR" "curl-installed virtual environment"
fi
- # Remove the vocalinux data directory if empty (contains venv)
- local VOCALINUX_DATA_DIR="$HOME/.local/share/vocalinux"
- if [ -d "$VOCALINUX_DATA_DIR" ] && [ -z "$(ls -A "$VOCALINUX_DATA_DIR" 2>/dev/null)" ]; then
- safe_remove "$VOCALINUX_DATA_DIR" "empty vocalinux data directory"
+ # Remove the voculinux data directory if empty (contains venv)
+ local VOCULINUX_DATA_DIR="$HOME/.local/share/voculinux"
+ if [ -d "$VOCULINUX_DATA_DIR" ] && [ -z "$(ls -A "$VOCULINUX_DATA_DIR" 2>/dev/null)" ]; then
+ safe_remove "$VOCULINUX_DATA_DIR" "empty voculinux data directory"
fi
}
@@ -364,35 +364,35 @@ remove_curl_install_files() {
# remove_application_files() (they exist for both curl and repo installs).
# Remove activation script in ~/.local/bin
- safe_remove "$CURL_BIN_DIR/activate-vocalinux.sh" "activation script in ~/.local/bin"
+ safe_remove "$CURL_BIN_DIR/activate-voculinux.sh" "activation script in ~/.local/bin"
}
# Function to remove application files
remove_application_files() {
# Only the copy inside a source checkout. A relative path would delete
- # whatever activate-vocalinux.sh happens to sit in $PWD.
+ # whatever activate-voculinux.sh happens to sit in $PWD.
if [[ -n "$SOURCE_CHECKOUT" ]]; then
- safe_remove "$SOURCE_CHECKOUT/activate-vocalinux.sh" "local activation script"
+ safe_remove "$SOURCE_CHECKOUT/activate-voculinux.sh" "local activation script"
fi
# Remove launcher wrappers in ~/.local/bin created by install.sh. These are
# regular files in a repo/dev install and may be symlinks in a curl install;
# safe_remove handles both (and dangling symlinks).
- safe_remove "$CURL_BIN_DIR/vocalinux" "vocalinux launcher script"
- safe_remove "$CURL_BIN_DIR/vocalinux-gui" "vocalinux-gui launcher script"
+ safe_remove "$CURL_BIN_DIR/voculinux" "voculinux launcher script"
+ safe_remove "$CURL_BIN_DIR/voculinux-gui" "voculinux-gui launcher script"
# Remove desktop entry
- safe_remove "$DESKTOP_DIR/vocalinux.desktop" "desktop entry"
+ safe_remove "$DESKTOP_DIR/voculinux.desktop" "desktop entry"
- safe_remove "$AUTOSTART_DIR/vocalinux.desktop" "autostart desktop entry"
+ safe_remove "$AUTOSTART_DIR/voculinux.desktop" "autostart desktop entry"
# Remove icons
print_info "Removing application icons..."
local ICONS=(
- "vocalinux.svg"
- "vocalinux-microphone.svg"
- "vocalinux-microphone-off.svg"
- "vocalinux-microphone-process.svg"
+ "voculinux.svg"
+ "voculinux-microphone.svg"
+ "voculinux-microphone-off.svg"
+ "voculinux-microphone-process.svg"
)
for icon in "${ICONS[@]}"; do
@@ -428,7 +428,7 @@ remove_config_and_data() {
safe_remove "$IBUS_DATA_DIR" "IBus runtime data directory"
}
-# Clean build artifacts inside a Vocalinux source checkout.
+# Clean build artifacts inside a Voculinux source checkout.
# $1 must be an absolute directory. A relative path would follow the caller's
# working directory ($HOME, when the website command runs this script from
# /tmp). -xdev stays on one filesystem. -prune removes a directory without
@@ -453,7 +453,7 @@ cleanup_build_artifacts() {
safe_remove "$root/build" "build directory"
safe_remove "$root/dist" "distribution directory"
- # vocalinux metadata lives in src/ (setuptools src layout) and sometimes as
+ # voculinux metadata lives in src/ (setuptools src layout) and sometimes as
# *.egg-info at the checkout root. Do not search the whole tree: .venv is
# a separate dev environment and its egg-info has to stay.
find "$root/src" -xdev -name "*.egg-info" -type d -prune -exec rm -rf {} + \
@@ -482,7 +482,7 @@ cleanup_build_artifacts() {
print_warning "Failed to remove some temporary files."
}
- safe_remove "$root/vocalinux-run.py" "wrapper script"
+ safe_remove "$root/voculinux-run.py" "wrapper script"
}
# Function to verify uninstallation
@@ -509,7 +509,7 @@ verify_uninstallation() {
fi
# Check if launcher wrappers (files or symlinks) still exist
- for launcher in vocalinux vocalinux-gui; do
+ for launcher in voculinux voculinux-gui; do
if [ -e "$CURL_BIN_DIR/$launcher" ] || [ -L "$CURL_BIN_DIR/$launcher" ]; then
print_warning "Launcher script still exists: $CURL_BIN_DIR/$launcher"
((ISSUES++))
@@ -517,19 +517,19 @@ verify_uninstallation() {
done
# Check if desktop entry still exists
- if [ -f "$DESKTOP_DIR/vocalinux.desktop" ]; then
- print_warning "Desktop entry still exists: $DESKTOP_DIR/vocalinux.desktop"
+ if [ -f "$DESKTOP_DIR/voculinux.desktop" ]; then
+ print_warning "Desktop entry still exists: $DESKTOP_DIR/voculinux.desktop"
((ISSUES++))
fi
- if [ -f "$AUTOSTART_DIR/vocalinux.desktop" ]; then
- print_warning "Autostart desktop entry still exists: $AUTOSTART_DIR/vocalinux.desktop"
+ if [ -f "$AUTOSTART_DIR/voculinux.desktop" ]; then
+ print_warning "Autostart desktop entry still exists: $AUTOSTART_DIR/voculinux.desktop"
((ISSUES++))
fi
# Check if any icons still exist
local ICON_COUNT=0
- for icon in vocalinux.svg vocalinux-microphone.svg vocalinux-microphone-off.svg vocalinux-microphone-process.svg; do
+ for icon in voculinux.svg voculinux-microphone.svg voculinux-microphone-off.svg voculinux-microphone-process.svg; do
if [ -f "$ICON_DIR/$icon" ]; then
((ICON_COUNT++))
fi
@@ -598,13 +598,13 @@ print_uninstallation_summary() {
fi
}
-# Kill any running Vocalinux processes first
-kill_vocalinux_processes
+# Kill any running Voculinux processes first
+kill_voculinux_processes
# Perform uninstallation steps
remove_virtual_environment
# Clean the checkout before remove_curl_install_files. A script that lives in
-# ~/.local/share/vocalinux-install is both the checkout and the curl clone, and
+# ~/.local/share/voculinux-install is both the checkout and the curl clone, and
# that step deletes the directory.
if [[ -n "$SOURCE_CHECKOUT" ]]; then
cleanup_build_artifacts "$SOURCE_CHECKOUT"
diff --git a/uv.lock b/uv.lock
index b08ca91..199f238 100644
--- a/uv.lock
+++ b/uv.lock
@@ -3281,7 +3281,7 @@ wheels = [
]
[[package]]
-name = "vocalinux"
+name = "voculinux"
source = { editable = "." }
dependencies = [
{ name = "evdev", marker = "sys_platform == 'linux'" },
diff --git a/vocalinux.desktop b/voculinux.desktop
similarity index 87%
rename from vocalinux.desktop
rename to voculinux.desktop
index 2fddf9b..42be6a5 100644
--- a/vocalinux.desktop
+++ b/voculinux.desktop
@@ -1,11 +1,11 @@
[Desktop Entry]
Version=1.0
Type=Application
-Name=Vocalinux
+Name=Voculinux
Comment=Seamless voice dictation system for Linux
GenericName=Voice Typing
-Exec=vocalinux
-Icon=vocalinux
+Exec=voculinux
+Icon=voculinux
Terminal=false
Categories=Utility;Accessibility;AudioVideo;
Keywords=voice;typing;dictation;speech;recognition;transcription;accessibility;
diff --git a/web/package.json b/web/package.json
index dd90673..a28a6c1 100644
--- a/web/package.json
+++ b/web/package.json
@@ -1,5 +1,5 @@
{
- "name": "vocalinux-website",
+ "name": "voculinux-website",
"version": "0.18.5",
"private": true,
"type": "module",
@@ -20,7 +20,7 @@
"test:all": "npm run test && npm run test:types",
"test:viewport": "node scripts/viewport-qa.mjs http://127.0.0.1:3456",
"render:social": "node scripts/render-social-assets.mjs",
- "deploy": "next build && touch out/.nojekyll && echo 'vocalinux.com' > out/CNAME"
+ "deploy": "next build && touch out/.nojekyll && echo 'voculinux.com' > out/CNAME"
},
"dependencies": {
"@types/node": "^20.14.10",
diff --git a/web/src/app/page.tsx b/web/src/app/page.tsx
index 376f492..a935bd5 100644
--- a/web/src/app/page.tsx
+++ b/web/src/app/page.tsx
@@ -27,8 +27,8 @@ const homeJsonLd = [
{
"@context": "https://schema.org",
"@type": "SoftwareApplication",
- "@id": "https://vocalinux.com/#softwareapplication",
- name: "Vocalinux",
+ "@id": "https://voculinux.com/#softwareapplication",
+ name: "Voculinux",
applicationCategory: "UtilitiesApplication",
operatingSystem: "Linux",
isAccessibleForFree: true,
@@ -46,9 +46,9 @@ const homeJsonLd = [
name: "Jatin K Malik",
url: "https://github.com/jatinkrmalik",
},
- url: "https://vocalinux.com/",
+ url: "https://voculinux.com/",
downloadUrl: GITHUB_REPO_URL,
- screenshot: "https://vocalinux.com/og-image.png",
+ screenshot: "https://voculinux.com/og-image.png",
featureList: [
"Local speech recognition with whisper.cpp, Faster Whisper, Whisper, VOSK, and Parakeet",
"Remote API speech recognition for compatible self-hosted transcription servers",
@@ -85,7 +85,7 @@ const homeJsonLd = [
mainEntity: [
{
"@type": "Question",
- name: "Does Vocalinux work offline?",
+ name: "Does Voculinux work offline?",
acceptedAnswer: {
"@type": "Answer",
text: "Local engines process speech on your Linux machine. Remote API is optional and only talks to servers you configure.",
@@ -93,10 +93,10 @@ const homeJsonLd = [
},
{
"@type": "Question",
- name: "Does Vocalinux collect usage telemetry?",
+ name: "Does Voculinux collect usage telemetry?",
acceptedAnswer: {
"@type": "Answer",
- text: "No. The installed app does not send usage telemetry, analytics events, or background usage pings. Even the project maintainer cannot see how many people install or actively use Vocalinux.",
+ text: "No. The installed app does not send usage telemetry, analytics events, or background usage pings. Even the project maintainer cannot see how many people install or actively use Voculinux.",
},
},
{
@@ -104,7 +104,7 @@ const homeJsonLd = [
name: "Which Linux distributions are supported?",
acceptedAnswer: {
"@type": "Answer",
- text: "Vocalinux supports Ubuntu, Fedora, Debian, Arch, Linux Mint, Pop!_OS, and other modern Linux distributions across X11 and Wayland.",
+ text: "Voculinux supports Ubuntu, Fedora, Debian, Arch, Linux Mint, Pop!_OS, and other modern Linux distributions across X11 and Wayland.",
},
},
{
@@ -120,12 +120,12 @@ const homeJsonLd = [
name: "What happens when I close my laptop lid?",
acceptedAnswer: {
"@type": "Answer",
- text: "Vocalinux v0.10.1+ automatically recovers speech recognition and keyboard shortcuts after system suspend/resume. No manual restart needed.",
+ text: "Voculinux v0.10.1+ automatically recovers speech recognition and keyboard shortcuts after system suspend/resume. No manual restart needed.",
},
},
{
"@type": "Question",
- name: "Does Vocalinux preserve my keyboard layout?",
+ name: "Does Voculinux preserve my keyboard layout?",
acceptedAnswer: {
"@type": "Answer",
text: "Yes. v0.10.1+ preserves your XKB keyboard layout when activating IBus, so you won't unexpectedly switch to US layout mid-dictation.",
@@ -136,27 +136,27 @@ const homeJsonLd = [
{
"@context": "https://schema.org",
"@type": "HowTo",
- name: "Install Vocalinux on Linux",
+ name: "Install Voculinux on Linux",
description: "Install offline voice dictation on Linux in a few minutes.",
totalTime: "PT10M",
step: [
{
"@type": "HowToStep",
name: "Run the install command",
- text: "Copy the install command from vocalinux.com and run it in terminal.",
- url: "https://vocalinux.com/#install",
+ text: "Copy the install command from voculinux.com and run it in terminal.",
+ url: "https://voculinux.com/#install",
},
{
"@type": "HowToStep",
name: "Complete the guided setup",
text: "Pick your speech engine and model size in the interactive installer.",
- url: "https://vocalinux.com/#install",
+ url: "https://voculinux.com/#install",
},
{
"@type": "HowToStep",
name: "Start dictating",
- text: "Launch vocalinux and hold Right Alt (Option) to begin dictation, or choose toggle mode in Settings.",
- url: "https://vocalinux.com/#install",
+ text: "Launch voculinux and hold Right Alt (Option) to begin dictation, or choose toggle mode in Settings.",
+ url: "https://voculinux.com/#install",
},
],
},
@@ -291,7 +291,7 @@ export default function HomePage() {
@@ -599,7 +599,7 @@ export default function HomePage() {
- Vocalinux does not need a Voca cloud to transcribe. The important
+ Voculinux does not need a Voca cloud to transcribe. The important
boundary is the engine you selected.