Every URL the player opens is a media-server stream or a local file, so mpv's
bundled ytdl_hook has nothing to resolve. It still ran an on_load hook per
open and, whenever an open failed, spawned yt-dlp with the full stream URL in
its argv — access token included, readable through /proc on Linux. It also
added ~700ms to every failed open and buried the real "[stream] Failed to
open" line under three ytdl_hook errors.
mpv decides whether to load the builtin script inside mpv_initialize, so this
has to be an option set beforehand rather than a property set from Dart.
Verified against mpv 0.41: --ytdl=yes logs "Loading lua script
@ytdl_hook.lua", --ytdl=no never loads it.
Apple is deliberately excluded: the bundled libmpv is built without Lua, so
the option does not exist there and setting it would only print an mpv error
on every player init.
The Linux native reliability job stopped compiling mpv_player.cc: the
node-conversion builder exposed a leaf named `Bool`, and X11's Xlib.h —
reached through epoxy/egl.h -> EGL/eglplatform.h — defines `Bool` as a
macro for `int`, so the declaration was rewritten into nonsense.
Renames that leaf to `Boolean` across the shared walk and all three
builders. The name is the only thing that changes; no conversion
behaviour differs.
Consolidates duplicated logic behind shared implementations — paginated
grid tabs, focus chrome, cached remote stores, sheet selection columns,
the server artifact store and a test fixture layer — and removes code
that had become unreachable. Net reduction of about 5,500 lines with no
behaviour change.
Where a fix had landed separately in code that moved into a shared
helper, the fix was re-applied inside the helper rather than left behind
in the copy that went away.
Create the mpv host window with WS_DISABLED so Windows skips the video subtree
when it picks the window that owns a contact and hands the input to the parent
Flutter view instead. Touch over the video never reached Flutter before: mpv's
inner window owns the contact from its own thread, and neither relay worked
from there - Flutter resolves WM_POINTER with GetPointerInfo, which only
answers for a message the calling thread retrieved, and the system discards a
cross-thread pointer send outright. WS_EX_TRANSPARENT and an HTTRANSPARENT
WM_NCHITTEST reply are both same-thread-only, so disabling the subtree is the
one hit-test opt-out that applies across threads. The mouse relay stays for
input that still reaches mpv's window.
Repair the contract test that covers this. It drove its pointer assertions with
cross-thread sends that Windows drops, so every touch assertion had been dead
since it was added and the suite fails "primary touch must press once" on main.
Relaying those sends through the window's own thread runs all eight tests, and
injected mouse and touch presses over the disabled host now assert delivery to
the parent view; removing WS_DISABLED fails the suite.
close#1556
Introduces shared seams for paginated views, D-pad reorder, media control
routing, async singletons and the device method channel, then points the
open-coded copies at them.
Also removes unused models and duplicated provider/server plumbing, folds
the twice-implemented artifact store in the server, and factors the
repeated Flutter toolchain prologue in CI into a composite action.
Audio-only mpv core on every platform (dedicated
com.plezy/mpv_audio_player channels): parameterized android/windows/
linux mpv plugins and a new apple MpvAudioPlayerCore, all skipping
video/window paths (vid=no, audio-display=no, gapless-audio=weak).
MusicPlaybackService drives an in-memory queue with shuffle/repeat,
file-loaded-event gapless arming (property edges coalesce and the
android bridge drops them), per-track progress reporting, OS media
controls, audio focus, sleep timer, and error auto-skip.
PlaybackCoordinator enforces one live native player: starting video
disposes the audio core first.
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
- 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