INCOMING.FRM

VERSION 5.00 
Begin VB.Form Form1
Caption = "Incoming"
ClientHeight = 5025
ClientLeft = 60
ClientTop = 345
ClientWidth = 4800
LinkTopic = "Form1"
ScaleHeight = 5025
ScaleWidth = 4800
StartUpPosition = 3 'Windows Default
Begin VB.CommandButton pbDisconnect
Caption = "Disconnect"
Height = 375
Index = 1
Left = 1440
TabIndex = 3
Top = 2760
Width = 2055
End
Begin VB.CommandButton pbAnswer
Caption = "Answer"
Default = -1 'True
Height = 375
Index = 0
Left = 1440
TabIndex = 2
Top = 2160
Width = 2055
End
Begin VB.CommandButton RegisterForReceiveCall
Caption = "Register the Application for Receiving Calls"
Height = 615
Left = 1440
TabIndex = 1
Top = 1200
Width = 2055
End
Begin VB.Frame Frame1
Caption = "Register"
Height = 1815
Left = 240
TabIndex = 4
Top = 240
Width = 4335
Begin VB.ComboBox cmbAddressTypes
Height = 315
Left = 1800
TabIndex = 0
Top = 360
Width = 2175
End
Begin VB.Label Label1
Caption = "Calls you want to receive:"
Height = 495
Left = 360
TabIndex = 5
Top = 360
Width = 1095
End
End
Begin VB.Label lblStatus
Height = 1335
Left = 1080
TabIndex = 7
Top = 3480
Width = 3495
End
Begin VB.Label lblStatusTitle
Caption = "Status:"
Height = 255
Left = 360
TabIndex = 6
Top = 3480
Width = 615
End
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
' INCOMING.EXE
'
' Example of receiving calls with TAPI 3.0
'
' This application will allow a user to receive audio calls
' by using TAPI 3.0.
'
' The application will simply look for the 1st address that is able
' to receive calls of the specified type (phone calls, or h323 calls -
' the user is allowed to decide). The address is also chosen
' only if it supports at least 2 media types (the idea is that
' usually the first 2 media types will be "audio in" and "audio out").
' It will register then itself on this address to receive calls.
' On the received calls, it will select 2 media terminals before
' calling answer. The media terminals are created by using the
' first 2 media types enumerated by the address, with their default
' terminals.
' The app will display messages to announce whenever a new call
' arrives and also when a call state event fires.
'
' This application does not make outgoing calls.
'

Option Explicit

Dim gobjTapi As TAPI
Dim gobjDestAddress As Address
Dim WithEvents gobjAddressWithEvents As Address
Attribute gobjAddressWithEvents.VB_VarHelpID = -1
Dim gobjTerminal1 As Terminal
Dim gobjTerminal2 As Terminal
Dim gguidMediaType1
Dim gguidMediaType2
Dim gobjReceivedCallInfo As ITCallInfo

Dim gbSupportedCall As Boolean

Private Sub Form_Load()

pbAnswer(0).Enabled = False

'populate combo box with names of call types
'attach to each combo item the address type that
'can receive that type of call

cmbAddressTypes.AddItem ("Phone Calls")
cmbAddressTypes.ItemData(cmbAddressTypes.NewIndex) = ADDRESSTYPE_PHONENUMBER

cmbAddressTypes.AddItem ("H323 Calls")
cmbAddressTypes.ItemData(cmbAddressTypes.NewIndex) = ADDRESSTYPE_IPADDRESS

'set selection on 1st item
cmbAddressTypes.ListIndex = 0

End Sub

Private Sub Form_Unload(Cancel As Integer)

'release all global objects

Set gobjReceivedCallInfo = Nothing
Set gobjTerminal1 = Nothing
Set gobjTerminal2 = Nothing
Set gobjAddressWithEvents = Nothing
Set gobjDestAddress = Nothing
If Not (gobjTapi Is Nothing) Then
gobjTapi.Shutdown
End If
Set gobjTapi = Nothing

