Files
LlamaCasty/HANDOFF.md
T
gramps 071ec8be0c TASK 21 slice 1 step 4: wire media into resolver + preview routing
Wire the MediaVideoSourceManager into the live pipeline (new partial
ViewModels/MainViewModel.Media.cs mirrors Webcam/Background partials):
readonly _mediaManager assigned in the core ctor (decode at 1920x1080 master,
dispatcher-coalesced preview), OnMediaPreviewBitmapChanged adopts the shared
bitmap onto every IsMediaSource with a matching MediaPath, a
Source { IsMediaSource, MediaPath } case in ResolveOutputFrame feeds
GetLatestFrame, and the manager is disposed on shutdown.

Source.DisplaySource now routes VideoImageSource for MediaSource (Source.cs),
so media previews/canvas show decoded video.

Compositor needs no change: BlitContent UniformToFill-scales any frame to the
element rect. Decoder/manager/seam derived-work mirrors ScreenCaptureManager
(citation in commit for slice-step-3).

Test (one unit for this change, mirroring the live-capture case):
Source_DisplaySource_IsVideoImageSource_WhenMediaSource. 14/14 media +
DisplaySource tests pass, build 0 warnings. Docs (TASKS/HANDOFF/ai.md) updated.
2026-08-31 19:32:41 -07:00

4.2 KiB

HANDOFF — Session State

Branch / Commit State

main, working through TASK 21 (media source). Local commits ahead of origin/main (not yet pushed — user pushes at agreed checkpoints):

  • a1d9751 — docs: ffmpeg decode-contract verification recipe + WSL CLR boundary
  • 8f49010 — TASK 21 Increment B: FFmpeg rawvideo video decoder -> VideoFrame
  • f89b9f9 — docs: default-device audio assumption (README + startup log)
  • e8ff4df — TASK 22: global audio sync offset (positive delay at the mixer out)

Prior milestones pushed through origin/main: TASK 31 (3bf053a..670fe3a), plus the full refactor series (Commit F 3107f92, Commit G 85893ea).

What's In Flight

TASK 21 (media source) — slice 1 step 3 shipped (the session-manager + interface); next open work is the VM wire-in (slice 1 step 4).

Increment A (the Source model: MediaSourceType, SourceType.MediaSource, MediaPath/MediaIsLooping/MediaVolume/MediaPlaybackState + LayoutStore persistence) and Increment B (the decoder MediaVideoSource) shipped earlier.

This session:

  • Refactored Services/MediaVideoSource.cs onto the new Services/IMediaFrameSource.cs (Key, FrameAvailable, Completed, StartAsync/StopAsync; Start→StartAsync, FrameReady→FrameAvailable) — behavior preserved, MediaVideoSourceTests updated and passing.
  • Added Services/MediaVideoSourceManager.cs — app-wide decode-session ownership refcounted by MediaPath, Func<string, IMediaFrameSource?> factory seam, AcquireAsync/ReleaseAsync/ReleaseAllAsync/GetLatestFrame, frames coalesced onto the UI dispatcher onto one shared WriteableBitmap per file, MediaFailed + PreviewBitmapChanged. Structural mirror of ScreenCaptureManager.
  • Added ytLive.Tests/MediaVideoSourceManagerTests.cs (5 unit + 1 integration: single shared bitmap, coalesce-to-latest). Verified: all 10 media tests pass (5 manager + 3 reader + 1 decoder integration + 1), build 0 warnings.

Slice 1 step 4 (wire-in) shipped: _mediaManager wired in the core ctor (path => new MediaVideoSource(path, 1920, 1080, new FfmpegLocator(), new FfmpegDecodeProcess()), dispatched preview), OnMediaPreviewBitmapChanged sets VideoImageSource on every IsMediaSource with a matching MediaPath, a Source { IsMediaSource, MediaPath } case in ResolveOutputFrame feeds _mediaManager.GetLatestFrame, Source.DisplaySource routes VideoImageSource for MediaSource, and the manager is disposed on shutdown. Lives in the new ViewModels/MainViewModel.Media.cs partial. Verified: 14/14 media + DisplaySource tests pass, build 0 warnings.

Next (slice 1 step 4's remaining open end): no session acquisition yet — nothing AcquireAsyncs a media path, so no frames flow until the UI picker (a later slice) starts a session on add and releases on remove.

Next (slice 2): native-FPS pacing (ffprobe FPS probe + per-frame pacing seam). Slice 3: loop control (restart decode on Completed when MediaIsLooping).

Landmine: a stale testhost can lock ytLive.Tests's ytLive.dll and break dotnet build of the test project — kill it first (cmd.exe /c "taskkill /PID N /F") on MSB3027. Full-suite vstest hangs headless (RealAppHost/WASAPI) — only filtered pure tests run in WSL; user verifies the GUI suites on native Windows PowerShell (which may also hang if WASAPI startup blocks — pre-existing, not this change).

Next

  1. Commit slice 1 step 4 (this unit): resolver/preview wire-in + Source.DisplaySource media branch + tests.
  2. Slice 2: native-FPS pacing (ffprobe FPS probe + per-frame pacing seam).
  3. Slice 3: loop control (restart decode on Completed when MediaIsLooping).
  4. UI picker slice: acquire/release media sessions on add/remove (the remaining slice-1-step-4 open end).
  5. Await user push checkpoint for the pending TASK 22/21 commits.

The directive (2026-08-31, user)

Rewrite the project into functional components to aid AI retrieval — Services/ChatOverlayLayer.cs / SceneGraph.cs style (owner-state extraction), not line-count chasing. Audio assumption is now an explicit contract (README "Audio Assumption"): the app uses system defaults, never fights Windows device locking, and does not debug user audio issues — OS's problem, not ours.