VideoPlayer: preserve mute state across lazy mpv creation
The popout's VideoPlayer is constructed with no mpv attached — mpv
gets wired up in _ensure_mpv on the first set_media call. main_window's
_open_fullscreen_preview syncs preview→popout state right after the
popout is constructed, so it writes is_muted *before* mpv exists. The
old setter only forwarded to mpv if mpv was set:
@is_muted.setter
def is_muted(self, val: bool) -> None:
if self._mpv:
self._mpv.mute = val
self._mute_btn.setText("Unmute" if val else "Mute")
For the popout's pre-mpv VideoPlayer this updated the button text but
silently dropped the value. _ensure_mpv then created the mpv instance
later with default mute=False, so the popout always opened unmuted
even when the embedded preview was muted (or when a previous popout
session had muted and then closed).
Fix: introduce a Python-side _pending_mute field that survives the
lazy mpv creation. The setter writes to _pending_mute unconditionally
and forwards to mpv if it exists. The getter returns _mpv.mute when
mpv is set, otherwise _pending_mute. _ensure_mpv replays _pending_mute
into the freshly-created mpv instance after applying the volume from
the slider, mirroring the existing volume-from-slider replay pattern
that already worked because the slider widget exists from construction
and acts as the volume's persistent storage.
Also threaded _pending_mute through _toggle_mute so the click-driven
toggle path stays consistent with the setter path — without it, a
mute toggle inside the popout would update mpv but not _pending_mute,
and the next sync round-trip via the setter would clobber it.
Verified manually:
- popout video, click mute, close popout, reopen on same video →
mute persisted (button shows "Unmute", audio silent)
- toggle to unmute, close, reopen → unmuted persisted
- embedded preview video mute → close popout → state propagates
correctly via _on_fullscreen_closed's reverse sync
This commit is contained in:
parent
44a20ac057
commit
0a6818260e
@ -226,6 +226,14 @@ class VideoPlayer(QWidget):
|
||||
# observer firings so widget-driven re-emissions don't trigger
|
||||
# repeated _fit_to_content calls (which would loop forever).
|
||||
self._last_video_size: tuple[int, int] | None = None
|
||||
# Pending mute state — survives the lazy mpv creation. The popout's
|
||||
# video player is constructed with no mpv attached (mpv is wired
|
||||
# in _ensure_mpv on first set_media), and main_window's open-popout
|
||||
# state sync writes is_muted before mpv exists. Without a Python-
|
||||
# side fallback the value would be lost — the setter would update
|
||||
# button text but the actual mpv instance (created later) would
|
||||
# spawn unmuted by default. _ensure_mpv replays this on creation.
|
||||
self._pending_mute: bool = False
|
||||
|
||||
def _ensure_mpv(self) -> mpvlib.MPV:
|
||||
"""Set up mpv callbacks on first use. MPV instance is pre-created."""
|
||||
@ -234,6 +242,7 @@ class VideoPlayer(QWidget):
|
||||
self._mpv = self._gl_widget._mpv
|
||||
self._mpv['loop-file'] = 'inf' # default to loop mode
|
||||
self._mpv.volume = self._vol_slider.value()
|
||||
self._mpv.mute = self._pending_mute
|
||||
self._mpv.observe_property('duration', self._on_duration_change)
|
||||
self._mpv.observe_property('eof-reached', self._on_eof_reached)
|
||||
self._mpv.observe_property('video-params', self._on_video_params)
|
||||
@ -258,10 +267,11 @@ class VideoPlayer(QWidget):
|
||||
def is_muted(self) -> bool:
|
||||
if self._mpv:
|
||||
return bool(self._mpv.mute)
|
||||
return False
|
||||
return self._pending_mute
|
||||
|
||||
@is_muted.setter
|
||||
def is_muted(self, val: bool) -> None:
|
||||
self._pending_mute = val
|
||||
if self._mpv:
|
||||
self._mpv.mute = val
|
||||
self._mute_btn.setText("Unmute" if val else "Mute")
|
||||
@ -405,6 +415,7 @@ class VideoPlayer(QWidget):
|
||||
def _toggle_mute(self) -> None:
|
||||
if self._mpv:
|
||||
self._mpv.mute = not self._mpv.mute
|
||||
self._pending_mute = bool(self._mpv.mute)
|
||||
self._mute_btn.setText("Unmute" if self._mpv.mute else "Mute")
|
||||
|
||||
# -- mpv callbacks (called from mpv thread) --
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user