<%@ page language="java" import="java.io.*, java.net.*, java.util.*, javax.xml.parsers.*, org.w3c.dom.*, com.cisco.ipphone.sdk.*, com.cisco.ipphone.sdk.mconference.*" %>

<%

///////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Title:  		MConference
// Author: 		kstearns
// Source File(s):  mconference.jsp
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Description:
//
// MConference is a sample application which allows users to create, join, and control IP multicast conferences
// from an XML phone service.
//
// The primary objective of this application is to provide an example of a large-scale (thousands of participants), arbitrated conference
// which is primarily one-way in nature.
// Conference arbitration can be enabled/disabled by the conference owner. When arbitration is
// enabled participants must request permission which is then granted by the conference owner.
// When conference arbitration is disabled, participants can simply push-to-talk similar to a
// hoot-and-holler network.
//
///////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Requirements and Caveats:
//
// -  Client: Cisco IP Phone XSI Browser
//
// - All phones using the MConference application should be associated to a valid user in the LDAP directory.
//   This is not strictly required to work, but if the userID for a phone cannot be identified it will appear as 'unknown'.
//
// - In order for MConference to work, the PUSH userID and PUSH password hard-coded below
//   MUST have authority to PUSH to all phones used by the application.
//   For example, a new application user ID of 'sdkapps' could be created in the Global Directory.
//   All phones using the application are then selected as Associated Devices for user 'sdkapps'.
//
//   NOTE: For large-scale PUSH applications, associating hundreds or even thousands of devices to a single user
//         (for purposes of PUSH authentication) is *NOT ACCEPTABLE*.
//         In this case, the PUSH authentication *MUST* be offloaded from the CallManager server to an external
//         web server - see the PushAuthenticate ASP sample script for more information.
//
// - MConference is designed to support a maximum of 256 active conferences. This could be easily extended thru
//   code modifications. In reality, only 100 Conferences can be used, since the IP phones aren't capable
//   of displaying more than 100 menu options. This could be easily overcome be adding a paging feature to the
//   phone, but probably isn't practical because of the cumbersome phone UI - even 100 is too many to scroll thru.
//   A better solution would be to create administrative groups which would filter and display only those
//   Conferences pertinent to the user.
//
// - MConference has been designed to work properly with Extension Mobility.
//
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

//
//  Edit the following Strings for your environment.
//  This is for sample purposes only - placing passwords and other
//  sensitive information in an open text file is obviously NOT recommended !!!
//

String ldapServer = "10.32.250.141";
int ldapPort = 8404;
String ldapRoot = "o=cisco.com";
String ldapUserId = "cn=Directory Manager, o=cisco.com";
String ldapPassword = "c1sc0";

String callManager = "10.32.250.141";
String callManagerUserId = "administrator";
String callManagerPassword = "c1sc0";

String pushUserId = "sdkapps";
String pushPassword = "sdkapps";
String extMobUserId = pushUserId;
String extMobPassword = pushPassword;
String[] excludedUsers = { pushUserId };

String ipmcPrefix = "239.0.0.";

String thisServer = InetAddress.getLocalHost().getHostAddress();
String thisPath = request.getRequestURI();
int thisPort = request.getServerPort();
thisPort = 8080;
String thisPage = "http://" + thisServer + ":" + thisPort + thisPath;
String remoteIP = request.getRemoteAddr();

//////////////////////////////////////////////////////////////////////////////////////////////////////

//  The "conference" querystring parameter is passed between nearly all pages to reference a specific
//  conference number. Notice that this could also be accomplished via Session-scoped variables, but
//  my design goal was to make the application as scalable as absolutely possible - eliminating Session
//  state on the web server by passing querystring parameters helps with that objective.

int i = 0;
int conf = -1;
if (request.getParameter("conference") != null) {
  conf = Integer.parseInt(request.getParameter("conference"));
}

