[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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Speechd] callbacks,
Gary Cramblitt <=