Fix Qt TTS backend tracking with non-BMP text

This commit is contained in:
Kovid Goyal 2024-09-01 22:40:11 +05:30
parent 0674374749
commit c347ecd628
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 14 additions and 5 deletions

View File

@ -9,7 +9,7 @@ from calibre.gui2.main_window import MainWindow
from calibre.gui2.tts2.manager import TTSManager
TEXT = '''\
Demonstration of DOCX support in calibre
Demonstration 😹 🐈 of DOCX support in calibre
This document demonstrates the ability of the calibre DOCX Input plugin to convert the various typographic features in a Microsoft Word
(2007 and newer) document. Convert this document to a modern ebook format, such as AZW3 for Kindles or EPUB for other ebook readers,

View File

@ -11,6 +11,8 @@ class QtTTSBackend(TTSBackend):
def __init__(self, engine_name: str = '', parent: QObject|None = None):
super().__init__(parent)
self.speaking_text = ''
self.last_word_offset = 0
self._qt_reload_after_configure(engine_name)
@property
@ -37,6 +39,8 @@ class QtTTSBackend(TTSBackend):
self.tts.stop()
def say(self, text: str) -> None:
self.last_word_offset = 0
self.speaking_text = text
self.tts.say(text)
def error_message(self) -> str:
@ -90,7 +94,12 @@ class QtTTSBackend(TTSBackend):
self._current_settings = settings
def _saying_word(self, word: str, utterance_id: int, start: int, length: int) -> None:
self.saying.emit(start, length)
# Qt's word tracking is broken with non-BMP unicode chars, the
# start and length values are totally wrong, so track manually
idx = self.speaking_text.find(word, self.last_word_offset)
if idx > -1:
self.saying.emit(idx, len(word))
self.last_word_offset = idx + len(word)
def _state_changed(self, state: QTextToSpeech.State) -> None:
self.state_changed.emit(state)

View File

@ -180,9 +180,9 @@ def default_engine_name() -> str:
return 'sapi' if tweaks.get('prefer_winsapi') else 'winrt'
if ismacos:
return 'darwin'
if 'flite' in available_engines():
return 'flite'
return 'speechd'
if 'speechd' in available_engines():
return 'speechd'
return 'flite'
class TTSBackend(QObject):