response.setContentType("text/xml");
response.addHeader("Cache-control", "no-cache");

//  Create the necessary service providers to handle the lookup requests

LDAPProvider ldapProv = new LDAPProvider(ldapServer, ldapUserId, ldapPassword, ldapPort, ldapRoot);
EMProvider emProv = new EMProvider(callManager, callManagerUserId, callManagerPassword, extMobUserId, extMobPassword);

  // The old IPAddressProvider was used on older CallManager servers that only supported the DeviceListX page
  // Recent CUCM versions support the new RIS interface for realtime information
  // IPAddressProvider ipProv = new IPAddressProvider(callManager, callManagerUserId, callManagerPassword);
 IPAddressProviderIF ipProv = new RisProvider(callManager, callManagerUserId, callManagerPassword);

//  Get a reference to the ConferenceManager object - this provides access
//  to all of the current conference state information

ConferenceManager theCM = ConferenceManager.getConferenceManager();

//  Also get references to the list of conferences as well as the currently
//  requested conference (based on the 'conference' querystring parameter).

ConferenceManager.Conference[] theConferences = theCM.getConferences();
ConferenceManager.Conference thisConference = null;

for (i=0; i < theConferences.length; i++) {
  if (theConferences[i].getId() == conf) {
    thisConference = theConferences[i];
  }
}

//  If no 'action' was specified in the URL, then just set it to 'main' to display the main page

String action = request.getParameter("action");
if (action == null) {
  action="main";
}

//////////////////////////////////////////////////////////////////////////////////////

if (action.equals("main")) {

  // List the available conferences and actions
  %>
  <CiscoIPPhoneMenu>
    <Title>MConference</Title>
    <Prompt>Select a Conference</Prompt>
  <%
  for (i=0; i < theConferences.length; i++) {
    out.println("<MenuItem><Name>" + theConferences[i].getName() + " (" + theConferences[i].getOwner() + ")</Name>");
    out.println("<URL>QueryStringParam:conference=" + theConferences[i].getId() + "</URL></MenuItem>");
  }
  %>
  <SoftKeyItem>
    <Name>Join</Name>
    <URL><%=thisPage%>?action=join</URL>
    <Position>1</Position>
  </SoftKeyItem>
  <SoftKeyItem>
    <Name>Delete</Name>
    <URL><%=thisPage%>?action=delete</URL>
    <Position>2</Position>
  </SoftKeyItem>
  <SoftKeyItem>
    <Name>New</Name>
    <URL><%=thisPage%>?action=createinput</URL>
    <Position>3</Position>
  </SoftKeyItem>
  <SoftKeyItem>
    <Name>Exit</Name>
    <URL>SoftKey:Exit</URL>
    <Position>4</Position>
  </SoftKeyItem>
  </CiscoIPPhoneMenu>
  <%
}

//////////////////////////////////////////////////////////////////////////////////////

if (action.equals("join")) {
  response.addHeader("Expires", "Thur, 23 Aug 2001 10:00:00 GMT");
  String rxUri = "RTPMRx:" + ipmcPrefix + thisConference.getIpmcAddr() + ":20480";
  %>
  <CiscoIPPhoneExecute>
    <ExecuteItem URL="<%=thisPage%>?action=join_response&amp;conference=<%=conf%>"/>
    <ExecuteItem URL="<%=rxUri%>"/>
  </CiscoIPPhoneExecute>
  <%
}

//////////////////////////////////////////////////////////////////////////////////////

