YisMan
2007-09-03 19:46:00 UTC
Hello everyone,
First thanks again to Grant Schenck and Matthias Moetje for their input on
my previous post, titled "Monitor Incoming Calls in MS Access". With their
guidance I progressed my code pretty much.
Now to the current problem. The code that I have now recognizes incoming
calls, but occasionally retrieves the Caller ID info, though most of the time
doesn't. The code is below. I'm working on this for weeks, but not making any
progress.
It seems to me that the problem is that the registration gets lost after the
call to the CallInfoObject.Call.CallInfoString method. thats why Iput a
"Register" call after each call to "CallInfoString". On the other hand my
googling tells me that all TAPI object must be completely destroyed between
each call to CallInfoString. So I'm torn balancing between destruction and
reregistration, which are pretty much two opposites, and have'nt found the
right mix yet.
Another oddity, which I'm not positive about, and is difficult to test for
sure. Sometimes when the TE_CALLINFOCHANGE is raised in debugging mode (due
to a breakpoint) then it actually DOES get Caller ID. As if it is a timing
problem.
The entire code is simply a class module which I call MCHTapi. I have one
more line of code, that is a global variable declared in a regular module as
such:
Public mTAPI As New MCHTapi
Here is the entire code as is. My greatest appreciation to all who are
taking the time to read this and respond to it.
Option Explicit
Const MediaAudio As Integer = 8
Const MediaModem As Integer = 16
Const MediaFax As Integer = 32
Const MediaVideo As Long = 32768
Public WithEvents oTAPI As TAPI3Lib.TAPI ' will hold our TAPI object
'Private oAddress As ITAddress ' will hold our selected address (you can
hold many address in an array)
Private RegCookie As Integer
Private CallNotificationObject As ITCallNotificationEvent
Private CallStateObject As ITCallStateEvent
Private CallInfoObject As ITCallInfoChangeEvent
Private CurrentCallerID As String
Dim MediaTypes As Long
'property let NewTAPI as TAPI3Lib.TAPI
'Public Property Let NewTAPI(objTapi As TAPI)
'Set oTAPI = objTapi
'Setup
'End Property
'Public Property Get NewTAPI() As TAPI3Lib.TAPI
'Set NewTAPI = oTAPI
'End Property
Sub Setup()
'Reset
Initialize
Register
End Sub
Private Sub oTAPI_Event(ByVal TapiEvent As TAPI3Lib.TAPI_EVENT, ByVal pEvent
As Object)
' If Not CallInfoObject Is Nothing Then Debug.Print
CallInfoObject.Call.CallInfoString(CIS_CALLERIDNUMBER)
'Debug.Print "Type " & TapiEvent & " Event Raised at " & Time()
Select Case TapiEvent
Case TE_TAPIOBJECT '1
Debug.Print "TE_TAPIOBJECT Event Raised at " & Time()
Case TE_ADDRESS '2
Debug.Print "TE_ADDRESS Event Raised at " & Time()
Case TE_CALLNOTIFICATION '4
Debug.Print "TE_CALLNOTIFICATION Event Raised at " & Time()
Set CallNotificationObject = pEvent
CallNotificationEvent
Case TE_CALLSTATE '8
Debug.Print "TE_CALLSTATE Event Raised at " & Time()
Set CallStateObject = pEvent
CallStateEvent
Case TE_CALLMEDIA '16
Debug.Print "TE_CALLMEDIA Event Raised at " & Time()
Case TE_CALLHUB '32
Debug.Print "TE_CALLHUB Event Raised at " & Time()
Case TE_CALLINFOCHANGE '64
Debug.Print "TE_CALLINFOCHANGE Event Raised at " & Time()
Set CallInfoObject = pEvent
CallInfoEvent
Case TE_PRIVATE '128
Debug.Print "TE_PRIVATE Event Raised at " & Time()
Case TE_REQUEST '256
Debug.Print "TE_REQUEST Event Raised at " & Time()
Case TE_AGENT '512
Debug.Print "TE_AGENT Event Raised at " & Time()
Case TE_AGENTSESSION '1024
Debug.Print "TE_AGENTSESSION Event Raised at " & Time()
Case TE_QOSEVENT '2048
Debug.Print "TE_QOSEVENT Event Raised at " & Time()
Case TE_AGENTHANDLER '4096
Debug.Print "TE_AGENTHANDLER Event Raised at " & Time()
Case TE_ACDGROUP '8192
Debug.Print "TE_ACDGROUP Event Raised at " & Time()
Case TE_QUEUE '16384
Debug.Print "TE_QUEUE Event Raised at " & Time()
Case TE_DIGITEVENT '32768
Debug.Print "TE_DIGITEVENT Event Raised at " & Time()
Case TE_GENERATEEVENT '65536
Debug.Print "TE_DIGITEVENT Event Raised at " & Time()
Case TE_ASRTERMINAL '131072
Debug.Print "TE_ASRTERMINAL Event Raised at " & Time()
Case TE_TTSTERMINAL '262144
Debug.Print "TE_TTSTERMINAL Event Raised at " & Time()
Case TE_FILETERMINAL '524288
Debug.Print "TE_FILETERMINAL Event Raised at " & Time()
Case TE_TONETERMINAL '1048576
Debug.Print "TE_TONETERMINAL Event Raised at " & Time()
Case TE_PHONEEVENT '2097152
Debug.Print "TE_PHONEEVENT Event Raised at " & Time()
Case TE_TONEEVENT '4194304
Debug.Print "TE_TONEEVENT Event Raised at " & Time()
Case TE_GATHERDIGITS '8388608
Debug.Print "TE_GATHERDIGITS Event Raised at " & Time()
Case TE_ADDRESSDEVSPECIFIC '16777216
Debug.Print "TE_ADDRESSDEVSPECIFIC Event Raised at " & Time()
Case TE_PHONEDEVSPECIFIC '33554432
Debug.Print "TE_PHONEDEVSPECIFIC Event Raised at " & Time()
End Select
'ResetTapi
'On Error Resume Next
'Debug.Print CallInfoObject.Call.CallInfoString(CIS_CALLERIDNUMBER)
End Sub
Private Sub CallNotificationEvent()
' here we should check to see various notifications of new and ended calls
Debug.Print "CallNotificationEvent Type " & CallNotificationObject.Event & "
" & Time()
Select Case CallNotificationObject.Event
Case CNE_MONITOR
' the notification is for a monitored call
Debug.Print "Call Notification: CNE_MONITOR " & Time()
Case CNE_OWNER
' the notification is for an owned call
Debug.Print "Call Notification: CNE_OWNER " & Time()
End Select
Set CallNotificationObject = Nothing
End Sub
Private Sub CallStateEvent()
'Debug.Print "CallStateEvent Called " & Now()
' here we should check to see call state and handle connects and
disconnects
Select Case CallStateObject.State
Case CALL_STATE.CS_IDLE '0
Debug.Print "Call State: CS_IDLE " & Time()
Case CALL_STATE.CS_INPROGRESS '1
Debug.Print "Call State: CS_INPROGRESS " & Time()
Case CALL_STATE.CS_OFFERING '4
Debug.Print "Call State: CS_OFFERING " & Time()
' a call is offering so if you dont want it then pass it
' the code to pass the call is the following
'Dim CallControl As ITBasicCallControl = CallStateObject.Call
'CallControl.HandoffIndirect
(CallStateObject.Call.CallInfoLong(CALLINFO_LONG.CIL_MEDIATYPESAVAILABLE)
Case CALL_STATE.CS_CONNECTED '2
Debug.Print "Call State: CS_CONNECTED " & Time()
' call is connected
Case CALL_STATE.CS_QUEUED
Debug.Print "Call State: CS_QUEUED " & Time()
' call is beeing queued
Case CALL_STATE.CS_HOLD
Debug.Print "Call State: CS_HOLD " & Time()
' call is on hold
Case CALL_STATE.CS_DISCONNECTED
CurrentCallerID = ""
Debug.Print "Call State: CS_DISCONNECTED " & Time()
'Register
' call is disconnected
End Select
Set CallStateObject = Nothing
End Sub
Private Sub CallInfoEvent()
Debug.Print "CallInfoEvent Called " & Time()
Dim CallerID As String
On Error Resume Next
CallerID = Nz(CallInfoObject.Call.CallInfoString(CIS_CALLERIDNUMBER), "")
On Error GoTo 0
Application.SysCmd acSysCmdSetStatus, "CID: " & CallerID
'Set CallInfoObject = Nothing
If CallerID = "" Or CallerID = CurrentCallerID Then GoTo Finish
Debug.Print "Last Caller: " & CurrentCallerID
CurrentCallerID = CallerID
'If CallerID = "" Then CallerID = "0527649971"
Debug.Print "Caller ID: "; CallerID
CallerID = Canonical(CallerID)
Dim PersonID As Integer
PersonID = Nz(DLookup("personid", "persons", "instr(phone1 & '|' &
phone2 & '|' & phonework & '|' & cell1 & '|' & cell2 & '|' & cell3 & '|' &
fax1 & '|' & fax2,'" & CallerID & "')"))
If PersonID = 0 Then GoTo Finish
DoCmd.OpenForm "frperson", , , "personid=" & PersonID
Forms("frperson").lbCalling.Visible = True
Application.SysCmd acSysCmdClearStatus
'ResetTapi
Finish:
Shutdown
Initialize
Register
End Sub
Sub Shutdown()
oTAPI.Shutdown
Set oTAPI = Nothing
Set CallNotificationObject = Nothing
Set CallStateObject = Nothing
Set CallInfoObject = Nothing
End Sub
Sub Register()
Dim Address As ITAddress
Dim oAddress As ITAddress
For Each Address In oTAPI.Addresses ' AddressCollection ' looping
through address collection
If Address.State = ADDRESS_STATE.AS_INSERVICE Then ' checking if
address is working
Dim MediaSupport As ITMediaSupport
Set MediaSupport = Address ' extracting meida support interface
from the address
MediaTypes = MediaSupport.MediaTypes ' extracting media types
supporting
Set MediaSupport = Nothing ' dispose of the object
If (MediaTypes And MediaModem) = MediaModem Then
If (MediaTypes And MediaAudio) = MediaAudio Then
Set oAddress = Address ' select this address
Exit For
End If
End If
End If
Next Address
If oAddress Is Nothing Then Exit Sub
Debug.Print "Registered at " & Time()
RegCookie = oTAPI.RegisterCallNotifications(oAddress, True, False,
MediaTypes, 1)
oTAPI.EventFilter = (1 Or 2 Or 4 Or 8 Or 16 Or 32 Or 64 Or 128 Or 256 Or
512 Or 1024 Or 2048 Or _
4096 Or 8192 Or 16384 Or 32768 Or 65536 Or 131072 Or 262144 Or
524288 Or 1048576 Or 2097152 Or 4194304 Or _
8388608 Or 16777216 Or 33554432)
End Sub
Sub Initialize()
Dim m_TAPI As New TAPI
m_TAPI.Initialize
Set oTAPI = m_TAPI
Set m_TAPI = Nothing
End Sub
Thankfully, YisMan
--Ever stop to think, and then forget to start again?
First thanks again to Grant Schenck and Matthias Moetje for their input on
my previous post, titled "Monitor Incoming Calls in MS Access". With their
guidance I progressed my code pretty much.
Now to the current problem. The code that I have now recognizes incoming
calls, but occasionally retrieves the Caller ID info, though most of the time
doesn't. The code is below. I'm working on this for weeks, but not making any
progress.
It seems to me that the problem is that the registration gets lost after the
call to the CallInfoObject.Call.CallInfoString method. thats why Iput a
"Register" call after each call to "CallInfoString". On the other hand my
googling tells me that all TAPI object must be completely destroyed between
each call to CallInfoString. So I'm torn balancing between destruction and
reregistration, which are pretty much two opposites, and have'nt found the
right mix yet.
Another oddity, which I'm not positive about, and is difficult to test for
sure. Sometimes when the TE_CALLINFOCHANGE is raised in debugging mode (due
to a breakpoint) then it actually DOES get Caller ID. As if it is a timing
problem.
The entire code is simply a class module which I call MCHTapi. I have one
more line of code, that is a global variable declared in a regular module as
such:
Public mTAPI As New MCHTapi
Here is the entire code as is. My greatest appreciation to all who are
taking the time to read this and respond to it.
Option Explicit
Const MediaAudio As Integer = 8
Const MediaModem As Integer = 16
Const MediaFax As Integer = 32
Const MediaVideo As Long = 32768
Public WithEvents oTAPI As TAPI3Lib.TAPI ' will hold our TAPI object
'Private oAddress As ITAddress ' will hold our selected address (you can
hold many address in an array)
Private RegCookie As Integer
Private CallNotificationObject As ITCallNotificationEvent
Private CallStateObject As ITCallStateEvent
Private CallInfoObject As ITCallInfoChangeEvent
Private CurrentCallerID As String
Dim MediaTypes As Long
'property let NewTAPI as TAPI3Lib.TAPI
'Public Property Let NewTAPI(objTapi As TAPI)
'Set oTAPI = objTapi
'Setup
'End Property
'Public Property Get NewTAPI() As TAPI3Lib.TAPI
'Set NewTAPI = oTAPI
'End Property
Sub Setup()
'Reset
Initialize
Register
End Sub
Private Sub oTAPI_Event(ByVal TapiEvent As TAPI3Lib.TAPI_EVENT, ByVal pEvent
As Object)
' If Not CallInfoObject Is Nothing Then Debug.Print
CallInfoObject.Call.CallInfoString(CIS_CALLERIDNUMBER)
'Debug.Print "Type " & TapiEvent & " Event Raised at " & Time()
Select Case TapiEvent
Case TE_TAPIOBJECT '1
Debug.Print "TE_TAPIOBJECT Event Raised at " & Time()
Case TE_ADDRESS '2
Debug.Print "TE_ADDRESS Event Raised at " & Time()
Case TE_CALLNOTIFICATION '4
Debug.Print "TE_CALLNOTIFICATION Event Raised at " & Time()
Set CallNotificationObject = pEvent
CallNotificationEvent
Case TE_CALLSTATE '8
Debug.Print "TE_CALLSTATE Event Raised at " & Time()
Set CallStateObject = pEvent
CallStateEvent
Case TE_CALLMEDIA '16
Debug.Print "TE_CALLMEDIA Event Raised at " & Time()
Case TE_CALLHUB '32
Debug.Print "TE_CALLHUB Event Raised at " & Time()
Case TE_CALLINFOCHANGE '64
Debug.Print "TE_CALLINFOCHANGE Event Raised at " & Time()
Set CallInfoObject = pEvent
CallInfoEvent
Case TE_PRIVATE '128
Debug.Print "TE_PRIVATE Event Raised at " & Time()
Case TE_REQUEST '256
Debug.Print "TE_REQUEST Event Raised at " & Time()
Case TE_AGENT '512
Debug.Print "TE_AGENT Event Raised at " & Time()
Case TE_AGENTSESSION '1024
Debug.Print "TE_AGENTSESSION Event Raised at " & Time()
Case TE_QOSEVENT '2048
Debug.Print "TE_QOSEVENT Event Raised at " & Time()
Case TE_AGENTHANDLER '4096
Debug.Print "TE_AGENTHANDLER Event Raised at " & Time()
Case TE_ACDGROUP '8192
Debug.Print "TE_ACDGROUP Event Raised at " & Time()
Case TE_QUEUE '16384
Debug.Print "TE_QUEUE Event Raised at " & Time()
Case TE_DIGITEVENT '32768
Debug.Print "TE_DIGITEVENT Event Raised at " & Time()
Case TE_GENERATEEVENT '65536
Debug.Print "TE_DIGITEVENT Event Raised at " & Time()
Case TE_ASRTERMINAL '131072
Debug.Print "TE_ASRTERMINAL Event Raised at " & Time()
Case TE_TTSTERMINAL '262144
Debug.Print "TE_TTSTERMINAL Event Raised at " & Time()
Case TE_FILETERMINAL '524288
Debug.Print "TE_FILETERMINAL Event Raised at " & Time()
Case TE_TONETERMINAL '1048576
Debug.Print "TE_TONETERMINAL Event Raised at " & Time()
Case TE_PHONEEVENT '2097152
Debug.Print "TE_PHONEEVENT Event Raised at " & Time()
Case TE_TONEEVENT '4194304
Debug.Print "TE_TONEEVENT Event Raised at " & Time()
Case TE_GATHERDIGITS '8388608
Debug.Print "TE_GATHERDIGITS Event Raised at " & Time()
Case TE_ADDRESSDEVSPECIFIC '16777216
Debug.Print "TE_ADDRESSDEVSPECIFIC Event Raised at " & Time()
Case TE_PHONEDEVSPECIFIC '33554432
Debug.Print "TE_PHONEDEVSPECIFIC Event Raised at " & Time()
End Select
'ResetTapi
'On Error Resume Next
'Debug.Print CallInfoObject.Call.CallInfoString(CIS_CALLERIDNUMBER)
End Sub
Private Sub CallNotificationEvent()
' here we should check to see various notifications of new and ended calls
Debug.Print "CallNotificationEvent Type " & CallNotificationObject.Event & "
" & Time()
Select Case CallNotificationObject.Event
Case CNE_MONITOR
' the notification is for a monitored call
Debug.Print "Call Notification: CNE_MONITOR " & Time()
Case CNE_OWNER
' the notification is for an owned call
Debug.Print "Call Notification: CNE_OWNER " & Time()
End Select
Set CallNotificationObject = Nothing
End Sub
Private Sub CallStateEvent()
'Debug.Print "CallStateEvent Called " & Now()
' here we should check to see call state and handle connects and
disconnects
Select Case CallStateObject.State
Case CALL_STATE.CS_IDLE '0
Debug.Print "Call State: CS_IDLE " & Time()
Case CALL_STATE.CS_INPROGRESS '1
Debug.Print "Call State: CS_INPROGRESS " & Time()
Case CALL_STATE.CS_OFFERING '4
Debug.Print "Call State: CS_OFFERING " & Time()
' a call is offering so if you dont want it then pass it
' the code to pass the call is the following
'Dim CallControl As ITBasicCallControl = CallStateObject.Call
'CallControl.HandoffIndirect
(CallStateObject.Call.CallInfoLong(CALLINFO_LONG.CIL_MEDIATYPESAVAILABLE)
Case CALL_STATE.CS_CONNECTED '2
Debug.Print "Call State: CS_CONNECTED " & Time()
' call is connected
Case CALL_STATE.CS_QUEUED
Debug.Print "Call State: CS_QUEUED " & Time()
' call is beeing queued
Case CALL_STATE.CS_HOLD
Debug.Print "Call State: CS_HOLD " & Time()
' call is on hold
Case CALL_STATE.CS_DISCONNECTED
CurrentCallerID = ""
Debug.Print "Call State: CS_DISCONNECTED " & Time()
'Register
' call is disconnected
End Select
Set CallStateObject = Nothing
End Sub
Private Sub CallInfoEvent()
Debug.Print "CallInfoEvent Called " & Time()
Dim CallerID As String
On Error Resume Next
CallerID = Nz(CallInfoObject.Call.CallInfoString(CIS_CALLERIDNUMBER), "")
On Error GoTo 0
Application.SysCmd acSysCmdSetStatus, "CID: " & CallerID
'Set CallInfoObject = Nothing
If CallerID = "" Or CallerID = CurrentCallerID Then GoTo Finish
Debug.Print "Last Caller: " & CurrentCallerID
CurrentCallerID = CallerID
'If CallerID = "" Then CallerID = "0527649971"
Debug.Print "Caller ID: "; CallerID
CallerID = Canonical(CallerID)
Dim PersonID As Integer
PersonID = Nz(DLookup("personid", "persons", "instr(phone1 & '|' &
phone2 & '|' & phonework & '|' & cell1 & '|' & cell2 & '|' & cell3 & '|' &
fax1 & '|' & fax2,'" & CallerID & "')"))
If PersonID = 0 Then GoTo Finish
DoCmd.OpenForm "frperson", , , "personid=" & PersonID
Forms("frperson").lbCalling.Visible = True
Application.SysCmd acSysCmdClearStatus
'ResetTapi
Finish:
Shutdown
Initialize
Register
End Sub
Sub Shutdown()
oTAPI.Shutdown
Set oTAPI = Nothing
Set CallNotificationObject = Nothing
Set CallStateObject = Nothing
Set CallInfoObject = Nothing
End Sub
Sub Register()
Dim Address As ITAddress
Dim oAddress As ITAddress
For Each Address In oTAPI.Addresses ' AddressCollection ' looping
through address collection
If Address.State = ADDRESS_STATE.AS_INSERVICE Then ' checking if
address is working
Dim MediaSupport As ITMediaSupport
Set MediaSupport = Address ' extracting meida support interface
from the address
MediaTypes = MediaSupport.MediaTypes ' extracting media types
supporting
Set MediaSupport = Nothing ' dispose of the object
If (MediaTypes And MediaModem) = MediaModem Then
If (MediaTypes And MediaAudio) = MediaAudio Then
Set oAddress = Address ' select this address
Exit For
End If
End If
End If
Next Address
If oAddress Is Nothing Then Exit Sub
Debug.Print "Registered at " & Time()
RegCookie = oTAPI.RegisterCallNotifications(oAddress, True, False,
MediaTypes, 1)
oTAPI.EventFilter = (1 Or 2 Or 4 Or 8 Or 16 Or 32 Or 64 Or 128 Or 256 Or
512 Or 1024 Or 2048 Or _
4096 Or 8192 Or 16384 Or 32768 Or 65536 Or 131072 Or 262144 Or
524288 Or 1048576 Or 2097152 Or 4194304 Or _
8388608 Or 16777216 Or 33554432)
End Sub
Sub Initialize()
Dim m_TAPI As New TAPI
m_TAPI.Initialize
Set oTAPI = m_TAPI
Set m_TAPI = Nothing
End Sub
Thankfully, YisMan
--Ever stop to think, and then forget to start again?