Important: Inside Macintosh: Sound is deprecated as of Mac OS X v10.5. For new audio development in Mac OS X, use Core Audio. See the Audio page in the ADC Reference Library.
The Speech Manager makes it easy for you to synchronize other activities to speech generation by allowing you to install various types of callback procedures on a speech channel. A callback procedure is a procedure that executes whenever a certain type of event is about to occur or has occurred. For example, you might use a word callback procedure to ensure that whenever the Speech Manager is about to speak a word, the word is visible onscreen. Callback procedures also allow you to synchronize more mundane activities with the Speech Manager; for example, you might need to know when you can dispose of a certain text buffer that you had asked the Speech Manager to speak. This section provides an overview of the different callback procedures that you can define.
Implementing Callback Procedures
The
soTextDoneCallBack
andsoSpeechDoneCallBack
speech information selectors allow you to designate text-done and speech-done callback procedures. A text-done callback procedure executes whenever the Speech Manager finishes processing a buffer of text to be spoken. This procedure usually executes before the Speech Manager has finished generating speech from the text and indeed often before it has started. The text-done callback procedure provides a mechanism that allows you to specify to the Speech Manager an additional buffer of text to be spoken, so that speech is generated continuously. Once your text-done callback procedure executes, you can release the memory occupied by the text buffer processed. A speech-done callback procedure does not execute until after the Speech Manager has completed generating speech from a buffer of text.If your application uses or supports embedded speech commands, it may need to use the
soSyncCallBack
andsoErrorCallBack
speech information selectors to designate a synchronization callback procedure or an error callback procedure. A synchronization callback procedure executes whenever the Speech Manager encounters a synchronization command embedded within a text buffer to be spoken. An error callback procedure executes whenever the Speech Manager encounters an error when attempting to process an embedded speech command. The Speech Manager passes information about the synchronization message or type of error to your callback procedure. If your application does not use synchronization or error callback procedures, it can obtain information about synchronization or error messages by continually polling the speech channel by using theGetSpeechInfo
function with thesoErrors
orsoRecentSync
selectors.The
soPhonemeCallBack
andsoWordCallBack
speech information selectors allow you to designate a phoneme callback procedure and a word callback procedure, respectively. A phoneme callback procedure executes whenever a phoneme is about to be spoken on a speech channel. A word callback procedure executes whenever a word is about to be spoken on a speech channel.Since callback procedures execute at interrupt time they face several restrictions, as discussed in detail in Inside Macintosh: Processes. Most significantly, your callback procedure must not allocate or move memory or call any Toolbox or Operating System routine that might do so. Thus, typically a callback procedure simply sets a flag variable; for example, a phoneme callback procedure might change a variable that indicates which phoneme is being spoken. Your application can then poll this flag variable each time through its main event loop and perform whatever activity is desired if it finds that the flag variable has changed. Remember to design callback procedures to execute quickly.
Because they execute at interrupt time, callback procedures also cannot access application global variables unless the A5 register contains the value of the application's A5, as discussed in Inside Macintosh: Memory. Fortunately, the Speech Manager provides a mechanism that makes it easy to ensure that A5 is set correctly. Your application can call the
SetSpeechInfo
function with thesoCurrentA5
selector to pass the application's A5 in thespeechInfo
parameter to the Speech Manager. The Speech Manager will then set the A5 register to the passed value whenever it executes an application-defined callback procedure for that speech channel.Sometimes your application might wish to provide a callback procedure with additional information beyond that which can be provided by examining application global variables. For example, a callback procedure might need to know from which document speech is being generated. Your application can use the
SetSpeechInfo
function with thesoRefCon
selector to specify a 4-byte reference constant value--for example, a handle to a document record--that the Speech Manager passes to all callback procedures on a particular speech channel. Your application can use the same callback procedure on multiple speech channels, for each of which the Speech Manager can pass a different value to the callback procedure. Thus, as long as your application never uses a single speech channel to generate speech on multiple documents simultaneously, it can use the reference constant value mechanism to pass document-specific information to a callback procedure. Typically, you use the reference constant to contain a pointer or handle to more extensive information that the callback procedure would require.Listing 4-6 shows how you can indicate to the Speech Manager both the value to which it should set the A5 register when it executes a callback procedure on a particular speech channel and the reference constant value to pass to that callback procedure.
Listing 4-6 Setting up a speech channel for callbacks
FUNCTION MySetupCallbacks (chan: SpeechChannel; refCon: LongInt): OSErr; VAR myA5: LongInt; {application's A5} myErr: OSErr; BEGIN myA5 := SetCurrentA5; {get application's A5} {Pass A5 value to speech channel.} myErr := SetSpeechInfo(chan, soCurrentA5, Ptr(myA5)); IF myErr = noErr THEN {set the reference constant} myErr := SetSpeechInfo(chan, soRefCon, Ptr(refCon)); MySetupCallbacks := myErr; END;TheMySetupCallbacks
function defined in Listing 4-6 uses theSetSpeechInfo
function with both thesoCurrentA5
and thesoRefCon
selectors to prepare a specific speech channel for callbacks. Note that your application can callMySetupCallbacks
as many times as desired for any particular speech channel; you might do this if you want to change the reference constant value to be passed to the speech channel.Unlike other selectors, the
soCurrentA5
andsoRefCon
selectors do not require that you pass a pointer to the information you are specifying in thespeechInfo
parameter. Because an application's A5 value and a speech channel's reference constant value are always each 4 bytes long (the same size as thespeechInfo
parameter), your application passes these values directly, casting them to pointer values.After your application sets up the A5 register and defines a reference constant value, it can install the appropriate type or types of callback procedure. Listing 4-7 shows how you might install a word callback procedure.
Listing 4-7 Installing a word callback procedure
PROCEDURE MyInstallWordCallback (chan: SpeechChannel; callbackProc: ProcPtr; refCon: LongInt); VAR myErr: OSErr; BEGIN myErr := MySetupCallbacks(chan, refCon); {set up callbacks} myErr := SetSpeechInfo(chan, soWordCallBack, callbackProc); IF myErr <> noErr THEN DoError(myErr); {respond to an error} END;TheMyInstallWordCallback
procedure defined in Listing 4-7 first prepares for callbacks by calling theMySetupCallbacks
function defined in Listing 4-6 for the speech channel and reference constant value specified by thechan
andrefCon
parameters, respectively. Then it installs the callback procedure specified by thecallbackProc
parameter by using theSetSpeechInfo
function with thesoWordCallBack
speech information selector. If, for example, you want to pass to your word callback procedure a pointer to the window containing the document being used for speech generation, you might call theMyInstallWordCallback
procedure like this:
MyInstallWordCallback(mySpeechChan, @MyWordCallBack, LongInt(myWindow));Listing 4-8 defines a simple word callback procedure.Listing 4-8 A typical word callback procedure
PROCEDURE MyWordCallback (chan: SpeechChannel; refCon: LongInt; wordPos: LongInt; wordLen: Integer); BEGIN gWindowBeingRead := WindowPtr(refCon); gWordPos := wordPos; gWordLen := wordLen; END;Because of the restrictions on callback procedures, a typical callback procedure usually just sets global flag variables based on the information passed to it. In Listing 4-8, the callback procedure copies information from the
- WARNING
- Callback procedures are called at interrupt time and therefore must not attempt to allocate, move, or dispose of memory; dereference an unlocked handle; or call other routines that do so. Also, a callback procedure is a Pascal procedure and must preserve all registers other than A0-A1 and D0-D2.
refCon
,wordPos
, andwordLen
parameters to the three global variables gWindowBeingRead, gWordPos, and gWordLen. You can then call a routine to check the values of these global variables once each time through your application's event loop and respond appropriately if thegWindowBeingRead
global variable is notNIL
. (Your application would have to initialize the variable toNIL
.) For example, the routine might ensure that the word about to be spoken is visible onscreen and scroll the document appropriately if it is not.Although they have different uses, speech-done callback procedures, synchronization callback procedures, error callback procedures, and phoneme callback procedures are typically defined in ways similar to that of the word callback procedure in Listing 4-8. See "Application-Defined Routines" beginning on page 4-82 for complete information on callback routines.
Text-done callback procedures are usually more complex than the other types. You can use a text-done callback procedure simply to determine when the Speech Manager has completed processing a buffer of input text. The callback procedure can just set a global flag variable that is inspected once each time through the application's main event loop; when the flag variable indicates that the input buffer processing is complete, you can dispose of the input buffer.