Introduction to CCXML, Part IV

Thursday Nov 7th 2002 by Jonathan Eisenzopf
Share:

In Part IV of the Introduction to CCXML, we will learn how to set up and breakdown a 2-party conference call using <join> and <unjoin>. We will also learn more about state variables and their use in CCXML.

In Part IV of the Introduction to CCXML, we will learn how to set up and breakdown a 2-party conference call using <join> and <unjoin>. We will also learn more about state variables and their use in CCXML.

Overview

We're going to build on the concepts that were introduced in the first three CCXML tutorials and extend them to simple call conferencing. In CCXML, there are two different types of conferencing elements. The simplest type uses the <join> and <unjoin> elements to conference two call legs together. The limitation is that it can only handle 2 callers. For multi-party conference calls, we would have to use the <createconference> and <destroyconference> elements. In this tutorial, we're going to stick with a two party conference call and look at multi-party conference calls in the next part of the Introduction to CCXML.

State Variables

One of the new concepts that I'm going to introduce in this tutorial is the state variable. A state variable is initialized when the CCXML application starts up. This variable changes its value (or state) as the call progresses. The name of the state variable is defined by the statevariable attribute in the <eventhandler> element:

<eventhandler statevariable="current_state">

The <eventhandler> element only points to the name of the variable that will be used as the state variable. It's still up to you to initialize the variable in the CCXML file:

<var name="current_state" expr="'init'"/>

You should set the state to an initial value that indicates that the program has just started, such as init or start, though there is not a standard naming scheme for the state variable.

This state variable defines the current state of the call and can be used to make decisions about what to do next. For example, we may not want to start an interactive VoiceXML dialog until the caller has listened to a disclaimer dialog first. To accomplish this, we would create a state variable that would change as soon as the caller had listened to the terms, which would trigger and play the main dialog.

<transition name="evt" state="'ready'"
            event="connection.CONNECTION_CONNECTED">
  <assign name="incoming_callid" 
          expr="evt.callid"/>
  <assign name="current_state" 
          expr="'playing_terms'"/>            
  <dialogstart src="'play_terms.vxml'"/>
</transition>

<transition name="evt" 
            state="'playing_terms'" 
            event="dialog.exit">
  <assign name="current_state" 
          expr="'running_main_dialog'"/>
  <var name="age" expr="evt.age"/>
  <if cond="age > 21">
    <dialogstart src="'main.vxml'"/>
    <else/>
      <exit/>
  </if>
</transition>

<transition name="evt" 
            state="'running_main_dialog'" 
            event="dialog.exit">
  <exit/>
</transition>

In the CCXML fragment above, the name of the state variable is current_state, which is defined elsewhere. When the call is connected and the CONNECTION_CONNECTED event is triggered, it's caught by the first <transition> element based on the matching event attribute and matching value for the state attribute. When a call is connected and this event handler is executed, the state variable will be changed to playing_terms and the VoiceXML dialog play_terms.vxml will be started.

When the dialog has completed and exited, the dialog.exit event is triggered by the CCXML interpreter. Notice how the second and third <transition> elements are both catching the dialog.exit event? What makes them different is that the second event handler will only be executed when the state variable is set to playing_terms whereas the third will only execute when the state variable is set to running_main_dialog. The ability to execute different handlers for the same event is what the state variable gives us. Think of it as a second way we can match or define event handlers; first by the named event, and second by the state variable. While we have less control over which events get fired by the CCXML interpreter, we do have TOTAL control over the value of the state variable.

So, when play_terms.vxml has completed execution, the second event handler will be triggered and the main.vxml dialog will start running. We've also changed the value of the state variable from playing_terms to running_main_dialog so that when main.vxml has completed executing, it will trigger the third event handler and call <exit/> ending the call. You can view the entire CCXML program here.

Accessing Values Returned from Dialogs

Another concept that we need to grasp for the example that we will be looking at in a few minutes in the method by which VoiceXML dialogs can pass form field values back to the calling CCXML interpreter. This is done by specifying the list of variables in the namelist attribute of the <exit> element (within the VoiceXML file; not the CCXML file):