'empty combo box
Dim i
For i = 1 To cmbAddressTypes.ListCount
cmbAddressTypes.RemoveItem (0)
Next i
End Sub

Private Sub DisplayCallState(State As CALL_STATE)
Dim strMsg As String

Select Case State
Case CS_CONNECTED
strMsg = "call state: CS_CONNECTED" & Chr(13)
strMsg = strMsg & "The call was answered, now you can disconnect "
strMsg = strMsg & "or wait for disconnected state. "
strMsg = strMsg & "Don't press Answer before new call arrives. "
lblStatus.Caption = strMsg

Case CS_DISCONNECTED
strMsg = "call state: CS_DISCONNECTED" & Chr(13)
strMsg = strMsg & "Call will be released. "
strMsg = strMsg & "New incoming calls will be accepted. "
lblStatus.Caption = strMsg

Case CS_HOLD
lblStatus.Caption = "call state: CS_HOLD"
Case CS_IDLE
lblStatus.Caption = "call state: CS_IDLE"

Case CS_INPROGRESS
lblStatus.Caption = "call state: CS_INPROGRESS"

Case CS_OFFERING
If gbSupportedCall = True Then
strMsg = "call state: CS_OFFERING"
strMsg = strMsg & Chr(13) & "A call was received. You can answer it"
lblStatus.Caption = strMsg
End If

Case CS_QUEUED
lblStatus.Caption = "call state: CS_QUEUED"
Case Else
lblStatus.Caption = "call state: unknown!!"
End Select
End Sub

Private Sub pbAnswer_Click(index As Integer)
Dim strMsg

If gobjReceivedCallInfo Is Nothing Then
strMsg = "There is no call to be answered!"
lblStatus.Caption = strMsg
Exit Sub
End If

If Not (gobjReceivedCallInfo.CallState = CS_OFFERING) Then
strMsg = "Cannot answer call that doesn't have offering state."
strMsg = strMsg & " Did you already press Answer?"
lblStatus.Caption = strMsg
Exit Sub
End If

'query ITBasicCallControl, the call control interface
Dim objCallControl As ITBasicCallControl
Set objCallControl = gobjReceivedCallInfo

'
'prepare the terminals (take the default terminals)
'
'query ITTerminalSupport from Address object
Dim objTerminalSupport As ITTerminalSupport

Set objTerminalSupport = gobjDestAddress

Set gobjTerminal1 = objTerminalSupport.GetDefaultTerminal(gguidMediaType1)
Set gobjTerminal2 = objTerminalSupport.GetDefaultTerminal(gguidMediaType2)

'release not needed objects
Set objTerminalSupport = Nothing

'Select the media-terminals before answering

'Create the media-terminals, then put them in array,
'then put array in variant
Dim MediaTerminals As Variant
Dim arrMediaTerminals(0 To 1) As ITMediaTerminal
MediaTerminals = arrMediaTerminals
Set MediaTerminals(0) = gobjTapi.CreateMediaTerminal( _
gguidMediaType1, gobjTerminal1)
Set MediaTerminals(1) = gobjTapi.CreateMediaTerminal( _
gguidMediaType2, gobjTerminal2)
objCallControl.SelectMediaTerminals (MediaTerminals)

Set MediaTerminals(0) = Nothing
Set MediaTerminals(1) = Nothing
Set gobjTerminal1 = Nothing
Set gobjTerminal2 = Nothing


'Answer
objCallControl.Answer

'disable the button
pbAnswer(0).Enabled = False

'release the call control interface
Set objCallControl = Nothing

End Sub

Private Sub pbDisconnect_Click(index As Integer)

If gobjReceivedCallInfo Is Nothing Then
Dim strMsg As String
strMsg = "There is no call to be disconnected."
lblStatus.Caption = strMsg
Exit Sub
End If

'disconnect the call: need to query its call control interface for this
Dim objCallControl As ITBasicCallControl

Set objCallControl = gobjReceivedCallInfo

objCallControl.Disconnect (DC_NORMAL)

'release the call control interface
Set objCallControl = Nothing

End Sub

