diff --git a/setup.py b/setup.py index cb141f3e..c5da7d24 100755 --- a/setup.py +++ b/setup.py @@ -97,6 +97,7 @@ setup( "pyudev", "setuptools", "pexpect", + "pyttsx3", ], ) diff --git a/src/fenrir/speechDriver/genericDriver.py b/src/fenrir/speechDriver/genericDriver.py index 39a97640..7fdd40d8 100644 --- a/src/fenrir/speechDriver/genericDriver.py +++ b/src/fenrir/speechDriver/genericDriver.py @@ -9,6 +9,7 @@ from core import debug from threading import Thread, Lock from queue import Queue, Empty from subprocess import Popen +from core.speechDriver import speechDriver class speakQueue(Queue): def clear(self): @@ -18,8 +19,9 @@ class speakQueue(Queue): except Empty: pass -class driver(): +class driver(speechDriver): def __init__(self): + speechDriver.__init__(self) self.proc = None self.speechThread = Thread(target=self.worker) self.lock = Lock() diff --git a/src/fenrir/speechDriver/pyttsxDriver.py b/src/fenrir/speechDriver/pyttsxDriver.py new file mode 100644 index 00000000..1ea98e29 --- /dev/null +++ b/src/fenrir/speechDriver/pyttsxDriver.py @@ -0,0 +1,86 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Fenrir TTY screen reader +# By Chrys, Storm Dragon, and contributers. +# Espeak driver + +from threading import Thread, Lock +from core import debug +from core.speechDriver import speechDriver + +class driver(speechDriver): + def __init__(self): + speechDriver.__init__(self) + self._engine = None + def initialize(self, environment): + self.env = environment + def shutdown(self): + if self._isInitialized: + self.cancel() + self._engine.endLoop() + self._initialized = False + def eventLoop(self): + self._engine.startLoop() + def startEngine(self): + try: + import pyttsx3 + if self.module != '': + self._engine = pyttsx3.init(self.module) + else: + self._engine = pyttsx3.init() + self.eventLoopThread = Thread(target=self.eventLoop) + self._isInitialized = True + self.eventLoopThread.start() + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('SpeechDriver:initialize:' + str(e),debug.debugLevel.ERROR) + + def speak(self,text, interrupt=True): + if not self._isInitialized: + self.startEngine() + if not self._isInitialized: + return + if not interrupt: + self.cancel() + try: + self._engine.setProperty('volume', self.volume) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('SpeechDriver:speak:volume:' + str(e),debug.debugLevel.ERROR) + try: + self._engine.setProperty('rate', self.rate) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('SpeechDriver:speak:rate:' + str(e),debug.debugLevel.ERROR) + try: + self._engine.setProperty('pitch', self.pitch) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('SpeechDriver:speak:pitch:' + str(e),debug.debugLevel.ERROR) + if self.language != None: + if self.language != '': + try: + self._engine.setProperty('voice', self.language) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('SpeechDriver:speak:language:' + str(e),debug.debugLevel.ERROR) + + elif self.voice != None: + if self.voice != '': + try: + self._engine.setProperty('voice', self.voice) + except Exception as e: + self.env['runtime']['debug'].writeDebugOut('SpeechDriver:speak:voice:' + str(e),debug.debugLevel.ERROR) + self._engine.say(text) + + def cancel(self): + if not self._isInitialized: + return + self._engine.stop() + self._engine.proxy.stop() + + def setPitch(self, pitch): + if not self._isInitialized: + return + self.pitch = pitch + + def setRate(self, rate): + if not self._isInitialized: + return + self.rate = rate