With aynchronous operation, SpeechSpeak() will not actually start the speaking of the text. Rather, it will return immediately with the text queued (ie, waiting) to be spoken. The text will not actually start speaking until such time as you call your GUI's function to service messages. For example, REXX GUI's function to do that is GuiGetMsg(), so the text will not start until your next call to GuiGetMsg().
When you call your GUI's function to service messages, the text will start speaking in the background, and your script can go on to service other messages/events that happen with your GUI (such as the user clicking on controls in one of your windows). The text will finish speaking on its own.
If it is important for you to know when the text has actually started, and then finished, speaking, you can choose to have the speech engine send a message to one of your windows. You set this up by passing the handle of one of your windows to SpeechOpen(). You can also pass a message number that you would like to be used for the message sent to you (so that there is no conflict with any other message numbers you may be using with other add-on DLLs). By default, the message number used is WM_APP + 1000 (ie, 33768). When the text starts playing, a message is sent to your window with that message number. You can look for, and process, these messages in the procedure for your window. (For REXX GUI, you would look for message number 33768 in your WM_EXTRA subroutine). You can then pass ARG(1) and ARG(2) to SpeechEvent which will return the string "START" or "STOP", depending upon whether playback has started or stopped.
If aynchronous operation is used with SpeechSpeak(), then the text will be playing in the background. During playback, you can call SpeechControl() to stop the speaking, or pause it, or resume speaking that was previously paused.
Here is an example of a REXX Gui script that presents a window with a box into which you can type some text to speak. When you click on the Speak button, the text is spoken. This demonstrates asynchronous speaking.
/* GUIBEGIN WINDOW , 54, 263, 257, 54, POPUP | CAPTION | SYSMENU | MINBOX | MAXBOX | THICK, , REXX Speech example FONT 8, 400, MS Shell Dlg TEXT 6, 7, 72, 8, GROUP, , , , Type phrase to speak: ENTRY 79, 3, 175, 16, H_AUTO | BORDER | TABSTOP, CLIENTEDGE, SpeakText TEXT 5, 45, 247, 8, GROUP, , SpeakDone PUSH 140, 24, 40, 14, DEFAULT | TABSTOP, , SpeakButton, ALT "S", &Speak PUSH 40, 24, 80, 14, TABSTOP, , SpeakNewVoice, ALT "P", &Pick Voice DEND GUIEND */ OPTIONS 'C_CALL' /* Load and register functions in REXXGUI.DLL and REXXSPEECH.DLL. */ LIBRARY rexxgui, rexxspeech GuiErr = 'SYNTAX' GuiHeading = 1 GuiCreateWindow('NORMAL') /* Let the user pick out an initial voice to use, and open that voice. */ voice = ChooseSpeakingVoice() IF voice == 0 THEN RETURN Again: DO FOREVER GuiGetMsg() IF EXISTS('GuiObject') == 0 THEN DO IF EXISTS('GuiSignal') THEN DO /* Was it our SpeakButton's WM_CLICK that called GuiWake()? */ IF GuiSignal == 'SpeakButton' THEN DO /* SpeakText has been set to the text to speak. Speak it now. NOTE: * We use asynchronous mode. SpeechSpeak() will return immediately * and we can continue on with our message loop while the text is * speaking in the background. When the text is done, our window's * WM_EXTRA subroutine will be called with a message number of * 33768. If there's an error starting the speech, then SpeechSpeak() * will return that now, and we'll display it in our window. */ error = SpeechSpeak(voice, SpeakText, "A") IF error \== "" THEN GuiAddCtlText("SpeakDone", "Error speaking text:" error) END END END /* We have no Child Window Layout scripts, so we can skip any further checking * of GuiSignal and GuiObject. */ CATCH SYNTAX IF GuiInfo() \== "" THEN DO /* End this script if all windows are closed */ CONDITION('M') SIGNAL Again END FINALLY /* Close the speech voice. */ SpeechClose(voice) GuiDestroyWindow() END RETURN ChooseSpeakingVoice: PROCEDURE EXPOSE GuiWindow /* Let the user pick out a voice to use. NOTE: We pass our REXX GUI window * handle created above to let the speech dialog be tied to that window. */ id = SpeechVoiceDlg(GuiWindow) IF id == "" THEN DO GuiSay("Error getting speech device ID, or user cancelled") RETURN 0 END /* Open that speech engine, and save its voice parameter. NOTE: We pass * our REXX GUI window handle created above to have the speech engine * cause its events in our window. One such event happens when a phrase * is done speaking. */ voice = SpeechOpen(id, GuiWindow) IF voice == "" THEN DO GuiSay("Error opening/initializing the speech voice!") RETURN 0 END RETURN voice /* Called by Reginald when the user clicks on the "Pick Voice" button. */ WM_CLICK_SpeakNewVoice: /* First close whatever voice we already have open. This is safe * to call even if the voice we pass was never opened. */ SpeechClose(voice) /* Now let the user pick a new voice and open it. */ voice = ChooseSpeakingVoice() RETURN /* Called by Reginald when the user clicks on the "Speak" button. */ WM_CLICK_SpeakButton: /* Get the text typed by the user. */ GuiGetCtlValue("SpeakText") /* Let our main message loop return from GuiGetMsg(). Set GuiSignal to * "SpeakButton" so it knows that the user clicked the "Speak" button. */ GuiWake("SpeakButton") RETURN /* Called by Reginald when our window receives an event that REXX GUI itself * doesn't know about. REXX GUI does not know about speech engine events, * so it calls our "EXTRA" event handler. It passes two args, which are the * data for the event. The third arg is the message number. For a speech * engine event, the default message number is 33768. */ WM_EXTRA: /* Is it a message from the Speech engine? */ IF ARG(3) == 33768 THEN DO /* Call SpeechEvent to deduce what type of speech event happened */ IF SpeechEvent(voice, ARG(1), ARG(2)) == "START" THEN /* Display a message that the text is speaking. */ GuiAddCtlText("SpeakDone", "Speaking...") /* Otherwise first arg = 2, which means text is done speaking. */ ELSE /* Display a message that the text is done speaking. */ GuiAddCtlText("SpeakDone", "Done speaking text.") END /* Don't let Rexx Gui process this event. */ RETURN ""