if (action.equals("join_response")) {
  response.addHeader("Expires", "Thur, 23 Aug 2001 10:00:00 GMT");
  if (thisConference != null) {
    //  If that conference exists, then get the IPMc address used for the conference
    if (remoteIP.equals(thisConference.getOwnerIP()))
    {
      //  If this user is the Owner of the conference, join them as the Owner
      %>
      <CiscoIPPhoneText>
      <Title>MConference</Title>
      <Text>You are joined as the Owner of conference:
<%=thisConference.getName()%> (<%=thisConference.getOwner()%>)</Text>
      <Prompt>Select an option</Prompt>
      <SoftKeyItem>
       <Name>Talk</Name>
       <URL>RTPMTx:<%=ipmcPrefix + thisConference.getIpmcAddr() + ":20480"%></URL>
       <Position>1</Position>
      </SoftKeyItem>
      <SoftKeyItem>
       <Name>Mute</Name>
       <URL>RTPMTx:Stop</URL>
       <Position>2</Position>
      </SoftKeyItem>
      <SoftKeyItem>
       <Name>Manage</Name>
       <URL><%=thisPage%>?action=talkers&amp;conference=<%=conf%></URL>
       <Position>3</Position>
      </SoftKeyItem>
      <SoftKeyItem>
       <Name>HangUp</Name>
       <URL><%=thisPage%>?action=hangup&amp;conference=<%=conf%></URL>
       <Position>4</Position>
      </SoftKeyItem>
      </CiscoIPPhoneText>
      <%
    }
    else
    {
      //  Otherwise, join them as a participant

      Phone thePhone = ipProv.getPhone(remoteIP);

      //  Get the user logged into or associated with this device
      //  If it can't be found, use their IP address as their name.

      String userName = "";
      if (thePhone != null) {
        User theUser = thePhone.getCurrentExtMobUser(emProv);
        if (theUser == null) {
          User[] users = thePhone.getControllingUsers(ldapProv, excludedUsers);
          if (users.length != 0) {
            theUser = users[0];
          }
        }
        if (theUser != null) {
          theUser.loadAttributes(ldapProv);
          if (theUser.getFirstName() != null) {
            userName = userName + theUser.getFirstName();
          }
          if (theUser.getLastName() != null) {
            userName = userName + " " + theUser.getLastName();
          }
        }
      }
      if (userName.equals("")) {
        userName = remoteIP;
      }
      userName = URLEncoder.encode(userName, "UTF-8");

      out.println("<CiscoIPPhoneText>");
      out.println("<Title>MConference</Title>");
      out.println("<Prompt>Select an option</Prompt>");
      out.println("<Text>You have joined conference:\r\n"+thisConference.getName()+" ("+thisConference.getOwner()+")\r\n");

      if (thisConference.arbitrated) {
        out.println("Press 'TalkReq' to Request\r\npermission to Talk</Text>");
        out.println("<SoftKeyItem>");
        out.println("<Name>TalkReq</Name>");
        out.println("<URL>"+thisPage+"?action=talkrequest&amp;conference="+conf+"&amp;talker="+userName+"</URL>");
      }
      else {
        out.println("Press and hold 'Talk' to talk</Text>");
        out.println("<SoftKeyItem>");
        out.println("<Name>Talk</Name>");
        out.println("<URL>"+thisPage+"?action=talkstop&amp;conference="+conf+"&amp;talker="+userName+"</URL>");
        out.println("<URLDown>"+thisPage+"?action=talkstart&amp;conference="+conf+"&amp;talker="+userName+"</URLDown>");
      }
      %>
      <Position>1</Position>
      </SoftKeyItem>
      <SoftKeyItem>
       <Name>HangUp</Name>
       <URL><%=thisPage%>?action=hangup&amp;conference=<%=conf%></URL>
       <Position>4</Position>
      </SoftKeyItem>
      </CiscoIPPhoneText>
      <%
    }
  }
}


//////////////////////////////////////////////////////////////////////////////////////

if (action.equals("hangup")) {
  response.addHeader("Expires", "Thur, 23 Aug 2001 10:00:00 GMT");
  %>
  <CiscoIPPhoneExecute>
    <ExecuteItem URL="<%=thisPage%>?action=hangup_response"/>
    <ExecuteItem URL="RTPMRx:Stop"/>
    <ExecuteItem URL="RTPMTx:Stop"/>
  </CiscoIPPhoneExecute>
  <%
}

if (action.equals("hangup_response")) {
  response.addHeader("Expires", "Thur, 23 Aug 2001 10:00:00 GMT");

  //  Instruct the ConferenceManager to remove the current user from the Requests and Talkers tables
  //  If they weren't currently Talking or Requesting to Talk, the request gets ignored

  theCM.removeTalker(conf, remoteIP);
  theCM.removeTalkRequest(conf, remoteIP);

  //  Refresh back to main page after 2 seconds

  response.addHeader("Refresh", "2;URL=" + thisPage);

  %>
  <CiscoIPPhoneText>
   <Title>MConference</Title>
   <Text>You have left the conference.</Text>
   <Prompt></Prompt>
   <SoftKeyItem>
    <Name></Name>
    <URL></URL>
    <Position>1</Position>
   </SoftKeyItem>
  </CiscoIPPhoneText>
  <%
}


//////////////////////////////////////////////////////////////////////////////////////

if (action.equals("createinput")) {
  response.addHeader("Expires", "Thur, 23 Aug 2001 10:00:00 GMT");

  //  Input page to collect conference information

  %>
  <CiscoIPPhoneInput>
    <Title>MConference</Title>
    <Prompt>Enter Conference Info</Prompt>
    <URL><%=thisPage%>?action=create</URL>
    <InputItem>
      <DisplayName>Name</DisplayName>
      <QueryStringParam>conferencename</QueryStringParam>
      <DefaultValue></DefaultValue>
      <InputFlags>A</InputFlags>
    </InputItem>
  </CiscoIPPhoneInput>
  <%
}


//////////////////////////////////////////////////////////////////////////////////////

if (action.equals("create")) {
  response.addHeader("Expires", "Thur, 23 Aug 2001 10:00:00 GMT");

  Phone thePhone = ipProv.getPhone(remoteIP);

  String conferenceName = request.getParameter("conferencename");
  if (conferenceName == null) conferenceName = " ";

  //  Get the user logged into or associated with this device
  //  If it can't be found, use their IP address as their name.

  String userName = "";
  if (thePhone != null) {
    User theUser = thePhone.getCurrentExtMobUser(emProv);
    if (theUser == null) {
      User[] users = thePhone.getControllingUsers(ldapProv, excludedUsers);
      if (users.length != 0) {
        theUser = users[0];
      }
    }
    if (theUser != null) {
      theUser.loadAttributes(ldapProv);
      if (theUser.getFirstName() != null) {
        userName = userName + theUser.getFirstName();
      }
      if (theUser.getLastName() != null) {
        userName = userName + " " + theUser.getLastName();
      }
    }
  }
  if (userName.equals("")) {
    userName = remoteIP;
  }

  ConferenceManager.Conference newConf = theCM.createConference(conferenceName, userName, remoteIP);
  if (newConf != null) {
    response.addHeader("Refresh", "3;URL=" + thisPage + "?action=main");
    %>
    <CiscoIPPhoneText>
    <Title>MConference</Title>
    <Text>Successfully created conference: <%=conferenceName%> (<%=userName%>)</Text>
    <Prompt>Select an option</Prompt>
    </CiscoIPPhoneText>
    <%
  }
  else {
    response.addHeader("Refresh", "3;URL=" + thisPage);
    %>
    <CiscoIPPhoneText>
    <Title>MConference</Title>
    <Text>Max number of Conferences exceeded. Create Conference failed.</Text>
    <Prompt></Prompt>
    </CiscoIPPhoneText>
    <%
  }
}


//////////////////////////////////////////////////////////////////////////////////////

