The service was registered to run from wherever it was installed FROM (Environment
.ProcessPath), so installing from a dev/test folder pinned it there: it locked those
files (blocking every rebuild) and, for a real user installing from the app folder,
would lock the app's own binaries and break the auto-updater. Stopping it also needed
admin, so only the app's UAC-prompting Service menu could do it.
Fixes:
- The service now installs its OWN copy of the program into ProgramData\RemSound\
service\bin and is registered to run from there. Never touches the install/dev
folder again. CopyProgramTo copies the exe + DLLs + runtimes + default sounds but
excludes user-state folders; uninstall removes the bin copy.
- Install grants Authenticated Users start/stop/query on the service (sc sdset, ACE
merged into the existing DACL) so it can be stopped with a plain `sc stop
RemSoundService` or the Service menu -- no admin, no app. Pure SDDL-amend helper is
unit-tested (placement + idempotency).
- The app installer now asks, after install, whether to also install the service
(optional, its own UAC step; declining is fine -- Service menu installs it later).
- deploy-test.ps1: only a copy running FROM the publish folder locks its binaries, so
only that forces a sounds-only deploy. The service (ProgramData) and an installed app
no longer make the script silently skip the binary publish -- the bug that had us
testing stale builds for rounds.
New self-test "Service self-contained install" (runs-from-own-bin, SDDL amend, copy
exclusions). Gate: 40/40.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Local checkpoint - NOT for public release.
- build-release.ps1: abort if RELEASE_NOTES.md is missing or doesn't mention the tag
(it leads with "# RemSound <tag>"), so a stale notes file from the previous release
can't ship with the wrong content via `gh release create --notes-file`.
- deploy-test.ps1: a binary deploy now runs the build-and-test gate (run-tests.ps1)
first and refuses to deploy a build that didn't pass - so a test build Ed picks up
has always passed the suite. Sound-only refreshes skip it (no code change). New
-SkipGate switch overrides when the gate was just run. Verified end-to-end.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Local checkpoint - NOT for public release.
Two gaps found reviewing the publish/release scripts:
- deploy-test.ps1: the binary sync (publish -> D:\Dropbox\remsound) used /E with no /MIR,
so it never DELETES user data - but it could OVERWRITE it if publish\ ever accumulated a
"user settings and logs" folder. Added /XD/'user settings and logs','recordings','logs',
'profiles','config' + /XF 'global config.json','remsound.config.json' so the binary sync
is physically incapable of touching Ed's profiles/logs/config in either direction. Test
deploys keep ALL of his data current, by construction.
- build-release.ps1: never checked the -Tag against the csproj <Version>. A mismatch ships
RemSound-<tag>.zip containing a different version's binary, which the in-app updater (it
downloads by tag name) reads as a perpetual "update available". Now aborts up front if
tag != csproj <Version> - also catches a forgotten version bump.
The intended split was already correct: test deploy keeps everything; build-release
publishes to a fresh folder, strips pdb, and scans staged files AND the zip for any
profiles/logs/config/recordings, aborting if found.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reworks the per-peer shaping tab (held for next release):
* Renamed the tab to "Volume, pan and EQ for peers"; the Preferences toggle now defaults ON.
* Collapsed the two master switches (Enable EQ / Enable pan) into ONE: "Enable volume, pan and
EQ for all peers" (Alt+E). Volume now obeys it too. PeerDspChain.Build takes a single enabled
flag; Profile.EnableAllPeerShaping replaces the two bools (old ones kept for load-migration).
* Peer picker is now a CheckedListBox: ticking a peer shapes them (per-peer bypass via new
PeerShaping.Enabled, default true); the focused row is the one the controls edit. Effective
shaping = master switch AND that peer's tick. Letter-nav suppressed so keys never toggle a tick.
* Three EQ modes, renamed: "3 band simple EQ", "12 band advanced graphic EQ", and the new
"16 band parametric EQ" (PeerEqMode.Parametric16Band).
* Parametric EQ: up to 16 user bands, each a boost/cut across a start->end range (PeerShaping
.ParametricBands; ParametricToPeaking maps range -> peaking centre+Q, shared by DSP and curve).
Add band dialog (spin-or-type, numeric-only, live preview, OK/Escape); Bands list sorted
bass->treble reading "X Hz to Y Hz, plus/minus N dB"; Delete key / Delete button, multi-select.
Set peer EQ to default clears the parametric list too.
* dB now spoken as words ("plus 3 dB" / "minus 6 dB" / "flat") on the graphic sliders and the
parametric list, since NVDA users typically have punctuation off and never hear a "+".
* New unbound machine-wide global shortcut "Toggle volume, pan and EQ for all peers" (not stored
in any profile) via the hotkey controller + settings store.
* Renamed the Inputs/outputs "Set volume for all received audio" to "Master receive volume".
* Added EqCurveControl: a purely-visual EQ response graph (not focusable, invisible to NVDA).
* Full manual sweep (readme.html + regenerated MANUAL.md).
Build clean; --selftest passes. Deployed to both test folders. Held for next release.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>