Merge pull request #31 from imonlinux/fix_mpv_race_condition

Fix mpv race condition
This commit is contained in:
imonlinux
2025-11-17 15:28:46 -08:00
committed by GitHub
2 changed files with 22 additions and 6 deletions
+10 -2
View File
@@ -213,8 +213,16 @@ async def main() -> None:
break break
assert stop_model is not None assert stop_model is not None
music_player = MpvMediaPlayer(device=args.audio_output_device, initial_volume=preferences.volume_level) music_player = MpvMediaPlayer(
tts_player = MpvMediaPlayer(device=args.audio_output_device, initial_volume=preferences.volume_level) loop=loop, # <-- MODIFIED
device=args.audio_output_device,
initial_volume=preferences.volume_level
)
tts_player = MpvMediaPlayer(
loop=loop, # <-- MODIFIED
device=args.audio_output_device,
initial_volume=preferences.volume_level
)
state = ServerState( state = ServerState(
name=args.name, name=args.name,
+12 -4
View File
@@ -6,6 +6,7 @@ improves readability with docstrings, and standardizes method signatures.
""" """
from __future__ import annotations from __future__ import annotations
import asyncio
import logging import logging
import os import os
from threading import Lock, Timer from threading import Lock, Timer
@@ -71,7 +72,13 @@ def _select_backend(player: MPV, device: Optional[str]) -> None:
class MpvMediaPlayer: class MpvMediaPlayer:
"""A media player class that wraps the python-mpv library.""" """A media player class that wraps the python-mpv library."""
def __init__(self, device: Optional[str] = None, initial_volume: float = 1.0) -> None: def __init__(
self,
loop: asyncio.AbstractEventLoop,
device: Optional[str] = None,
initial_volume: float = 1.0
) -> None:
self.loop = loop # <-- ADDED
self.player = MPV( self.player = MPV(
video=False, video=False,
terminal=False, terminal=False,
@@ -180,15 +187,16 @@ class MpvMediaPlayer:
self._run_done_callback() self._run_done_callback()
def _run_done_callback(self) -> None: def _run_done_callback(self) -> None:
"""Safely runs the done_callback if it exists.""" """Safely runs the done_callback on the main asyncio loop."""
with self._done_callback_lock: with self._done_callback_lock:
cb = self._done_callback cb = self._done_callback
self._done_callback = None self._done_callback = None
if cb: if cb:
try: try:
cb() # Use call_soon_threadsafe to run the callback on the main loop
self.loop.call_soon_threadsafe(cb) # <-- MODIFIED
except Exception: except Exception:
_LOGGER.exception("Error in done_callback") _LOGGER.exception("Error scheduling done_callback")
def _mpv_log(self, level: str, prefix: str, text: str) -> None: def _mpv_log(self, level: str, prefix: str, text: str) -> None:
"""Routes mpv's internal logs to our logger.""" """Routes mpv's internal logs to our logger."""