'this "callback" function must be reentrant
Private Sub gobjAddressWithEvents_CallEventNotification(ByVal pAddress As TAPI3Lib.ITAddress, ByVal CallEventType As TAPI3Lib.CALL_EVENT_TYPE, ByVal pEvent As Object)

Dim strMsg

If CallEventType = CET_CALLOWNER Then

gbSupportedCall = True

If Not (gobjReceivedCallInfo Is Nothing) Then
gbSupportedCall = False

strMsg = "This app doesn't support a second call. "
strMsg = strMsg & "Unsupported second call will be rejected!"
lblStatus.Caption = strMsg

'pEvent is declared as Object, so for using it you must
'query its call control interface, ITBasicCallControl
Dim objReceivedCallControl As ITBasicCallControl
Set objReceivedCallControl = pEvent

'Reject the not supported call by calling Disconnect
'Note: this second call will arrive only if tapi provider
'supports more than 1 call per address.
Dim code As DISCONNECT_CODE
code = DC_REJECTED
objReceivedCallControl.Disconnect (code)

'release all objects that are not needed any longer
'it is important to release also the received object pEvent

Set objReceivedCallControl = Nothing
Set pEvent = Nothing

Exit Sub
End If

'query ITCallInfo interface from pEvent, and store it
Set gobjReceivedCallInfo = pEvent

'reenable the button
pbAnswer(0).Enabled = True

End If

If CallEventType = CET_CALLSTATEEVENT Then

'for this type of event, the object pEvent must be
'queried for its ITCallStateEvent interface
Dim objCallStateEvent As ITCallStateEvent
Set objCallStateEvent = pEvent

Dim State As CALL_STATE
Dim objEventCallInfo As ITCallInfo

'extract the call object from pEvent (from its
'ITCallStateEvent interface)
Set objEventCallInfo = objCallStateEvent.Call
State = objCallStateEvent.State

DisplayCallState (State)

If objEventCallInfo Is gobjReceivedCallInfo Then

If State = CS_DISCONNECTED Then
'after call is disconnected, you don't need
'its object anymore; you can only release it
Set gobjReceivedCallInfo = Nothing
End If

End If

'release not needed objects
Set objEventCallInfo = Nothing
Set objCallStateEvent = Nothing
End If

'always release the received pEvent
Set pEvent = Nothing
Exit Sub
End Sub

Private Sub RegisterForReceiveCall_Click()

If Not (gobjTapi Is Nothing) Then
Dim strMsg
strMsg = "You already did that :-)"
strMsg = strMsg & Chr(13)
strMsg = strMsg & "Restart the app if you want to register another address."
lblStatus.Caption = strMsg
Exit Sub
End If

RegisterForReceiveCall.MousePointer = vbHourglass

'create the tapi object
Set gobjTapi = New TAPI

'call Initialize before calling any other tapi function
gobjTapi.Initialize

'pick up the collection of addresses
Dim objcollAddress As ITCollection
Set objcollAddress = gobjTapi.Addresses

'search address that supports the desired address type
Dim nAddressIndex
nAddressIndex = FindAddressIndex(objcollAddress)

If nAddressIndex < 1 Or nAddressIndex > objcollAddress.Count Then

strMsg = "Could not find an appropriate address for this address type!" & _
Chr(13) & "Need 2 media types at least to be available on that address."
lblStatus.Caption = strMsg

'release all objects
Set objcollAddress = Nothing
If Not (gobjTapi Is Nothing) Then
gobjTapi.Shutdown
End If
Set gobjTapi = Nothing
RegisterForReceiveCall.MousePointer = vbDefault
Exit Sub
End If

'pick up the "N"-th address - the address on which
'you want to receive calls
Set gobjDestAddress = objcollAddress.Item(nAddressIndex)
Set objcollAddress = Nothing 'no more needed, release

'
'pick up first 2 media types supported by this address
'

Dim objMediaSupport As ITMediaSupport
Dim objCollMediaTypes As ITCollection

'query ITMediaSupport interface from Address object
Set objMediaSupport = gobjDestAddress

'pick up the collection of media types
Set objCollMediaTypes = objMediaSupport.MediaTypes

