CCXML 1.0-W3C Development GuideHome  |  Frameset Home

  Limiting Call length  |  TOC  |  Answering Machine Detection  

Duplex and Half Duplex Conferencing


Note: This example application requires the enabling of outdial priveleges on the Voxeo network, and the provisioning of a alphanumeric token string to your application. In order to get hooked up with all these neat features, check our Support Guide for all the juicy details.

Note: The code presented within this tutorial is intended for the "Prophecy - CCXML 1.0" application type only. Attempts to utilize this code on the "CCXML - Voxeo" application type will not function, as the latter platform is based on the W3C specification from 2002.  Prophecy CCXML 1.0 is compliant to the most recent specification from 2006.

So we have covered CCXML 1.0 conferencing in our tutorials, and have messed with some of the neater tricks of the trade with HTTP-initiated outbound calls. Let's now tackle how to create an 'eavesdropping' conference call, where we have a single 'moderator' who will monitor the course of the conversation. Of course, while we want the moderator to be able to hear the participants speaking, we want to mask any sound coming from this heavy-breathing moderator, so our conference participants can have an uninterrupted chat. To do so, we will access the 'duplex' attribute of the <join> element.

So what exactly does the term 'duplex' mean to us in the context of the CCXML 1.0 application? A look at any telephony dictionary indicates how this factors into this little experiment:

Full duplex is data transmission that takes place in two directions simultaneously, which is essentially any telephone call. Since data transmission happens at the same time in both directions, both caller and callee can interrupt the other, talk over each other, etc.

Half duplex allows data transmission in but one direction. A half-duplex connection is much like talking with any teenager, you can talk until you are blue in the face, but they won't hear a word you say.

With us so far? Let's now take a peek at how we can use duplex and half-duplex connections to string us together an eavesdropping application. For this sample application, we will assume that the moderator/admin will be based on the caller's ANI value. We will also allow for a three-digit conference ID for all participants, so our conference mixer isn't limited to but one conference at a time. So, let's start out simple, and first take a peek at the VXML dialog that will be invoked when we get a caller dialing into the app:


ccxml_vxml.xml


<?xml version="1.0" encoding="UTF-8"?>

<vxml version="2.0">

  <var name="admin" expr="'no'"/>
  <var name="callid" expr="session.connection.originator.uri"/>

  <form>
  <block>
    <log expr="'*** CALLID = ' + callid"/>
  </block>

    <field name="verify" type="digits?length=3">
      <prompt>
      <break/>
        Enter your conference ID now.
      </prompt>
      <filled>
          <log expr="'*** session.callerid =' + session.connection.originator.uri"/>
          <!--*** SOME SIP CONNECTION ID THAT MATCHES THE ADMINISTRAOTORS CALLER ID *** -->
          <if cond="callid == '4072223333@127.0.0.1'">
            <assign name="admin" expr="'yes'"/>
            <log expr="'*** CALLERID INDICATES THAT THE ADMIN HAS DIALED IN ***'"/>
          <else/>
            <assign name="admin" expr="'no'"/>
          <log expr="'*** CALLERID INDICATES THAT A NON ADMIN HAS DIALED IN ***'"/>
          </if>
            <exit namelist="verify admin"/>           
      </filled>
    </field>

  </form>
</vxml>


Nothing to it, right? As promised, we base Admin status on CallerID, and have a simple form/field/filled to take the conference ID from the caller, at which point we will return to our CCXML application.


CCXML_ListenOnly.xml

What's so different about this CCXML code from what we have seen thusfar? Not all that much, truth be told. We are going to want to keep track of all conference participants, but this is good practice, anyhow. Letting folks join 'willy nilly' and not having proper cleanup code can lead to 'zombie' sessions, which is bad all the way around. So, once we have the logic in place to track when a caller enters the conferencing fray, we also want to catch when someone leaves the party, and track that as well. Once we programatically determine that there is no one left on the conference, we destroy the conference, thus making everyone happy. Including the Voxeo Engineers.

The other Big Difference between the below code and what we are already familiar with, is that of the conference Moderator. Remember, we assigned the Admin status via ANI in the VXML dialog, and passed this status variable to the CCXML 1.0 by way of the <exit namelist> element/attribute. So, when the CCXML 1.0 layer figures out that there is an Admin coming in, it will create a half duplex connection, and sit in a holding pattern until we have more people to join the conference. When we have a 'ham and egger', (non-admin), join the conference, then the CCXML layer will programatically create a full duplex connection, allowing all the non-admins to chat.



<?xml version="1.0" encoding="UTF-8"?>
<ccxml version="1.0" xmlns="http://www.w3.org/2002/09/ccxml">

