Пример #1
0
class Client:
    def __init__(self):
        from calibre_extensions.cocoa import NSSpeechSynthesizer
        self.nsss = NSSpeechSynthesizer()

    def __del__(self):
        self.nsss = None

    def speak_simple_text(self, text):
        self.nsss.speak(text)
Пример #2
0
 def __init__(self, settings=None, dispatch_on_main_thread=lambda f: f()):
     from calibre_extensions.cocoa import NSSpeechSynthesizer
     self.nsss = NSSpeechSynthesizer(self.handle_message)
     self.default_system_rate = self.nsss.get_current_rate()
     self.default_system_voice = self.nsss.get_current_voice()
     self.current_callback = None
     self.current_marked_text = self.last_mark = None
     self.dispatch_on_main_thread = dispatch_on_main_thread
     self.status = {'synthesizing': False, 'paused': False}
     self.apply_settings(settings)
Пример #3
0
class Client:

    mark_template = '[[sync 0x{:x}]]'

    @classmethod
    def escape_marked_text(cls, text):
        return text.replace('[[', ' [ [ ').replace(']]', ' ] ] ')

    def __init__(self, dispatch_on_main_thread):
        from calibre_extensions.cocoa import NSSpeechSynthesizer
        self.nsss = NSSpeechSynthesizer(self.handle_message)
        self.current_callback = None
        self.dispatch_on_main_thread = dispatch_on_main_thread

    def __del__(self):
        self.nsss = None

    shutdown = __del__

    def handle_message(self, message_type, data):
        from calibre_extensions.cocoa import MARK, END
        if message_type == MARK:
            event = Event(EventType.mark, data)
        elif message_type == END:
            event = Event(EventType.end if data else EventType.cancel)
        else:
            return
        if self.current_callback is not None:
            try:
                self.current_callback(event)
            except Exception:
                import traceback
                traceback.print_exc()

    def speak_simple_text(self, text):
        self.current_callback = None
        self.nsss.speak(self.escape_marked_text(text))

    def speak_marked_text(self, text, callback):
        self.current_callback = callback
        self.nsss.speak(text)

    @property
    def status(self):
        ans = self.nsss.status()
        ans['synthesizing'] = ans.get('synthesizing', False)
        ans['paused'] = ans.get('paused', False)
        return ans