gguidMediaType1 = objCollMediaTypes.Item(1)
gguidMediaType2 = objCollMediaTypes.Item(2)

'release not needed objects
Set objMediaSupport = Nothing
Set objCollMediaTypes = Nothing

'
'pick up the default terminal for each media type
'

' Dim objTerminalSupport As ITTerminalSupport
'
' 'query ITTerminalSupport from Address object
' Set objTerminalSupport = gobjDestAddress
'
' Set gobjTerminal1 = objTerminalSupport.GetDefaultTerminal(gguidMediaType1)
' Set gobjTerminal2 = objTerminalSupport.GetDefaultTerminal(gguidMediaType2)
'
' 'release not needed objects
' Set objTerminalSupport = Nothing
'
'register (specify) media types for which you want
'to receive calls;
'only calls that have this media type will be offered to the app
'the media types must be passed to RegisterCallTypes in
'an array contained in a variant
Dim arrMediaTypes(0 To 1) As String
Dim bOutgoing, bOwner, bMonitor
Dim MediaTypes As Variant
bOutgoing = False
'bOwner = True ensures that app receives incoming calls
'and their call state events
bOwner = True
bMonitor = False
arrMediaTypes(0) = gguidMediaType1
arrMediaTypes(1) = gguidMediaType2
MediaTypes = arrMediaTypes
Call gobjDestAddress.RegisterCallTypes(bOutgoing, bOwner, _
bMonitor, MediaTypes)

'register the outgoing interface (the one that will actually
'receive and process the events)
On Error Resume Next
Set gobjAddressWithEvents = gobjDestAddress
If Err.Number <> 0 Then
strMsg = "Registering for receiving calls failed." & Chr(13) & _
"If you have a data modem, replace it with a voice modem"
strMsg = strMsg & "Quit the app and try again."
lblStatus.Caption = strMsg
RegisterForReceiveCall.MousePointer = vbDefault
Exit Sub
End If

'from now on the app is able to receive calls made on the
'specified address, with the specified media type

RegisterForReceiveCall.MousePointer = vbDefault

lblStatus.Caption = "Waiting for a call..."

End Sub

'Search through all addresses and return the index of the one that matches
'the address type selected in the combo box with address types. Also, the
'found address must support at least 2 media types (so that later we can
'safely use the first and second media type).
'Note: usually, the first 2 media types are "audio in" and "audio out".
'Return 0 if no address found. Otherwise return its index, which will be
'between 1 and Addresses.Count
Private Function FindAddressIndex(objCollAddresses As ITCollection) As Long
Dim nSelectedType As Long
Dim indexAddr As Long, indexType As Long
Dim objCrtAddress As Address
Dim objCollAddrTypes As ITCollection
Dim objMediaSupport As ITMediaSupport
Dim objCollMediaTypes As ITCollection
Dim bFound As Boolean

'
'retrieve from combo box the type of the selected address type
'
nSelectedType = cmbAddressTypes.ItemData(cmbAddressTypes.ListIndex)

'
'search through all addresses the first one that matches this type
'and also supports at least one media type
'
bFound = False

For indexAddr = 1 To objCollAddresses.Count
Set objCrtAddress = objCollAddresses.Item(indexAddr)
Set objMediaSupport = objCrtAddress
Set objCollMediaTypes = objMediaSupport.MediaTypes

If objCollMediaTypes.Count >= 2 Then
Set objCollAddrTypes = objCrtAddress.AddressTypes

For indexType = 1 To objCollAddrTypes.Count
If nSelectedType = objCollAddrTypes.Item(indexType) Then
bFound = True
Exit For
End If
Next indexType

Set objCollAddrTypes = Nothing
End If

Set objCollMediaTypes = Nothing
Set objMediaSupport = Nothing
Set objCrtAddress = Nothing

If bFound = True Then Exit For
Next indexAddr

'
'return the index of the found address, or 0 if no address found
'
If bFound = True Then
FindAddressIndex = indexAddr
Else
FindAddressIndex = 0
End If
Exit Function
End Function