From f64b9e3e2c5270be19d5b7166e587e406f1c0516 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 1 Feb 2023 22:39:53 +0530 Subject: [PATCH] Dont block UI while waiting for speech to start --- src/calibre/gui2/tts/windows.py | 8 +++++++- src/calibre/gui2/viewer/tts.py | 4 +++- src/calibre/utils/windows/winspeech.py | 8 +++----- src/pyj/read_book/read_aloud.pyj | 2 ++ 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/calibre/gui2/tts/windows.py b/src/calibre/gui2/tts/windows.py index c9957e5fcb..2709a9d8e2 100644 --- a/src/calibre/gui2/tts/windows.py +++ b/src/calibre/gui2/tts/windows.py @@ -76,7 +76,13 @@ class Client: self.current_chunk_idx += 1 self.backend.speak(self.current_chunks[self.current_chunk_idx], is_cued=True) elif x.state is MediaState.failed: - raise x.as_exception() + self.clear_chunks() + self.callback_ignoring_errors(Event(EventType.cancel)) + e = x.as_exception() + e.display_to_user = True + raise e + elif x.state is MediaState.opened: + self.callback_ignoring_errors(Event(EventType.begin)) elif isinstance(x, Error): raise x.as_exception(check_for_no_audio_devices=True) else: diff --git a/src/calibre/gui2/viewer/tts.py b/src/calibre/gui2/viewer/tts.py index 3e2f77ddb2..31e7174be8 100644 --- a/src/calibre/gui2/viewer/tts.py +++ b/src/calibre/gui2/viewer/tts.py @@ -57,9 +57,11 @@ class TTS(QObject): def dispatch_on_main_thread(self, func): try: func() - except Exception: + except Exception as e: import traceback traceback.print_exc() + if getattr(e, 'display_to_user', False): + error_dialog(self.parent(), _('Error in speech subsystem'), str(e), det_msg=traceback.format_exc(), show=True) @property def tts_client_class(self): diff --git a/src/calibre/utils/windows/winspeech.py b/src/calibre/utils/windows/winspeech.py index e612bf890f..c7b65c4495 100644 --- a/src/calibre/utils/windows/winspeech.py +++ b/src/calibre/utils/windows/winspeech.py @@ -121,8 +121,8 @@ class Error(NamedTuple): def as_exception(self, msg='', check_for_no_audio_devices=False): if check_for_no_audio_devices and self.hr == 0xc00d36fa: - raise NoAudioDevices() - raise SpeechError(self, msg) + return NoAudioDevices() + return SpeechError(self, msg) class Synthesizing(NamedTuple): @@ -396,9 +396,7 @@ class WinSpeech: st = 'cued' if is_cued else ('ssml' if is_xml else 'text') sz = encode_to_file_object(text, shm) self.current_speak_cmd_id = self.send_command(f'speak {st} shm {sz} {shm.name}') - x = self.wait_for('speech synthesis to start', MediaStateChanged, related_to=self.current_speak_cmd_id, timeout=8) - if x.state is MediaState.failed: - raise x.as_exception() + self.wait_for('speech synthesis to start', Synthesizing, related_to=self.current_speak_cmd_id, timeout=8) return self.current_speak_cmd_id def dispatch_message(self, x): diff --git a/src/pyj/read_book/read_aloud.pyj b/src/pyj/read_book/read_aloud.pyj index 6c5ede5a41..dcfb99ad2a 100644 --- a/src/pyj/read_book/read_aloud.pyj +++ b/src/pyj/read_book/read_aloud.pyj @@ -243,6 +243,8 @@ class ReadAloud: self.play() if data is not None: pass + elif which is 'cancel': + self.state = STOPPED def send_message(self, type, **kw): self.view.iframe_wrapper.send_message('tts', type=type, **kw)