etIVR4LineBuffers Sample Program

TeleTools

The etIVR4LineBuffers sample program is just like the etIVR4Line sample program but demonstrates playing and recording wave files using memory buffers instead of directly to disk file.  This can increase speed and performance for systems with heavy wave file access.  This program shows one method of building an application that supports multiple telephone devices simultaneously. It is a simple Interactive Voice Response system (IVR) that automatically answers incoming calls, plays and records wave files and responds to DTMF tones.  In addition, this sample program demonstrates how to read back the CallerID number to the caller.

Bookmarks to sections about IVR4Line on this page:

Requirements
Using This Sample Program
Download this Sample Program 
How this Sample Program Works
Source Code
Release Notes

Other links:

Development Environment Technical Information
Telephony Hardware Technical Information

 

Requirements

  • Windows machine

  • TAPI Telephony Device, device capable of multiple lines,  or multiple devices (1,2,3 or 4).  This program will work with only 1 device, but with multiple line devices, it will show you how to create an IVR that can work with multiple lines and multiple callers.  Even two or more voice modems will work, though people with devices such as Dialogic cards will really see how to develop a commercial application.

  • WAVE files in the appropriate format for your device copied to the same folder as this sample program.  NOTE: Dialogic users be sure to download 11kHz samples from HERE

Using This Sample Program

FIRST: Make sure to have your wave files into the same directory as the sample.  If your device does not support 8kHz, 16bit, Mono format, be sure to get other formats from our web site "working with wave files" page.

Each line tab will allow you select a device from the dropdown combobox. You can create a one line Interactive Voice System if you only have one device, or if you have a multi-port line device such as a dialogic card, or multiple devices like 2 or more voice modems, you can see how to use TeleTools to create an IVR that can handle hundreds of simultaneous callers.

Select your device(s) and then activate them by checking the Active checkbox. Press the TeleScope button for each of the lines to popup our powerful testing, prototyping, diagnostic and logging tool that will allow you to monitor and even alter and work with the call progress on each line.

Now simply call into the lines you have activated and listen for the wave greeting.  You will be able to press DTMF digits to play different messages based on your selections while the TeleScope logs show you exactly what is happening.  

The etPlay and etRecord TeleScopes will show you what is going on with wave files and even the details of the wave format and position.  You could use these methods and properties to allow precise positioning of a wave file to allow you to pause, stop, rewind, or even break one wave file up into component parts to play your custom message.  TeleTools makes programming complex applications like IVR's a snap.  Using SAPI, you can even play dynamic Text-To-Speech (TTS) messages as well as recorded wave files.  See our main samples page for more samples and information.

Download this Sample Program

For Use TeleTools v3.7

File

Purpose

EXE Ready to run!  (includes wave files)
Borland Delphi 5,6,7 Source code and wave files
Dialogic Wave files wave files in 11kHz, 8bit, mono format
Tell us what you need? Click here and tell us what you need!

 

How this Sample Program Works

The etLine.Call.Tag property and etLine.OnDigitReceived event are utilized to create a simple "State Machine". See the etLine1.OnDigitReceived event handler routine for more information.

In the Form_Load event handler, a number of global variables are initialized. For each page in the tab control, SetControls is called to make the local Controls variable point to correct controls and initialize the ComboDevice(X) and the etLine(X) control to point to the corresponding device. (e.g. On the first page, the first TAPI line device is selected; on the second page, the second TAPI line device is selected, and so forth.) If there are fewer than four available telephony devices, the pages that are not needed are hidden. In the play and record status fields, the SetPlayRecordDevices routine is called to set the play and record devices associated with the TAPI line device.

Here in Form_Load is where we also load the wave files from disk and place them in buffers.  Here is the code that does the work:

    etPlay1.Source.BufferLoadFromFile("filename")             ' loads a wave file from disk
    giBufferForThisWave = etPlay1.Source.BufferHandle      '  puts the handle to the wave in a variable
    etPlay1.Source.BufferName = "myFileName"                  ' names our buffer for reference

In the even handler for the CheckActive(X).OnClick events of the CheckActive(X) controls, if the control is currently checked, etPlay(X).Device.Active is checked (validated) to see if a wave file is currently playing, if it is, then it is stopped by setting etPlay(X).Device.Active = False. etRecord(X).Device.Active is also checked and stopped if necessary. If the etLine(X).Call.Active property is True then it is set to False, this will cause the etLine(X).Call.Hangup method to be called. The line device is deactivated by setting the property etLine(X).Device.Active = FALSE.

If the CheckActive(X) control is currently unchecked, the TAPI line device is activated by setting etLine(X).Device.Active to True. If the error LINEERR_INVALIDMEDIAMODE is returned when activating the line device, the device is probably not 100% TAPI compliant. The etLine(X).Device.MediaModes.Active is set to LINEMEDIAMODE_DATAMODEM and etLine(X).Device.Active is once again set to True. We are assuming that the device is a modem that it does not support the voice features. Therefore we attempt to activate the modem in data mode. The program will not work properly in this mode.  If you have a voice modem, but it is only being reported as a datamodem, please check the help file or web page for information about "working with modems".

