locked
SpeakAsyncCancel not working RRS feed

  • Question

  • I have a custom activity where a prompt is played.  Under certain conditions, I need to stop playing the first prompt and then start playing a different one. 

     

    I start the first prompt playing by calling SpeakAsync() on the ISynthesizer object.  I do not wire up an event handler for the SpeakCompleted event.  While this is playing I do some other stuff. 

     

    To stop playing the first prompt I wire up an event handler to the SpeakCompleted event and call SpeakAsyncCancel() on the ISynthesizer object. 

     

    Then in the event handler for the SpeakCompleted event, I call SpeakAsync() with the new prompt. 

     

    In previous releases, this worked, but it has stopped working in the latest beta release. 

     

    The first prompt does not stop playing when the SpeakAsyncCancel() method is called and the event handler that I set up for the SpeakCompleted event never gets called.  Even when the prompt actually finishes, the event handler does not get called. 

     

    If I just call SpeakAsync() for the new prompt without trying to cancel the first one, I get an exception because the synthesizer is not idle.

     

    Is there some other way to do this?

    Monday, June 11, 2007 5:28 PM

Answers

  • Your scenario as described should work.  Working backwards through your question:

     

    "If I just call SpeakAsync() for the new prompt without trying to cancel the first one, I get an exception because the synthesizer is not idle."

    That is expected.  You are correct that you need to invoke SpeakAsyncCancel and wait for the SpeakCompleted first.

     

    "...the event handler that I set up for the SpeakCompleted event never gets called.  Even when the prompt actually finishes, the event handler does not get called."

    This suggests that there is some underlying problem which is not directly related to the SpeakAsyncCancel.  Enable Speech Server event logging and look at the logs; PromptCompleteEvent is logged when the prompt completes.  ApplicationInterfaceEvent ("ISynthesizer.SpeakCompleted") is additionally logged if there is a handler wired up to the event.  Is PromptCompleteEvent raised?  If is, when is it logged w.r.t. ApplicationInterfaceEvent ("ISynthesizer.SpeakAsyncCancel")?  When you hit this condition are you getting any events?  Eg. does ITelephonySession.Closed fire if the far end hangs up?  I am wondering if you are blocking the serialized callback thread as this would prevent any speech events firing. 

     

    "The first prompt does not stop playing when the SpeakAsyncCancel() method is called"

    Even if you're blocking the serialized callback thread, the cancel request should still go through.  Are there any errors in the logs?  How are you determining that cancel is being invoked whilst the prompt is playing? 

     

    "In previous releases, this worked, but it has stopped working in the latest beta release."

    AFAIK nothing has intentionally changed here.

     

    "I start the first prompt playing by calling SpeakAsync() on the ISynthesizer object.  I do not wire up an event handler for the SpeakCompleted event.  "

    SpeakAsyncCancel is a no-op if the prompt has already completed.  When you need to cancel the prompt, how do you know whether or not the 1st prompt is still playing?  Unless I'm forgetting something, the only way is to track it yourself by wiring up to SpeakCompleted, or to invoke SpeakAsync() and catch the exception.  The former is preferred since exceptions are expensive and ideally should not be part of normal call flow on a server.

    Monday, June 11, 2007 8:12 PM

