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 will show you:

Show this course in printer-friendly format



Pre-requisites

Course Pre-requisites

Minimum pre-requisites:

To compile the samples you need:

To run the samples you need:


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:


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?

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:


The Diva Component API supports both very simple and more complex applications


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:


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.

* 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



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:

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:



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:


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

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

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:


The template form (image & VB source , C# source ) contains the following controls which retain their default names:

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.


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.


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:


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:

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:


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:


Using non-blocking mode
In the Component API, there are two ways of using non-blocking (asynchronous) mode:



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)

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

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:


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



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
 

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
 


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



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

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)

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

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

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:

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:


The DivaCall method Connect allows you to initiate calls of any type. The parameters of Connect are:



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.


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



Incoming calls - non-blocking

Incoming calls

Incoming calls can be slightly more complicated than outgoing calls since the application has additional decisions to make:

This is a normal sequence for accepting an incoming call:

The application now continues as for the outgoing call:

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:

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



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


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

Multiple Incoming Call sample, Non-blocking (Asynchronous)

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
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.