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
Engine.isBusy() does not seem to return consistent value, according to documentation #13
Comments
Thanks for the feedback. I haven't had a chance to dig in yet. If this is blocking you in any way and you have a fix + tests, please open a pull request. Otherwise, I'll try to get to it when I have some time to dig in. |
I experienced the same thing and wanted to provide some code and "log" data that shows some more information to this issue. This was tested with the v1.1 from the repository without any modifications. In the docs it says for the function The test script: import os
import sys
sys.path.insert(0, os.path.join('..', '..'))
import pyttsx
import time
def onWord(name, location, length):
print 'word', name, location, length
print("Is busy while speaking? - [{}]".format(engine.isBusy()))
if location > 10:
engine.stop()
engine = pyttsx.init()
print("Is busy directly after init? - [{}]".format(engine.isBusy()))
time.sleep(2)
print("Is busy 2 seconds after init? - [{}]".format(engine.isBusy()))
engine.connect('started-word', onWord)
print("Is busy after connecting callback? - [{}]".format(engine.isBusy()))
time.sleep(3)
print("Is busy before queueing say command? - [{}]".format(engine.isBusy()))
engine.say('The quick brown fox jumped over the lazy dog.')
print("Is busy after queueing say command? - [{}]".format(engine.isBusy()))
time.sleep(2)
print("Is busy before runAndWait? - [{}]".format(engine.isBusy()))
engine.runAndWait()
print("Is busy after runAndWait? - [{}]".format(engine.isBusy()))
time.sleep(2)
print("Is busy before queueing 2nd say command? - [{}]".format(engine.isBusy()))
engine.say('The quick brown fox jumped over the lazy dog.')
print("Is busy after queueing 2nd say command? - [{}]".format(engine.isBusy()))
time.sleep(2)
print("Is busy before 2nd runAndWait? - [{}]".format(engine.isBusy()))
engine.runAndWait()
print("Is busy after 2nd runAndWait? - [{}]".format(engine.isBusy())) Output under Windows 7:
Output under Ubuntu:
One can see, that under both OSs the driver claims to be busy with speaking an utterance right after initialization and during configuration. And it is still busy while queueing the first utterance until the first call to The second observation is, that the driver again claims to be busy when a sentence is added with the A third - platform dependent - observation is, that the driver under Windows seems to be not busy while actually making an utterance which seems to be wrong as far as I understand it. In my experience the errors in the Ubuntu output can be igrnored since I was able to hear the utterance. You might notice that stopping the utterance in the example code works for the first execution of |
Finally getting some time to dig into this bug. The problem at hand is that the _busy internal flag is being used both to represent "is the driver ready to process the next utterance" and "is the driver busy outputting an utterance." One way to fix is to follow @quattrinili 's approach: avoid relying on _busy for utterance queue pumping. Another approach is to invent a new _speaking instance var, update it appropriately throughout the code, and return it from isBusy instead of the internal state flag. (The naming is unfortunately, but changing the semantics of isBusy and inventing a new isSpeaking seems wrong.) Looking at the discrepancies across the driver implementations that had to do with mitigating platform differences in loop pumping behavior, I'm leaning toward the second solution. I think it better avoids regressing cross-platform behavior by duplicating a bit of internal state. Will give it some more thought and testing before committing to an approach. |
As written in the title, isBusy() function does not return consistent value (at least on how I interpreted the documentation), namely True if the engine is currently busy speaking an utterance or False if not.
This can be checked when the engine is initialized, which obviously is not currently busy speaking, but still the function returns true.
The reason why this happen is that when the engine is initialized, the corresponding variable that saves whether the engine is busy or not is initialized to True.
Just initializing that value to False does not make the engine working correctly (i.e., using say() and runAndWait()). In the following I report what happens when _busy is initialized to False explaining why it does not work.
When say() is called, the command is pushed in the queue and _pump() is called, launching the command to start the utterance.
Then, when runAndWait() is called endLoop() is pushed in the command queue and "pumped" (according to _push() implementation) and then startLoop() is called. Note that when endLoop() is pushed in the command queue, variable _busy is False. So, as endLoop() is called, then the utterance is interrupted.
A possible solution is the following:
In driver.py (diff w.r.t. the current version on the repository (downloaded on July 20th, 2013) containing the modifications http://pastebin.com/mrvD6G4a):
In espeak.py (diff w.r.t. the current version on the repository (downloaded on July 20th, 2013) containing the modifications: http://pastebin.com/uin8ybPG; note that these modifications should be replicated in the other drivers):
The idea is that instead of setting variable _busy in an ad hoc way so that commands can be pumped, actually pump commands when they are actually processed.
This modification should correctly set the variable _busy (namely True if the engine is currently busy speaking an utterance or False if not), at least in the scenario I considered (i.e., call of say() and runAndWait()). For other scenarios (e.g., using externalLoop()), it should be carefully checked if the system still works.
The text was updated successfully, but these errors were encountered: