mirror of
https://github.com/ankitects/anki.git
synced 2025-09-19 06:22:22 -04:00
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
1 changed files with 4 additions and 18 deletions
|
@ -129,7 +129,6 @@ class AVPlayer:
|
||||||
def _stop_if_playing(self) -> None:
|
def _stop_if_playing(self) -> None:
|
||||||
if self.current_player:
|
if self.current_player:
|
||||||
self.current_player.stop()
|
self.current_player.stop()
|
||||||
self.current_player = None
|
|
||||||
|
|
||||||
def _pop_next(self) -> Optional[AVTag]:
|
def _pop_next(self) -> Optional[AVTag]:
|
||||||
if not self._enqueued:
|
if not self._enqueued:
|
||||||
|
@ -235,17 +234,15 @@ class SimpleProcessPlayer(Player): # pylint: disable=abstract-method
|
||||||
self._lock = threading.Lock()
|
self._lock = threading.Lock()
|
||||||
|
|
||||||
def play(self, tag: AVTag, on_done: OnDoneCallback) -> None:
|
def play(self, tag: AVTag, on_done: OnDoneCallback) -> None:
|
||||||
|
self._terminate_flag = False
|
||||||
self._taskman.run_in_background(
|
self._taskman.run_in_background(
|
||||||
lambda: self._play(tag), lambda res: self._on_done(res, on_done)
|
lambda: self._play(tag), lambda res: self._on_done(res, on_done)
|
||||||
)
|
)
|
||||||
|
|
||||||
def stop(self) -> None:
|
def stop(self) -> None:
|
||||||
self._terminate_flag = True
|
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:
|
def _play(self, tag: AVTag) -> None:
|
||||||
assert isinstance(tag, SoundOrVideoTag)
|
assert isinstance(tag, SoundOrVideoTag)
|
||||||
self._process = subprocess.Popen(
|
self._process = subprocess.Popen(
|
||||||
|
@ -264,19 +261,11 @@ class SimpleProcessPlayer(Player): # pylint: disable=abstract-method
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
with self._lock:
|
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?
|
# should we abort playing?
|
||||||
if self._terminate_flag:
|
if self._terminate_flag:
|
||||||
self._process.terminate()
|
self._process.terminate()
|
||||||
self._process = None
|
self._process = None
|
||||||
self._terminate_flag = False
|
return
|
||||||
raise PlayerInterrupted()
|
|
||||||
|
|
||||||
# wait for completion
|
# wait for completion
|
||||||
try:
|
try:
|
||||||
|
@ -284,17 +273,14 @@ class SimpleProcessPlayer(Player): # pylint: disable=abstract-method
|
||||||
if self._process.returncode != 0:
|
if self._process.returncode != 0:
|
||||||
print(f"player got return code: {self._process.returncode}")
|
print(f"player got return code: {self._process.returncode}")
|
||||||
self._process = None
|
self._process = None
|
||||||
self._terminate_flag = False
|
|
||||||
return
|
return
|
||||||
except subprocess.TimeoutExpired:
|
except subprocess.TimeoutExpired:
|
||||||
|
# process still running, repeat loop
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _on_done(self, ret: Future, cb: OnDoneCallback) -> None:
|
def _on_done(self, ret: Future, cb: OnDoneCallback) -> None:
|
||||||
try:
|
try:
|
||||||
ret.result()
|
ret.result()
|
||||||
except PlayerInterrupted:
|
|
||||||
# don't fire done callback when interrupted
|
|
||||||
return
|
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
showWarning(
|
showWarning(
|
||||||
_(
|
_(
|
||||||
|
|
Loading…
Reference in a new issue