if (action.equals("delete")) {
  response.addHeader("Expires", "Thur, 23 Aug 2001 10:00:00 GMT");

  //  Refresh back to the Delete List after deleting this conference

  response.addHeader("Refresh", "3;URL=" + thisPage + "?action=main");

  //  Instruct the ConfernceManager to delete the conference

  ConferenceManager.Conference deleted = theCM.deleteConference(conf);
  String delName = "";
  String delOwner = "";
  if (deleted != null) {
    delName = deleted.getName();
    delOwner = deleted.getOwner();
  }
  %>
  <CiscoIPPhoneText>
    <Title>MConference</Title>
    <Text>You have deleted
<%=delName%> (<%=delOwner%>)</Text>
    <Prompt>Select an option</Prompt>
  </CiscoIPPhoneText>
  <%
}

//////////////////////////////////////////////////////////////////////////////////////

if (action.equals("talkrequest")) {
  response.addHeader("Expires", "Thur, 23 Aug 2001 10:00:00 GMT");
  if (!thisConference.arbitrated) {
    response.sendRedirect(thisPage+"?action=join&conference="+conf);
  }

  String talker = request.getParameter("talker");

  //  Add a Request to Talk

  theCM.addTalkRequest(conf, new Participant(talker, remoteIP));
  Phone.push(thisPage+"?conference="+conf+"&amp;action=requests", thisConference.getOwnerIP(), pushUserId, pushPassword, false);

  %>
  <CiscoIPPhoneText>
    <Title>MConference</Title>
    <Text>Your request to Talk
has been sent.

    Please wait for a reply ...</Text>
    <Prompt>Select an option</Prompt>
    <SoftKeyItem>
     <Name>HangUp</Name>
     <URL><%=thisPage%>?action=hangup&amp;conference=<%=conf%></URL>
     <Position>4</Position>
    </SoftKeyItem>

  </CiscoIPPhoneText>
  <%

}

//////////////////////////////////////////////////////////////////////////////////////

if (action.equals("requests")) {
  response.addHeader("Expires", "Thur, 23 Aug 2001 10:00:00 GMT");

  //  Query the ConferenceManager for current Requests for this conference

  Participant[] requests = theCM.getTalkRequests(conf);

  //  If there are Requests to Talk for this conference, then list them in a menu with the option to Permit
  if (requests.length != 0) {
    %>
    <CiscoIPPhoneMenu>
      <Title>MConference: Requests</Title>
      <Prompt>Select an Option</Prompt>
    <%
    for (i=0; i < requests.length; i++) {
      out.println("<MenuItem><Name>" + requests[i].name + "</Name>");
      String userName = URLEncoder.encode(requests[i].name, "UTF-8");
      out.println("<URL>" + thisPage + "?action=talkpermit&amp;conference=" + conf + "&amp;talker=" + userName + "&amp;talkerIP=" + requests[i].ipAddress + "</URL></MenuItem>");
    }
    %>
    <SoftKeyItem>
    <Name>Permit</Name>
    <URL>SoftKey:Select</URL>
    <Position>1</Position>
    </SoftKeyItem>
    <%
  }
  else {
    %>
    <CiscoIPPhoneText>
     <Title>MConference: Requests</Title>
     <Text>No Requests to Talk</Text>
     <Prompt>Select an Option</Prompt>
    <%
  }
  out.println("<SoftKeyItem>");
  if (thisConference.arbitrated) {
    out.println("<Name>ArbOff</Name>");
  }
  else {
    out.println("<Name>ArbOn</Name>");
  }
  out.println("<URL>"+thisPage+"?action=arb&amp;conference="+conf+"&amp;source=requests</URL>");

  %>
  <Position>3</Position>
  </SoftKeyItem>
  <SoftKeyItem>
  <Name>Talkers</Name>
  <URL><%=thisPage%>?action=talkers&amp;conference=<%=conf%></URL>
  <Position>2</Position>
  </SoftKeyItem>
  <SoftKeyItem>
  <Name>Back</Name>
  <URL><%=thisPage%>?action=join&amp;conference=<%=conf%></URL>
  <Position>4</Position>
  </SoftKeyItem>
  <%
  out.println((requests.length !=0) ? "</CiscoIPPhoneMenu" : "</CiscoIPPhoneText");
}

