speechd-discuss
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Speechd] callbacks


From: Gary Cramblitt
Subject: [Speechd] callbacks
Date: Sun Aug 13 12:52:48 2006

Here's my suggestions for implementing callbacks in Speech Dispatcher.  My 
C/C++ skills aren't perfect, so..

The traditional subscribe/callback mechanism.

Define your event types, i.e., begin-sentence, end-sentence, end-job, etc.

Define a bunch of constants, assigning one bit to each type of event.

This allows applications to pass an event mask when they subscribe specifying 
the kind of events they'd like to receive.

As you probably know, C libraries cannot call into C++ object methods.  To 
work around this, allow apps to pass a void* when subscribing.  Speech 
Dispatcher stores this along with the app's subscription information and 
passes it back in each callback.  C++ uses this by passing an object "this" 
reference when subscribing and then using the passed-back pointer in the 
callback handler to call into the object that subscribed.  Other applications 
can use the pointer for whatever they wish, or just pass a NULL.

So a subscription call from inside C++ class called MyObj might look like 
this:

int event_mask = SPD_EVENT_STARTSENTENCE;
spd_set_callback(connection, &handle_spd_event, event_mask, this);

with the callback handler coded like this:

extern "C" {
static int handle_spd_event(spd_event* event, int type, void* objptr);
}

int handle_spd_event(spd_event* event, int type, void* objptr)
{
    return static_cast<MyObj*>(objptr)->spdEvent(event, type);
}

spdEvent is a method in MyObj for handling the event.   In this example, 
"type" will equal SD_EVENT_STARTSENTENCE.  "event" is a pointer to a 
structure within Speech Dispatcher (or perhaps instead, an event ID) 
containing information about the event.  The application can make calls into 
Speech Dispatcher, passing this pointer/ID, to request additional information 
about the event.  For example

  int sentence_num = spd_get_event_sentence_num(event);

The return value of the callback can be used for feedback to Speech 
Dispatcher.  Normally, the handler should return 0.  But perhaps a value of 1 
would indicate to Speech Dispatcher to stop the synthesis.  At any rate, you 
should allow a return code for future flexibility.

The nice thing about this setup is you can extend it later by adding 
additional event types, event information retrieval routines, or handler 
return codes without breaking existing apps.

Some other issues/ideas.

You'll want to insulate Speech Dispatcher callbacks from long-running callback 
handlers.  In KTTSD, I plan to decouple the callback from Speech Dispatcher 
by posting an event into the Qt event loop and returning immediately, but you 
might want to think about insulating Speech Dispatcher from other apps, 
perhaps by issuing callbacks in a separate thread.  (But then, I know threads 
can be problematic on some platforms..)

It might be handy to pass an additional parameter or two in the callback that 
contains most-used information, so that the handler doesn't have to call into 
Speech Dispatcher to retrieve event information.  For example, KTTSD will 
want to know the "job" number and sentence number when receiving 
SENTENCESTARTED, so if this info were in the callback, a call into Speech 
Dispatcher would be unnecessary.

How long should Speech Dispatcher keep event information around?  I think the 
rule "It keeps the information until the handler returns." should be 
adequate.

I don't know how well the void* pointer method would work for other 
object-oriented languages, like Python.  Anyone?

You'll probably want to typedef some of the "int's" in my sample code above 
for future expansion, i.e., the callback prototype might be

sbd_result_t handle_spd_event(spd_event* event, spd_eventtype_t type, void* 
objptr)

where sbd_result_t and spd_eventtype_t are typedef'd to int.

How much information would be available for each event type?  For starters, 
maybe not much, but you'll probably want to keep pointers to running job data 
structures.  The problem with that is, what happens if a callback handler 
cancels the job on which the event was issued?  Or stated another way, 
re-entrancy is an issue.  For starters, I see no problem with limiting calls 
from event handlers to the "get_event_info" kind, but it is something to 
think about.

-- 
Gary Cramblitt (aka PhantomsDad)
KDE Text-to-Speech Maintainer
http://accessibility.kde.org/developer/kttsd/index.php


reply via email to

[Prev in Thread] Current Thread [Next in Thread]