Пример #4
0
class Client:

    mark_template = '[[sync 0x{:x}]]'
    END_MARK = 0xffffffff
    name = 'nsss'
    min_rate = 10
    max_rate = 340
    chunk_size = 0

    @classmethod
    def escape_marked_text(cls, text):
        return text.replace('[[', ' [ [ ').replace(']]', ' ] ] ')

    def __init__(self, settings=None, dispatch_on_main_thread=lambda f: f()):
        from calibre_extensions.cocoa import NSSpeechSynthesizer
        self.nsss = NSSpeechSynthesizer(self.handle_message)
        self.default_system_rate = self.nsss.get_current_rate()
        self.default_system_voice = self.nsss.get_current_voice()
        self.current_callback = None
        self.current_marked_text = self.last_mark = None
        self.dispatch_on_main_thread = dispatch_on_main_thread
        self.status = {'synthesizing': False, 'paused': False}
        self.settings = settings or {}
        self.ignore_next_stop_event = False
        self.apply_settings()

    def apply_settings(self, new_settings=None):
        if self.status['paused']:
            self.nsss.resume()
            self.ignore_next_stop_event = True
            self.status = {'synthesizing': False, 'paused': False}
        if new_settings is not None:
            self.settings = new_settings
        self.nsss.set_current_voice(self.settings.get('voice') or self.default_system_voice)
        rate = self.settings.get('rate', self.default_system_rate)
        self.nsss.set_current_rate(rate)

    def __del__(self):
        self.nsss = None
    shutdown = __del__

    def handle_message(self, message_type, data):
        from calibre_extensions.cocoa import MARK, END
        event = None
        if message_type == MARK:
            self.last_mark = data
            event = Event(EventType.mark, data)
        elif message_type == END:
            if self.ignore_next_stop_event:
                self.ignore_next_stop_event = False
                return
            event = Event(EventType.end if data else EventType.cancel)
            self.status = {'synthesizing': False, 'paused': False}
        if event is not None and self.current_callback is not None:
            try:
                self.current_callback(event)
            except Exception:
                import traceback
                traceback.print_exc()

    def speak_simple_text(self, text):
        self.current_callback = None
        self.current_marked_text = self.last_mark = None
        self.nsss.speak(self.escape_marked_text(text))
        self.status = {'synthesizing': True, 'paused': False}

    def speak_marked_text(self, marked_text, callback):
        text = ''.join(add_markup(marked_text, self.mark_template, self.escape_marked_text, self.chunk_size))
        self.current_callback = callback
        self.current_marked_text = text
        self.last_mark = None
        self.nsss.speak(text)
        self.status = {'synthesizing': True, 'paused': False}
        self.current_callback(Event(EventType.begin))

    def pause(self):
        if self.status['synthesizing']:
            self.nsss.pause()
            self.status = {'synthesizing': True, 'paused': True}
            if self.current_callback is not None:
                self.current_callback(Event(EventType.pause))

    def resume(self):
        if self.status['paused']:
            self.nsss.resume()
            self.status = {'synthesizing': True, 'paused': False}
            if self.current_callback is not None:
                self.current_callback(Event(EventType.resume))

    def resume_after_configure(self):
        if self.status['paused']:
            self.resume()
            return
        if self.last_mark is None:
            idx = -1
        else:
            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):
        self.nsss.stop()

    @property
    def rate(self):
        return self.nss.get_current_rate()

    @rate.setter
    def rate(self, val):
        val = val or self.default_system_rate
        self.nss.set_current_rate(float(val))

    def get_voice_data(self):
        ans = getattr(self, 'voice_data', None)
        if ans is None:
            ans = self.voice_data = self.nsss.get_all_voices()
        return ans

    def config_widget(self, backend_settings, parent):
        from calibre.gui2.tts.macos_config import Widget
        return Widget(self, backend_settings, parent)

    def change_rate(self, steps=1):
        rate = current_rate = self.settings.get('rate', self.default_system_rate)
        step_size = (self.max_rate - self.min_rate) // 10
        rate += steps * step_size
        rate = max(self.min_rate, min(rate, self.max_rate))
        if rate != current_rate:
            self.settings['rate'] = rate
            prev_state = self.status.copy()
            self.pause()
            self.apply_settings()
            if prev_state['synthesizing']:
                self.status = {'synthesizing': True, 'paused': False}
                self.resume_after_configure()
            return self.settings
Пример #5
0
 def __init__(self):
     from calibre_extensions.cocoa import NSSpeechSynthesizer
     self.nsss = NSSpeechSynthesizer()
