Using the Diva Component API
Introduction
About this course
Course Introduction
This course is a 'get you started' course that aims to show you how to
create Visual C# and Visual Basic 2005 programs that use
the Diva family
of analog, ISDN, E1/T1, SS7 hardware adapters and SoftIP Voice over IP virtual adaptersto make or receive voice, data and fax calls.
Note that Diva Client products are not supported.
-
we do not assume knowledge of the underlying communications technologies like ISDN, SS7 or SIP.
-
the sample code provided is intended to be used with Microsoft Visual Basic 2005 or higher or Visual C# 2005 or higher.
-
this course incorporates its own documentation
so that methods and properties in the text can link directly to more detailed information in a pop-up window.
The complete Component Reference Guide is also available in PDF format.
- the course is intended to be used with the Component API that is included with the
Diva SDK Version 4.0 or higher.
-
The Component API is the natural choice for VB programmers.
-
C# programmers can choose between the Component API and the Diva API for .Net.
We will show you:
-
how to create VB and C# programs that make and receive voice, data and fax calls
-
how to create both simple programs that handle one call and more powerful programs that can
handle many simultaneous calls.
Show this course in printer-friendly format
Pre-requisites
Course Pre-requisites
Minimum pre-requisites:
-
To follow this course you need a basic knowledge of Visual Basic 2005 or Visual C# 2005.
To compile the samples you need:
-
A PC running Windows 2000, XP or 2003, with .Net Framework 2.0 and Visual Basic or Visual C# Express Edition
-
Diva SDK 4.0 (or higher) - DsSDK.dll and divaSDK.dll must be present
To run the samples you need:
-
A PC running Windows 2000, XP or 2003, with .Net Framework 2.0
-
A Diva card (with current drivers)
-
Diva SDK 4.0 (or higher) - DsSDK.dll and divaSDK.dll must be present
-
Some of the examples require two connection channels to a public or private network so that you can make a call to yourself
-
Some of the examples receive calls from (or make calls to) a telephone
-
To use the examples with Diva SoftIP you can use a soft-phone VoIP client to call to SoftIP on the same PC
Note: The source code in this training course is provided by Dialogic Corporation "AS IS",
without warranty of any kind, either expressed or implied. Dialogic Corporation shall not be liable
for any damages arising out of your use of the source code in this course, even if it has
been advised of the possibility of such damages.
About the Component API
What is the Component API?
What is the Diva API?
The Diva Component API is a part of the
Diva SDK.
The Diva SDK enables the development of applications that use Dialogic's
Diva hardware adapters
and Diva SoftIP virtual adapters
to implement a wide variety of functionality. Note that
Diva Client products are not supported.
The Diva SDK consists of these three main APIs:
- Diva API - for C and C++ applications
- Diva Component API
- Diva API for .Net
The Diva API is designed to make the Diva family easy to use with Visual C and C++ (see the
Using the Diva API with Visual C++ training course).
The Diva Component API consists of COM components that make using the Diva family
even easier for programming environments that have built-in support for COM such as Visual Basic 6, Visual Basic 2005
and Visual C#.
The current version of the Component API (4.0) has only minor differences in functionality compared
to the Diva API for C++. These differences mainly affect programmers writing passive monitoring
and recording applications.
The Diva API for .Net provides a convenient framework for using all the functionality
of the Diva API for C++ in C# applications.
This option is particularly useful for developers who are writing monitoring applications in C# or for developers
already familiar with using the Diva API with C++ who are now migrating to C# in order to make use of the
.Net Framework.
Which API?
What is the Diva API?
Which API should you choose?
- C and C++ programmers should choose the Diva API
- Visual Basic programmers will almost always choose the Diva Component API
- Visual C# programmers can choose between the Diva API for .Net and the Component API.
-
For many C# programmers the Component API is the easiest and most appropriate choice because it includes almost all
of the functionality of the C/C++ Diva API while encapsulating and hiding most of the complexity within
the Component API objects.
-
C# programmers should choose the Diva API for .Net if they are more comfortable with the
C++ style of API than the Component or object model or if they are implementing an application that requires
functions currently unsupported by the Component API.
Mixing the APIs - using both Diva API for C/C++ and Diva Component API in one application
The SimplePhone sample shows how a Component API program
can use an Audio Provider DLL written in C using the Diva API for C/C++.
The Component API program can handle the high-level functions and the GUI while the Audio Provider handles the time-critical
streaming functions.
How can you use the API?
Applications
Example applications:
-
Unified messaging (UM) server (Fax, email, voicemail, SMS, VoIP).
-
Fax server applications, sending and receiving faxes.
-
Voice applications, making and receiving voice calls over analog, ISDN, E1/T1, SS7 or VoIP connections.
-
Computer telephony integration (CTI) server; for example: DTMF detection, recording and playback of .WAV files.
-
Telephony supplementary services (including line interconnect, conferencing, hold/retrieve, transfer).
The Diva Component API supports both very simple and more complex applications
-
Simple single-call programs can use 'blocking' (also known as 'synchronous') operation
-
More complex multi-call applications can use 'non-blocking' (asynchronous) operation and can use 'events'
-
Fully-scalable applications can be built by defining a 'call-handler' class to handle 120 or more calls
The Diva Component API is a simple, high level API that allows most of the call control offered by
low-level APIs, but with much greater ease-of-use:
-
The programmer does not need detailed knowledge of underlying technology and protocols.
-
Unnecessary communications complexity is hidden from the programmer, allowing the programmer to
concentrate on adding value and speeding development.
-
Default values for method parameters (not available in C#)
make simple applications quick and simple to create and errors are reduced.
-
At the same time, for more advanced applications where more precise control over calls is required,
GetCallProperty
and
SetCallProperty
(new in SDK 4.0) provide access to the same
low-level call properties available in the Diva API for C++
See also:
List of Diva Component API methods
Diva advantages
Diva Advantages
The Diva Component API incorporates all Dialogic's knowledge of ISDN, analog and VoIP protocols
so that you don't need to know about all the protocol variations and possible error
conditions.
-
Diva is a family of mature hardware and software products, approved and sold worldwide.
-
Applications built with the Diva Component API inherit this stability and compatibility.
-
Diva offers solutions from 2 to 120* channels per card and from 2 to 480 channels per PC.
-
All Diva products (apart from Diva Client) use a common hardware and software architecture.
-
All hardware and software products in the Diva family are accessible using the Diva Component API,
with no difference in the way you program for a 2 channel card and a 30 channel card
or for an analog card and an ISDN card
or for a hardware device and a VoIP-based virtual adapter.
-
An application running on an E1/ISDN connection today can run on an E1/SS7 connection tomorrow, with
no changes.
-
An application written for analog, BRI or PRI connections can be moved to VoIP (H.323 or SIP) using
Diva SoftIP
with no changes.
* 96 channels per card in North America.
Preparing to use the API
Installation
Configure Visual Studio
The Diva SDK that contains the API is a
free download
from Dialogic's website.
Two files - dsSDK.DLL and divaSDK.DLL - from the BIN directory in the SDK are required by the Diva Component API. These two DLLs should be copied to
the Windows\SYSTEM32 directory. Additionally, DivaSDK.DLL needs to be 'registered' before it can be used.
Diva API Configuration program
The program '
Config.exe
' is provided in the BIN directory to help you to install the DLLs,
register the DivaSDK.DLL and check the installed versions of the DLLs.
Manual registration of DivaSDK.dll
If you choose not to use the config.exe program to register the DLL, use the following command
in the system32 directory after copying the DivaSDK.dll:
c:\WINNT\system32>regsvr32 DIVASDK.dll
Using Visual Basic or C# with the Diva Component API
-
Select the DivaSDK Type Library as a 'reference' in your Visual Basic or C# project.
This is accomplished from the Project > References menu where you need to select
DivaSDK 1.0 Type Library in the 'COM' tab.
-
Add the statement "Imports DIVASDKlib" (or "using DIVASDKLib" in C#) to your code so that
you don't have to add 'DIVASDKLib' to the
beginning of all Diva Component API references in your program.
Deployment
Deploy
The versions of dsSDK.DLL and DivaSDK.DLL installed on the target system must match the files that you developed with.
When you install the Diva drivers on Windows 2003 or XP a version of the dsSDK.DLL will be automatically
copied to the Windows\SYSTEM32 directory.
When you deploy your application you will need to:
-
copy both the .exe file and the Interop.DIVASDKLib.dll file created automatically by Visual Studio
-
copy the correct version of DivaSDK.DLL
-
check that the version of dsSDK.DLL that is present matches the version of DivaSDK.DLL
Since you cannot always control the version of the
Diva drivers that are installed on the target system
(and therefore the version of dsSDK.DLL will change)
you may decide to ship
the correct versions of both dsSDK.DLL and DivaSDK.DLL with your application and make sure that
they are installed in Windows\system32 replacing the dsSDK.DLL installed with the Diva drivers.
Component API objects
Component API objects
Component API Objects
The objects implemented by the Diva Component API are:
DivaSystem:
The DivaSystem method
GetDevice
provides access to DivaDevice objects so that Diva hardware and software characteristics can be queried.
The DivaSystem method
CreateInstance
creates DivaInstance objects.
DivaInstance:
If you need to create more than one DivaCall object - so that you can handle multiple simultaneous
calls in one multi-threaded program - then you must create all the DivaCall objects using the
CreateCall
method of DivaInstance. The DivaCall objects will inherit the default properties set in the DivaInstance,
but can be overridden.
DivaCall:
Each DivaCall object represents a call and can be used to make an outgoing call or answer an incoming call.
DivaDevice:
DivaDevice allows you to interrogate the Diva hardware or software - each DivaDevice object
represents a Diva line device (or virtual device in the case of SoftIP) and is accessed through
the DivaSystem
GetDevice
method
DivaConference:
allows you to manage a conference with unlimited members.
The conference, including mixing and automatic gain control, is handled by the underlying
Diva communication platform. Members of the conference are of type
DivaCall.
The conference object is created by the
DivaInstance.CreateConference
method
See also: Component API Object Hierarchy diagram
Notes:
-
Simple single-call programs can create a DivaCall object directly - see the following examples -
and don't need to use DivaSystem or DivaInstance. If your program handles two or more simultaneous calls, then
it must use
DivaSystem and
DivaInstance and the
DivaCall
objects must be created using the
CreateCall method of DivaInstance.
-
To interrogate the hardware - to find out how many devices or lines are available, for instance -
use DivaSystem
and DivaDevice.
DivaCall object
DivaCall Object
DivaCall
is the most important object in the Component API and the one that you will use most.
If you haven't already done so, it's worth taking some time now to take a look at the
DivaCall
methods
and
properties
that the Component API makes available.
In addition to these 'standard' properties, access to more low-level call properties is available through
DivaCPT
and the
GetCallProperty
and
SetCallProperty
methods.
Notes:
-
Simple single-call programs can create a DivaCall object directly - see the following examples -
and don't need to use DivaSystem or DivaInstance.
-
If your program handles two or more simultaneous calls, then it must use
DivaSystem and
DivaInstance and the
DivaCall
objects must be created using the
CreateCall method of DivaInstance.
- Where possible, re-use DivaCall objects rather than destroying them and creating new ones.
- If the DivaCall property
SignalEvents
is set to 'True' and you wish to disable the DivaCall object and stop it answering calls, call the
Listen
method with the value
DivaListenServices.DivaListenServiceNone.
-
If you wish to destroy a DivaCall object in your program, be sure to disable it before destroying it:
VB example: (
Show C# version)
' disable the DivaCall and prevent it from anwering calls
res = CallObj.Listen(DivaListenServices.DivaListenServiceNone)
' destroy the DivaCall
CallObj = Nothing
C# example: (
Show VB version)
// disable the DivaCall and prevent it from anwering calls
res = CallObj.Listen(DivaListenServices.DivaListenServiceNone);
// destroy the DivaCall��������������
CallObj = null;
Making and receiving calls
Making and receiving calls
Making a call
Programs and scripts can use the Component API in either 'blocking' or 'non-blocking' mode.
The following examples use 'blocking' mode because this is the simplest. For more complex scripts
and applications 'non-blocking' mode can make it easier to create programs that can cope with unforeseen
sequences of events or errors.
See the section 'Handling multiple calls' for more information.
We can create the DivaCall object directly here because we are handling only one call;
if we were creating more than one DivaCall object then we would have to use
DivaSystem and
DivaInstance and the
DivaCall
objects would be created using the
CreateCall method of DivaInstance.
To make a call
The following code makes a call with
Connect
, plays the wave file with
SendVoiceFile
when the call is answered and
Disconnects.
VB example: (Show C# version)
Imports DivaSDKlib
...
Dim res As DivaResultCodes
Dim num As String = "1234567"
' Single call program, so create DivaCall directly
Dim CallObj As New DivaCall()
res = CallObj.Connect(num)
If res = DivaResultCodes.DivaResultSuccess Then
res = CallObj.SendVoiceFile("defaultgreeting.wav")
' Using synchronous (blocking) mode so next line is executed after
' completion of previous operation
res = CallObj.Disconnect
End If
C# example: (Show VB version)
using DIVASDKLib;
...
DivaResultCodes res ;
String num = "384720";
// Single call program, so create DivaCall directly
DivaCall CallObj = new DivaCall();
res = CallObj.Connect(num, DivaCallTypes.DivaCallType_Voice );
if (res == DivaResultCodes.DivaResultSuccess)
{
res = CallObj.SendVoiceFile("defaultgreeting.wav", DivaAudioFmt.DivaAudioAutodetect);
// Using synchronous (blocking) mode so next line is executed after
// completion of previous operation
res = CallObj.Disconnect();
}
To receive a call
The following code waits for a call using
WaitForCall
and records a wave file with
RecordVoiceFile
when a call is received.
VB example: (Show C# version)
Imports DivaSDKlib
...
Dim res As DivaResultCodes
' Single call program, so create DivaCall directly
Dim CallObj As New DivaCall()
' Using synchronous (blocking) mode with 'WaitForCall' rather than Asynchronous 'Listen'
res = CallObj.WaitForCall
If res = DivaResultCodes.DivaResultSuccess Then
res = CallObj.RecordVoiceFile("myfile.wav")
' Using synchronous (blocking) mode so next line is executed after
' completion of previous operation
res = CallObj.Disconnect
End If
C# example: (Show VB version)
using DIVASDKLib;
...
DivaResultCodes res ;
// Single call program, so create DivaCall directly
DivaCall CallObj = new DivaCall();
// Using synchronous (blocking) mode with 'WaitForCall' rather than Asynchronous 'Listen'
res = CallObj.WaitForCall((int)DivaCallTypes.DivaCallType_Voice, "", 0);
if (res == DivaResultCodes.DivaResultSuccess)
{
res = CallObj.RecordVoiceFile("myfile.wav",DivaAudioFmt.DivaAudioWav_PCM_8K8BitMono, 100, 10, "#");
// Using synchronous (blocking) mode so next line is executed after
// completion of previous operation
res = CallObj.Disconnect();
}
Of course, these samples are too simple for real-life use;
for instance, they do not report to you whether they worked or not.
However, they do show how simple it is to use the Diva Component API.
Samples
Sample code
Template program
Most of the code examples in this course can be run in Visual Basic 2005 Express (or Visual Studio 2005)
by copying the code into the Button1.Click handler of the template program described below.
The template program (
VB source
,
C# source
) includes:
- A form Load handler that runs when the program starts. This
helps reduce the chances of the program crashing by handling the following error conditions:
-
SDK not installed
-
Diva adapter, drivers or virtual adapter are not installed
- A subroutine called 'Log' that logs messages to the list box
The
template form
(image &
VB source
,
C# source
)
contains the following controls which retain their default names:
-
A text box called TextBox1 (textBox1 in C#)
-
not used in every code example; used for the number to call in examples that make outgoing calls
-
A button called Button1 (button1 in C#)
-
A list box called ListBox1 (listBox1 in C#) that contains an activity log
Alternatively, you can
download the
VB source or
C# source for both the template program and the form.
Sample programs
To get you started, we've created two very simple sample programs based
on the template program
(VB source,
C# source)
and template form
(image &
VB source,
C# source)
Note: .Net Framework 2.0 is required to run the executables.
How to compile the samples
Sample code
Before you start:
You don't need a Diva adapter in your development PC to compile these samples but you
do need to install the Diva SDK and register the Component API DLL.
Please check that you have installed the Diva SDK as described in the section
'Preparing to use the API'
in this course.
Using the 'project' downloads
This option is most appropriate for users who are already familiar with using Visual Basic or Visual C# 2005 projects.
-
Download either the
Make call project or the
Answer Call project
-
Extract the files in the compressed folder
-
Open Visual Basic or Visual C# 2005 Express Edition (or Visual Studio) and open the File > Open project... dialog
-
Navigate to the location of the extracted project files, select the MakeCall1.sln (orAnswerCall1.sln) file
and click 'Open'
-
Use the 'Build' menu option to compile the project
Creating a new program in Visual Basic or Visual C# 2005 Express Edition
Use this option if you want to create a Diva Component API project from the beginning yourself.
This option
is most appropriate for those less experienced in using the programming environment and will help you understand how
the project is created.
-
Open Visual Basic or Visual C# 2005 Express Edition (or Visual Studio)
-
Select File > New Project
-
Select 'Windows Application', enter an appropriate name for your new project and click 'OK'.
-
You will be presented with a blank form. Drag from the Toolbox 'Common Controls' section:
- A Button
- A Text box
- A List box
- Arrange and size these controls so that the form looks similar to the
template form;
leave the control names at their default values.
- Switch to 'Code view' (press F7 or select View > Code or right-click on the
form and select 'View Code')
-
Select Project > Add reference... , then select the COM tab. Select
'Diva SDK 1.0 Type Library' and click 'OK'.
-
If the 'Diva SDK 1.0 Type Library' entry is not present in the list,
please check that you have installed the Diva SDK and registered the Component API as
described in the section
'Preparing to use the API'
in this course.
- Cut and paste the whole of one of the samples Make a call
(VB)
(C#)
or Answer a call
(VB)
(C#)
into the source window, replacing the existing contents.
-
Select Build > Build project-name to compile the program
Compiling code examples from the following pages in this course
Follow the same procedure as above, but replace the last two steps with the following three steps:
- Cut and paste the whole of the template program source
(VB)
(C#)
into the source window, replacing the existing contents.
-
Cut and paste the code example into the Button1_Click sub-routine.
-
Select Build > Build project-name to compile the program
Common errors
Namespace or type specified in the Imports 'DivaSDKlib' doesn't contain any
public member or cannot be found...
- you have not added the reference to 'Diva SDK 1.0 Type Library':
Type 'DivaCall' not defined
- you have not coded the 'Imports DivaSDKlib' or 'using DIVASDKLib;' statement.
Other files
You will find other files used by the example code (such as defaultgreeting.wav and faxdoc.tif)
in various places in the samples directory of SDK 4.0. However, so that you don't have to go looking,
zipped archives of these two files are provided here:
Voice, tones, fax & data
Playing a voice file
Send and receive faxes
This code sample shows how
SendVoiceFile
can be used to automatically play a message on connection of a call.
The message
is followed by a tone which in this case is the '*' dial-digit tone, sent using
SendDigits.
Dim res As DivaResultCodes
Dim num As String = "384720"
Dim digits As String = "*"
' Single call program, so create DivaCall directly
Dim CallObj As DivaCall = new DivaCall()
Log("calling " & num)
res = CallObj.Connect ( num )
If res = DivaResultCodes.DivaResultSuccess Then
Log("playing voice file ")
res = CallObj.SendVoiceFile ("defaultgreeting.wav", DivaAudioFmt.DivaAudioAutodetect)
' Using synchronous (blocking) mode so next line is executed after
' completion of previous operation
Log("file played, sending [" & digits & "]")
res = CallObj.SendDigits(digits)
res = CallObj.Disconnect
End If
The Component API will accept .WAV files in μ-law (North America) and A-law (Europe) formats as well as
both 8-bit and 16-bit PCM formats at a sampling rate of 8kHz.
The available formats are enumerated in DivaAudioFmt.
The format of the defaultgreeting.wav file is detected automatically in this case.
The DivaCall object is created directly here because the code handles only one call; to create more than
one DivaCall object in your program use
DivaSystem and
DivaInstance and create the
DivaCall
objects using the
CreateCall method of DivaInstance.
Recording a voice file
Send and receive faxes
The following sample shows the use of
RecordVoiceFile.
This method has three possible ways of determining when the recording should end:
- the total time of the recording
- silence detection
- detection of DTMF dial-digits
In this case, the
RecordVoiceFile will terminate after 30 seconds or when a '*' character is detected. Ten seconds
of silence will also terminate the recording.
The reason for the termination of the recording can be determined from the
result code returned
by the RecordVoiceFile method. For more information, refer to the reference entry for
RecordVoiceFile.
Dim res As DivaResultCodes
' Single call program, so create DivaCall directly
Dim CallObj As DivaCall = new DivaCall()
CallObj.EnableDigitDetection = True
Log("waiting for a voice call")
res = CallObj.WaitForCall
If res = DivaResultCodes.DivaResultSuccess Then
Log("voice call received from " & CallObj.CallingNumber)
res = CallObj.RecordVoiceFile("voicefile.wav", DivaAudioFmt.DivaAudioWav_PCM_8K8BitMono, 30, 10, "*")
' Using synchronous (blocking) mode so next line is executed after
' completion of previous operation
Log("recorded file " & res.ToString)
Log("detected digits: " & CallObj.DetectedDigits)
res = CallObj.Disconnect
Log("disconnected " & res.ToString)
End If
RecordVoiceFile will record .WAV files in μ-law (North America) and A-law (Europe) formats as well as
both 8-bit and 16-bit PCM formats at a sampling rate of 8kHz. In the above example the default format is used.
See the
DivaAudioFmt constants for more information.
The DivaCall object is created directly here because the code handles only one call; to create more than
one DivaCall object in your program use
DivaSystem and
DivaInstance and create the
DivaCall
objects using the
CreateCall method of DivaInstance.
Sending and receiving tones
Send and receive tones
Sending dial-digit tones
The following code sample makes a voice call and sends a string of digits using
DTMF (dual-tone multi-frequency) tones with the
SendDigits
method.
Dim res As DivaResultCodes
Dim num As String = "384720"
Dim digits As String = "*1234#"
' Single call program, so create DivaCall directly
Dim CallObj As DivaCall = new DivaCall()
Log("making voice call to " & num )
res = CallObj.Connect( num )
If res = DivaResultCodes.DivaResultSuccess Then
Log("connected, sending digits " & digits )
res = CallObj.SendDigits(digits)
' Using synchronous (blocking) mode so next line is executed after
' completion of previous operation
Log("digits sent with result " & res.ToString )
res = CallObj.Disconnect
Log( "disconnected with result " & res.ToString )
else
Log("call failed with result " & res.ToString )
End If
Receiving dial-digit tones
The following code sample enables the detection of dial-digit tones by setting the
EnableDigitDetection
property before using the
GetDigits
method with a maximum wait time of 30 seconds.
Dim res As DivaResultCodes
' Single call program, so create DivaCall directly
Set CallObj = CreateObject("DivaSDK.DivaCall")
CallObj.EnableDigitDetection = True
Log("waiting for a voice call")
res = CallObj.WaitForCall
If res = DivaResultCodes.DivaResultSuccess Then
Log("voice call received")
res = CallObj.GetDigits(6, 30, 0, digits)
' Using synchronous (blocking) mode so next line is executed after
' completion of previous operation
Log("received digits " & digits)
res = CallObj.Disconnect
Log("disconnected with result " & res.ToString)
End If
The DivaCall object is created directly here because the code handles only one call; to create more than
one DivaCall object in your program use
DivaSystem and
DivaInstance and create the
DivaCall
objects using the
CreateCall method of DivaInstance.
Sending a fax
Send and receive faxes
The following code uses the optional
CallType
parameter to the
Connect
method to specify that we are making a fax call.
The
SendFax
method automatically converts the .tif file to fax format and transmits it.
See also: Helpweb page about TIFF file formats compatible with fax transmission.
Dim res As DivaResultCodes
Dim num As String = "384720"
' Single call program, so create DivaCall directly
Dim CallObj As DivaCall = new DivaCall()
CallObj.FaxLocalID = "Test fax sender"
CallObj.FaxHeadline = "Diva Component API"
Log("making fax call to " & num)
res = CallObj.Connect(num, DivaCallTypes.DivaCallType_Fax )
If res = DivaResultCodes.DivaResultSuccess Then
Log("connected to " & CallObj.FaxRemoteID & ", sending fax")
res = CallObj.SendFax("FaxDoc.tif")
' Using synchronous (blocking) mode so next line is executed after
' completion of previous operation
Log(CallObj.FaxPages & " pages sent with result " & res.ToString )
res = CallObj.Disconnect
Log("disconnected with result " & res.ToString )
else
Log("call failed with result " & res.ToString)
End If
FaxLocalID
should be set to your local fax number and
FaxHeadline
is the header line printed at the top of the fax page.
Note: The fax parameters
FaxLocalID
and
FaxHeadline
are exchanged with the remote fax machine during the initial connection process so
you must set them before the 'Connect' method is called.
After the Connect has completed, the ID of the remote fax machine is available in the
FaxRemoteID property.
After the fax has been sent the number of pages sent is available in the
FaxPages
property.
The DivaCall object is created directly here because the code handles only one call; to create more than
one DivaCall object in your program use
DivaSystem and
DivaInstance and create the
DivaCall
objects using the
CreateCall method of DivaInstance.
Receiving a fax
Send and receive faxes
The following code uses the optional
CallType
parameter to the
WaitForCall
method to specify that we are waiting for a fax call.
The
ReceiveFax
method automatically converts the received fax to .tif format.
Dim res As DivaResultCodes
' Single call program, so create DivaCall directly
Dim CallObj As DivaCall = new DivaCall()
CallObj.FaxLocalID = "Test fax receiver"
Log("waiting for a fax call")
res = CallObj.WaitForCall( DivaCallTypes.DivaCallType_Fax )
If res = DivaResultCodes.DivaResultSuccess Then
Log("fax call received from " & CallObj.CallingNumber)
Log("ID: " & CallObj.FaxRemoteID )
res = CallObj.ReceiveFax("myfax.tif")
' Using synchronous (blocking) mode so next line is executed after
' completion of previous operation
Log(CallObj.FaxPages & " pages received with result " & res.ToString)
res = CallObj.Disconnect
Log("disconnected with result " & res.ToString)
End If
FaxLocalID
should be set to your local fax number.
Note: The fax parameters
FaxLocalID
and
FaxHeadline
are exchanged with the remote fax machine during the initial connection process so
you must set them before the 'Connect' method is called.
After the
WaitForCall
has completed, the phone number of the remote fax machine is available
in the
CallingNumber
property while the fax ID is available in the
FaxRemoteID property.
After the fax has been received the number of pages received is available in the
FaxPages
property.
The DivaCall object is created directly here because the code handles only one call; to create more than
one DivaCall object in your program use
DivaSystem and
DivaInstance and create the
DivaCall
objects using the
CreateCall method of DivaInstance.
Send data
Send and receive data
The Component API allows you to send and receive 'raw' or 'plain' data over the connection.
This data is not changed or interpreted in any way and can contain any value, including the
hex value X'00'.
To send or receive data the
CallType
must be one of the 'data' CallTypes, such as DivaCallType_Modem or DivaCallType_DigitalData, and
not DivaCallType_Voice or DivaCallType_Fax; it is not possible to send or receive
plain data on a voice or fax call using the Component API.
Dialogic recommends that
applications that perform audio-stream processing should be written using C++ with the
Diva API or Visual C# using the Diva API for .Net rather than the Component API.
Methods are provided for sending and receiving either single bytes or arrays of data.
Both Visual Basic 2005 and C# are able to use the array methods.
The single byte methods are provided for Visual Basic 6 and VBScript, neither of which is
able to use the array methods.
The following code uses the optional
CallType
parameter to the
Connect
method to specify that we are making a digital data call.
Because Visual Basic 2005 supports
the plain data array, this example uses
SendData rather than
SendDataByte.
Dim res As DivaResultCodes
Dim num As String = "1234567"
Dim TxData(10) As Byte
' data array initialised here
' Single call program, so create DivaCall directly
Dim CallObj As DivaCall = new DivaCall()
res = CallObj.Connect( num , DivaCallTypes.DivaCallType_DigitalData)
If res = DivaResultCodes.DivaResultSuccess Then
res = CallObj.SendData( 10, TxData )
' Using synchronous (blocking) mode so next line is executed after
' completion of previous operation
CallObj.Disconnect
End If
The DivaCall object is created directly here because the code handles only one call; to create more than
one DivaCall object in your program use
DivaSystem and
DivaInstance and create the
DivaCall
objects using the
CreateCall method of DivaInstance.
Receive data
Send and receive data
The following code uses the optional
CallType
parameter to the
WaitForCall
method to specify that we are waiting for a digital data call.
Because Visual Basic 2005 supports
the plain data array, this script uses
ReceiveData rather than
ReceiveDataByte which must
be used with VB6 or VBScript.
Dim RxData(10) As Byte
Dim BytesReceived As Integer
Dim res As DivaResultCodes
' Single call program, so create DivaCall directly
Dim CallObj As DivaCall = new DivaCall()
res = CallObj.WaitForCall(DivaCallTypes.DivaCallType_DigitalData)
Log("Connected to " & CallObj.CallingNumber & " call type= " & CallObj.CallType)
res = CallObj.ReceiveData(10, RxData, BytesReceived, 5, 10)
' Using synchronous (blocking) mode so next line is executed after
' completion of previous operation
Log("ReceiveData returned " & res & " Bytes received: " & BytesReceived)
CallObj.Disconnect()
The DivaCall object is created directly here because the code handles only one call; to create more than
one DivaCall object in your program use
DivaSystem and
DivaInstance and create the
DivaCall
objects using the
CreateCall method of DivaInstance.
Accessing the adapters
Get information about Diva adapters
Information about hardware
So far, we have used only the DivaCall component to make and receive single calls.
In order to retrieve information
from the API about the both hardware adapters and virtual adapters (SoftIP)
we need to use the
DivaSystem
and
DivaDevice
components.
The DivaSystem property
TotalChannels
gives us the total number of channels available across all devices and
NumDevices
gives us the number of Diva line devices found in the system.
Note that multi-port Diva adapters show up as one line device per port with the
relevant number of channels.
For example: Diva 4BRI has 4 line devices each with 2 channels;
Diva 2PRI has 2 line devices each with 30 channels on E1 or 24 channels on T1.
The DivaSystem method
GetDevice
is used to retrieve each device in turn so that its
properties
can be examined.
Dim Dev As DivaDevice
Dim i As Integer
Dim Sys As DivaSystem = New DivaSystem()
Log("found " & Sys.NumDevices & " devices")
Log("found " & Sys.TotalChannels & " channels")
For i = 1 To Sys.NumDevices
Dev = Sys.GetDevice(i)
Log("Device: " & i)
Log(" - channels: " & Dev.Channels)
Log(" - SN: " & Dev.SerialNumber)
Log(" - fax: " & Dev.FaxSupported)
Log(" - modem: " & Dev.ModemSupported)
Log(" - A-law: " & Dev.CodecALaw)
Next
Sample code for detecting hardware and virtual adapters and their capabilities
Note: .Net Framework 2.0 is required to run the executable.
Specify the adapter to use
Configure Visual Studio
By default, the Connect method will use the first available channel on the first available Diva device.
To control the device that an outbound call will use, first set the
Device
property of the DivaCall object to the index of the device.
Dim num As String = "384720"
Dim Dev As Integer = 2
' Single call program, so create DivaCall directly
Dim CallObj As DivaCall = New DivaCall()
CallObj.Device = Dev
Log("calling " & num & " on device " & Dev)
res = CallObj.Connect ( num )
By default the
WaitForCall
method
(and the asynchronous
Listen
method that will be described in later sections)
will accept a call on any device. To control the device that an incoming call
will be handled, first set the
Device
property of the DivaCall object to the index of the device.
Dim Dev As Integer = 2
' Single call program, so create DivaCall directly
Dim CallObj As DivaCall = New DivaCall()
CallObj.Device = Dev
log("waiting for a call on device " & Dev)
res = CallObj.WaitForCall
Handling multiple calls
Scalable program architecture
Scalable program architecture
So far, we have only created programs that handle one call.
Now, we will create multi-threaded, multi-call
programs that can fully utilise the capabilities of the Diva adapters.
Multi-call programs
It is possible to create multi-call programs using the Component API with AsyncMode = True
(non-blocking mode) and SignalEvents = True using the same programming techniques we have used
for single-call programs. However, programs like this have limited practical scalability because you have to
code duplicate set of event handlers for each call object. This is the only way to create multi-call programs
in Visual Basic 6, principally because this environment does not provide sufficient support for
multi-threading applications.
Fully-scalable programs using Visual C# and Visual Basic 2005
Visual C# and Visual Basic 2005 do support multi-threading and
allow us to implement fully-scalable multi-call programs in a very convenient and
efficient way using a call-handler class, without mandating the use of non-blocking mode and events and
without having to create duplicate code for each call object.
The technique described here allows us to scale-up the blocking-mode programming techniques
demonstrated on the previous pages of this course to handle 100 or more calls, right up to the limits
imposed by the Diva adapters.
Before we start to describe how to create scalable programs,
there are several pre-requisite topics that we need to introduce or review:
-
Non-blocking (asynchronous) mode - what do we mean by 'blocking' and 'non-blocking'?
-
Events - how do events work in the Component API?
-
Creating more than one DivaCall using the DivaInstance method
CreateCall
-
Using
Listen
rather than
WaitForCall
to prepare DivaCall objects to receive a call
-
Listen is a non-blocking method and
returns immediately
- Listen must be used with
SignalEvents
= True
-
In Visual Basic, the DivaCall must be declared using the parameter 'WithEvents'
- An
OnIncomingCall
handler must be coded to handle the event that is raised when an incoming call is detected
-
Creating the 'call-handler' class
-
The InitializeCall method of the call-handler class is called by the main program to create
the DivaCall and start answering calls on an incoming call channel
-
The TerminateCall method of the call-handler class is called by the main program to 'shut down'
an incoming call channel
These topics are covered in detail on the following pages.
An introduction to non-blocking mode
Blocking and non-blocking mode
Synchronous (Blocking) mode
When operating in synchronous (blocking) mode an application issues a command and does not receive
control back until the command has completed (either with success or failure).
Synchronous (blocking) mode is the default in the Diva Component API, unless overidden as described below.
Asynchronous (Non-blocking) mode
When operating in asynchronous (non-blocking) mode an application issues a command and gets control
back immediately so that it can continue processing other tasks (such as handling other calls).
Asynchronous mode is activated in the Diva Component API by setting the DivaCall property
AsyncMode
to 'True'.
Setting non-blocking or blocking operation
There are two ways of setting the mode of operation in the Component API:
- DivaCall property
AsyncMode
-
CallObj.AsyncMode = False sets blocking (synchronous) mode
-
CallObj.AsyncMode = True sets non-blocking (asynchronous) mode
- The first parameter of the
DivaSystem
method
CreateInstance
, a boolean parameter called 'bBlocking',
sets the default value of AsyncMode for all DivaCall objects created using the
DivaInstance method
'CreateCall'.
The mode can always be overidden using the
AsyncMode
property of the DivaCall.
-
InstObj = SysObj.CreateInstance(True,... sets the default for DivaCall objects to blocking (synchronous) mode
-
InstObj = SysObj.CreateInstance(False,... sets the default for DivaCall objects to non-blocking (asynchronous) mode
Note: bBlocking is the inverse of AsyncMode: 'bBlocking = True' means 'AsyncMode = False'.
Using non-blocking mode
In the Component API, there are two ways of using non-blocking (asynchronous) mode:
- Use the synchronous method
WaitAsyncComplete
to wait for the completion of all the asynchronous commands that you have issued
- Use asynchronous mode with the DivaCall property
SignalEvents
set to 'True' so that an event handler subroutine in your program is called by the Component API.
Events
Blocking and non-blocking mode
Using SignalEvents = True
When you set the DivaCall property
SignalEvents
to 'True' for a call, (and, in VB, declare the DivaCall object 'WithEvents'), your program is notified by a
DivaCall event
of the completion of every command that could take an indeterminate period of time to complete,
especially those commands that request an action in the communications network or at another device.
VB example: (Show C# version)
Dim WithEvents CallObj As DivaCall
' Single call program, so create DivaCall directly
CallObj = CreateObject("DivaSDK.DivaCall")
CallObj.SignalEvents = True
res = CallObj.Connect(num)
C# example: (Show VB version)
DivaCall CallObj;
' Single call program, so create DivaCall directly
CallObj = (DivaCall) new DivaCall();
CallObj.SignalEvents = 1
CallObj.OnIncomingCall += new _IDivaCallEvents_OnIncomingCallEventHandler(CallObj_OnIncomingCall);
CallObj.OnConnected += new _IDivaCallEvents_OnConnectedEventHandler(CallObj_OnConnected);
CallObj.OnDisconnected += new _IDivaCallEvents_OnDisconnectedEventHandler(CallObj_OnDisconnected);
res = CallObj.Connect(num)
For each event that you wish to handle you create a routine similar to these:
VB example: (Show C# version)
Sub CallObj_OnIncomingCall() Handles CallObj.OnIncomingCall
log("EVENT: incoming call ")
End Sub
Sub CallObj_OnConnected() Handles CallObj.OnConnected
log("EVENT: call connected ")
End Sub
Sub CallObj_OnDisconnected() Handles CallObj.OnDisconnected
log("EVENT: call disconnected " )
End Sub
C# example: (Show VB version)
void CallObj_OnIncomingCall()
{
log("EVENT: incoming call ");
}
void CallObj_OnConnected()
{
log("EVENT: call connected ");
}
void CallObj_OnDisconnected()
{
log("EVENT: call disconnected " );
}
You don't have to create an event handler for every
DivaCall event,
but only those events that you want to use in your program.
See also:
List of DivaCall events
Why use non-blocking mode?
Blocking and non-blocking mode
Why use Asynchronous mode and Events?
Using blocking mode when you are handling more than one call
in the same program can result in a call being lost because another call
blocks processing at an 'unexpected' time.
Using asynchronous (non-blocking) mode with events enabled is often a convenient way to program
applications that handle more than one call at a time, especially when inputs (such as a user pressing a
button on the phone or hanging up at the 'wrong time') can happen unpredictably
and covering all the error conditions becomes difficult with if - then - else - end if statements
Total flexibility
'CallObj.AsyncMode = True'
and
'CallObj.SignalEvents = True'
are often used together, but they don't have to be used together.
The Component API does not restrict you to using either synchronous or asynchronous mode
in a program: each call can be dynamically switched from one mode to the other at any time.
In addition, you can use asynchronous mode with both
WaitAsyncComplete
and
'CallObj.SignalEvents = True'
in the same program.
So, the following three modes of operation can co-exist in the same program:
- blocking (synchronous) mode
- non-blocking (asynchronous) mode with
WaitAsyncComplete
- non-blocking (asynchronous) mode with
'CallObj.SignalEvents = True'
The Component API leaves you free to choose the most appropriate methodology for each part of your application.
Creating multiple DivaCalls
Scalable program architecture
Creating more than one DivaCall object
Because we are handling more than one call, we must use the DivaInstance method
CreateCall
to create the DivaCall objects.
First the
DivaSystem object is created
and then the
DivaInstance is created
by calling the
CreateInstance method of DivaSystem.
The DivaCall objects are created by calling the
CreateCall method of
DivaInstance.
The following example code is not taken from our 'scalable program' that uses a call-handling class,
but, for clarity, shows how multiple DivaCall objects can be created in a non-scalable simple program.
VB example: (Show C# version)
' handling two calls, so need to create DivaSystem and DivaInstance
Dim SysObj As DivaSystem
Dim InstObj As DivaInstance
SysObj = New DivaSystem()
' CreateInstance parameters: Default DivaCall blocking; max channels; buffers; buffer size
InstObj = SysObj.CreateInstance(True, 2, 4, 500)
' handling two calls, so need to create DivaCall objects using CreateCall
Dim CallObj1 As DivaCall
Dim CallObj2 As DivaCall
CallObj1 = InstObj.CreateCall
CallObj2 = InstObj.CreateCall
C# example: (Show VB version)
// handling two calls, so need to create DivaSystem and DivaInstance
DivaSystem SysObj;
DivaInstance InstObj;
SysObj = (DivaSystem) new DivaSystem();
// CreateInstance parameters: Default DivaCall blocking; max channels; buffers; buffer size
InstObj = SysObj.CreateInstance(1, 2, 4, 500);
// handling two calls, so need to create DivaCall objects using CreateCall
DivaCall CallObj1;
DivaCall CallObj2;
CallObj1 = InstObj.CreateCall;
CallObj2 = InstObj.CreateCall;
Using 'Listen', not 'WaitForCall'
Scalable program architecture
Using the Asynchronous method 'Listen'
The asynchronous DivaCall method
Listen
is the non-blocking alternative to the blocking mode method
WaitForCall.
Because
Listen
is an inherently asynchronous method, it always returns immediately and you must enable
SignalEvents
and code an
OnIncomingCall
handler that will be called by the component API when an incoming call is received by a Diva
adapter.
In Visual Basic, since we are specifying SignalEvents = True, we must declare CallObj 'WithEvents'
Dim WithEvents CallObj As DivaCall
Listen
can be used in both non-blocking and blocking modes but always behaves as an asynchronous
(non-blocking) method.
VB example: (Show C# version)
Private Sub Main_Load(ByVal eventSender As System.Object, _
ByVal eventArgs As System.EventArgs) Handles MyBase.Load
CallObj = New DivaCall()
CallObj.SignalEvents = True
' Listen returns immediately, OnIncomingCall handler is called when a call comes in
retVal = CallObj.Listen ( DivaListenServices.DivaListenServiceAll )
...
End Sub
C# example: (Show VB version)
private void Form1_Load(object sender, EventArgs e)
{
CallObj = (DivaCall) new DivaCall();
CallObj.SignalEvents = 1
CallObj.OnIncomingCall += new _IDivaCallEvents_OnIncomingCallEventHandler(CallObj_OnIncomingCall);
// Listen returns immediately, OnIncomingCall handler is called when a call comes in
retVal = CallObj.Listen ( DivaListenServices.DivaListenServiceAll ) ;
...
}
The following event handler handles the
OnIncomingCall
event by calling the
Answer method.
VB example: (Show C# version)
Sub CallObj_OnIncomingCall() Handles CallObj.OnIncomingCall
Dim retVal As DivaResultCodes
'This will be called when the call is signaled.
retVal = CallObj.Answer ( DivaCallTypes.DivaCallTypeVoice )
if retVal = DivaResultCodes.DivaResultSuccess Then
'perform call processing
End If
End Sub
C# example: (Show VB version)
private void CallObj_OnIncomingCall()
{
DivaResultCodes retVal;
//This will be called when the call is signaled.
retVal = CallObj.Answer ( DivaCallTypes.DivaCallTypeVoice )
if (retVal == DivaResultCodes.DivaResultSuccess) {
//perform call processing
}
End Sub
Initializing more than one incoming call in blocking mode
If you wish to handle more than one incoming call at the same time then you must use Listen rather than
WaitForCall when you initialise the DivaCall objects.
Call-handler class
Scalable program architecture
Call-handler class
The call-handler class allows the code that handles one call to be coded once and the main program can
then create as many call-handlers as it needs, depending on how many channels are available
or how many calls it wishes to handle.
Multi-threaded operation
Each copy of the call-handler that is created by the main program to handle a single call runs
independently, so you are free to use blocking (synchronous) mode
in the call-handler without stopping activity on other calls. The only exception is that the 'InitializeCall'
subroutine in the call-handler class must use non-blocking mode with events because it is called from the
main program
thread.
Multiple call-handler classes
You can create more than one call-handler class; so, for example, you could have an IncomingCallHandler
and an OutGoingCallHandler.
Blocking sample - part 1
Scalable program architecture
Sample code
This blocking-mode multi-channel application will answer calls on two channels.
The same program could be used
to handle hundreds of calls by setting nchannels to
DivaSys.TotalChannels.
In this example, the class that contains the event handlers is called 'IncomingCallHandler'.
The following page shows how the main program uses this class.
IncomingCallHandler class
The call-handler class contains a method 'InitializeCall' that initializes a DivaCall object and
a method 'TerminateCall' that terminates (disconnects) a call.
The InitializeCall method uses the non-blocking
Listen rather than the blocking
WaitForCall and
SignalEvents = True
is specified so that the MyCall_OnIncomingCall handler is called when a call is detected and the Component API raises
the
OnIncomingCall event.
In this blocking-mode example, all the call handling could be coded in the MyCall_OnIncomingCall subroutine.
More event handlers (to handle events like
OnConnected,
OnVoiceStreamed,
OnToneReceived,
OnDisconnected)
could be coded and this would make it easier to
handle unexpected sequences of events.
VB example: (Show C# version)
Class IncomingCallHandler
Dim WithEvents MyCall As DivaCall
Dim logChannel As Long
Dim theParent As MainProgram
Dim bShutdown As Boolean
Dim bActive As Boolean
Sub InitializeCall(ByVal Channel As Long, ByRef hParent As AnsweringMachine, _
ByRef Inst As DivaInstance)
logChannel = Channel
theParent = hParent
bShutdown = False
bActive = False
theParent.LogChannel(logChannel, "Create new DivaCall object")
MyCall = Inst.CreateCall()
MyCall.EnableDigitDetection = True
' Asynchronous (non-blocking) method 'Listen' must be used with
' SignalEvents = True. WaitForCall would block here.
MyCall.SignalEvents = True
' The Non-blocking method 'Listen' returns immediately and
' the OnIncomingCall handler will be called by the Component API
' when a call comes in.
MyCall.Listen(DivaListenServices.DivaListenServiceAll)
End Sub
Sub TerminateCall()
bShutdown = True
theParent.LogChannel(logChannel, "Disconnect DivaCall, active: " & bActive)
If (bActive) Then
MyCall.Disconnect()
End If
End Sub
' The OnIncomingCall handler is called by the Component API when a call is received
Sub MyCall_OnIncomingCall() Handles MyCall.OnIncomingCall
' call processing coded here
' Methods used here can be blocking or non-blocking
End Sub
End Class
C# example: (Show VB version)
class IncomingCallHandler
{
private DivaCall MyCall;
private long logChannel;
private MainProgram theParent;
private bool bShutdown;
private bool bActive;
private DivaInstance theInst;
public void InitializeCall(long Channel, Form1 hParent, ref DivaInstance Inst)
{
DivaResultCodes res;
logChannel = Channel;
theParent = hParent;
theInst = Inst;
bShutdown = false;
bActive = false;
theParent.LogChannel(logChannel, "Create new instance for incoming call");
MyCall = (DivaCall)Inst.CreateCall();
MyCall.EnableDigitDetection = 1;
// Asynchronous (non-blocking) method 'Listen' must be used with
// SignalEvents = True. WaitForCall would block here.
MyCall.SignalEvents = 1;
MyCall.OnIncomingCall += new _IDivaCallEvents_OnIncomingCallEventHandler(MyCall_OnIncomingCall);
// The Non-blocking method 'Listen' returns immediately and
// the OnIncomingCall handler will be called by the Component API
// when a call comes in.
res = MyCall.Listen(DivaListenServices.DivaListenServiceAll, "");
theParent.LogChannel(logChannel, "Listening for a call " + res);
}
public void TerminateCall()
{
bShutdown = true;
theParent.LogChannel(logChannel, "Destroy instance, active: " + bActive);
if ((bActive))
{
MyCall.Disconnect();
}
MyCall.Listen(DivaListenServices.DivaListenServiceNone,"");
MyCall = null;
}
// The OnIncomingCall handler is called by the Component API when a call is received
public void MyCall_OnIncomingCall()
{
// call processing coded here
// Methods used here can be blocking or non-blocking
}
end class
Blocking sample - part 2
Scalable program architecture
Sample code - continued
Application start
The main program creates the IncomingCallHandler and calls the InitializeCall method for the
number of calls that it wishes to handle.
VB example: (Show C# version)
' Array to hold the call instances
' Each entry in the array references a call
Dim nchannels As Integer = 2
Dim AllCalls(nchannels) As IncomingCallHandler
Dim DivaSys As DivaSystem
Dim DivaInst As DivaInstance
Dim nInst As Integer
' creating more than one DivaCall, so must use DivaSystem and DivaInstance
' and pass a reference to the DivaInstance to the IncomingCallHandler InitializeCall method
' so that it can call the DivaInstance CreateCall method.
DivaSys = CreateObject("DivaSDK.DivaSystem")
' CreateInstance parameters: Default DivaCall blocking; max channels; buffers; buffer size
DivaInst = DivaSys.CreateInstance(True, nchannels, 7, 1024)
' create the incoming call-handlers
For nInst = 1 To nchannels
AllCalls(nInst) = New IncomingCallHandler()
AllCalls(nInst).InitializeCall(nInst, Me, DivaInst)
Next nInst
C# example: (Show VB version)
// Array to hold the call instances
// Each entry in the array references a call
private IncomingCallHandler[] InCalls = new IncomingCallHandler[120];
private DivaInstance DivaInst;
private DivaSystem DivaSys;
private int nChannels;
// creating more than one DivaCall, so must use DivaSystem and DivaInstance
// and pass a reference to the DivaInstance to the IncomingCallHandler InitializeCall method
// so that it can call the DivaInstance CreateCall method.
DivaSys = (DivaSystem) new DivaSystem()
// CreateInstance parameters: Default DivaCall blocking; max channels; buffers; buffer size
DivaInst = DivaSys.CreateInstance(1, nchannels, 7, 1024)
// create the incoming call-handlers
for ( nInst = 1; nInst <= nChannels; nInst++)
{
InCalls[nInst].TerminateCall();
InCalls[nInst] = null;
}
For more detail see the complete program listings
(VB
C#).
If you wish to compile this sample, you will need to create
a form similar to this.
Alternatively, you can download the source
(VB
C#)
for both the program and the form
or
download the project
(VB
C#).
Download executable (.Net Framework 2.0 required):
Using non-blocking mode
Using non-blocking mode
Advanced techniques
Section contents overview
This section covers the use of non-blocking (asynchronous) mode and events in more depth than
in the Introduction to non-blocking mode
page in the previous section.
We also show how non-blocking mode is used to:
Non-blocking sample program
The previous section 'Handling multiple calls' showed how a fully-scalable blocking-mode (synchronous) program that
handles many simultaneous calls can be created using a call-handler class in either C# or Visual Basic 2005.
The
sample program at the end of this section is a
non-blocking (asynchronous) version of the 'MultipleIncomingCalls'
program in the 'Handling multiple calls' section.
Non-blocking mode overview
Using Events in Visual Basic
Non-blocking mode was introduced in the 'Handling multiple calls' section so that we could understand
the operation of the non-blocking 'Listen' method. Now, all the methods we use will use non-blocking mode
so it is necessary to review what we learnt about non-blocking mode previously.
Since asynchronous mode and events will typically be used with more complex programs
that support more than one simultaneous call, we use the
DivaInstance
method
CreateCall to create the
DivaCall objects.
VB example: (Show C# version)
' handling multiple calls, so need to create DivaSystem and DivaInstance
Dim SysObj As DivaSystem
Dim InstObj As DivaInstance
SysObj = New DivaSystem()
' CreateInstance parameters: bBlocking; max channels; buffers; buffer size
' Default for DivaCalls is bBlocking = False which means AsyncMode = True
InstObj = SysObj.CreateInstance(False, 4, 4, 500)
C# example: (Show VB version)
// handling multiple calls, so need to create DivaSystem and DivaInstance
DivaSystem SysObj;
DivaInstance InstObj;
SysObj = (DivaSystem) new DivaSystem();
// CreateInstance parameters: bBlocking; max channels; buffers; buffer size
// Default for DivaCalls is bBlocking = False which means AsyncMode = True
InstObj = (DivaInstance) SysObj.CreateInstance(0, 4, 4, 500);
Each DivaCall object that you use must be declared in Visual Basic as follows:
Dim WithEvents CallObj As DivaCall
The DivaCall properties
SignalEvents
and
AsyncMode
must be set to True for each DivaCall object:
VB example: (Show C# version)
' handling multiple calls, so need to create DivaCall objects using CreateCall
CallObj = InstObj.CreateCall
CallObj.SignalEvents = True
' the default value for AsyncMode is already set to True by the CreateCall
'(because bBlocking is set to False in CreateInstance)
' but this can be confusing, so we will explicitly set AsyncMode = True just to be sure
CallObj.AsyncMode = True
C# example: (Show VB version)
DivaCall CallObj;
// handling multiple calls, so need to create DivaCall objects using CreateCall
CallObj = (DivaCall) InstObj.CreateCall;
CallObj.SignalEvents = 1;
// the default value for AsyncMode is already set to True by the CreateCall
// (because bBlocking is set to False in CreateInstance)
// but this can be confusing, so we will explicitly set AsyncMode = True just to be sure
CallObj.AsyncMode = 1;
// Hook-up the event handlers here
CallObj.OnIncomingCall += new _IDivaCallEvents_OnIncomingCallEventHandler(CallObj_OnIncomingCall);
CallObj.OnConnected += new _IDivaCallEvents_OnConnectedEventHandler(CallObj_OnConnected);
CallObj.OnDisconnected += new _IDivaCallEvents_OnDisconnectedEventHandler(CallObj_OnDisconnected);
For each event that you wish to handle you code a handler:
VB example: (Show C# version)
Sub CallObj_OnIncomingCall() Handles CallObj.OnIncomingCall
log("EVENT: incoming call ")
End Sub
Sub CallObj_OnConnected() Handles CallObj.OnConnected
log("EVENT: call connected ")
End Sub
Sub CallObj_OnDisconnected() Handles CallObj.OnDisconnected
log("EVENT: call disconnected " )
End Sub
C# example: (Show VB version)
void CallObj_OnIncomingCall()
{
log("EVENT: incoming call ");
}
void CallObj_OnConnected()
{
log("EVENT: call connected ");
}
void CallObj_OnDisconnected()
{
log("EVENT: call disconnected " );
}
Note: you don't have to create an event handler for every
DivaCall event
, but only those events that you want to use in your program.
Call handling - non-blocking
Advanced Call Handling
Using events and asynchronous mode changes the way calls are handled:
Outgoing calls are still made using
Connect
but the Connect command now returns immediately and the connection establishment, if successful,
is signaled some time later with the event
OnConnected
Incoming calls are handled by first issuing a
Listen
(rather than the synchronous WaitForCall) and then handling the
OnIncomingCall
event that is signaled when a call comes in
When you receive an
OnIncomingCall
event after issuing a
Listen,
the call is not yet connected as it is when you use the
WaitForCall
method used in the 'simple' synchronous blocking examples.
The OnIncomingCall event is only a notification that an
incoming call is available; you can look at the call properties - such as the
CalledNumber,
CallingNumber
or the
CallType
- and decide whether to:
-
Answer
the call immediately
-
Reject
the call immediately
-
delay your decision by issuing
Alert
while you perform a database look-up or determine if the user is available to receive the call.
After sending 'Alert', you can Answer or Reject the call, or, indeed, do nothing.
-
ignore the call (do nothing)
If you decide to
Answer
the call, then the event
OnConnected
will signal that the connection is successfully established and available for use.
Outgoing calls - non-blocking
DivaConnect
The normal sequence for an outgoing call is:
-
Application issues
Connect
for the appropriate call type
-
API sends event
OnConnected
to signal that the call establishment is complete.
-
Application handles OnConnected and performs any required processing.
-
Application issues
Disconnect.
Note that the program must not assume that the call is disconnected
as soon as the Disconnect has been issued: you must wait for the OnDisconnected event that
signals that the call has been terminated.
-
API sends event
OnDisconnected.
-
Application handles OnDisconnected.
The DivaCall method
Connect
allows you to initiate calls of any type.
The parameters of Connect are:
-
A string containing the digits to dial
-
The CallType; the possible values are defined in
DivaCallTypes
Outgoing call example
Outgoing call example
This example, based on the 'scalable' program structure using a call-handler class described in the
section 'Handling multiple calls', shows how Async mode and events are used to make an outgoing call.
-
Event handling for the CallObj object is enabled by 'Dim WithEvents MyCall As DivaCall'
-
Asynchronous operation is enabled by 'CallObj.AsyncMode
= True'
-
Events are switched on by 'MyCall.SignalEvents
= True'
-
InitializeCall is called by the main program to create the DivaCall
-
TerminateCall is called by the main program to destroy the DivaCall
-
ConnectCall is called by the main program to make a call
-
The 'MyCall_event' subroutines handle the events raised by the Component API that we are interested in
VB example: (Show C# version)
Class OutgoingCallHandler
Dim WithEvents MyCall As DivaCall
Dim logChannel As Long
Dim theParent As MainProgram
Dim bShutdown As Boolean
Dim bActive As Boolean
Dim theInst As DivaInstance
Sub InitializeCall(ByVal Channel As Long, ByRef hParent As MainProgram, ByRef Inst As DivaInstance)
logChannel = Channel
theParent = hParent
theInst = Inst
bShutdown = False
bActive = False
theParent.LogChannel(logChannel, "Create new instance for outgoing call")
MyCall = Inst.CreateCall()
MyCall.EnableDigitDetection = True
MyCall.AsyncMode = True
MyCall.SignalEvents = True
End Sub
Sub TerminateCall()
bShutdown = True
theParent.LogChannel(logChannel, "Destroy instance, active: " & bActive)
If (bActive) Then
MyCall.Disconnect()
End If
MyCall.Listen(DivaListenServices.DivaListenServiceNone)
MyCall = Nothing
End Sub
Sub MyCall_Connect(ByVal number As String)
Dim res As DivaResultCodes
theParent.LogChannel(logChannel, "Making voice call to " & number)
res = MyCall.Connect(number, DivaCallTypes.DivaCallType_Voice)
bActive = True
End Sub
Sub MyCall_OnConnected() Handles MyCall.OnConnected
Dim retVal As DivaResultCodes
theParent.LogChannel(logChannel, "Connected " & MyCall.CallingNumber & " - stream announcement")
retVal = MyCall.SendVoiceFile("DefaultGreeting.wav")
End Sub
End Class
C# example: (Show VB version)
class OutgoingCallHandler
{
private DivaCall MyCall ;
private int logChannel;
private Form1 theParent;
private bool bShutdown;
private bool bActive;
private DivaInstance theInst;
public void InitializeCall(int Channel , Form1 hParent, DivaInstance Inst )
{
logChannel = Channel;
theParent = hParent;
theInst = Inst;
bShutdown = false;
bActive = false;
theParent.LogChannel(logChannel, "Create new instance for outgoing call");
MyCall = (DivaCall) Inst.CreateCall();
MyCall.EnableDigitDetection = 1;
MyCall.AsyncMode = 1;
MyCall.SignalEvents = 1;
MyCall.OnConnected += new _IDivaCallEvents_OnConnectedEventHandler(MyCall_OnConnected);
}
public void TerminateCall()
{
bShutdown = true;
theParent.LogChannel(logChannel, "Destroy instance, active: " + bActive);
if (bActive)
{
MyCall.Disconnect();
}
MyCall.Listen(DivaListenServices.DivaListenServiceNone, "");
MyCall = null;
}
public void MyCall_Connect(string number)
{
DivaResultCodes res;
theParent.LogChannel(logChannel, "Making voice call to " + number);
res = MyCall.Connect(number, DivaCallTypes.DivaCallType_Voice);
bActive = true;
}
public void MyCall_OnConnected()
{
DivaResultCodes res;
theParent.LogChannel(logChannel, "Connected " + MyCall.CallingNumber + " - stream announcement");
res = MyCall.SendVoiceFile("DefaultGreeting.wav",DivaAudioFmt.DivaAudioAutodetect);
}
}
Incoming calls - non-blocking
Incoming calls
Incoming calls can be slightly more complicated than outgoing calls since the application has additional decisions to make:
-
the calls it wishes to be notified about
-
whether to answer a call or reject it
This is a normal sequence for accepting an incoming call:
The application now continues as for the outgoing call:
-
Application handles OnConnected and performs any required processing
-
Application issues Disconnect
Disconnect
-
API sends event
OnDisconnected
-
Application handles OnDisconnected
If the application does not wish to handle the call it can issue
Reject,
no more events are signalled for this call and so no further action is necessary.
Upon disconnection, the call object automatically returns to listening for an incoming call.
If you wish to disable this default behaviour and so stop this DivaCall object from handling more calls,
you need to call the Listen method again with the
DivaListenServices
value 'DivaListenServicesNone' (0).
Incoming call example
Using Listen
Listen
allows the application to pre-select which incoming calls it wishes to be informed of
by means of an
OnIncomingCall event.
The selection criteria are:
-
whether to listen for digital calls or analog calls (or 'all calls') - see
DivaListenServices
for options
-
the local number (or numbers) to listen on (optional, default is 'all')
You can also set the Diva line device that you wish to listen on by setting the
Device
property of the call before issuing the
Listen.
The following example listens for voice calls and answers the call
after retrieving the calling number (caller =
CallObj.CallingNumber
).
When the call has been connected (signaled by the
OnConnected
event) the program sends a voice message.
When all of the message has been streamed on to the line, the
OnVoiceStreamed
event is sent by the API.
VB example: (Show C# version)
Class IncomingCallHandlerAsync
Dim WithEvents MyCall As DivaCall
Dim logChannel As Long
Dim theParent As MainProgram
Dim bShutdown As Boolean
Dim bActive As Boolean
Dim theInst As DivaInstance
Sub InitializeCall(ByVal Channel As Long, ByRef hParent As MainProgram, _
ByRef Inst As DivaInstance)
Dim res As DivaResultCodes
logChannel = Channel
theParent = hParent
theInst = Inst
bShutdown = False
bActive = False
theParent.LogChannel(logChannel, "Create new instance for incoming call")
MyCall = Inst.CreateCall()
MyCall.EnableDigitDetection = True
MyCall.AsyncMode = True
MyCall.SignalEvents = True
theParent.LogChannel(logChannel, "Waiting for a voice call")
res = MyCall.Listen(DivaListenServices.DivaListenServiceAll)
End Sub
Sub TerminateCall()
bShutdown = True
theParent.LogChannel(logChannel, "Destroy instance, active: " & bActive)
If (bActive) Then
MyCall.Disconnect()
End If
MyCall.Listen(DivaListenServices.DivaListenServiceNone)
MyCall = Nothing
End Sub
Sub MyCall_OnIncomingCall() Handles MyCall.OnIncomingCall
Dim retVal As DivaResultCodes
Dim RecordFile As String = ""
If bShutdown = False Then
bActive = True
theParent.LogChannel(logChannel, "Incoming call to " & MyCall.CalledNumber & _
" from " & MyCall.CallingNumber)
retVal = MyCall.Answer(DivaCallTypes.DivaCallType_Voice)
End If
End Sub
Sub MyCall_OnConnected() Handles MyCall.OnConnected
Dim retVal As DivaResultCodes
theParent.LogChannel(logChannel, "Connected " & MyCall.CallingNumber & _
" - stream announcement")
retVal = MyCall.SendVoiceFile("DefaultGreeting.wav")
End Sub
Sub MyCall_OnVoiceStreamed(ByVal wrapped As Integer) Handles MyCall.OnVoiceStreamed
Dim retVal As DivaResultCodes
Dim RecordFile As String = ""
theParent.LogChannel(logChannel, "Announcement ended ")
RecordFile = "IMsg_" & MyCall.CallingNumber & "_" & logChannel & ".wav"
theParent.LogChannel(logChannel, "Start recording to " & RecordFile)
retVal = MyCall.RecordVoiceFile(RecordFile, DivaAudioFmt.DivaAudioDefault, _
10, 5, "*#1234567890")
End Sub
End Class
C# example: (Show VB version)
class IncomingCallHandlerAsync
{
private DivaCall MyCall;
private int logChannel;
private Form1 theParent;
private bool bShutdown;
private bool bActive;
private DivaInstance theInst;
public void InitializeCall(int Channel, Form1 hParent, ref DivaInstance Inst)
{
DivaResultCodes res;
logChannel = Channel;
theParent = hParent;
theInst = Inst;
bShutdown = false;
bActive = false;
theParent.LogChannel(logChannel, "Create new instance for incoming call");
MyCall = (DivaCall)Inst.CreateCall();
MyCall.EnableDigitDetection = 1;
MyCall.AsyncMode = 1;
MyCall.SignalEvents = 1;
MyCall.OnIncomingCall += new _IDivaCallEvents_OnIncomingCallEventHandler(MyCall_OnIncomingCall);
MyCall.OnConnected += new _IDivaCallEvents_OnConnectedEventHandler(MyCall_OnConnected);
MyCall.OnVoiceStreamed += new _IDivaCallEvents_OnVoiceStreamedEventHandler(MyCall_OnVoiceStreamed);
MyCall.OnRecordEnded += new _IDivaCallEvents_OnRecordEndedEventHandler(MyCall_OnRecordEnded);
MyCall.OnDisconnected += new _IDivaCallEvents_OnDisconnectedEventHandler(MyCall_OnDisconnected);
MyCall.OnToneReceived += new _IDivaCallEvents_OnToneReceivedEventHandler(MyCall_OnToneReceived);
MyCall.Device = 1;
res = MyCall.Listen(DivaListenServices.DivaListenServiceAll, "");
theParent.LogChannel(logChannel, "Listening for a call " + res);
}
public void TerminateCall()
{
bShutdown = true;
theParent.LogChannel(logChannel, "Destroy instance, active: " + bActive);
if ((bActive))
{
MyCall.Disconnect();
}
MyCall.Listen(DivaListenServices.DivaListenServiceNone,"");
MyCall = null;
}
public void MyCall_OnIncomingCall()
{
DivaResultCodes retVal;
theParent.LogChannel(logChannel, "Incoming call to " + MyCall.CalledNumber + " from " + MyCall.CallingNumber);
if (bShutdown == false)
{
bActive = true;
retVal = MyCall.Answer(DivaCallTypes.DivaCallType_Voice);
}
}
public void MyCall_OnConnected()
{
DivaResultCodes retVal;
theParent.LogChannel(logChannel, "Connected " + MyCall.CallingNumber + " - stream announcement");
retVal = MyCall.SendVoiceFile("DefaultGreeting.wav",DivaAudioFmt.DivaAudioAutodetect);
}
public void MyCall_OnVoiceStreamed(int wrapped)
{
DivaResultCodes retVal;
string RecordFile = "";
theParent.LogChannel(logChannel, "Announcement ended ");
RecordFile = "IMsg_" + MyCall.CallingNumber + "_" + logChannel + ".wav";
theParent.LogChannel(logChannel, "Start recording to " + RecordFile);
retVal = MyCall.RecordVoiceFile(RecordFile, DivaAudioFmt.DivaAudioWav_aLaw8K8BitMono, 100, 10, "#");
}
public void MyCall_OnRecordEnded(DivaRecordEndReason reason)
{
theParent.LogChannel(logChannel, "Recording ended with reason " + reason );
theParent.LogChannel(logChannel, "Disconnecting " + MyCall.CallingNumber);
MyCall.Disconnect();
}
public void MyCall_OnDisconnected()
{
theParent.LogChannel(logChannel, "Disconnected " + MyCall.CallingNumber);
bActive = false;
}
public void MyCall_OnToneReceived(byte tone)
{
theParent.LogChannel(logChannel, "Tone received " + Strings.Chr(tone) + " (" + tone + ")");
}
}
Alert
Deciding whether to answer
The previous example shows how the parameters of the
Listen
and the
Device
property
can be used to filter the incoming calls that you are informed of by
OnIncomingCall
events.
In addition, the previous example showed how the caller's number can be retrieved using the
CallingNumber
property before answering the call.
You may wish to examine other
call properties
before deciding whether to
Answer,
ignore or
Reject
the call; for instance:
CallType,
CalledNumber.
If there could be any delay in handling the
OnIncomingCall
event - if, for instance, you wish to perform a database look-up using the
CallingNumber
- then you should issue an
Alert
to inform the caller that the call is 'ringing' and may be answered.
If the calling party does not receive this indication the call could be dropped by the network
after about 2 seconds, so it is safer to issue the
Alert
if you aren't immediately accepting the call.
Sub CallObj_OnIncomingCall() Handles CallObj.OnIncomingCall
Dim res As DivaResultCodes
res = CallObj.Alert
'
' perform some more processing here
'
res = CallObj.Answer
End Sub
Reject
Reject
Calling the
Reject
method indicates that the application does not wish to take the call and doesn't want any other application
to be able to accept the call (although any other application that may have been offered the call
could already have accepted it). The reason parameter can take one of the
DivaRejectCode
values.
Sub CallObj_OnIncomingCall() Handles CallObj.OnIncomingCall
Dim res As DivaResultCodes
res = CallObj.Alert
'
' perform some more processing here, decide to reject the call
'
res = CallObj.Reject(DivaRejectCode.DivaRejectNormalCallClearing)
End Sub
Play voice - non-blocking mode
Send and receive faxes
This example shows how
SendVoiceFile
can be used to automatically play a message on connection of a call.
In non-blocking (asynchronous) mode the
SendVoiceFile
method returns immediately.
Sub CallObj_OnConnected() Handles CallObj.OnConnected
Dim res As DivaResultCodes
Log("incoming call connected")
res = CallObj.SendVoiceFile("myfile.wav")
Log("sending file " & res)
End Sub
The Component API calls your
OnVoiceStreamed
event handler to signal that the voice streaming operation has ended.
Sub CallObj_OnVoiceStreamed(ByVal bWrapped As Integer) _
Handles CallObj.OnVoiceStreamed
Dim res As DivaResultCodes
Log("file sent")
res = CallObj.Disconnect
Log("disconnect " & res)
End Sub
Record voice - non-blocking mode
Send and receive faxes
The following sample shows the use of
RecordVoiceFile.
This method has three possible ways of determining when the recording should end: the total
time of the recording; silence detection; detection of DTMF dial-digits. In this case, the
RecordVoiceFile will terminate after 20 seconds, when a '*' character is detected or when 5 seconds of silence is detected.
In non-blocking (asynchronous) mode the
RecordVoiceFile
method returns immediately, before
the recording is complete. Completion of the recording, and the 'reason' for completion, are signaled by the
OnRecordEnded
event.
Sub CallObj_OnConnected() Handles CallObj.OnConnected
Dim res As DivaResultCodes
Log("incoming call connected")
res = CallObj.RecordVoiceFile("myvoicefile.wav", 0, 20, 5, "*")
Log("recording file " & res.ToString & "(" & res & ")" )
End Sub
The Component API calls your
OnRecordEnded
event handler to signal that the recording has ended, at the same time
indicating why the recording was ended.
Sub CallObj_OnRecordEnded(ByVal reason As DivaRecordEndReason) _
Handles CallObj.OnRecordEnded
Log("EVENT: file recorded - " & reason.ToString)
End Sub
Handling tones - non-blocking
Send and receive tones
Sending dial-digit tones
The following code sends a string of digits using DTMF (dual-tone multi-frequency) tones with the
SendDigits
method.
Sending tones is the same in non-blocking mode as it is in blocking mode.
Sub CallObj_OnConnected() Handles CallObj.OnConnected
Dim res As DivaResultCodes
Log("call connected")
res = CallObj.SendDigits( "*1234" )
Log("sending digits " & res)
End Sub
Receiving dial-digit tones as they occur
In both synchronous and asynchronous mode, the detection of dial-digit tones is enabled by setting the call
property
EnableDigitDetection
to 'True'.
If SignalEvents = True, then the
OnToneReceived
event handler in your program will be called for every tone that is received. This could be used, for example,
to allow a user to terminate an IVR process by pressing '*' at any time.
CallObj.EnableDigitDetection = True
...
Sub CallObj_OnToneReceived(ByVal tone As Byte) Handles CallObj.OnToneReceived
Log("EVENT: tone received - " & Chr(tone) & " (" & tone & ")")
' add processing for received tone here
End Sub
Receiving dial-digit tones in a single string
You may find it more convenient to use the
DetectedDigits method
to retrieve all the digits that have been entered and buffered in one operation.
digitString = CallObj.DetectedDigits
The detected digit buffer can be cleared using
ClearDetectedDigits
Send fax - non-blocking
Send and receive faxes
The following code uses the optional
CallType
parameter to the
Connect
method to specify that we are making a fax call.
CallObj.FaxHeadline = "Test Fax"
CallObj.FaxLocalId = "Fax sender"
...
res = CallObj.Connect(CallNum, DivaCallTypes.DivaCallType_Fax)
...
Sub CallObj_OnConnected() Handles CallObj.OnConnected
Dim res As DivaResultCodes
Log("incoming call connected " & CallObj.FaxRemoteId )
res = CallObj.SendFax("FaxDoc1.tif")
Log("sending fax " )
End Sub
In non-blocking (asynchronous) mode, SendFax returns immediately without waiting for the
fax to be transmitted and
your program's
OnFaxPageProcessed
and
OnFaxProcessed
event handlers are called to inform you of progress. Note that
for single page faxes - and for the last page of a multi-page fax - only the
OnFaxProcessed
event occurs.
Sub CallObj_OnFaxPageProcessed(ByVal PagesDone As Integer) _
Handles CallObj.OnFaxPageProcessed
Log("EVENT: fax page processed " & PagesDone)
End Sub
Sub CallObj_OnFaxProcessed() Handles CallObj.OnFaxProcessed
Log("EVENT: fax processed")
End Sub
Receive fax - non-blocking
Send and receive faxes
The following code uses the optional
CallType
parameter to the
Answer
method to specify that we are answering in fax mode.
CallObj.FaxHeadline = "Test Fax"
CallObj.FaxLocalId = "fax receiver"
res = CallObj.Listen(DivaCallTypes.DivaCallType_Fax)
Sub CallObj_OnIncomingCall() handles CallObj.OnIncomingCall
Dim res As DivaResultCodes
res = CallObj.Answer(DivaCallTypes.DivaCallType_Fax)
End Sub
Sub CallObj_OnConnected() Handles CallObj.OnConnected
Dim res As DivaResultCodes
Log("call connected " & CallObj.FaxRemoteId )
res = CallObj.Receivefax(myfax.tif")
Log("receiving fax fax " )
End Sub
In non-blocking (asynchronous) mode, the
ReceiveFax
method returns immediately and your program's
OnFaxPageProcessed
and
OnFaxProcessed
event handlers are called to inform you of progress. Note that
for single page faxes - and for the last page of a multi-page fax - only the
OnFaxProcessed event occurs.
Sub CallObj_OnFaxPageProcessed(ByVal PagesDone As Integer) _
Handles CallObj.OnFaxPageProcessed
Log("EVENT: fax page processed " & PagesDone)
End Sub
Sub CallObj_OnFaxProcessed() Handles CallObj.OnFaxProcessed
Log("EVENT: fax processed")
End Sub
Send data - non-blocking
Send data
The Component API allows you to send and receive 'raw' or 'plain' data over the ISDN connection.
This data is not changed or interpreted in any way and can contain any value, including the
hex value X'00'.
To send or receive data the
CallType
must be one of the 'data' CallTypes, DivaCallType_Modem (2) or DivaCallType_DigitalData (3)
not DivaCallType_Voice or DivaCallType_Fax; it is not recommended to send or receive
plain data on a voice or fax call using the Component API.
Dialogic recommends that
applications that perform audio-stream or fax processing on multiple channels should use the
Audio Provider model where low-level, time-critical
functions are handled in a DLL written using the Diva C/C++ API. Alternatively, the whole
application could be written using the Diva C/C++ API or in C# using the Diva API for .Net.
Methods are provided for sending and receiving either single bytes or arrays of data.
Visual Basic 2005 is able to use the array methods
SendData
and
ReceiveData.
The single byte methods
SendDataByte
and
ReceiveDataByte
are provided for Visual Basic 6 and VBScript, neither of which is
able to use the array methods.
The following example uses the optional
CallType
parameter to the
Connect
method to specify that we are making a digital data call.
res = CallObj.Connect(CallNum, DivaCallTypes.DivaCallType_DigitalData)
...
Private Sub CallObj_OnConnected() Handles CallObj.OnConnected
Dim res As DivaResultCodes
Log("connected ")
res = CallObj.SendData(10, TxData)
Log("data sent")
End Sub
Receive data - non-blocking
Send and receive data
The following example uses the optional
CallType
parameter to the
Listen
and
Answer
methods to specify that we are establishing a digital data call.
res = CallObj.Listen(DivaCallTypes.DivaCallType_DigitalData)
...
Private Sub CallObj_OnIncomingCall() Handles CallObj.OnIncomingCall
Dim res As DivaResultCodes
Log("incoming call from " & CallObj.CallingNumber & " call type=" & CallObj.CallType)
res = CallObj.Answer(DivaCallTypes.DivaCallType_DigitalData)
End Sub
In non-blocking (asynchronous) mode, the Component API calls the
OnDataAvailable
event handler in your program to notify
you that data is available.
Private Sub CallObj_OnDataAvailable(ByVal n As Integer) Handles CallObj.OnDataAvailable
Dim res As DivaResultCodes
Dim i As Integer
Dim MyMessage As String = ""
Log("data available " & n & " bytes")
res = CallObj.ReceiveData(n, RxData, BytesReceived)
Log("data received " & BytesReceived)
For i = 0 To n-1
MyMessage = MyMessage & Chr(RxData(i))
Next
Log("Message received: " & MyMessage)
End Sub
Non-blocking sample - part 1
Non-blocking sample
Sample code
This non-blocking multi-channel application will answer calls on two channels.
The same program could be used
to handle hundreds of calls by setting nchannels to
DivaSys.TotalChannels.
In this example, the class that contains the event handlers is called 'IncomingCallHandlerAsync'.
The following page shows how the main program uses this class.
IncomingCallHandlerAsync class
The call-handler class contains a method 'InitializeCall' that initializes a DivaCall object and
a method 'TerminateCall' that terminates (disconnects) a call.
The InitializeCall and TerminateCall methods are almost exactly the same as the blocking-mode example -
the only difference is the
MyCall.AsyncMode = True.
All the call handling uses event handlers (to handle the events
OnConnected,
OnVoiceStreamed,
OnToneReceived,
OnDisconnected)
VB example: (Show C# version)
Complete program listing
Class IncomingCallHandlerAsync
Dim WithEvents MyCall As DivaCall
Dim logChannel As Long
Dim theParent As MainProgram
Dim bShutdown As Boolean
Dim bActive As Boolean
Dim theInst As DivaInstance
Sub InitializeCall(ByVal Channel As Long, ByRef hParent As MainProgram, ByRef Inst As DivaInstance)
Dim res As DivaResultCodes
logChannel = Channel
theParent = hParent
theInst = Inst
bShutdown = False
bActive = False
theParent.LogChannel(logChannel, "Create new instance for incoming call")
MyCall = Inst.CreateCall()
MyCall.EnableDigitDetection = True
MyCall.AsyncMode = True
MyCall.SignalEvents = True
theParent.LogChannel(logChannel, "Waiting for a voice call")
res = MyCall.Listen(DivaListenServices.DivaListenServiceAll)
End Sub
Sub TerminateCall()
bShutdown = True
theParent.LogChannel(logChannel, "Destroy instance, active: " & bActive)
If (bActive) Then
MyCall.Disconnect()
End If
MyCall.Listen(DivaListenServices.DivaListenServiceNone)
MyCall = Nothing
End Sub
Sub MyCall_OnIncomingCall() Handles MyCall.OnIncomingCall
Dim retVal As DivaResultCodes
Dim RecordFile As String = ""
If bShutdown = False Then
bActive = True
theParent.LogChannel(logChannel, "Incoming call to " & MyCall.CalledNumber & " from " & MyCall.CallingNumber)
retVal = MyCall.Answer(DivaCallTypes.DivaCallType_Voice)
End If
End Sub
Sub MyCall_OnConnected() Handles MyCall.OnConnected
Dim retVal As DivaResultCodes
theParent.LogChannel(logChannel, "Connected " & MyCall.CallingNumber & " - stream announcement")
retVal = MyCall.SendVoiceFile("DefaultGreeting.wav")
End Sub
Sub MyCall_OnVoiceStreamed(ByVal wrapped As Integer) Handles MyCall.OnVoiceStreamed
Dim retVal As DivaResultCodes
Dim RecordFile As String = ""
theParent.LogChannel(logChannel, "Announcement ended ")
RecordFile = "IMsg_" & MyCall.CallingNumber & "_" & logChannel & ".wav"
theParent.LogChannel(logChannel, "Start recording to " & RecordFile)
retVal = MyCall.RecordVoiceFile(RecordFile, DivaAudioFmt.DivaAudioDefault, 10, 5, "*#1234567890")
End Sub
Sub MyCall_OnRecordEnded(ByVal reason As DivaRecordEndReason) Handles MyCall.OnRecordEnded
theParent.LogChannel(logChannel, "Recording ended with reason '" & reason )
theParent.LogChannel(logChannel, "Disconnecting " & MyCall.CallingNumber)
MyCall.Disconnect()
End Sub
Sub MyCall_OnDisconnected() Handles MyCall.OnDisconnected
theParent.LogChannel(logChannel, "Disconnected " & MyCall.CallingNumber)
bActive = False
End Sub
Sub MyCall_OnToneReceived(ByVal tone As Byte) Handles MyCall.OnToneReceived
theParent.LogChannel(logChannel, "Tone received " & Chr(tone) & " (" & tone & ")")
End Sub
End Class
C# example: (Show VB version)
Complete program listing
class IncomingCallHandlerAsync
{
private DivaCall MyCall;
private int logChannel;
private Form1 theParent;
private bool bShutdown;
private bool bActive;
private DivaInstance theInst;
public void InitializeCall(int Channel, Form1 hParent, ref DivaInstance Inst)
{
DivaResultCodes res;
logChannel = Channel;
theParent = hParent;
theInst = Inst;
bShutdown = false;
bActive = false;
theParent.LogChannel(logChannel, "Create new instance for incoming call");
MyCall = (DivaCall)Inst.CreateCall();
MyCall.EnableDigitDetection = 1;
MyCall.AsyncMode = 1;
MyCall.SignalEvents = 1;
MyCall.OnIncomingCall += new _IDivaCallEvents_OnIncomingCallEventHandler(MyCall_OnIncomingCall);
MyCall.OnConnected += new _IDivaCallEvents_OnConnectedEventHandler(MyCall_OnConnected);
MyCall.OnVoiceStreamed += new _IDivaCallEvents_OnVoiceStreamedEventHandler(MyCall_OnVoiceStreamed);
MyCall.OnRecordEnded += new _IDivaCallEvents_OnRecordEndedEventHandler(MyCall_OnRecordEnded);
MyCall.OnDisconnected += new _IDivaCallEvents_OnDisconnectedEventHandler(MyCall_OnDisconnected);
MyCall.OnToneReceived += new _IDivaCallEvents_OnToneReceivedEventHandler(MyCall_OnToneReceived);
MyCall.Device = 1;
res = MyCall.Listen(DivaListenServices.DivaListenServiceAll, "");
theParent.LogChannel(logChannel, "Listening for a call " + res);
}
public void TerminateCall()
{
bShutdown = true;
theParent.LogChannel(logChannel, "Destroy instance, active: " + bActive);
if ((bActive))
{
MyCall.Disconnect();
}
MyCall.Listen(DivaListenServices.DivaListenServiceNone,"");
MyCall = null;
}
public void MyCall_OnIncomingCall()
{
DivaResultCodes retVal;
theParent.LogChannel(logChannel, "Incoming call to " + MyCall.CalledNumber + " from " + MyCall.CallingNumber);
if (bShutdown == false)
{
bActive = true;
retVal = MyCall.Answer(DivaCallTypes.DivaCallType_Voice);
}
}
public void MyCall_OnConnected()
{
DivaResultCodes retVal;
theParent.LogChannel(logChannel, "Connected " + MyCall.CallingNumber + " - stream announcement");
retVal = MyCall.SendVoiceFile("DefaultGreeting.wav",DivaAudioFmt.DivaAudioAutodetect);
}
public void MyCall_OnVoiceStreamed(int wrapped)
{
DivaResultCodes retVal;
string RecordFile = "";
theParent.LogChannel(logChannel, "Announcement ended ");
RecordFile = "IMsg_" + MyCall.CallingNumber + "_" + logChannel + ".wav";
theParent.LogChannel(logChannel, "Start recording to " + RecordFile);
retVal = MyCall.RecordVoiceFile(RecordFile, DivaAudioFmt.DivaAudioWav_aLaw8K8BitMono, 100, 10, "#");
}
public void MyCall_OnRecordEnded(DivaRecordEndReason reason)
{
theParent.LogChannel(logChannel, "Recording ended with reason " + reason );
theParent.LogChannel(logChannel, "Disconnecting " + MyCall.CallingNumber);
MyCall.Disconnect();
}
public void MyCall_OnDisconnected()
{
theParent.LogChannel(logChannel, "Disconnected " + MyCall.CallingNumber);
bActive = false;
}
public void MyCall_OnToneReceived(byte tone)
{
theParent.LogChannel(logChannel, "Tone received " + Strings.Chr(tone) + " (" + tone + ")");
}
}
Non-blocking sample - part 2
Non-blocking sample
Sample code - continued
Application start
The main program creates the IncomingCallHandlerAsync array and calls the InitializeCall method for the
number of calls that it wishes to handle.
VB example: (Show C# version)
Complete program listing
' Array to hold the call instances
' Each entry in the array references a call
Dim nchannels As Integer = 2
Dim InCalls(nchannels) As IncomingCallHandlerAsync
' creating more than one DivaCall, so must use DivaSystem and DivaInstance
' and pass a reference to the DivaInstance to the IncomingCallHandlerAsync InitializeCall method
' so that it can call the DivaInstance CreateCall method.
Dim DivaSys As DivaSystem = New DivaSystem()
' CreateInstance parameters: Default DivaCall blocking; max channels; buffers; buffer size
Dim DivaInst As DivaInstance = DivaSys.CreateInstance(False, nchannels, 7, 1024)
Dim nInst As Integer
' create the incoming call-handlers
For nInst = 1 To nchannels
InCalls(nInst) = New IncomingCallHandlerAsync()
InCalls(nInst).InitializeCall(nInst, Me, DivaInst)
Next nInst
C# example: (Show VB version)
Complete program listing
// Array to hold the call instances
// Each entry in the array references a call
IncomingCallHandlerAsync[] InCalls = new IncomingCallHandlerAsync[120];
// creating more than one DivaCall, so must use DivaSystem and DivaInstance
// and pass a reference to the DivaInstance to the IncomingCallHandlerAsync.InitializeCall method
// so that it can call the DivaInstance CreateCall method.
DivaSystem DivaSys = (DivaSystem) new DivaSystem();
int nChannels = 2;
// CreateInstance parameters: Default DivaCall blocking; max channels; buffers; buffer size
// Default for DivaCalls is set to non-blocking
DivaInstance DivaInst = (DivaInstance) DivaSys.CreateInstance(0, nChannels, 7, 1024);
// create the incoming call-handlers
for ( nInst = 1; nInst <= nChannels; nInst++)
{
InCalls[nInst] = new IncomingCallHandlerAsync();
InCalls[nInst].InitializeCall(nInst, this, ref DivaInst);
}
Multiple Incoming Call sample, Non-blocking (Asynchronous)
-
IncomingMultipleCallsAsync
Note: .Net Framework 2.0 is required to run the executable.
Samples
Sample code
Samples
Note
1. Projects are for Visual Basic 2005 or C# 2005
2. Executables require .Net Framework 2.0
Samples
- Samples from this training course
- Other samples (adapted to Visual Basic 2005 Express from samples provided with the SDK)
See also:
- SimplePhone with 'APSoundDevice' Audio Provider -
shows how to create an Audio Provider DLL in C that uses the Diva API to handle low-level time-critical
audio-streaming and processing tasks while the Component API program handles everything else.
Note: The source code in this training course is provided by Dialogic Corporation "AS IS",
without warranty of any kind, either expressed or implied. Dialogic Corporation shall not be liable
for any damages arising out of your use of the source code in this course, even if it has
been advised of the possibility of such damages.
Please note that purchase of a Dialogic product does not provide a license to any patents not owned
or duly licensed by Dialogic Corporation or its subsidiaries. Please read the
Legal Notice.