Commit Graph
5 Commits
Author SHA1 Message Date
yusufipek e40191e3a7 Give the tray an icon a black bar cannot swallow
A session that names no desktop, which is what i3 and a bare X11 login are,
leaves Qt with hicolor as its only icon theme, and hicolor has none of the four
names the tray asks for. So fromTheme returns nothing and the shapes drawn in
trayicon.py are used, as they are on macOS. They were drawn in black, which
macOS recolours through the mask and X11 does not, and i3's bar is black: the
icon was there all along, painted onto a bar of its own colour. Outside macOS
they are now white over a dark copy of themselves spread a pixel out, which
stands out on a dark bar and stays readable on a light one, and the mask is set
only where something reads it.

The .desktop files had the same hole from the other side. They named
audio-input-microphone, which is in Breeze and in Adwaita but not in hicolor, so
the menu entry and the autostart entry were blank on the same systems. install.sh
now draws the application icon into ~/.local/share/icons/hicolor and both entries
name it; uninstall.sh takes it back. The windows carry it too on X11, where a
window has no .desktop file to be looked up in.

Closes #27
2026-08-16 13:28:57 +03:00
yusufipek 0e767454f3 Let a recording be held while something else happens
A phone call in the middle of a dictation left two choices: send what
was said so far off to be transcribed, or throw it away. Both end the
sentence you were in the middle of. Now the recording can be held: the
microphone stays ours, what was said before the pause stays in the
buffer, and what is said during it is dropped.

The capture program keeps running and keeps handing blocks over, which
are read and thrown away rather than left in the pipe. Stopping it
instead would mean asking the sound server for the device again on the
way back, and that is the one moment another application can take it: a
recording would be lost to the phone call it was paused for.

The clock stops with it. Paused time is time the recording does not
have, so the indicator and the length limit both go by what was
actually captured, and a five minute limit is not spent waiting.

The indicator says so as well, since a pulsing dot, moving bars and a
counting clock otherwise all say the words are still going in: the
ribbon freezes where the pause found it and turns amber behind two
bars. The tray menu holds and resumes it, `dikte pause` does, and so
does a global shortcut, which starts empty because holding a recording
is not something a keyboard has a habit for.

Dictation and a command to the agent both, whichever is recording. A
meeting is left out: it writes to a file as it goes and keeps two
streams aligned itself, and neither of those wants a hole in it.
2026-08-16 13:06:36 +03:00
yusufipek 5547f85848 Keep the wheel off the boxes and a floor under the window
Two things the scrolling tabs brought with them.

A combo box and a spin box read the wheel as a change of value, and Qt
hands them the focus before delivering it. Now that every tab scrolls,
rolling down the API tab with the pointer over the model box picks a
different model on the way past, and Save writes it down. The boxes take
the focus by click or by tab only, and a wheel that arrives at one
without the focus is refused rather than swallowed, so it carries on up
to the scroll area and the page moves instead.

A tab that scrolls also asks for no height of its own, which left
nothing to stop the window being dragged down to a tab bar and half a
button. It has a floor now, and the floor never asks for more room than
the screen was just found to have.
2026-08-16 12:09:21 +03:00
yusufipek 1135362afa Let the test server open its port without asking who 127.0.0.1 is
The stand-in whisper server in the ggml tests is an http.server, and
http.server looks up the reverse name of the address it bound in between
the bind and the listen. On Linux that answers at once. On a Mac nothing
answers and the lookup sits in a resolver timeout for thirty-five
seconds, with the port closed the whole time and _wait_ready watching it.

Seven tests start a server and one of them starts two, so the macOS job
spent 330 of its 334 seconds inside that lookup while the same suite took
fifteen seconds on Linux. Binding through socketserver and naming the
server after the address it already has skips the question.
2026-08-16 11:57:55 +03:00
yusufipekandbenfirad 322e06dd7a Keep the meeting a quiet microphone gave us, and read both captures at once
A recording is never deleted for being disappointing. A microphone that
handed over nothing still leaves the right channel, which is everyone
else, and an hour of them is worth more than the empty channel costs; the
one thing the user cannot get back is the half that was there. So the
exact-zero check stays and stops throwing the file away: it says what the
microphone did, in a tray warning next to the recording being written up,
and the minutes are produced from what there is.

Reading the two capture pipes in turn from one thread put the failure it
was meant to fix back in a worse place. A microphone that stops delivering
leaves that read waiting forever, and the far side is not read either
until its pipe fills and its ffmpeg stops writing into it: the meeting
freezes, the levels sit still, and nothing is said for as long as nobody
looks. Each stream now has a reader of its own and a queue, so neither can
hold the other up, and a side that has said nothing for STALL_SECONDS ends
the recording the way a dead ffmpeg already did, out loud and keeping what
was captured.

Which system needs how many processes belongs in the table with everything
else that differs, so meeting() returns the list of commands it takes:
one on PulseAudio, one per device on a Mac. meeting_commands() is the
chooser again rather than a function with a Mac inside it, and the empty
entry in COREAUDIO is gone. The two AVFoundation targets are resolved
against a single device listing, which costs one ffmpeg run instead of two
and cannot see the indexes renumber between the microphone and the far
side.

Co-authored-by: benfirad <[email protected]>
2026-08-16 10:20:23 +03:00