87509bcf99
TASKS.md is now the index (status table, open items, research pointer). 33 files: 32 task files + 1 research facts file. The full take-saga narrative and all design decisions are preserved verbatim; the catalog makes the queue readable without opening every task body. Schema and AGENTS.md updated to reflect the new layout.
47 lines
3.3 KiB
Markdown
47 lines
3.3 KiB
Markdown
# TASK 11 — Post-pause polish batch: the creator's 8 review issues (2026-08-15, shipped)
|
|
|
|
> Catalog: [`TASKS.md`](../TASKS.md) — status and requirements live here.
|
|
|
|
|
|
**Status: ✅ SHIPPED 2026-08-15 — 197 tests passing, 0 warnings (ONE integration test:
|
|
`AudioPipelineTests.Mix_HonorsProviderGains_AndGameMute_KillsTheLoopback`).**
|
|
|
|
The creator reviewed the TASK 8 build and filed 8 issues. All fixed in one branch on `main`:
|
|
|
|
1. ✅ **Desktop/game audio volume slider had no effect** (headset OR stream) — the `AudioMixer`'s
|
|
`micGain`/`loopbackGain` seams defaulted to unity because the VM never passed them; the sliders
|
|
were decorative. Fixed: new `AudioGainProvider` (`Services/Audio/`) hands `MicMuted`/`MicVolume`/
|
|
`GameMuted`/`GameAudioVolume` to the mixer at construction, read live each mix tick.
|
|
2. ✅ **Desktop/game mute button had no effect** — same root cause; `GameMuted` now zeroes the
|
|
loopback on the stream. Locally, `MusicPlayer.LocalGain` (new) is scaled by the game bar on every
|
|
volume/mute change + on TRAX load, so the creator **hears** the control work on the music (the
|
|
track rides the loopback channel, so it ducks locally exactly as it does on stream).
|
|
3. ✅ **TRAX played once then stopped** — `MusicPlayer.OnPlaybackStopped` only looped when
|
|
`Position >= Length`, unreliable for `MediaFoundationReader`; now any clean stop
|
|
(`e.Exception == null`) rewinds + replays; only errors/explicit stops surface via `PlaybackEnded`.
|
|
4. ✅ **TRAX/MIC buttons swapped** — TRAX no longer sits between MIC and the (mic-specific) meter;
|
|
the footer's mic cluster is MIC + meter + mute + volume.
|
|
5. ✅ **Mic source persists across restarts** — `LayoutStore` gained a `Settings` key/value table
|
|
(`SaveMicSourceName`/`LoadMicSourceName`); the VM saves on pick and restores before the mixer's
|
|
first `Start`, so a restart reconnects the same already-vetted device (green dot) or reports it
|
|
missing (yellow) instead of falling back to the default endpoint.
|
|
6. ✅ **TRAX moved into the game audio bar** — left of the "Desktop Audio" label in the preview
|
|
overlay (the creator's follow-up pick), no longer in the footer; its tooltip teaches the clicks
|
|
("left-click pauses/plays, right-click chooses a track").
|
|
7. ✅ **Backdrop's icons shifted right** — the trash button's `Collapsed` released its column; a new
|
|
`HiddenBoolToVisibilityConverter` keeps the slot reserved (`Hidden`), so edit/eye stay in their
|
|
fixed columns for every source row.
|
|
8. ✅ **No separation between scenes and sources** — a 1px hairline with top/bottom padding now sits
|
|
between the two listboxes in the left panel.
|
|
|
|
### Design decisions
|
|
|
|
1. **The gain seams are the one source of truth** — `AudioGainProvider` is a thin seam (four Funcs)
|
|
so the mixer contract and the mute⇔zero-volume rule are testable without constructing the VM.
|
|
2. **Stream-honest AND locally audible** — the game bar's controls now do two things: scale the
|
|
loopback on the stream and scale the music in the headphones. Native game audio is untouched
|
|
(system output, OBS-style non-monitored); an OBS-style monitor loop is out of scope.
|
|
3. **Persist the DisplayName, not the device ID** — the FriendlyName match was already the mic's
|
|
identity end-to-end; `Settings` just makes it survive restarts.
|
|
|