mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Read Aloud: Fix clicking in text to change what is being read causing tracking of currently read word to fail when using the legacy Windows TTS engine (winsapi)
See #2080705 (Download read aloud api failed)
This commit is contained in:
parent
152af7ae51
commit
c07c662a5a
@ -13,8 +13,9 @@ class QtTTSBackend(TTSBackend):
|
|||||||
super().__init__(parent)
|
super().__init__(parent)
|
||||||
self.speaking_text = ''
|
self.speaking_text = ''
|
||||||
self.last_word_offset = 0
|
self.last_word_offset = 0
|
||||||
self._qt_reload_after_configure(engine_name)
|
|
||||||
self.last_spoken_word = None
|
self.last_spoken_word = None
|
||||||
|
self.ignore_tracking_until_state_changes_to_speaking = False
|
||||||
|
self._qt_reload_after_configure(engine_name)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def available_voices(self) -> dict[str, tuple[Voice, ...]]:
|
def available_voices(self) -> dict[str, tuple[Voice, ...]]:
|
||||||
@ -43,6 +44,8 @@ class QtTTSBackend(TTSBackend):
|
|||||||
self.last_word_offset = 0
|
self.last_word_offset = 0
|
||||||
self.last_spoken_word = None
|
self.last_spoken_word = None
|
||||||
self.speaking_text = text
|
self.speaking_text = text
|
||||||
|
if self.tts.engine() == 'sapi':
|
||||||
|
self.ignore_tracking_until_state_changes_to_speaking = True
|
||||||
self.tts.say(text)
|
self.tts.say(text)
|
||||||
|
|
||||||
def error_message(self) -> str:
|
def error_message(self) -> str:
|
||||||
@ -96,18 +99,23 @@ class QtTTSBackend(TTSBackend):
|
|||||||
self._current_settings = settings
|
self._current_settings = settings
|
||||||
|
|
||||||
def _saying_word(self, word: str, utterance_id: int, start: int, length: int) -> None:
|
def _saying_word(self, word: str, utterance_id: int, start: int, length: int) -> None:
|
||||||
|
# print(f'{repr(word)=} {start=} {length=}, {repr(self.speaking_text[start:start+length])=} {self.ignore_tracking_until_state_changes_to_speaking=}')
|
||||||
|
if self.ignore_tracking_until_state_changes_to_speaking:
|
||||||
|
return
|
||||||
# Qt's word tracking is broken with non-BMP unicode chars, the
|
# Qt's word tracking is broken with non-BMP unicode chars, the
|
||||||
# start and length values are totally wrong, so track manually
|
# start and length values are totally wrong, so track manually
|
||||||
# print(f'{repr(word)=} {idx=} {start=} {length=}, {repr(self.speaking_text[start:start+length])=}')
|
|
||||||
key = word, start, length
|
key = word, start, length
|
||||||
# Qt sometimes repeats words with windows modern engine at least, for a test case see https://bugs.launchpad.net/calibre/+bug/2080708
|
# Qt sometimes repeats words with windows modern engine at least, for a test case see https://bugs.launchpad.net/calibre/+bug/2080708
|
||||||
if self.last_spoken_word == key:
|
if self.last_spoken_word == key:
|
||||||
return
|
return
|
||||||
self.last_spoken_word = key
|
self.last_spoken_word = key
|
||||||
idx = self.speaking_text.find(word, self.last_word_offset)
|
idx = self.speaking_text.find(word, self.last_word_offset)
|
||||||
|
# print(f'{self.last_word_offset=} {idx=}')
|
||||||
if idx > -1:
|
if idx > -1:
|
||||||
self.saying.emit(idx, len(word))
|
self.saying.emit(idx, len(word))
|
||||||
self.last_word_offset = idx + len(word)
|
self.last_word_offset = idx + len(word)
|
||||||
|
|
||||||
def _state_changed(self, state: QTextToSpeech.State) -> None:
|
def _state_changed(self, state: QTextToSpeech.State) -> None:
|
||||||
|
if self.ignore_tracking_until_state_changes_to_speaking and state is QTextToSpeech.State.Speaking:
|
||||||
|
self.ignore_tracking_until_state_changes_to_speaking = False
|
||||||
self.state_changed.emit(state)
|
self.state_changed.emit(state)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user