mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
macOS: Workaround for Apple being unable to resume speech after changing the voice
This commit is contained in:
parent
c8306289f9
commit
ed4a397de1
@ -166,6 +166,7 @@ class Client:
|
|||||||
text = self.current_marked_text[idx:]
|
text = self.current_marked_text[idx:]
|
||||||
self.ensure_state(use_ssml=True)
|
self.ensure_state(use_ssml=True)
|
||||||
self.ssip_client.speak(wrap_in_ssml(text), callback=self.current_callback)
|
self.ssip_client.speak(wrap_in_ssml(text), callback=self.current_callback)
|
||||||
|
resume_after_configure = resume
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self.current_callback = self.current_marked_text = self.last_mark = None
|
self.current_callback = self.current_marked_text = self.last_mark = None
|
||||||
|
@ -21,6 +21,7 @@ class Client:
|
|||||||
self.default_system_rate = self.nsss.get_current_rate()
|
self.default_system_rate = self.nsss.get_current_rate()
|
||||||
self.default_system_voice = self.nsss.get_current_voice()
|
self.default_system_voice = self.nsss.get_current_voice()
|
||||||
self.current_callback = None
|
self.current_callback = None
|
||||||
|
self.current_marked_text = self.last_mark = None
|
||||||
self.dispatch_on_main_thread = dispatch_on_main_thread
|
self.dispatch_on_main_thread = dispatch_on_main_thread
|
||||||
self.status = {'synthesizing': False, 'paused': False}
|
self.status = {'synthesizing': False, 'paused': False}
|
||||||
self.apply_settings(settings)
|
self.apply_settings(settings)
|
||||||
@ -38,6 +39,7 @@ class Client:
|
|||||||
from calibre_extensions.cocoa import MARK, END
|
from calibre_extensions.cocoa import MARK, END
|
||||||
event = None
|
event = None
|
||||||
if message_type == MARK:
|
if message_type == MARK:
|
||||||
|
self.last_mark = data
|
||||||
if data == self.END_MARK:
|
if data == self.END_MARK:
|
||||||
event = Event(EventType.end)
|
event = Event(EventType.end)
|
||||||
self.status = {'synthesizing': False, 'paused': False}
|
self.status = {'synthesizing': False, 'paused': False}
|
||||||
@ -56,6 +58,7 @@ class Client:
|
|||||||
|
|
||||||
def speak_simple_text(self, text):
|
def speak_simple_text(self, text):
|
||||||
self.current_callback = None
|
self.current_callback = None
|
||||||
|
self.current_marked_text = self.last_mark = None
|
||||||
self.nsss.speak(self.escape_marked_text(text))
|
self.nsss.speak(self.escape_marked_text(text))
|
||||||
self.status = {'synthesizing': True, 'paused': False}
|
self.status = {'synthesizing': True, 'paused': False}
|
||||||
|
|
||||||
@ -64,6 +67,8 @@ class Client:
|
|||||||
# on macOS didFinishSpeaking is never called for some reason, so work
|
# on macOS didFinishSpeaking is never called for some reason, so work
|
||||||
# around it by adding an extra, special mark at the end
|
# around it by adding an extra, special mark at the end
|
||||||
text += self.mark_template.format(self.END_MARK)
|
text += self.mark_template.format(self.END_MARK)
|
||||||
|
self.current_marked_text = text
|
||||||
|
self.last_mark = None
|
||||||
self.nsss.speak(text)
|
self.nsss.speak(text)
|
||||||
self.status = {'synthesizing': True, 'paused': False}
|
self.status = {'synthesizing': True, 'paused': False}
|
||||||
self.current_callback(Event(EventType.begin))
|
self.current_callback(Event(EventType.begin))
|
||||||
@ -82,6 +87,19 @@ class Client:
|
|||||||
if self.current_callback is not None:
|
if self.current_callback is not None:
|
||||||
self.current_callback(Event(EventType.resume))
|
self.current_callback(Event(EventType.resume))
|
||||||
|
|
||||||
|
def resume_after_configure(self):
|
||||||
|
if self.status['paused'] and self.last_mark is not None and self.current_marked_text:
|
||||||
|
mark = self.mark_template.format(self.last_mark)
|
||||||
|
idx = self.current_marked_text.find(mark)
|
||||||
|
if idx == -1:
|
||||||
|
text = self.current_marked_text
|
||||||
|
else:
|
||||||
|
text = self.current_marked_text[idx:]
|
||||||
|
self.nsss.speak(text)
|
||||||
|
self.status = {'synthesizing': True, 'paused': False}
|
||||||
|
if self.current_callback is not None:
|
||||||
|
self.current_callback(Event(EventType.resume))
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self.nsss.stop()
|
self.nsss.stop()
|
||||||
|
|
||||||
|
@ -100,6 +100,9 @@ class TTS(QObject):
|
|||||||
def resume(self, data):
|
def resume(self, data):
|
||||||
self.tts_client.resume()
|
self.tts_client.resume()
|
||||||
|
|
||||||
|
def resume_after_configure(self, data):
|
||||||
|
self.tts_client.resume_after_configure()
|
||||||
|
|
||||||
def callback(self, event):
|
def callback(self, event):
|
||||||
data = event.data
|
data = event.data
|
||||||
if event.type is event.type.mark:
|
if event.type is event.type.mark:
|
||||||
|
@ -137,7 +137,8 @@ class ReadAloud:
|
|||||||
|
|
||||||
def play(self):
|
def play(self):
|
||||||
if self.state is PAUSED:
|
if self.state is PAUSED:
|
||||||
ui_operations.tts('resume')
|
ui_operations.tts('resume_after_configure' if self.waiting_for_configure else 'resume')
|
||||||
|
self.waiting_for_configure = False
|
||||||
self.state = PLAYING
|
self.state = PLAYING
|
||||||
elif self.state is STOPPED:
|
elif self.state is STOPPED:
|
||||||
self.send_message('play')
|
self.send_message('play')
|
||||||
@ -203,7 +204,6 @@ class ReadAloud:
|
|||||||
self.view.show_next_spine_item()
|
self.view.show_next_spine_item()
|
||||||
elif which is 'configured':
|
elif which is 'configured':
|
||||||
if self.waiting_for_configure:
|
if self.waiting_for_configure:
|
||||||
self.waiting_for_configure = False
|
|
||||||
self.play()
|
self.play()
|
||||||
if data is not None:
|
if data is not None:
|
||||||
pass
|
pass
|
||||||
|
Loading…
x
Reference in New Issue
Block a user