v4.0: full audio-cue system, cause-aware auto-tune, four-tab Preferences, install-side default sounds

Audio cues
- Cues for send/receive on-off, minimise/restore, checkbox tick/untick, and tab switch
- Soft keyboard clicks while typing, with a distinct passkey sound on password fields
- Per-cue "Choose sound" variant picker; "(none)" silences a cue; front-most missing-sound warning
- Send/receive cues take priority over the generic checkbox sound; programmatic ticks stay silent

Preferences
- Redesigned into four tabs (General, Audio cues, Startup behaviour, Update settings)
- Startup behaviour moved in from the Options menu
- NVDA now announces the dialog on open (focus a real named control, not the quiet tab control)

Auto-tune
- Cause-aware: tells device render-callback stalls (more buffer can't fix) apart from genuine
  network/buffer starvation, so it no longer pins latency high on chunky onboard cards
- Lowering the target eases the buffer down (glide) instead of trimming it, so no clicks while tuning

Sounds layout
- Shipped defaults moved out of the per-user folder into an install-side "default sounds" folder,
  so updates can refresh them; user customs are Browse-picked file paths and are left untouched
- Startup migration removes both legacy sound folders; verified from oldest (v1.0-v3.3) and v3.4 layouts

Quiet automated launches
- New --silent launch flag mutes all cue sounds and suppresses the startup dialogs (migration notice,
  update check, Realtek/mic/missing-sound warnings) so test launches never disturb the user
- run-tests / build-release / SelfTest repointed to the new "default sounds" layout

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Ednunp
2026-06-13 11:57:19 +01:00
co-authored by Claude Opus 4.8
parent 0b7ad49021
commit a408d2b56e
61 changed files with 548 additions and 139 deletions
+21 -20
View File
@@ -14,7 +14,7 @@
tag_name on the latest GitHub release; bump it on every public release. The
AssemblyVersion / FileVersion default to this value, and Assembly.GetName().Version
is what the About dialog and the updater both read. -->
<Version>3.9</Version>
<Version>4.0</Version>
</PropertyGroup>
<ItemGroup>
@@ -57,17 +57,18 @@
</ItemGroup>
<ItemGroup>
<!-- All cue sounds live in a sounds\ subfolder under the build/publish output (moved out of the
install-root flat layout 2026-05-28). Every WAV in the source sounds\ folder ships, via a
wildcard, so the numbered cue variants ("connect 1.wav", "connect 2.wav", ...), the
keyboard-click sounds ("key 1.wav".."key 4.wav") and the password "passkey.wav" are all
carried without per-file edits, and adding more sounds later needs no csproj change.
Filenames containing a space are preserved verbatim (via %(Filename)%(Extension)) so the
load-by-filename path in CueSounds / KeyClickService finds them exactly as written. The
EnsureCueSoundsPublished target below is the belt-and-braces that guarantees these reach a
PUBLISH output even when MSBuild's incremental Content-copy marker would skip them. -->
<Content Include="..\..\sounds\*.wav">
<Link>sounds\%(Filename)%(Extension)</Link>
<!-- Shipped DEFAULT cue sounds live in a "default sounds\" subfolder under the build/publish
output (2026-06-13: moved out of the per-user folder, which never overwrote them, so a
changed default sound could never reach an existing user). They are part of the install:
the auto-updater (and a dev republish) always overwrites this folder, so a tweaked default
always lands. The user's OWN custom sounds are NOT here - they're explicit file paths set
via the Preferences Browse picker, which the updater never touches. Every WAV in the source
"default sounds\" folder ships via a wildcard (numbered variants, key clicks, passkey), so
adding sounds later needs no csproj change. Spaces in filenames are preserved verbatim. The
EnsureCueSoundsPublished target below guarantees they reach a PUBLISH output even when
MSBuild's incremental Content-copy marker would skip them. -->
<Content Include="..\..\default sounds\*.wav">
<Link>default sounds\%(Filename)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<!-- User manual. F1 anywhere in the app opens this via the user's default browser
@@ -80,20 +81,20 @@
</Content>
</ItemGroup>
<!-- Guarantee the cue WAVs land in a PUBLISHED build. The sounds\ Content items above use
<!-- Guarantee the cue WAVs land in a PUBLISHED build. The Content items above use
CopyToOutputDirectory=PreserveNewest, but MSBuild's incremental "copy already done" marker
(obj\...\.csproj.CopyComplete) can skip that copy when publishing into a fresh output folder
whose marker is up to date — which silently shipped the v3.9 zip with NO cue sounds at all
(startup sound + connect/disconnect/record/etc.). This explicit post-publish copy is marker-
independent: it always copies every WAV from the source sounds\ folder into the published
sounds\ folder. Build-release.ps1 zips the publish output, so this is what makes the release
reliably contain the sounds. (The self-test "Bundled resources present" step verifies it.) -->
whose marker is up to date — which silently shipped the v3.9 zip with NO cue sounds at all.
This explicit post-publish copy is marker-independent: it always copies every WAV from the
source "default sounds\" folder into the published "default sounds\" folder. Build-release.ps1
zips the publish output, so this is what makes the release reliably contain the sounds. (The
self-test "Bundled resources present" step verifies it.) -->
<Target Name="EnsureCueSoundsPublished" AfterTargets="Publish">
<ItemGroup>
<_CueWavs Include="..\..\sounds\*.wav" />
<_CueWavs Include="..\..\default sounds\*.wav" />
</ItemGroup>
<Copy SourceFiles="@(_CueWavs)"
DestinationFolder="$(PublishDir)sounds"
DestinationFolder="$(PublishDir)default sounds"
SkipUnchangedFiles="false" />
</Target>
</Project>