I am working on an Activity for the One Laptop Per Child project. As you may know, OLPC activities often use pygtk. My activity is for reading Project Gutenberg Etexts, and I have been asked to add text to speech to that Activity using speech-dispatcher. The idea is to have karaoke-style highlighting, so that as each word is spoken it is also highlighted in the text. This should help children learn to read. To do this I have to synchronize highlighting and speaking.

Speech-dispatcher can do callbacks when it is finished speaking, so my plan was to use gobject.timeout_add() to call a function at regular intervals. This function would check a flag that would be set to True if speech-dispatcher was finished speaking. If True I would highlight and speak the next word, if false I would not. I would use speech-dispatcher callbacks to set the flag to True every time it finished speaking.

What I found out was that speech-dispatcher would not consistently execute the callbacks. When I pointed this out to the speech-dispatcher mailing list one of the developers recreated my problem, then found that it he just executed my method in a loop rather than using gobject.timeout_add() that the code in speech-dispatcher worked perfectly and all callbacks got executed. He is convinced that using gobject.timeout_add() interferes with socket activities in other threads. I have forwarded his email below.

Unfortunately, running that code in a loop is less than optimum. I need to be able to turn speech on and off, which I can't do in a simple loop. I need gobject.timeout_add() to work, or something similar, to get text to speech with highlighting.

I would appreciate any suggestions you have to offer.

James Simmons

--- Begin Message ---

The code is attached. This is not an OLPC Activity but a standalone program I use to try out new features
Hello James,

I have tried to run the code you've sent and I can reliably reproduce the issue. I believe it has something to do with the way how you call speechd.client.speak() from inside the gtk loop, because outside of it, everything works normally (even in your application).

I'm not familiar with PyGTK however, so I don't see what exactly is going wrong. I'll try to describe my findings in hope you or someone else will have someidea.

As you describe, in your program, the SSIP Python interface often fails to deliver a callback to the client application (in fact, it freezes and no other communication with Speech Dispatcher is possible). The exact reason is that in self._socket.recv(1024) (socket.socket.recv()) fails to return although the logs of Speech Dispatcher prove some new data have been written to the socket.

I found that this happens when cb_next_word is
called as a callback from keypress_cb() via
 timeout_id = gobject.timeout_add(100, self.next_word_cb)
but it doesn't happen, if I call it directly (around line 75):

  self.karaoke = True
               self.finished_flag = True
#timeout_id = gobject.timeout_add(100, self.next_word_cb) while True:
                   self.next_word_cb()
                   time.sleep(0.1);
           return True

This variant will reliably speak the whole document word-by-word with all the expected callbacks received.

Another interesting observation is that the mentioned _socket.recv(1024) returns and correctly receives all the pending callbacks just after I hit CTRL-C on the python interpreter running ReadETextsActivity.py and thus kill the main program thread.

Now, the _socket.recv() function in the python speechd library runs in a separate thread that is being launched from the Client object constructor. So apparently gobject.timeout_add() somehow disturbs socket opperations in other threads.

It seems really strange to me and quite unlikely that the python bindings themselves would be responsible.

With regards,
Hynek Hanke








--- End Message ---
_______________________________________________
pygtk mailing list   pygtk@daa.com.au
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/

Reply via email to