//////////////////////////////////////////////////////////////////////////

if (action.equals("talkers")) {
  response.addHeader("Expires", "Thur, 23 Aug 2001 10:00:00 GMT");

  //  Refresh this page every 5 seconds

  response.addHeader("Refresh", "5;URL=" + thisPage + "?action=talkers&conference=" + String.valueOf(conf));

  //  Query the ConferenceManager for a list of current Talkers for this conference

  Participant[] talkers = theCM.getTalkers(conf);

  if (talkers.length != 0) {
    %>
    <CiscoIPPhoneMenu>
      <Title>MConference: Talkers</Title>
      <Prompt>Select an Option</Prompt>
    <%
    for (i=0; i < talkers.length; i++) {
      out.println("<MenuItem><Name>" + talkers[i].name + "</Name>");
      out.println("<URL>" + thisPage + "?action=ownerendtalk&amp;conference=" + conf + "&amp;talkerIP=" + talkers[i].ipAddress + "</URL></MenuItem>");
    }
    %>
    <SoftKeyItem>
      <Name>Mute</Name>
      <URL>SoftKey:Select</URL>
      <Position>1</Position>
    </SoftKeyItem>
    <%
  }
  else {

    //  If there aren't any Talkers, inform the Owner

    %>
    <CiscoIPPhoneText>
     <Title>MConference: Talkers</Title>
     <Text>No Talkers</Text>
     <Prompt>Select an Option</Prompt>
    <%
  }
  out.println("<SoftKeyItem>");
  if (thisConference.arbitrated) {
    %>
    <Name>ArbOff</Name>
    <URL><%=thisPage%>?action=arb&amp;conference=<%=conf%>&amp;source=talkers</URL>
    <Position>3</Position>
    </SoftKeyItem>
    <SoftKeyItem>
    <Name>Req'sts</Name>
    <URL><%=thisPage%>?action=requests&amp;conference=<%=conf%></URL>
    <Position>2</Position>
    <%
  }
  else {
    out.println("<Name>ArbOn</Name>");
    out.println("<URL>"+thisPage+"?action=arb&amp;conference="+conf+"&amp;source=talkers</URL>");
    out.println("<Position>3</Position>");
  }
  %>
  </SoftKeyItem>
  <SoftKeyItem>
  <Name>Back</Name>
  <URL><%=thisPage%>?action=join&amp;conference=<%=conf%></URL>
  <Position>4</Position>
  </SoftKeyItem>
  <%
  out.println((talkers.length !=0) ? "</CiscoIPPhoneMenu" : "</CiscoIPPhoneText");
}

//////////////////////////////////////////////////////////////////////////////////////

if (action.equals("talkpermit")) {
  response.addHeader("Expires", "Thur, 23 Aug 2001 10:00:00 GMT");

  //  After Permitting the participant to Talk, go back to the Requests page
  //  Another preference may be to take the Owner to the Talkers page, so they can see that the participant
  /////  has been added as a Talker - just change the action=requests to action=talkers if desired.

  response.addHeader("Refresh", "3;URL=" + thisPage + "?action=requests&conference=" + conf);

  //  Grab the name and IP address of the participant to be added as a Talker

  String talker = request.getParameter("talker");
  String talkerIP = request.getParameter("talkerIP");

  if (thisConference != null) {
    // PUSH commands to the participant's phone allowing the option to Talk
    // Also play a short tone to get the User's attention

    String talkerParam = URLEncoder.encode(talker, "UTF-8");
    String[] uris = { thisPage+"?action=talk&amp;conference="+conf+"&amp;talker="+talkerParam, "Play:vibe.raw" };
    Phone.push(uris, talkerIP, pushUserId, pushPassword, false);
  }

  %>
  <CiscoIPPhoneText>
    <Title>MConference</Title>
    <Text>You have granted <%=talker%> permission to Talk.</Text>
    <Prompt></Prompt>
  </CiscoIPPhoneText>
  <%

}


