Answered by:
sending RFC 2833 DTMF packets from an OCS application to SIP Peer

Question
-
What API call should I use for sending RFC 2833 DTMF packets from an OCS 2007 Speech Server application to the remote sip peer. This is for use after the call is answered ( In CONENCTED or ESTABLISHED state ). I found ISynthesizer:
enddtmfAsync but that seems to send only tones but not RFC packets. Thanks.
Wednesday, July 23, 2008 2:38 PM
Answers
-
Here's the code for the activity.
After you add it to your project or put it in its own dll you can add it to your workflow just like any other activity.
Remember to refresh your toolbox so it shows up.
Code Snippet/// <summary>
/// An activity used to generate Dtmf digits.
/// </summary>
public class GenerateDtmfActivity : SpeechCompositeActivity
{
private TimeSpan _interdigitTimeout = new TimeSpan(0, 0, 0, 0, 200);
public TimeSpan InterdigitTimeout
{
get { return _interdigitTimeout; }
set { _interdigitTimeout = value; }
}
private TimeSpan _toneDuration = new TimeSpan(0, 0, 0, 0, 500);
public TimeSpan ToneDuration
{
get { return _toneDuration; }
set { _toneDuration = value; }
}
private string _digitsToGenerate = string.Empty;
public string DigitsToGenerate
{
get { return _digitsToGenerate; }
set { _digitsToGenerate = value; }
}
/// <summary>
/// GenerateDtmfActivity: Default Constructor
/// </summary>
public GenerateDtmfActivity()
: base()
{
}
protected override void ExecuteCore(ActivityExecutionContext executionContext)
{
Workflow.TelephonySession.Synthesizer.SendDtmfCompleted += new EventHandler<Microsoft.SpeechServer.AsyncCompletedEventArgs>(Synthesizer_SendDtmfCompleted);
Workflow.TelephonySession.Synthesizer.SendDtmfAsync(DigitsToGenerate, InterdigitTimeout, ToneDuration);
}
void Synthesizer_SendDtmfCompleted(object sender, Microsoft.SpeechServer.AsyncCompletedEventArgs e)
{Workflow.TelephonySession.Synthesizer.SendDtmfCompleted -= Synthesizer_SendDtmfCompleted;
this.Close(e.Error);
}
}Sunday, July 27, 2008 10:57 PM
All replies
-
So you're not seeing the Dtmf packets being generated when you use the SendDtmfAsync function?Thursday, July 24, 2008 12:40 AM
-
Ahmed: The documentation did not say that it sends out RFC 2833 packets. And since the method belongs to Synthesizer, I thought may be it will send out tones.
If you can confirm to me that it is designed to send out RFC 2833 packets, that will be great. Does it also send out tones?
Thursday, July 24, 2008 2:07 AM -
The tones are represented using RFC 2833 packets. So yes, the packets are generated.
Thursday, July 24, 2008 2:24 PM -
Thanks Ahmed.Thursday, July 24, 2008 10:20 PM
-
I have now verified that I do get RFC DTMF packets.
I can use one more help. My simple minded first attempt at using SendDTMFAsync() did not quite work.
{
statementActivity1.MainPrompt.AppendText(
"Outpulse begin");TelephonySession.Synthesizer.SpeakCompleted +=
new EventHandler<Microsoft.SpeechServer.Synthesis.SpeakCompletedEventArgs>(Synthesizer_SpeakCompleted);}
void Synthesizer_SpeakCompleted(object sender, Microsoft.SpeechServer.Synthesis.SpeakCompletedEventArgs e){
System.
TimeSpan ts1 = new System.TimeSpan(2000000);TelephonySession.Synthesizer.SendDtmfCompleted +=
new EventHandler<Microsoft.SpeechServer.AsyncCompletedEventArgs>(Synthesizer_SendDtmfCompleted);TelephonySession.Synthesizer.SendDtmfAsync(
"2222222222222", ts1, ts1);}
private void Synthesizer_SendDtmfCompleted(object sender, Microsoft.SpeechServer.AsyncCompletedEventArgs e){
statementActivity2.MainPrompt.AppendText(
"Outpulse done, Hope you heard it, bye");}
With this code, I get a "synthesize not idle" error message and I do not get the digits. May be occasionally one or two.
I understand why this is so but do not know how to cleanly solve it.
I added a delay activity in between statement1 and statement2 with some unexplained results though one "hack" actually worked fully. Here are the results with the various values of timeout.
TimeoutDuration of the delayActivity = 00:00:00, then the behavior is same. No tones, no second prompt, "synthesizer not idle message". I understand this.
TimeoutDuration = 00:00:06 - I hear the tones, I hear the second prompt but the workflow hangs forever. It takes approx 5 seconds for the tone to complete. So any timeout value higher than that causes the workflow to hang.
May be using the DelayActivity is not wise.
1) What is the right way to do what I want to do?
2) Just out of curiosity, I would like to know the reasons for the above mentioned Delay activity behavior
Saturday, July 26, 2008 5:37 PM -
You probably just have your code in a CodeActivity, you need to put it in a class that inherits from SpeechCompositeActivity.
Essentially, SpeechCompositeActivity has the correct plumbing under the covers to ensure that the Speech events are propagated appropriatelly. The absense of this code results in the issues that you are observing.
Saturday, July 26, 2008 7:46 PM -
Ahmed:
I do not have a Code Activity. ( I did at one point but got rid of it ).
All my code is what is enclosed above, basically chaining eventhandlers. I have two statement activities ( with the delay activity being introduced later which we can set aside for now ).
statementActivity1's turnstarting sets up the first prompt. The speech completed event handler wires up the event handler for DtmfCompleted and fires of sendDTMFAsync. The DtmfCompleted event handler then sets up the prompt for statementActivity2. But, what happens is, after playing the statementActivity1's prompt, it goes straight to statementActivity2 and finds that the Synthesizer is busy because the synthesizer is playing the dtmf tones ( I think ).
(BTW, I do not need statementActivity2. I just put it there for playing around. It came in handy when I put in the delayactivity )
Sunday, July 27, 2008 12:55 AM -
Ah, understood. What I have done in the past is create a dtmf generation activity that way it's self contained. You could try that.Sunday, July 27, 2008 2:39 AM
-
Ahmed: Can you fill me in some more? What activity do I use? If you can provide me with some sample snippets of code, that will be wonderful. ( I am also a bit concerned that dialing digits is getting so involved, hope I am approaching this the right way )
Sunday, July 27, 2008 3:28 AM -
I put the two statmentactivity's inside a speechsequence activity and I still have the same issue. It simply runs to completion without waiting for the DtmfCompleted event. Is there a simple way to make it wait for a particular event?
Ahmed, are you suggesting that I need to write a GenerateDTMF custom activity as a subclass of SpeechCompositeActivity? That sounds like a whole bunch of code to write for the simple task of outpulsing digits.
Sunday, July 27, 2008 7:21 PM -
The problem is that Statement activities are authored to play the prompt and exit.
You're trying to force new features into the activities and make them do something they're not designed to.
So yes, if you want to generate Dtmf, you're going to have to write a completely new stand alone activity instead of trying to tack on new functionality to the provided activities. When you see what activities look like "under the covers" you'll see what I mean.
I have such an activity somewhere, I'll see if I can dig it up.Sunday, July 27, 2008 9:13 PM -
Sunday, July 27, 2008 10:07 PM
-
Here's the code for the activity.
After you add it to your project or put it in its own dll you can add it to your workflow just like any other activity.
Remember to refresh your toolbox so it shows up.
Code Snippet/// <summary>
/// An activity used to generate Dtmf digits.
/// </summary>
public class GenerateDtmfActivity : SpeechCompositeActivity
{
private TimeSpan _interdigitTimeout = new TimeSpan(0, 0, 0, 0, 200);
public TimeSpan InterdigitTimeout
{
get { return _interdigitTimeout; }
set { _interdigitTimeout = value; }
}
private TimeSpan _toneDuration = new TimeSpan(0, 0, 0, 0, 500);
public TimeSpan ToneDuration
{
get { return _toneDuration; }
set { _toneDuration = value; }
}
private string _digitsToGenerate = string.Empty;
public string DigitsToGenerate
{
get { return _digitsToGenerate; }
set { _digitsToGenerate = value; }
}
/// <summary>
/// GenerateDtmfActivity: Default Constructor
/// </summary>
public GenerateDtmfActivity()
: base()
{
}
protected override void ExecuteCore(ActivityExecutionContext executionContext)
{
Workflow.TelephonySession.Synthesizer.SendDtmfCompleted += new EventHandler<Microsoft.SpeechServer.AsyncCompletedEventArgs>(Synthesizer_SendDtmfCompleted);
Workflow.TelephonySession.Synthesizer.SendDtmfAsync(DigitsToGenerate, InterdigitTimeout, ToneDuration);
}
void Synthesizer_SendDtmfCompleted(object sender, Microsoft.SpeechServer.AsyncCompletedEventArgs e)
{Workflow.TelephonySession.Synthesizer.SendDtmfCompleted -= Synthesizer_SendDtmfCompleted;
this.Close(e.Error);
}
}Sunday, July 27, 2008 10:57 PM -
Ahmed: Thanks. Much appreciated.Monday, July 28, 2008 12:32 AM
-
I just tried with the code you gave. It works great. It takes care of my need cleanly. Thanks Ahmed.Monday, July 28, 2008 6:06 AM