<exit namelist="name address phone"/>

We can read in these returned variables in CCXML within the dialog.exit event handler. Looking at the second event handler listed in our previous example and also listed below:

<transition name="evt" 
            state="'playing_terms'" 
            event="dialog.exit">
  <assign name="current_state" 
          expr="'running_main_dialog'"/>
  <var name="age" expr="evt.age"/>
  <if cond="age > 21">
    <dialogstart src="'main.vxml'"/>
    <else/>
      <exit/>
  </if>
</transition>

You may have noticed before that the <var> element is initializing the age variable using the value from evt.age; but where did it get that value from? Well, each event handler can define the name of the object that holds an event object's values and whose name is defined by the name attribute of the <transition> element. So when the dialog.exit event is caught and the exiting dialog contains a form field variable named age which was returned with the <exit> element inside that VoiceXML dialog, we would have access to that variable through the evt object.

Calling Card Application with CCXML

Now we're going to tie everything we've learned about CCXML up to this point to develop an application that functions like a calling card: you dial a number, enter your calling card number, and then dial the number you wish to call.

For this application, we want to do the following:

  1. answer the incoming call
  2. start the VoiceXML dialog that  collects the caller's PIN code and the number they want to call
  3. dial the phone number (if their PIN code matched)
  4. Join the two call legs when the remote party answers the phone

You can view the full source of the application here.

During execution, the application will be in one of five states. The table below lists the state and their related events as well as the next state.

Notice that there are two separate events that might occur while in the dialing state. Either the outbound call will be connected, or it will fail. Also, you'll notice that we're handling the connection.CONNECTION_CONNECTED event in two different places. The first occurrence is triggered when the incoming call is answered and connected. The second occurrence is triggered when the outbound call (using the number they specified) is connected. In the first occurrence, we start the VoiceXML dialog that collects the caller's PIN code and phone number to dial. In the second occurrence, we're calling the <join> elements to join the inbound and outbound call legs together.

You can view the full source of the VoiceXML dialog that collects and returns the caller's PIN code and outbound phone number here.

Some things to notice in this new application:

Placing the outbound call:

<transition name="evt" 
            state="'getting_phone_number'"
            event="dialog.exit">
  <assign name="phone_number" 
          expr="evt.phone_number"/>
  <if cond="phone_number.length == 10">
    <assign name="current_state" expr="'dialing'"/>
    <createcall dest="phone_number"/>
    <else/>
      <exit/>
  </if>
</transition>

The <transition> element above sets the local variable phone_number with the return value from evt.phone_number. If the phone number is 10 digits long, then the state changes to dialing and an outbound call is initiated to the specified number with the <createcall> element.

Joining the Call Legs:

<transition name="evt" 
            state="'dialing'" 
            event="connection.CONNECTION_CONNECTED">
  <assign name="outgoing_callid" expr="evt.callid"/> 
  <join sessionid1="incoming_callid" 
        sessionid2="outgoing_callid"/>
</transition>

The <transition> element above joins the inbound and outbound call legs with the <join> element when the outbound call is connected. If the call is not connected for whatever reason (no answer, busy signal, disconnected number), then the <transition> element listed below is executed:

<transition state="'dialing'" 
            event="connection.CONNECTION_FAILED">
<log expr="'Failed making outbound call'"/>
<exit/>
</transition>

This event handler simply logs the error and exits the CCXML application, disconnecting the call.

Conclusion

If you've made it through the entire CCXML series so far, then you already have a good grasp of the CCXML language. Now you know how to create simple two-party conference calls with the <join> and element. The next and final tutorial in this series will demonstrate how to create multi-party conference calls using the <createconference> element.

About Jonathan Eisenzopf

Jonathan is a member of the Ferrum Group, LLC  which specializes in Voice Web consulting and training. Feel free to send an email to eisen@ferrumgroup.com regarding questions or comments about this or any article.

Share:
Home
Mobile Site | Full Site
Copyright 2017 © QuinStreet Inc. All Rights Reserved