//////////////////////////////////////////////////////////////////////////////////////

if (action.equals("talkstart")) {
  response.addHeader("Expires", "Thur, 23 Aug 2001 10:00:00 GMT");

  if (thisConference.arbitrated) {
    response.sendRedirect(thisPage+"?action=join&conference="+conf);
  }
  String talker = request.getParameter("talker");
  theCM.addTalker(conf, new Participant(talker, remoteIP));
  Phone.push(thisPage+"?conference="+conf+"&amp;action=talkers", thisConference.getOwnerIP(), pushUserId, pushPassword, false);
  %>
  <CiscoIPPhoneExecute>
    <ExecuteItem URL="RTPMTx:<%=ipmcPrefix + thisConference.getIpmcAddr()%>:20480"/>
  </CiscoIPPhoneExecute>
  <%
}

if (action.equals("talkstop")) {
  response.addHeader("Expires", "Thur, 23 Aug 2001 10:00:00 GMT");

  if (thisConference.arbitrated) {
    response.sendRedirect(thisPage+"?action=join&conference="+conf);
  }
  theCM.removeTalker(conf, remoteIP);
  %>
  <CiscoIPPhoneExecute>
    <ExecuteItem URL="RTPMTx:Stop"/>
  </CiscoIPPhoneExecute>
  <%
}

if (action.equals("talk")) {
  response.addHeader("Expires", "Thur, 23 Aug 2001 10:00:00 GMT");

  //  This method is called by the participant's phone AFTER the Owner has granted them permission to talk.

  String talker = request.getParameter("talker");

  //  Now that the participant has been granted permission to Talk, remove their Talk Requests
  theCM.removeTalkRequest(conf, remoteIP);
  theCM.addTalker(conf, new Participant(talker, remoteIP));

  String txUri = "RTPMTx:" + ipmcPrefix + thisConference.getIpmcAddr() + ":20480";
  %>
  <CiscoIPPhoneText>
    <Title>MConference</Title>
    <Text>You have been granted
permission to Talk.

Press Speak to begin
and Mute when finished.</Text>
    <Prompt></Prompt>
    <SoftKeyItem>
      <Name>Speak</Name>
      <URL><%=txUri%></URL>
      <Position>1</Position>
    </SoftKeyItem>
    <SoftKeyItem>
      <Name>Mute</Name>
      <URL><%=thisPage%>?action=endtalk&amp;conference=<%=conf%></URL>
      <Position>2</Position>
    </SoftKeyItem>
    <SoftKeyItem>
     <Name>HangUp</Name>
     <URL><%=thisPage%>?action=hangup&amp;conference=<%=conf%></URL>
     <Position>4</Position>
    </SoftKeyItem>
  </CiscoIPPhoneText>
  <%
}

//////////////////////////////////////////////////////////////////////////////////////

if (action.equals("endtalk")) {
  response.addHeader("Expires", "Thur, 23 Aug 2001 10:00:00 GMT");

  //  This method is called by the participant's phone when either they press 'EndTalk' or when
  //  the Owner of the conference chooses to 'Mute' the Talker
  %>
  <CiscoIPPhoneExecute>
    <ExecuteItem URL="<%=thisPage%>?action=endtalk_response&amp;conference=<%=conf%>"/>
    <ExecuteItem URL="RTPMTx:Stop"/>
  </CiscoIPPhoneExecute>
  <%
}

