Voice Introduction to CCXML, Part IV

Introduction to CCXML, Part IV

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 [email protected]
regarding questions or comments about this or any article.

Latest Posts

Related Stories