docs: rewrite HANDOFF for session end; import the TASK 21 picker spec from the old handoff into TASKS.md

The picker-slice deliverables + loop-provider rule lived only in HANDOFF (rewrite-every-
session = lose-it). Moved into TASK 21 where it's durable; HANDOFF rewritten: locked
decisions 1-9, queue order, landmines (incl. the 2 unpushed docs commits), no-suggestions
note carried.
This commit is contained in:
2026-09-01 19:04:21 -07:00
parent e1d8b10388
commit 711ba54af7
2 changed files with 83 additions and 93 deletions
+27
View File
@@ -1082,6 +1082,33 @@ The tasks below are ordered by dependency and risk. Each task builds on the prev
- **This pairs with TRAX** — TRAX is background music, media source is background video. Together they make non-Live scenes (Starting/BRB/Ending) feel polished.
- **Not a full NLE** — no trimming, no multi-track, no effects. Just "play this video in the scene."
### UI picker slice — spec (imported from HANDOFF 2026-09-01 so it can't be lost by a rewrite)
Nothing `AcquireAsync`s a media path yet, so **no frames flow in a running app** — decoder, manager,
pacing, and loop mechanism are shipped and unit-tested, but a media Source has no way to start a
session. Deliverables, in order:
1. **File picker + add/remove commands** (mirror `MainViewModel.Trax.cs:68` `OpenFileDialog` usage).
A "Media" source action opens an `OpenFileDialog` filtered to video (mp4/mov/avi); on OK set
`Source.MediaPath`, add to scene, and **`AcquireAsync(MediaPath)`**; on remove
**`ReleaseAsync(MediaPath)`** (refcounted — not `ReleaseAllAsync`, unless the path leaves the
layout entirely). On `StagedScene` layout loads/teardown, release every media path no longer
present and acquire new ones so sessions track the live layout.
2. **Wire `Source.MediaIsLooping` → `IMediaFrameSource.Looping`** — needs a manager-level per-**path**
loop provider. Ambiguity to rule + record: sessions are refcounted per `MediaPath` and shared
across scenes, but `MediaIsLooping` is per-`Source`. Chosen rule: the path's session `Looping` =
**any** live reference has it on (shared behaviour). Record it in the slice commit.
3. **Loop toggle + volume slider** in the source context menu / inspector (items 10/11).
4. `MediaVolume`/`MediaPlaybackState` wiring — audio path for media is future work (desktop loopback
already carries it, TRAX-style; `MediaVolume` slider can drive the local file's audio separately
later — out of this slice).
**Design notes to preserve:** `ResolveOutputFrame` reads `_mediaManager.GetLatestFrame(MediaPath)`;
`OnMediaPreviewBitmapChanged` adopts the shared `WriteableBitmap` per path; `MediaFailed` →
`OnMediaFailed` (currently `Debug.WriteLine` — surface in UI via toast, TASK 24 stack). The compositor
scales any frame size — media renders through the generic `frameFor(element)` path, no compositor
change. First GUI smoke test: add a short real mp4 on native Windows, confirm it plays and previews.
---
## TASK 22 — Audio sync offset