Once the etLine(X).Device has been dealt with, the SetPlayRecordDevices subroutine is called to update the etRecord(X) and etPlay(X) devices to work with the current etLine(X) device settings.

If the property etLine(X).TAPI.TSP contains the string "Universal Modem Driver" then the property etPlay(X).Volume.Enabled is set to false because voice modems do not support the volume features.

In the ComboDevice(X).OnChange events of the ComboDevice(X) controls the etLine(X).Device.Active property is checked to see if the current device is active, if so then CheckActive(X) is set to false causing the device to be deactivated. The etLine(X).Device.ID is set to the index value of the device chosen in the combo box.  In this way, we let you select, change and activate any of the Telephony devices whose TSP is listed in Windows.

In the etLine(X).OnConnected events of the etLine(X) controls. The property etLine(X).Call.MonitorDigits.Active property is set to True to begin monitoring for digits. The buffers are played with the following code for each of the controls:

    etPlay.Source.Buffer.Handle := giBufferForThisWave;  ' gets our handle to memory for the wave audio
    etPlay.Source.Buffer.Active := True
;                            ' plays the wave data in the buffer to the device

The etPlay(X).Device.Loop property is set to false so that this file will play only once. 

See the etPlay1Done event to find out what happened when a wave file is finished playing.

In etLine(X).OnDigitsReceived event handlers of the etLine(X) controls, the etPlay(X).Device.Active property is set to False to stop any wave files from playing. If an error occurs then the call is hung up by calling the method etLine(X).Call.Hangup. The etLine(X).Call.Tag property is then inspected and the correct action is taken based on the logic explained below.

If the Tag indicates that the line is currently recording (etLine(X).Call.Tag = TAG_RECORDING), then the recoding is stopped by setting etRecord(X).Device.Active = False. The file is then replayed by setting the etPlay.Source.BufferHandle property.  If there is an error, we try to play using direct file access instead of buffers by setting etPlay.Source.BufferActive = False and then setting etPlay(X).Source.FileName to the value in etRecord(X).Source.FileName. The etLine(X).Call.Tag property is set to TAG_WAVEPLAY, which tells the application to play the wave file at the end of this routine. If an error occurred when setting etRecord(X).Device.Active = False, then the DisplayRecordError routine is called.

If menu was playing when the user pressed a key (etLine(X).Call.Tag = TAG_MENU), we respond to the pressed key as follows:

  • If the Digit parameter is '1', the etLine(X).Call.CallerID information is played back in the form of wave files. The etLine(X).Call.Tag property is set to TAG_WAVEPLAY which tells the application to play the wave file at the end of this routine
  • If the Digit parameter is '2', '3',  or '4', then a corresponding wave file is played back to the caller using etPlay.Source.Buffer.Handle = giBufferMenuOpt(X). The etLine(X).Call.Tag property is set to TAG_WAVEPLAY which tells the application to play the wave file at the end of this routine.
  • If the Digit parameter is '5', then etRecord(X) will be used to record. The property etRecord(X).Source.FormatID is set to the correct wave format. (The formats we use are defined in etTTConst file note: for more information about wave formats see the sample program etWaveFormats). The property etRecord(X).Source.FileName is set to a name based on the TAPI line device currently selected. Recording begins by setting etRecord(X).Device.Active = TRUE. Recall that when another digit is received that recording is stopped and the wave file is played back. The property etLine(X).Call.Tag is set to TAG_RECORDING.
  • If the Digit parameter is '#' key, the etLine(X).Call.Hangup method is called. First recording or playing of wave files is stopped by setting Device.Active to False for the etRecord(X) and etPlay(X) controls.
  • If the Digit parameter is any other value then the wave file(s) stored in gsMenu will be played.

If the etLine(X).Call.Tag property has the value of TAG_MENU or TAG_WAVEPLAY then the file in the etPlay(X).Source.Buffer will be played.

In the OnDisconnected event handler, if the etPlay1.Device.Active property is True, then a wave file is currently playing and must be stopped by setting etPlay1.Device.Active = False. The etLine1.Call.Hangup method is called to hang up the call.

If the Count parameter in the OnRing event handler is greater than 2, then the etLine(X).Call.Answer method is called to answer the call.  This is how we automatically answer the call after 3 rings.

In the OnDone event handler, if the property etLine(X).Call.State is equal to LINECALLSTATE_CONNECTED, then the call is still connected, and if the etPlay(X).Device.Loop property is False, then the menu wave files will be played next.

