Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fixed issue where NSApp terminate called after endLoop #226

Merged
merged 2 commits into from
Aug 15, 2024

Conversation

randdvorak
Copy link
Contributor

The macOS driver uses PyObjC to driver the speech synthesis. In PyObjC after the event loop is stopped the app calls terminate. This remedies that by driving the runloop ourselves instead of calling AppHelper.startEventLoop. Everything else proceeds normally.

Copy link

@eriklutwin eriklutwin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a novice, but making these changes worked for me. My simple app had a tkinter window and button. Press the button and the app listens for a prompt. Depending upon the prompt it either says hello, goodbye or get the current weather and says it out loud. Before the changes, the app just quit. Now it does not and I can press the button and make another prompt.

@ekalosak
Copy link

ekalosak commented Jun 11, 2023

@nateshmbhat any thoughts on this PR? Or PR#271?

@holytony
Copy link

The macOS driver uses PyObjC to driver the speech synthesis. In PyObjC after the event loop is stopped the app calls terminate. This remedies that by driving the runloop ourselves instead of calling AppHelper.startEventLoop. Everything else proceeds normally.

This bug is such pain in the ass, now its 2024, it's still here

@technisculpt
Copy link

technisculpt commented Jan 31, 2024

@holytony you could instead use the apple speech API using subprocess as I implemented here.

Here is a simplified example:

from sys import platform
import subprocess
import pyttsx3

def mac_engine(_text, _voice, _rate, _path):
    subprocess.call(["say", _text, "-o", _path, f"--rate={_rate}", "-v", _voice])

def engine(_text, _voice, _rate, _path):
    engine = pyttsx3.init()
    voices = engine.getProperty('voices') 
    engine.setProperty('voice', voices[int(_voice)].id)
    engine.setProperty('rate', int(_rate))
    engine.save_to_file(_text, _path)
    engine.runAndWait() 
   
def text_to_speech(text, voice, rate, path):
    if sys.platform == "darwin":
        mac_engine(text, voice, rate, path)
    else:
        engine(text, voice, rate, path)

@holytony
Copy link

holytony commented Mar 5, 2024

@holytony you could instead use the apple speech API using subprocess as I implemented here.

Here is a simplified example:

from sys import platform
import subprocess
import pyttsx3

def mac_engine(_text, _voice, _rate, _path):
    subprocess.call(["say", _text, "-o", _path, f"--rate={_rate}", "-v", _voice])

def engine(_text, _voice, _rate, _path):
    engine = pyttsx3.init()
    voices = engine.getProperty('voices') 
    engine.setProperty('voice', voices[int(_voice)].id)
    engine.setProperty('rate', int(_rate))
    engine.save_to_file(_text, _path)
    engine.runAndWait() 
   
def text_to_speech(text, voice, rate, path):
    if sys.platform == "darwin":
        mac_engine(text, voice, rate, path)
    else:
        engine(text, voice, rate, path)

this actually works. also the pyttsx3 is blocking when it speaks, during which the UI would freeze when its called, even creating a new thread would't solve the problem, however, when I call subprocess say in a new thread, it works flawlessly, thank a lot.

@nateshmbhat nateshmbhat merged commit 25bfacd into nateshmbhat:master Aug 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants