Commit Graph
7 Commits
Author SHA1 Message Date
nomoreshow e0eae4d8fe Ship a managed Vulkan whisper-server for Linux x64 2026-09-04 00:34:55 +03:00
yusufipek c503d12e62 Leave both halves of libxkbcommon to the system
Qt's xcb plugin links libxkbcommon and libxkbcommon-x11, and the x11 half
hands keymap objects to the core half to free, so the pair must come from
one build. The build machine has only the core half installed, so
PyInstaller bundled that one alone and the other kept loading from the
user's system; an Ubuntu 22.04 core freeing what a current x11 half
allocated is the segfault of issue #57, which a Turkish layout happened
to move to startup. Every desktop that can show a window carries both
libraries from one build, so the bundle now carries neither.

Fixes #57
2026-08-27 16:25:59 +03:00
huseyin-emre-tigciandClaude Fable 5 6f601ab969 Let a second copy yield to the instance already running
listen() was the whole of the single-instance check and it cannot be one:
a Windows named pipe takes a second server on the same name rather than
refusing it, and everywhere else removeServer() first takes the live socket
away from the instance holding it. Starting Dikte over a running Dikte then
left two whole copies up, two tray icons and all, and the newer one's
sweep() killed the whisper the older one was answering dictations with. On
a machine that sleeps instead of logging out, that is one Start Menu click
away, and it cost a real dictation before it was understood.

A QLockFile in the data directory closes the race on all three systems,
taken before the QApplication is even built, and behind it the probe is the
side-effect-free status verb: the Settings window opens as the sign of life
only when a bare second start deliberately asks for it, not as a byproduct
of a probe racing a forwarded toggle. The two Windows relaunch dances
collapse into one ipc.respawn.

The checkout installer and the packaged setup each kept an autostart the
other could not see, so a machine that tried both started two copies at
every sign-in: each autostart now removes the other's entry, the silent
every-start repair backs off from a Run value whose target still exists,
and each uninstaller deletes the shared dikte.cmd only when the shim
names its own install.

Co-Authored-By: Claude Fable 5 <[email protected]>
2026-08-22 23:09:05 +03:00
yusufipek 29643f26b3 Keep the two Windows executables from being one file
Windows matches a filename without regard to its case, so Dikte.exe and
dikte.exe were one file in the installation directory: PyInstaller wrote
the console build second and that is the only one that landed. Every
launcher then opened a console window behind the tray, and closing it
killed the application.

The console one is dikte-cli.exe now, which the setup's shim names. The
build reads the PE subsystem of both afterwards, since a filesystem that
keeps the two names apart is exactly what the check would run on
otherwise.
2026-08-19 11:11:30 +03:00
yusufipek 23d56acfb5 Publish a Windows setup beside the AppImage and the disk image
The releases page had nothing for Windows, so the only way in was a
checkout, a Python and a pip install. What goes out now is one setup
program per release: PyInstaller's directory, the pinned ffmpeg the
disk image already uses, and Inno Setup around both. It installs for
the account alone, so no administrator is asked for.

Two executables over the one program there, because a windowed one on
Windows has no standard output at all: Dikte.exe for the Start Menu and
dikte.exe for the terminal, sharing everything they carry. The icon is
drawn by Dikte itself into an .ico, the way the Mac's .icns and Linux's
PNGs already are, so there is still no image file in the repository.

Starting at sign-in is a registry value rather than a Startup shortcut,
which is what lets the setup program, the uninstaller and
`dikte integrate` all mean the same thing: the wizard asks once, and
typing the command changes the answer later.

The three builds move into build.yml, which release.yml now calls
instead of holding its own copy, and which a pull request touching the
packaging runs on its own. A broken build is then a red pull request
rather than a failed release.
2026-08-18 16:08:47 +03:00
yusufipek 4cec05fa49 Look up the machine's certificates rather than the build machine's
A build carries the OpenSSL of the machine it was built on, and that
OpenSSL has one directory compiled into it as the only place it looks for
certificates. For an AppImage built on Ubuntu that is /usr/lib/ssl, which
Arch, Fedora and openSUSE do not have, so on any of them every HTTPS
request fails with CERTIFICATE_VERIFY_FAILED: transcription and cleanup
report it as a rejected key, and the model downloads fail too.

Ask the machine instead, from the list curl and Go use, and only when the
build's own answer turns out not to exist. The store on the machine
rather than a copy carried along, because a copy goes stale as roots are
rotated and would ignore a certificate somebody added themselves. Anybody
who has already set SSL_CERT_FILE is left alone.
2026-08-16 15:24:33 +03:00
yusufipek 7e510f8b35 Build an AppImage and a disk image, and publish them
Installing meant cloning the repository and running a shell script, which
is a fair ask of somebody who already has a terminal open and no ask at
all of anybody else. The releases page now carries an AppImage and a disk
image per Mac architecture: a push to master rebuilds a rolling "latest",
a v* tag publishes a version and leaves it there, and the Run button in
the Actions tab raises the number by running scripts/release.sh, which is
the same script and not a second copy of what it does.

Two things in the application had to give for that. A build has no
__main__.py on disk, and an AppImage is mounted somewhere new every run,
so the command a shortcut is registered with cannot go on being this
interpreter and this file; ipc.launcher() answers with the AppImage or
the bundle instead. And a build carries its own libstdc++, which every
process it starts inherits through LD_LIBRARY_PATH and none of them can
live with: ffmpeg, ydotool and wl-copy are the distribution's binaries
built against the distribution's libraries, and AppImageLauncher, which
is what starting the AppImage again goes through, refuses outright.
integrate.py puts that variable back before anything else runs.

Nothing installs itself over an installation that is already there.
install.sh's menu entry, install-mac.sh's login item and the desktop file
AppImageLauncher writes are each recognised and left alone, so trying a
download once does not quietly move the machine onto it. `dikte
integrate` is how you ask for it outright, and --remove takes it back.

The disk image carries an ffmpeg, pinned and checksummed, because macOS
records through one and ships nothing like it. It is signed ad-hoc and
not with an Apple certificate, so a first launch is refused until Open
Anyway and the permissions are asked for again after each update; both
READMEs and the release notes say so.
2026-08-16 15:03:44 +03:00