The OnClose Event. The etRecord(X).Device.Active and etPlay(X).Device.Active properties are set to False for all lines. This causes all recording and play to stop. The etLine(X).Call.Hangup method is called for each line which, causes all calls to hang up. The etLine(X).Device.Active property are set to False for all line device causing all devices to be deactivated.

The subroutine SetPlayRecordDevices sets the ID's for the play and record devices associated with your line devices. This is done by evaluating the properties etLine(X).WavePlay.Available and etLine(X).WaveRecord.Available, which will be True if Play or Record is supported and False if they are not. etPlay(X).Device.ID is set to etLine(X).WavePlay.ID and etRecord(X).Device.ID is set to etLine(X).WaveRecord.ID in order to select the wave devices associated to the line device. The LabelPlayDevice(X) control is updated with the etPlay(X).Device.Name and LabelRecordDevice(X) control is updated with the etRecord(X).Device.Name

CommandTeleScope(X).OnClick events of the CommandTeleScope(X) controls: This button causes the TeleScope.Visible properties to be toggled for the etLine(X), etPlay(X) and etRecord(X) controls. This causes the TeleScopes to be displayed or hidden.

The controls below containing (X) should be set with the name of the control ending in a digit (X) corresponding to the line its associated with.  For example for line 1, the CheckActive control would be CheckActive(1).

Control

Description

PageControl1 This control has 4 tabs, one for each TAPI line device.
CheckActive(X) Used to activate the TAPI Line device.
ComboDevice(X) Used to select the TAPI line device.
CommandTeleScope(X) When clicked the TeleScope.Visible property for the etLine, etPlay and etRecord controls are toggled to True or False causing the TeleScopes to be displayed or hidden.
LabelPlay(X) Displays "Play"
LabelPlayDevice(X) Displays the wave play associated with the TAPI line device.
LabelRecord(X) Displays "Record"
LabelRecordDevice(X) Displays the wave record associated with the TAPI line device.
LabelStatus(X) Displays the current status of the Call, Line, Play and Record
LabelLineStatus(X) Displays "Status"
etLine(X) The etLine control
etRecord(X) The etRecord control
etPlay(X) The etPlay control

 

Event Handler Routine

Description

etLine1_OnConnected

Event Handler Routine for: the etLine(X).OnConnected events of the etLine(X) controls.  A call is recognized as connected

etLine1_OnDigitReceived

Event Handler Routine for: the etLine(X).OnDigitsReceived events of the etLine(X) controls.  A DTMF digit has been detected

etLine1_OnDisconnected

Event Handler Routine for: the etLine(X).OnDisconnected events of the etLine(X) controls. The remote party has disconnected the call

etLine1_OnRing

Event Handler Routine for: the etLine(X).OnRing events of the etLine(X) controls. An incoming ring has been detected on the line device

etPlay1_OnDone

Event Handler Routine for: the etPlay(X).OnDone events of the etPlay(X) controls.  etPlay reports that the wave file has finished playing

Form_Unload

Event Handler Routine for: closing of the form. The etRecord(X).Device.Active and etPlay(X).Device.Active properties are set to False for all lines. 

Form_Load

Event Handler Routine for: creation of the form. A number of global variables are initialized. 

CheckActive_OnClick

Event Handler Routine for: the CheckActive(X).OnClick events of the CheckActive(X) controls. The code here checks to see if a wave file is playing, and stops the file before then deactivating the line device.

ComboDevice_OnClick

Event Handler Routine for: the ComboDevice(X).OnChange events of the ComboDevice(X) controls. The etLine(X).Device.Active property is checked to see if the current device is active, if so then CheckActive(X) is set to false causing the device to be deactivated. The etLine(X).Device.ID is set to the index value of the device chosen in the combo box.

CommandTeleScope_OnClick

Event Handler Routine for: the CommandTeleScope(X).OnClick events of the CommandTeleScope(X) controls. This button causes the TeleScope.Visible properties to be toggled for the etLine(X), etPlay(X) and etRecord(X) controls. This causes the TeleScopes to be displayed or hidden.

 

Subroutine

Description

SetLineDevice

This routine is used to set the etLine(X).Device.ID to a given TAPI line device.

SetPlayRecordDevices

This function tests to see if the current etLine(X) device supports playing and/or recording files. This is done by evaluating the properties etLine(X).WavePlay.Available and etLine(X).WaveRecord.Available

SetControls

This routine is used by the Delphi version of the etIVR4LineBuffers sample program to relate the controls. This routine is called by all other Event Handler Routines.

This routine uses the Sender parameter to set the remaining parameters to the related controls. This is one of the two routines used to relate controls to one another in order to make sharing code easy. This is just one example of how to share code. This method was chosen because it is relatively easy for both novice and expert programmers to understand.

Display[X]Error

The DisplayLineError, DisplayPlayError, and DisplayRecordError are used to test for errors and display them in a dialog box.

 

Release Notes

April 29, 2003

Published