fix audio getting stuck (1/2)
The problem was caused by stop() doing a spin loop on the main thread waiting for the completion signal. This prevented Qt's run loop from executing, and so the completion signal was never delivered, meaning longer files would time out. Fixed by reworking the code so that stop() does not block at all - instead it just sets the termination flag, and AVPlayer does not unset current_player. Then when the completion callback fires, it can advance to the next file. TTS code still needs updating, and the lock should be safe to remove as the start/stop logic is all on the main thread.
This commit is contained in:
parent
e7452300a2
commit
f30853f5ed
@ -129,7 +129,6 @@ class AVPlayer:
|
||||
def _stop_if_playing(self) -> None:
|
||||
if self.current_player:
|
||||
self.current_player.stop()
|
||||
self.current_player = None
|
||||
|
||||
def _pop_next(self) -> Optional[AVTag]:
|
||||
if not self._enqueued:
|
||||
@ -235,17 +234,15 @@ class SimpleProcessPlayer(Player): # pylint: disable=abstract-method
|
||||
self._lock = threading.Lock()
|
||||
|
||||
def play(self, tag: AVTag, on_done: OnDoneCallback) -> None:
|
||||
self._terminate_flag = False
|
||||
self._taskman.run_in_background(
|
||||
lambda: self._play(tag), lambda res: self._on_done(res, on_done)
|
||||
)
|
||||
|
||||
def stop(self) -> None:
|
||||
self._terminate_flag = True
|
||||
# block until stopped
|
||||
t = time.time()
|
||||
while self._terminate_flag and time.time() - t < 3:
|
||||
time.sleep(0.1)
|
||||
|
||||
# note: mplayer implementation overrides this
|
||||
def _play(self, tag: AVTag) -> None:
|
||||
assert isinstance(tag, SoundOrVideoTag)
|
||||
self._process = subprocess.Popen(
|
||||
@ -264,19 +261,11 @@ class SimpleProcessPlayer(Player): # pylint: disable=abstract-method
|
||||
|
||||
while True:
|
||||
with self._lock:
|
||||
# if .stop() timed out, another thread may run when
|
||||
# there is no process
|
||||
if not self._process:
|
||||
self._process = None
|
||||
self._terminate_flag = False
|
||||
return
|
||||
|
||||
# should we abort playing?
|
||||
if self._terminate_flag:
|
||||
self._process.terminate()
|
||||
self._process = None
|
||||
self._terminate_flag = False
|
||||
raise PlayerInterrupted()
|
||||
return
|
||||
|
||||
# wait for completion
|
||||
try:
|
||||
@ -284,17 +273,14 @@ class SimpleProcessPlayer(Player): # pylint: disable=abstract-method
|
||||
if self._process.returncode != 0:
|
||||
print(f"player got return code: {self._process.returncode}")
|
||||
self._process = None
|
||||
self._terminate_flag = False
|
||||
return
|
||||
except subprocess.TimeoutExpired:
|
||||
# process still running, repeat loop
|
||||
pass
|
||||
|
||||
def _on_done(self, ret: Future, cb: OnDoneCallback) -> None:
|
||||
try:
|
||||
ret.result()
|
||||
except PlayerInterrupted:
|
||||
# don't fire done callback when interrupted
|
||||
return
|
||||
except FileNotFoundError:
|
||||
showWarning(
|
||||
_(
|
||||
|
Loading…
Reference in New Issue
Block a user