Пример #6
0
class Client:

    mark_template = '[[sync 0x{:x}]]'
    END_MARK = 0xffffffff
    name = 'nsss'

    @classmethod
    def escape_marked_text(cls, text):
        return text.replace('[[', ' [ [ ').replace(']]', ' ] ] ')

    def __init__(self, settings=None, dispatch_on_main_thread=lambda f: f()):
        from calibre_extensions.cocoa import NSSpeechSynthesizer
        self.nsss = NSSpeechSynthesizer(self.handle_message)
        self.default_system_rate = self.nsss.get_current_rate()
        self.default_system_voice = self.nsss.get_current_voice()
        self.current_callback = None
        self.current_marked_text = self.last_mark = None
        self.dispatch_on_main_thread = dispatch_on_main_thread
        self.status = {'synthesizing': False, 'paused': False}
        self.apply_settings(settings)

    def apply_settings(self, new_settings=None):
        settings = new_settings or {}
        self.nsss.set_current_rate(
            settings.get('rate', self.default_system_rate))
        self.nsss.set_current_voice(
            settings.get('voice') or self.default_system_voice)

    def __del__(self):
        self.nsss = None

    shutdown = __del__

    def handle_message(self, message_type, data):
        from calibre_extensions.cocoa import MARK, END
        event = None
        if message_type == MARK:
            self.last_mark = data
            if data == self.END_MARK:
                event = Event(EventType.end)
                self.status = {'synthesizing': False, 'paused': False}
            else:
                event = Event(EventType.mark, data)
        elif message_type == END:
            if not data:  # normal end event is handled by END_MARK
                event = Event(EventType.cancel)
                self.status = {'synthesizing': False, 'paused': False}
        if event is not None and self.current_callback is not None:
            try:
                self.current_callback(event)
            except Exception:
                import traceback
                traceback.print_exc()

    def speak_simple_text(self, text):
        self.current_callback = None
        self.current_marked_text = self.last_mark = None
        self.nsss.speak(self.escape_marked_text(text))
        self.status = {'synthesizing': True, 'paused': False}

    def speak_marked_text(self, text, callback):
        self.current_callback = callback
        # on macOS didFinishSpeaking is never called for some reason, so work
        # around it by adding an extra, special mark at the end
        text += self.mark_template.format(self.END_MARK)
        self.current_marked_text = text
        self.last_mark = None
        self.nsss.speak(text)
        self.status = {'synthesizing': True, 'paused': False}
        self.current_callback(Event(EventType.begin))

    def pause(self):
        if self.status['synthesizing']:
            self.nsss.pause()
            self.status = {'synthesizing': True, 'paused': True}
            if self.current_callback is not None:
                self.current_callback(Event(EventType.pause))

    def resume(self):
        if self.status['paused']:
            self.nsss.resume()
            self.status = {'synthesizing': True, 'paused': False}
            if self.current_callback is not None:
                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):
        self.nsss.stop()

    @property
    def rate(self):
        return self.nss.get_current_rate()

    @rate.setter
    def rate(self, val):
        val = val or self.default_system_rate
        self.nss.set_current_rate(float(val))

    def get_voice_data(self):
        ans = getattr(self, 'voice_data', None)
        if ans is None:
            ans = self.voice_data = self.nsss.get_all_voices()
        return ans

    def config_widget(self, backend_settings, parent):
        from calibre.gui2.tts.macos_config import Widget
        return Widget(self, backend_settings, parent)
Пример #7
0
 def __init__(self, dispatch_on_main_thread):
     from calibre_extensions.cocoa import NSSpeechSynthesizer
     self.nsss = NSSpeechSynthesizer(self.handle_message)
     self.current_callback = None
     self.dispatch_on_main_thread = dispatch_on_main_thread
Пример #8
0
class Client:

    mark_template = '[[sync 0x{:x}]]'
    name = 'nsss'

    @classmethod
    def escape_marked_text(cls, text):
        return text.replace('[[', ' [ [ ').replace(']]', ' ] ] ')

    def __init__(self, dispatch_on_main_thread):
        from calibre_extensions.cocoa import NSSpeechSynthesizer
        self.nsss = NSSpeechSynthesizer(self.handle_message)
        self.current_callback = None
        self.dispatch_on_main_thread = dispatch_on_main_thread
        self.status = {'synthesizing': False, 'paused': False}

    def __del__(self):
        self.nsss = None

    shutdown = __del__

    def handle_message(self, message_type, data):
        from calibre_extensions.cocoa import MARK, END
        if message_type == MARK:
            event = Event(EventType.mark, data)
        elif message_type == END:
            event = Event(EventType.end if data else EventType.cancel)
            self.status = {'synthesizing': False, 'paused': False}
        else:
            return
        if self.current_callback is not None:
            try:
                self.current_callback(event)
            except Exception:
                import traceback
                traceback.print_exc()

    def speak_simple_text(self, text):
        self.current_callback = None
        self.nsss.speak(self.escape_marked_text(text))
        self.status = {'synthesizing': True, 'paused': False}

    def speak_marked_text(self, text, callback):
        self.current_callback = callback
        self.nsss.speak(text)
        self.status = {'synthesizing': True, 'paused': False}
        self.current_callback(Event(EventType.begin))

    def pause(self):
        if self.status['synthesizing']:
            self.nsss.pause()
            self.status = {'synthesizing': True, 'paused': True}
            if self.current_callback is not None:
                self.current_callback(Event(EventType.pause))

    def resume(self):
        if self.status['paused']:
            self.nsss.resume()
            self.status = {'synthesizing': True, 'paused': False}
            if self.current_callback is not None:
                self.current_callback(Event(EventType.resume))

    def stop(self):
        self.nsss.stop()