The two prior attempts at #783 failed for lack of a reliable trigger:
re-setting audio-device to its own value is a no-op, and gating
recovery on audio-device-list changes while current-ao is null never
fires in the real flows (a paused player only discovers the dead
WASAPI session at unpause, when the device list is already stable;
a zombie session that consumes samples silently never goes null).
Replace the single gate with a recovery scheduler on the mpv event
thread, ticked every wait-event timeout:
- WM_POWERBROADCAST resume (both PBT variants, via the plugin's
existing window-proc delegate) requests unconditional ao-reloads at
+1.5s and +6s after wake — the only trigger that reaches zombie
sessions; the second shot covers a first reload landing while the
audio stack is still restoring. The handoff is a single atomic
flag: no mpv calls or timers from the platform thread, so there is
nothing to clean up on dispose.
- current-ao falling to null arms clock-driven retries (budget 5,
x2 backoff capped at 8s); retries must be clock-driven because a
failed ao-reload falls back to null without a property change
event. A device-list change while null refreshes the budget, and
audio-device-list is now observed natively so recovery does not
depend on the Dart side.
Every trigger, attempt, and outcome logs as [mpv:audio-recovery] at
warn level so exported logs from the reporter are actionable if this
still misses. Verified with synthetic PBT_APMRESUMEAUTOMATIC while
playing and while paused: full WASAPI reinit both times, audio
restarts on unpause.
Ref #783
close#1453
Events were delivered to the Flutter event sink directly on the mpv event
thread while method replies were already marshaled; concurrent messenger
use from two threads intermittently crashed guests during the event burst
of an in-place media switch. Also joins the event thread before draining
platform tasks in the plugin destructor (reverse member destruction order
would otherwise let the event thread enqueue into a destroyed queue) and
coalesces the wakeup PostMessage behind a retry-safe flag.
- Default MPV native log level to "warn" instead of "v" (Linux/Windows),
add setLogLevel method channel to raise it when debug logging is enabled
- Coalesce MPV render requests via atomic compare_exchange on needs_redraw_
- Clear redraw flag before render so new redraws queue during current frame