In some of our previous posts, we’ve discussed routing two Channel Resources together to allow two different parties to speak to each other. However, sometimes you may need to allow three or more parties to speak to each other at a time.
Voice Elements Platform allows you to do just that — quickly and easily create Conferencing Applications.
All the functionality is there for creating simple conference calls to running complex call centers.
Let’s take a closer look at some sample code that demonstrates how to do the following:
- Get a conference PIN code from a user
- Create a conference
- Add a user to a conference
- Add a monitor to a conference (this is a participant that is muted)
Sample C# Code for an Easy Conference Application
using System; using System.Collections.Generic; using System.Text; using VoiceElements.Client; using VoiceElements.Common; using VoiceElements.Interface; using System.Threading; namespace VoiceApp { public class InboundConference { public ChannelResource ChannelResource { get; set; } public VoiceResource VoiceResource { get; set; } public TelephonyServer TelephonyServer { get; set; } public Log Log { get; set; } public string DeviceName { get; set; } public static Conference Conference { get; set; } public static object SyncVar = new object(); public bool ConferenceStarted = false; private ManualResetEvent m_TerminateCall = new ManualResetEvent(false); public InboundConference(TelephonyServer telephonyServer, ChannelResource channelResource, Log log) { TelephonyServer = telephonyServer; ChannelResource = channelResource; VoiceResource = channelResource.VoiceResource; Log = log; // Subscribe to the Disconnected event so that we know when the user hangs up and can dispose of the necessary resources ChannelResource.Disconnected += new VoiceElements.Client.Disconnected(ChannelResource_Disconnected); } void ChannelResource_Disconnected(object sender, VoiceElements.Client.DisconnectedEventArgs e) { // This will signal to the other thread that the call has disconnected so it may now clean up the associated telephony resources. m_TerminateCall.Set(); } public void RunScript() { try { Log.Write("Starting Script"); ChannelResource.Answer(); VoiceResource.TerminationDigits = "ANY"; int i = 0; for (i = 0; i < 3; i++) { if (i == 0) { VoiceResource.PlayTTS("Please enter your passcode followed by the pound sign"); } else { VoiceResource.PlayTTS("Invalid Conference ID. Please try again. Enter the passcode followed by the pound sign"); } VoiceResource.GetDigits(5, 20, "#", 4, false); string passcode = VoiceResource.DigitBuffer; VoiceResource.WipeDigitBuffer(); if (passcode == "123") { Log.Write("User entered correct passcode"); // You can add logic to do a database lookup instead! break; } } if (i >= 3) { // Disconnect the user because they exceeded the max attempts VoiceResource.PlayTTS("Goodbye!"); ChannelResource.Disconnect(); return; } lock (InboundConference.SyncVar) { // We'll create the conference if it doesn't exist. Otherwise we will add the user to the conference // If you would like to manage multiple conferences .NET Dictionaries come in handy, that way you can do a lookup to see if the conference they are trying to enter already exists. if (InboundConference.Conference == null) { // Get the Conference resource InboundConference.Conference = TelephonyServer.GetConference(); // Subscribe to the conference changed event InboundConference.Conference.ConferenceChanged += new ConferenceChanged(Conference_ConferenceChanged); // Set the ConferenceNotifyMode to On so that we are notified when users enter or leave the conference InboundConference.Conference.ConferenceNotifyMode = ConferenceNotifyMode.On; } } // We will clamp DTMF tones so that way when we add a menu other users won't hear when they press digits ChannelResource.ConferenceAttributes.MemberToneClamp = true; // We will add echo cancellation to improve voice quality ChannelResource.ConferenceAttributes.EchoCancellation = true; // Now we'll add the user to the conference InboundConference.Conference.Add(ChannelResource); // If you would like to add listen only (muted) participants you can user Monitors // Because the audio from monitors is not used for mixing in the conference you can create very large conferences if most of the participants are monitors //InboundConference.Conference.Monitor(ChannelResource); ConferenceStarted = true; // We will wait until the user disconnects before terminating the call m_TerminateCall.WaitOne(); } catch (HangupException hex) { Log.Write("Hangup Detected!"); } catch (Exception ex) { Log.WriteException(ex, "Unexpected Exception"); } finally { Log.Write("Ending call"); try { ChannelResource.Disconnect(); } catch { } try { ChannelResource.Dispose(); } catch { } } } void Conference_ConferenceChanged(ConferenceChangedEventArgs ccea) { Log.WriteWithId(InboundConference.Conference.ConferenceName, "The conference changed. Participants: {0} Monitors: {1}", InboundConference.Conference.Participants.Count, InboundConference.Conference.Monitors.Count); // We want to check to see if there are participants. If there are not we will dispose of the conference. if (!ConferenceStarted) { return; } if (InboundConference.Conference.Participants.Count > 0) { return; } //Unsubscribe from the conference changed event InboundConference.Conference.ConferenceChanged -= new ConferenceChanged(Conference_ConferenceChanged); // Dispose the conference and set to null InboundConference.Conference.Dispose(); InboundConference.Conference = null; } } }
The code above assumes that you have setup your new call event, and will create a new instance of the conference class and call the RunScript method, like below:
static void s_TelephonyServer_NewCall(object sender, VoiceElements.Client.NewCallEventArgs e) { try { InboundConference conference = new InboundConference(s_TelephonyServer, e.ChannelResource, s_Log); conference.RunScript(); } catch (Exception ex) { Log.WriteException(ex, "Unexpected Exception in Newcall!"); } }
Let’s review the main parts of this application:
Get a conference PIN From a User
This application is set up to use a hardcoded conference passcode of 123. However, you can make this as flexible as you would like. For more information on getting digits from a user, please review How to Create A Simple IVR
Create a conference
To create a conference, you need to get an available conference resource from your Telephony Server, like below:
InboundConference.Conference = TelephonyServer.GetConference();
You’ll want to make sure that you use a variable that is accessible from the other calls (which is why we set the conference to a static variable).
Add a User to a Conference
Adding a user to a conference is easy:
// Now we'll add the user to the conference InboundConference.Conference.Add(ChannelResource);
Adding a Monitor to a Conference
Adding a monitor (listen only or muted participant) is also easy:
// Now we'll add the user to the conference InboundConference.Conference.Monitor(ChannelResource);
Add Advanced Functionality
Keep in mind that you can make conferences very advanced by allowing users to enter digits to trigger certain functions such as:
-
- Recording the conference
- Muting certain participants
- Allow users to mute themselves
- Dial out to other users
- Show the speaking activity of certain users
Conferencing also allows you to create advanced call center software that allows certain users to use Coach and Pupil Relationships. These features are useful to allow a supervisor to tell an employee what to do when they are on the phone without allowing a customer to hear.
Want to learn more about Voice Elements Conferencing?
Check out these articles:
Conferencing Overview
Conferencing Tutorial
Conferencing Settings