jaredks / rumps

Ridiculously Uncomplicated macOS Python Statusbar apps
BSD 3-Clause "New" or "Revised" License
3.09k stars 179 forks source link

Conflict with pyttsx3 #145

Open a2435191 opened 4 years ago

a2435191 commented 4 years ago

rumps seems to conflict with the text-to-speech module pyttsx3. Here is the code I am using to test this (a button that plays a sound):

import rumps # menu bar app
rumps.debug_mode(TRUE)

import pyttsx3 # text to speech

engine = pyttsx3.init()

class myApp(rumps.App):
    def __init__(self):

        super().__init__(name = "myApp", title = "myApp")
        self.menu = ['Button']

    @rumps.clicked("Button")
    def play_sound(self, sender):

        engine.say('Hello world')
        engine.runAndWait()

        print("done playing sound")

if __name__ == "__main__":
    myApp().run()

And here is the error log:

(base) R5123028:Boring Button eab06$ /Library/Frameworks/Python.framework/Versions/3.8/bin/python3 "/Users/eab06/Desktop/WJB/Python Projects/Boring Button/test2.py"
2020-07-29 11:01:40.830 Python[8561:1626691] <MenuItem: ['Button' -> []; callback: <function myApp.play_sound at 0x10b547ca0>]>
2020-07-29 11:01:40.841 Python[8561:1626691] Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/rumps/rumps.py", line 1122, in callback_
    return _call_as_function_or_method(callback, self)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/rumps/rumps.py", line 397, in _call_as_function_or_method
    return method(event)
  File "/Users/eab06/Desktop/WJB/Python Projects/Boring Button/test2.py", line 18, in play_sound
    engine.runAndWait()
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pyttsx3/engine.py", line 180, in runAndWait
    self.proxy.runAndWait()
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pyttsx3/driver.py", line 192, in runAndWait
    self._driver.startLoop()
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pyttsx3/drivers/nsss.py", line 35, in startLoop
    AppHelper.runConsoleEventLoop()
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/PyObjCTools/AppHelper.py", line 252, in runConsoleEventLoop
    PyObjCAppHelperRunLoopStopper.addRunLoopStopper_toRunLoop_(stopper, runLoop)
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/PyObjCTools/AppHelper.py", line 154, in addRunLoopStopper_toRunLoop_
    raise ValueError("Stopper already registered for this runLoop")
ValueError: Stopper already registered for this runLoop

My current theory is that this is caused because both rumps and pyttsx3 use the module AppHelper.py. When pyttsx3 stops its main loop, it notices its stopper is already registered in the runLoop and throws an exception. Note that "done playing sound" is never printed; the program terminates immediately after the first 'Hello world' is spoken. Any help would be appreciated.