<meta name="author" content="Jeff Menkel"/>
<meta name="copyright" content="2007 Voxeo Corporation"/>
<meta name="description" content="Duplex Conferencing Tutorial"/>
<meta name="maintainer" content="YOUR_EMAIL@HERE.COM"/>

  <var name="state0" expr="'init'"/>
  <var name="smallConf"/>
  <var name="line_0"/>
  <var name="duplex"/>

  <!--
  Initially, the admin variable is 'no'. You can reset it to 'yes' based on
  any criteria you like (database info, callerID, etc.. In this example, we use
  callerID
  -->

  <var name="admin" expr="'no'"/>
 
  <!--
  Tracking number of particpants so we do not leave zombie conferences
  this variable should reference a session variable or database query
  on the developer side.
  -->

  <var name="participants" expr="0"/>
 
  <!--
  Track joinstatus of each caller so we do not decrement participants on unjoin
  and hang up
  -->

  <var name="joinstatus"/>
 
  <eventprocessor statevariable="state0">

  <!-- incoming call --> 
    <transition state="init" event="connection.alerting">
      <assign name="line_0" expr="event$.connectionid" />
      <accept/>
    </transition>

  <!-- incoming call connected -->
    <transition state="init" event="connection.connected">
      <log expr="'---- Master call answered...'"/>
  <!-- newly connected call must log in -->
      <log expr="'---- starting the login vxml ...'"/>   
      <assign name="state0" expr="'login'" /> 
      <dialogstart src="'ccxml_vxml.xml'" dialogid="loginscr" type="'application/voicexml+xml'"/>
    </transition>

  <!--
  Caller enters an arbitrary code (which is the conferenceID.
  If another caller enters the same code, they'll join that same conference.
  We advise protecting conferences with more authentication;
  this is just an example.
  -->

    <transition state="login" event="dialog.exit">
      <log expr="'---- Ended vxml login...'"/>
      <log expr="'---- About to create conference...'"/>
      <assign name="state0" expr="'conference'" />
  <!--
  In the vxml dialog, based on the ANI, we assign a variable 'admin'.
  Below, if the admin = 'yes' we assign a CCXML variable admin = 'yes'
  -->


      <log expr="'*** event$.values.admin =' + event$.values.admin"/>

      <if cond="event$.values.admin == 'yes'">     
        <assign name="admin" expr="'yes'" />
        <log expr="'*** ADMIN = TRUE ***'"/> 
      <else/>
        <assign name="admin" expr="'no'" />
        <log expr="'*** ADMIN = FALSE ***'"/> 
      </if>
      <createconference conferenceid="smallConf"/>
    </transition>
   
    <transition event="conference.created">
      <log expr="'---- conference created and its ID is [' + smallConf + ']'" />
  <!--
  Here if our CCXML variable admin == 'yes' then that caller joins the
  conference in listen-only mode
  -->

      <if cond="admin == 'yes'">
        <assign name="duplex" expr="'half'"/>
      <!-- Assigning duplex variable to Half -->
        <log expr="'**** DUPLEX IS: ' + duplex"/>   
        <join id1="line_0" id2="smallConf" duplex="duplex"/>
      <else/>
        <assign name="duplex" expr="'full'"/>
        <!-- Assigning duplex variable to Full -->
        <log expr="'**** DUPLEX IS: ' + duplex"/>
        <join id1="line_0" id2="smallConf" duplex="duplex"/>
      </if>
    </transition>

    <transition event="conference.joined">
  <!--
  Here we'll increment the number of conference participants
  again... participants references a session variable or something
  visible to all clients
  -->

      <assign name="participants" expr="participants+1" />
      <assign name="joinstatus" expr="'joined'" /> 
      <log expr="'---- call leg ' + event$.connectionid + ' has joined the conference'" />
    </transition>
   
    <transition event="conference.unjoined">
  <!--
  Here we'll decrement the number of conference participants
  again... participants references a session variable or something
  visible to all clients
  -->

      <assign name="participants" expr="participants-1" />
      <assign name="joinstatus" expr="'unjoined'" />
      <log expr="'---- call leg ' + event$.connectionid + ' has unjoined the conference'" />
    </transition>   

    <transition event="connection.disconnected">
      <if cond="joinstatus == 'joined'">       
        <assign name="participants" expr="participants-1" />
      </if>
  <!--
  When you are tracking # of participants with a session variable, you will
  want to re-include this so you do not leave zombie conferences.
  -->

      <if cond="participants == 0">         
        <destroyconference conferenceid="smallConf" />
        <assign name="state0" expr="'conferencedestroyed'" />
      <else/>
        <exit/>         
      </if>
    </transition>   
   
    <transition event="conference.destroyed">
      <exit/>
    </transition>

    <transition event="error.*">
      <log expr="'an error has occurred (' + event$.reason + ')'"/>
      <exit/>
    </transition>

  </eventprocessor>   
</ccxml>


Sample Code, Anyone?

You wanted it, you got it right HERE!




  ANNOTATIONS: EXISTING POSTS
0 posts - click the button below to add a note to this page

login
  Limiting Call length  |  TOC  |  Answering Machine Detection  

© 2008 Voxeo Corporation  |  Voxeo IVR  |  VoiceXML & CCXML IVR Developer Site