All replies

  • Your scenario as described should work.  Working backwards through your question:

     

    "If I just call SpeakAsync() for the new prompt without trying to cancel the first one, I get an exception because the synthesizer is not idle."

    That is expected.  You are correct that you need to invoke SpeakAsyncCancel and wait for the SpeakCompleted first.

     

    "...the event handler that I set up for the SpeakCompleted event never gets called.  Even when the prompt actually finishes, the event handler does not get called."

    This suggests that there is some underlying problem which is not directly related to the SpeakAsyncCancel.  Enable Speech Server event logging and look at the logs; PromptCompleteEvent is logged when the prompt completes.  ApplicationInterfaceEvent ("ISynthesizer.SpeakCompleted") is additionally logged if there is a handler wired up to the event.  Is PromptCompleteEvent raised?  If is, when is it logged w.r.t. ApplicationInterfaceEvent ("ISynthesizer.SpeakAsyncCancel")?  When you hit this condition are you getting any events?  Eg. does ITelephonySession.Closed fire if the far end hangs up?  I am wondering if you are blocking the serialized callback thread as this would prevent any speech events firing. 

     

    "The first prompt does not stop playing when the SpeakAsyncCancel() method is called"

    Even if you're blocking the serialized callback thread, the cancel request should still go through.  Are there any errors in the logs?  How are you determining that cancel is being invoked whilst the prompt is playing? 

     

    "In previous releases, this worked, but it has stopped working in the latest beta release."

    AFAIK nothing has intentionally changed here.

     

    "I start the first prompt playing by calling SpeakAsync() on the ISynthesizer object.  I do not wire up an event handler for the SpeakCompleted event.  "

    SpeakAsyncCancel is a no-op if the prompt has already completed.  When you need to cancel the prompt, how do you know whether or not the 1st prompt is still playing?  Unless I'm forgetting something, the only way is to track it yourself by wiring up to SpeakCompleted, or to invoke SpeakAsync() and catch the exception.  The former is preferred since exceptions are expensive and ideally should not be part of normal call flow on a server.

    Monday, June 11, 2007 8:12 PM
  • If I understand you correctly, what you've described should work. The one thing I'm suspicious of is that you first say that you do NOT have a SpeakCompleted handler wired up when you start the prompt, and that you later wire one up. You should wire up your SpeakCompleted handler before starting the SpeakAsync() operation, because otherwise there's a possibility of the prompt ending while you have no handler wired up. That would not, however, explain why calling SpeakAsyncCancel fails to cancel the prompt.

     

    Have you breakpointed your code to be sure you're actually calling SpeakAsyncCancel()? If so, can you run msslogtotext.exe on a .etl file (your MSS logs) and confirm that you see the correct ApplicationInterfaceEvent for when your app calls SpeakAsyncCancel()?

     

    Dan

    Monday, June 11, 2007 8:17 PM
  • Thank you for the quick responses. 

     

    Based on your suggestions, I made some changes so that the SpeakCompleted event is wired up before calling SpeakAsync() for the first prompt.  Now SpeakAsyncCancel() is working and the prompt playback is being cancelled.  I'm not sure why this made a difference, but it did.

     

    I'm also setting a flag so that I know if the first prompt finished or not.  If not, I call SpeakAsyncCancel() and start playing the next prompt in the event handler.  If the first prompt has finished playing, I don't call SpeakAsyncCancel() and just start playing the second prompt.

     

    Thanks a lot for your help.

    Tuesday, June 12, 2007 4:25 PM
  • Hi,

    funnily enough I have the same problem you had, but I am setting the event handler before calling SpeakAsync, so that doesn't seem to be the solution to my problem.

     

    Hopefully someone here can help me out with this.

    In my situation, whilst a prompt is speaking after a call to SpeakAsync and I want to stop the prompt, I call SpeakAsyncCancelAll. However this has no effect and the prompt continues to speak until it completes (at which point the SpeakCompleted handler is invoked, with e.Cancelled=false).

     

    But - if I build my prompt to first play an audio file (e.g. tada.wav) followed by some text to speak, and then start it with SpeakAsync, the audio file first plays (as expected). If I then call SpeakAsyncCancelAll whilst the audio file is playing, it immediately stops playing and calls the SpeakCompleted handler (with e.Cancelled=true), as expected.

    However once the text-to-speech part of the prompt has started, calling SpeakAsyncCancelAll has no effect, as per the previous paragraph.

     

    I just don't understand why it simply doesn't stop the speech when I call SpeakAsyncCancelAll (or SpeakAsyncCancel(prompt)). I've made the speech part of the prompt a few sentences long, and it always speaks the whole lot, after I try to cancel.

    Interestingly, calling Pause() on the synthesiser does immediately stop (pause) the speech, but if I then try to call SpeakAsyncCancel, it locks up. The point here is that clearly there is a mechanism available for the speech to be stopped (I was wondering if the ability to Cancel was somehow voice-specific... but it would be hard to believe)

     

    Any help/hints/things-to-try would be greatly appreciated!

    Thanks!

     

    Thursday, August 9, 2007 1:14 PM
  • 1. Exactly how are you constructing your prompt?

    2. Where are you finding the SpeakAsyncCancelAll method?

     

    Thursday, August 9, 2007 8:48 PM
  •  

    I must apologise, I'm using the System.Speech.Synthesis.SpeechSynthesizer class from the Windows SDK/.Net 3.

    I didn't realise this forum was for Office Communications Server/Speech Server... It came up in a search and it was exactly the problem I'm having.

     

    I'm building the prompt using the System.Speech.Synthesis.PromptBuilder which allows the composition of audio files and text to speak.

    SpeakAsyncCancelAll and SpeakAsyncCancel are methods of the System.Speech.Synthesis.SpeechSynthesizer class.

     

    If this is not the same as what you guys are using, I probably should post this on a more appropriate forum!

    Sorry!

    Friday, August 10, 2007 12:14 AM
  • This is for Speech Server, you want the Speech Desktop discussions - http://www.microsoft.com/communities/newsgroups/en-us/default.aspx?dg=microsoft.public.speech.desktop

     

     

    Friday, August 10, 2007 4:47 PM