if (action.equals("endtalk_response")) {
  response.addHeader("Expires", "Thur, 23 Aug 2001 10:00:00 GMT");

  response.addHeader("Refresh", "3;URL=" + thisPage + "?action=join&conference=" + String.valueOf(conf));

  theCM.removeTalker(conf, remoteIP);

  %>
  <CiscoIPPhoneText>
    <Title>MConference</Title>
    <Text>You have returned to Muted.</Text>
    <Prompt></Prompt>
   <SoftKeyItem>
     <Name>HangUp</Name>
     <URL><%=thisPage%>?action=hangup&amp;conference=<%=conf%></URL>
     <Position>4</Position>
    </SoftKeyItem>
  </CiscoIPPhoneText>
  <%
}

//////////////////////////////////////////////////////////////////////////////////////

if (action.equals("ownerendtalk")) {
  response.addHeader("Expires", "Thur, 23 Aug 2001 10:00:00 GMT");
  //  This method is called by the Owner of the conference when they wish to Mute a Talker

  response.addHeader("Refresh", "3;URL=" + thisPage + "?action=talkers&conference=" + conf);


  //  Get the IP address of the Talker passed from the Talkers list and PUSH a URI command to the
  //  particpant's phone telling it to execute an 'endtalk' action

  String talkerIP = request.getParameter("talkerIP");

  Phone.push(thisPage+"?action=endtalk&amp;conference="+conf, talkerIP, pushUserId, pushPassword, false);

  %>
  <CiscoIPPhoneText>
    <Title>MConference</Title>
    <Text>You have Muted the Talker.</Text>
    <Prompt></Prompt>
  </CiscoIPPhoneText>
  <%
}

//////////////////////////////////////////////////////////////////////////////////////

if (action.equals("arb")) {
  response.addHeader("Expires", "Thur, 23 Aug 2001 10:00:00 GMT");

  // Invert the arbitrated state of the conference
  thisConference.arbitrated = (thisConference.arbitrated) ? false : true;
  // Then redirect back to the calling page
  if (request.getParameter("source").equals("requests")) {
    response.sendRedirect(thisPage+"?action=requests&conference="+conf);
  }
  else {
    response.sendRedirect(thisPage+"?action=talkers&conference="+conf);
  }
}


//  THIS SAMPLE APPLICATION AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND BY CISCO, 
//  EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY
//  FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, SATISFACTORY QUALITY OR ARISING FROM A COURSE
//  OF DEALING, LAW, USAGE, OR TRADE PRACTICE.  CISCO TAKES NO RESPONSIBILITY REGARDING ITS USAGE IN AN
//  APPLICATION., THE APPLICATION IS PROVIDED AS AN EXAMPLE ONLY, THEREFORE CISCO DOES NOT MAKE ANY
//  REPRESENTATIONS REGARDING ITS RELIABILITY, SERVICEABILITY, OR FUNCTION.  IN NO EVENT DOES CISCO
//  WARRANT THAT THE SOFTWARE IS ERROR FREE OR THAT CUSTOMER WILL BE ABLE TO OPERATE THE SOFTWARE WITHOUT
//  PROBLEMS OR INTERRUPTIONS.  NOR DOES CISCO WARRANT THAT THE SOFTWARE OR ANY EQUIPMENT ON WHICH THE
//  SOFTWARE IS USED WILL BE FREE OF VULNERABILITY TO INTRUSION OR ATTACK.  THIS SAMPLE APPLICATION IS
//  NOT SUPPORTED BY CISCO IN ANY MANNER. CISCO DOES NOT ASSUME ANY LIABILITY ARISING FROM THE USE OF THE
//  APPLICATION. FURTHERMORE, IN NO EVENT SHALL CISCO OR ITS SUPPLIERS BE LIABLE FOR ANY INCIDENTAL OR
//  CONSEQUENTIAL DAMAGES, LOST PROFITS, OR LOST DATA, OR ANY OTHER INDIRECT DAMAGES EVEN IF CISCO OR ITS
//  SUPPLIERS HAVE BEEN INFORMED OF THE POSSIBILITY THEREOF.

%>


