S
StevenVibert
I'm rewriting a C++ TAPI app I wrote a while ago in C#. Everything
works fine for the first call. Unfortunately, all subsequent calls are
completely ignored by TAPI until I restart the app again.
I remember running into this same problem with my original C++ code and
it was being caused by my failure to release all call related tapi
resources. As a point of reference the C++ app has been running quite
well for over a year.
Anyway, I beleive I'm releasing all the tapi interfaces when I'm done
with them but nothing I've done has solved the problem. I'm at a
complete loss as to what might be causing the problem. Any thoughts
would be greatly appreciated.
Here's the code:
========================
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using TAPI3Lib;
namespace CallManager
{
/// <summary>
/// Summary description for TapiMsgWindow.
/// </summary>
public class TapiMsgWindow : System.Windows.Forms.Form
{
public delegate void TapiInitializationDelegate(object sender, bool
success);
public event TapiInitializationDelegate TapiInitialization;
public delegate void CallNotificationDelegate(object sender);
public event CallNotificationDelegate CallNotification;
public delegate void CallStateDelegate(object sender,
TAPI3Lib.CALL_STATE callState);
public event CallStateDelegate CallState;
public delegate void CallInfoDelegate(object sender,
CALLINFOCHANGE_CAUSE cic);
public event CallInfoDelegate CallInfo;
public delegate void CallerIDEventDelegate(object sender,
CallerIDInfo cidInfo);
public event CallerIDEventDelegate CallerIDEvent;
public enum MEDIATYPE
{
MediaAudio = 8,
MediaModem = 16,
MediaFax = 32,
MediaVideo = 32768,
}
private MainForm _ParentForm = null;
private TAPI3Lib.TAPIClass _TAPI = null;
private ITAddress ListenAddress = null;
private ITBasicCallControl Call = null;
private int RegEventsResult = -1;
private int mediaTypes = 0;
private bool IsNewCall = false;
private int CurrentRingCount = 0;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
public TapiMsgWindow()
{
InitializeComponent();
}
public TapiMsgWindow(MainForm parentForm) : this()
{
_ParentForm = parentForm;
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
_TAPI.UnregisterNotifications(RegEventsResult);
_TAPI.Shutdown();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.Size = new System.Drawing.Size(300,300);
this.Text = "TapiMsgWindow";
}
#endregion
public bool InitTAPI()
{
bool result = false;
_TAPI = new TAPI3Lib.TAPIClass();
try
{
_TAPI.Initialize();
_TAPI.Event += new
ITTAPIDispatchEventNotification_EventEventHandler(OnTapiEvent);
result = SelectAddress();
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
result = false;
}
if(TapiInitialization != null)
TapiInitialization(this, result);
return result;
}
private bool SelectAddress()
{
bool result = false;
ITCollection addresses = (ITCollection)_TAPI.Addresses;
ITAddress curAddress = null;
ListenAddress = null;
//Careful here. The array is 1 based NOT 0 based;
for(int i = 1; i <= addresses.Count; i++)
{
curAddress = (ITAddress)addresses;
if(curAddress.State == ADDRESS_STATE.AS_INSERVICE)
{
ITMediaSupport mediaSupport = (ITMediaSupport)curAddress;
// Get the supported media types...
mediaTypes = mediaSupport.MediaTypes;
mediaSupport = null;
if((mediaTypes & (int)MEDIATYPE.MediaAudio) ==
(int)MEDIATYPE.MediaAudio)
{
ListenAddress = curAddress;
break;
}
}
}
// Did we find the address we were looking for?
if(ListenAddress != null)
{
RegEventsResult = _TAPI.RegisterCallNotifications(ListenAddress,
true, true, mediaTypes, 1);
_TAPI.EventFilter = (int)(
TAPI_EVENT.TE_CALLNOTIFICATION |
TAPI_EVENT.TE_CALLSTATE |
TAPI_EVENT.TE_DIGITEVENT |
TAPI_EVENT.TE_CALLINFOCHANGE |
TAPI_EVENT.TE_ADDRESS
);
}
else
{
MessageBox.Show("No TAPI address selected");
result = false;
}
result = true;
return result;
}
private void OnTapiEvent(TAPI_EVENT TapiEvent, object pEvent)
{
switch(TapiEvent)
{
case TAPI_EVENT.TE_CALLSTATE:
{
OnCallStateEvent((ITCallStateEvent)pEvent);
break;
}
case TAPI_EVENT.TE_ADDRESS:
{
OnAddressEvent((ITAddressEvent)pEvent);
break;
}
case TAPI_EVENT.TE_CALLNOTIFICATION:
{
OnCallNotifyEvent((ITCallNotificationEvent)pEvent);
break;
}
case TAPI_EVENT.TE_CALLINFOCHANGE:
{
OnCallInfoEvent((ITCallInfoChangeEvent)pEvent);
break;
}
case TAPI_EVENT.TE_PHONEEVENT:
{
Marshal.ReleaseComObject(pEvent);
break;
}
case TAPI_EVENT.TE_DIGITEVENT:
{
OnDigitEvent((ITDigitDetectionEvent)pEvent);
break;
}
case TAPI_EVENT.TE_GATHERDIGITS:
{
OnGatherDigits((ITDigitsGatheredEvent)pEvent);
break;
}
case TAPI_EVENT.TE_CALLMEDIA:
{
OnCallMediaChanged((ITCallMediaEvent)pEvent);
break;
}
case TAPI_EVENT.TE_TONEEVENT:
{
OnCallToneEvent((ITToneDetectionEvent)pEvent);
break;
}
default:
{
Marshal.ReleaseComObject(pEvent);
break;
}
}
}
private void OnCallInfoEvent(ITCallInfoChangeEvent pEvent)
{
Console.WriteLine("CallInfoEvent:");
Console.WriteLine(pEvent.Cause.ToString());
if(CallInfo != null)
CallInfo(this, pEvent.Cause);
try
{
if(pEvent.Cause == CALLINFOCHANGE_CAUSE.CIC_CALLERID)
{
if(CurrentRingCount >= 2)
{
string callerIDName =
pEvent.Call.get_CallInfoString(CALLINFO_STRING.CIS_CALLERIDNAME);
string callerIDNumber =
pEvent.Call.get_CallInfoString(CALLINFO_STRING.CIS_CALLERIDNUMBER);
CallerIDInfo cidInfo = new CallerIDInfo(callerIDNumber,
callerIDName);
if(CallerIDEvent != null)
CallerIDEvent(this, cidInfo);
}
}
}
catch(Exception ex)
{
MessageBox.Show(string.Format("CallInfoEvent failed with the
following exception:{0}", ex.Message));
}
finally
{
Marshal.ReleaseComObject(pEvent);
}
}
private void OnDigitEvent(ITDigitDetectionEvent pEvent)
{
try
{
byte digit = pEvent.Digit;
int digitMode = pEvent.DigitMode;
}
finally
{
Marshal.ReleaseComObject(pEvent);
}
}
private void OnGatherDigits(ITDigitsGatheredEvent pEvent)
{
try
{
}
finally
{
Marshal.ReleaseComObject(pEvent);
}
}
private void OnCallMediaChanged(ITCallMediaEvent pEvent)
{
try
{
}
finally
{
Marshal.ReleaseComObject(pEvent);
}
}
private void OnCallToneEvent(ITToneDetectionEvent pEvent)
{
try
{
}
finally
{
Marshal.ReleaseComObject(pEvent);
}
}
private void OnAddressEvent(ITAddressEvent pEvent)
{
ADDRESS_EVENT addressEvent = pEvent.Event;
Marshal.ReleaseComObject(pEvent);
switch(addressEvent)
{
case ADDRESS_EVENT.AE_RINGING:
{
CurrentRingCount++;
break;
}
}
}
private void OnCallNotifyEvent(ITCallNotificationEvent pEvent)
{
CALL_NOTIFICATION_EVENT callEvent = pEvent.Event;
if(Call != null)
{
Marshal.ReleaseComObject(Call);
Call = null;
}
Call = (ITBasicCallControl)(object)pEvent.Call;
IsNewCall = true;
Marshal.ReleaseComObject(pEvent);
switch(callEvent)
{
case CALL_NOTIFICATION_EVENT.CNE_MONITOR:
{
break;
}
case CALL_NOTIFICATION_EVENT.CNE_OWNER:
{
break;
}
}
if(CallNotification != null)
CallNotification(this);
}
private void OnCallStateEvent(ITCallStateEvent pEvent)
{
CALL_STATE state = pEvent.State;
Marshal.ReleaseComObject(pEvent);
if(CallState != null)
CallState(this, state);
switch(state)
{
case CALL_STATE.CS_IDLE:
{
break;
}
case CALL_STATE.CS_INPROGRESS:
{
break;
}
case CALL_STATE.CS_OFFERING:
{
break;
}
case CALL_STATE.CS_CONNECTED:
{
break;
}
case CALL_STATE.CS_QUEUED:
{
break;
}
case CALL_STATE.CS_HOLD:
{
break;
}
case CALL_STATE.CS_DISCONNECTED:
{
CurrentRingCount = 0;
DisconnectTheCall();
ReleaseTheCall();
IsNewCall = false;
break;
}
}
}
private void DisconnectTheCall()
{
Call.Disconnect(DISCONNECT_CODE.DC_NORMAL);
}
private void ReleaseTheCall()
{
Marshal.ReleaseComObject(Call);
Call = null;
}
}
}
works fine for the first call. Unfortunately, all subsequent calls are
completely ignored by TAPI until I restart the app again.
I remember running into this same problem with my original C++ code and
it was being caused by my failure to release all call related tapi
resources. As a point of reference the C++ app has been running quite
well for over a year.
Anyway, I beleive I'm releasing all the tapi interfaces when I'm done
with them but nothing I've done has solved the problem. I'm at a
complete loss as to what might be causing the problem. Any thoughts
would be greatly appreciated.
Here's the code:
========================
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using TAPI3Lib;
namespace CallManager
{
/// <summary>
/// Summary description for TapiMsgWindow.
/// </summary>
public class TapiMsgWindow : System.Windows.Forms.Form
{
public delegate void TapiInitializationDelegate(object sender, bool
success);
public event TapiInitializationDelegate TapiInitialization;
public delegate void CallNotificationDelegate(object sender);
public event CallNotificationDelegate CallNotification;
public delegate void CallStateDelegate(object sender,
TAPI3Lib.CALL_STATE callState);
public event CallStateDelegate CallState;
public delegate void CallInfoDelegate(object sender,
CALLINFOCHANGE_CAUSE cic);
public event CallInfoDelegate CallInfo;
public delegate void CallerIDEventDelegate(object sender,
CallerIDInfo cidInfo);
public event CallerIDEventDelegate CallerIDEvent;
public enum MEDIATYPE
{
MediaAudio = 8,
MediaModem = 16,
MediaFax = 32,
MediaVideo = 32768,
}
private MainForm _ParentForm = null;
private TAPI3Lib.TAPIClass _TAPI = null;
private ITAddress ListenAddress = null;
private ITBasicCallControl Call = null;
private int RegEventsResult = -1;
private int mediaTypes = 0;
private bool IsNewCall = false;
private int CurrentRingCount = 0;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
public TapiMsgWindow()
{
InitializeComponent();
}
public TapiMsgWindow(MainForm parentForm) : this()
{
_ParentForm = parentForm;
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if(components != null)
{
components.Dispose();
_TAPI.UnregisterNotifications(RegEventsResult);
_TAPI.Shutdown();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.Size = new System.Drawing.Size(300,300);
this.Text = "TapiMsgWindow";
}
#endregion
public bool InitTAPI()
{
bool result = false;
_TAPI = new TAPI3Lib.TAPIClass();
try
{
_TAPI.Initialize();
_TAPI.Event += new
ITTAPIDispatchEventNotification_EventEventHandler(OnTapiEvent);
result = SelectAddress();
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
result = false;
}
if(TapiInitialization != null)
TapiInitialization(this, result);
return result;
}
private bool SelectAddress()
{
bool result = false;
ITCollection addresses = (ITCollection)_TAPI.Addresses;
ITAddress curAddress = null;
ListenAddress = null;
//Careful here. The array is 1 based NOT 0 based;
for(int i = 1; i <= addresses.Count; i++)
{
curAddress = (ITAddress)addresses;
if(curAddress.State == ADDRESS_STATE.AS_INSERVICE)
{
ITMediaSupport mediaSupport = (ITMediaSupport)curAddress;
// Get the supported media types...
mediaTypes = mediaSupport.MediaTypes;
mediaSupport = null;
if((mediaTypes & (int)MEDIATYPE.MediaAudio) ==
(int)MEDIATYPE.MediaAudio)
{
ListenAddress = curAddress;
break;
}
}
}
// Did we find the address we were looking for?
if(ListenAddress != null)
{
RegEventsResult = _TAPI.RegisterCallNotifications(ListenAddress,
true, true, mediaTypes, 1);
_TAPI.EventFilter = (int)(
TAPI_EVENT.TE_CALLNOTIFICATION |
TAPI_EVENT.TE_CALLSTATE |
TAPI_EVENT.TE_DIGITEVENT |
TAPI_EVENT.TE_CALLINFOCHANGE |
TAPI_EVENT.TE_ADDRESS
);
}
else
{
MessageBox.Show("No TAPI address selected");
result = false;
}
result = true;
return result;
}
private void OnTapiEvent(TAPI_EVENT TapiEvent, object pEvent)
{
switch(TapiEvent)
{
case TAPI_EVENT.TE_CALLSTATE:
{
OnCallStateEvent((ITCallStateEvent)pEvent);
break;
}
case TAPI_EVENT.TE_ADDRESS:
{
OnAddressEvent((ITAddressEvent)pEvent);
break;
}
case TAPI_EVENT.TE_CALLNOTIFICATION:
{
OnCallNotifyEvent((ITCallNotificationEvent)pEvent);
break;
}
case TAPI_EVENT.TE_CALLINFOCHANGE:
{
OnCallInfoEvent((ITCallInfoChangeEvent)pEvent);
break;
}
case TAPI_EVENT.TE_PHONEEVENT:
{
Marshal.ReleaseComObject(pEvent);
break;
}
case TAPI_EVENT.TE_DIGITEVENT:
{
OnDigitEvent((ITDigitDetectionEvent)pEvent);
break;
}
case TAPI_EVENT.TE_GATHERDIGITS:
{
OnGatherDigits((ITDigitsGatheredEvent)pEvent);
break;
}
case TAPI_EVENT.TE_CALLMEDIA:
{
OnCallMediaChanged((ITCallMediaEvent)pEvent);
break;
}
case TAPI_EVENT.TE_TONEEVENT:
{
OnCallToneEvent((ITToneDetectionEvent)pEvent);
break;
}
default:
{
Marshal.ReleaseComObject(pEvent);
break;
}
}
}
private void OnCallInfoEvent(ITCallInfoChangeEvent pEvent)
{
Console.WriteLine("CallInfoEvent:");
Console.WriteLine(pEvent.Cause.ToString());
if(CallInfo != null)
CallInfo(this, pEvent.Cause);
try
{
if(pEvent.Cause == CALLINFOCHANGE_CAUSE.CIC_CALLERID)
{
if(CurrentRingCount >= 2)
{
string callerIDName =
pEvent.Call.get_CallInfoString(CALLINFO_STRING.CIS_CALLERIDNAME);
string callerIDNumber =
pEvent.Call.get_CallInfoString(CALLINFO_STRING.CIS_CALLERIDNUMBER);
CallerIDInfo cidInfo = new CallerIDInfo(callerIDNumber,
callerIDName);
if(CallerIDEvent != null)
CallerIDEvent(this, cidInfo);
}
}
}
catch(Exception ex)
{
MessageBox.Show(string.Format("CallInfoEvent failed with the
following exception:{0}", ex.Message));
}
finally
{
Marshal.ReleaseComObject(pEvent);
}
}
private void OnDigitEvent(ITDigitDetectionEvent pEvent)
{
try
{
byte digit = pEvent.Digit;
int digitMode = pEvent.DigitMode;
}
finally
{
Marshal.ReleaseComObject(pEvent);
}
}
private void OnGatherDigits(ITDigitsGatheredEvent pEvent)
{
try
{
}
finally
{
Marshal.ReleaseComObject(pEvent);
}
}
private void OnCallMediaChanged(ITCallMediaEvent pEvent)
{
try
{
}
finally
{
Marshal.ReleaseComObject(pEvent);
}
}
private void OnCallToneEvent(ITToneDetectionEvent pEvent)
{
try
{
}
finally
{
Marshal.ReleaseComObject(pEvent);
}
}
private void OnAddressEvent(ITAddressEvent pEvent)
{
ADDRESS_EVENT addressEvent = pEvent.Event;
Marshal.ReleaseComObject(pEvent);
switch(addressEvent)
{
case ADDRESS_EVENT.AE_RINGING:
{
CurrentRingCount++;
break;
}
}
}
private void OnCallNotifyEvent(ITCallNotificationEvent pEvent)
{
CALL_NOTIFICATION_EVENT callEvent = pEvent.Event;
if(Call != null)
{
Marshal.ReleaseComObject(Call);
Call = null;
}
Call = (ITBasicCallControl)(object)pEvent.Call;
IsNewCall = true;
Marshal.ReleaseComObject(pEvent);
switch(callEvent)
{
case CALL_NOTIFICATION_EVENT.CNE_MONITOR:
{
break;
}
case CALL_NOTIFICATION_EVENT.CNE_OWNER:
{
break;
}
}
if(CallNotification != null)
CallNotification(this);
}
private void OnCallStateEvent(ITCallStateEvent pEvent)
{
CALL_STATE state = pEvent.State;
Marshal.ReleaseComObject(pEvent);
if(CallState != null)
CallState(this, state);
switch(state)
{
case CALL_STATE.CS_IDLE:
{
break;
}
case CALL_STATE.CS_INPROGRESS:
{
break;
}
case CALL_STATE.CS_OFFERING:
{
break;
}
case CALL_STATE.CS_CONNECTED:
{
break;
}
case CALL_STATE.CS_QUEUED:
{
break;
}
case CALL_STATE.CS_HOLD:
{
break;
}
case CALL_STATE.CS_DISCONNECTED:
{
CurrentRingCount = 0;
DisconnectTheCall();
ReleaseTheCall();
IsNewCall = false;
break;
}
}
}
private void DisconnectTheCall()
{
Call.Disconnect(DISCONNECT_CODE.DC_NORMAL);
}
private void ReleaseTheCall()
{
Marshal.ReleaseComObject(Call);
Call = null;
}
}
}