I write an IVR program with tapiex activex v3.6 and i want to get multi-calls per line but in my program when the program is in call and i want to call it at the same time, it is busy! what should i do? should i put the connected call in on hold? if yes when i have to do this? when the program is in call and someone try to call it at the same time, will an event fired up? if yes which event? should my program be multi-thread? i tried to make it multi-thread but this error happened!
'COM object that has been separated from its underlying RCW cannot be used.'
StartIvr();
//UiGlobal.ThreadManager.StartThread(o => StartIvr());
this is my startIvr method
private void StartIvr()
{
UI.Class.IVR.EventHandler eventHandler = new Class.IVR.EventHandler();
eventHandler.InitPhone();
eventHandler.OpenLine(null);
UiGlobal.eventHandler = eventHandler;
}
and this is my event handler class
class EventHandler
{
public List<string> linesName { get; set; }
public AxTAPIEXLib.AxTAPIExCtl Tapiex_com { get; set; }
public bool IsOutputCall = false;
CallHandler callHandler;
public EventHandler()
{
linesName = new List<string>();
Tapiex_com = new AxTAPIEXLib.AxTAPIExCtl();
}
public EventHandler(AxTAPIEXLib.AxTAPIExCtl Tapiex_com)
{
linesName = new List<string>();
this.Tapiex_com = Tapiex_com;
}
public ITAPILine Find_line(string LineName)
{
ITAPILine line = null;
for (int i = 0; i < Tapiex_com.Lines.Count; i++)
if (Tapiex_com.Lines.Item(i).Name == LineName)
{
line = Tapiex_com.Lines.Item(i);
break;
}
return line;
}
protected void Dispose(bool disposing)
{
if (disposing && (Tapiex_com != null))
{
Tapiex_com.Dispose();
}
}
public bool InitPhone()
{
Tapiex_com.CreateControl();
Tapiex_com.OnRing += new AxTAPIEXLib._ITAPIExEvents_OnRingEventHandler(this.Tapiex_com_OnRing);
Tapiex_com.OnDTMF += new AxTAPIEXLib._ITAPIExEvents_OnDTMFEventHandler(this.Tapiex_com_OnDTMF);
Tapiex_com.OnConnected += new AxTAPIEXLib._ITAPIExEvents_OnConnectedEventHandler(this.Tapiex_com_OnConnected);
Tapiex_com.OnDisConnected += new AxTAPIEXLib._ITAPIExEvents_OnDisConnectedEventHandler(this.Tapiex_com_OnDisConnected);
Tapiex_com.OnCallerID += new AxTAPIEXLib._ITAPIExEvents_OnCallerIDEventHandler(this.Tapiex_com_OnCallerID);
Tapiex_com.OnNewCall += new AxTAPIEXLib._ITAPIExEvents_OnNewCallEventHandler(this.Tapiex_com_OnNewCall);
bool init = Tapiex_com.initialize();
foreach (ITAPILine tmpline in Tapiex_com.Lines)
if ((tmpline.Caps.Media_Modes & LINEMEDIAMODE.MEDIAMODE_INTERACTIVEVOICE) > 0 ||
(tmpline.Caps.Media_Modes & LINEMEDIAMODE.MEDIAMODE_AUTOMATEDVOICE) > 0)
linesName.Add(tmpline.Name);
return init;
}
public bool OpenLine(string lineName)
{
if (lineName == null)
{
foreach (string item in linesName)
{
var line = Find_line(item);
if (!line.Opened)
line.Open();
}
return true;
}
else
{
var line = Find_line(lineName);
if (line != null)
{
if (!line.Opened)
line.Open();
return true;
}
else return false;
}
}
private void Tapiex_com_OnDTMF(object sender, _ITAPIExEvents_OnDTMFEvent e)
{
if (!IsOutputCall)
{
isInDTMFMethod = true;
callHandler.DTMF(e);
isInDTMFMethod = false;
}
}
private void Tapiex_com_OnNewCall(object sender, _ITAPIExEvents_OnNewCallEvent e)
{
callHandler = new CallHandler();
}
private void Tapiex_com_OnRing(object sender, AxTAPIEXLib._ITAPIExEvents_OnRingEvent e)
{
if (e.ringCount > 1) e.m_Call.Answer();
}
private void Tapiex_com_OnConnected(object sender, AxTAPIEXLib._ITAPIExEvents_OnConnectedEvent e)
{
callHandler.Connected(e, IsOutputCall);
}
private void Tapiex_com_OnDisConnected(object sender, AxTAPIEXLib._ITAPIExEvents_OnDisConnectedEvent e)
{
callHandler.HangUp(e.m_Call);
IsOutputCall = false;
}
private void Tapiex_com_OnCallerID(object sender, AxTAPIEXLib._ITAPIExEvents_OnCallerIDEvent e)
{
callHandler.GetCallerID(e);
}
Ok, that is a lot of questions in one post. My apologies if this lack a "practical" answer, but I would need several pages to cover all your items. So I'll make some general observation here in the hope it helps you narrow it down a bit.
1) Multiple lines on a device is not "normal" or "average" behavior, it is also not something TAPI gets to decide over, it is completely up to the PBX system. Most will only allow 1 call on an extension, some 2 and a few exceptions will allow more with special configuration settings. A device, as mostly is understood in TAPI is meant to represent an physical phone device. What an IVR generally will use is a "Trunk Line", but many PBX will not publish/expose those lines via TAPI.
2) ActiveX and COM need to be handled differently in multi threaded environment: different startup and stop functions. You might want to look for a tutorial or book on multi-threaded COM programming first.
3) TAPI primary focus is on monitoring and controlling extension, it's not really suited to support an IVR. I'm not saying it is impossible, but it is definitely the "hard way". In a contact center environment, TAPI is generally used to monitor the call after it has left the IVR, not for the IVR itself. You may want to consider building an IVR on a SIP, H323 or middle-ware stack instead.
4) If you're determined to do TAPI, I would recommend against a TAPI 3 implementation. TAPI 3 was an attempt to bring TAPI into the modern world (of 1999) and did not take everything, so there is a lot of missing bits. The technologies used are by now themselves out of date or deprecated. If you are serious in building something as complex as a commercial IVR system, you may wish to use a TAPI 2 based system, for a more complete and stable interface (and there are some .NET wrappers out there if you're not into native C/C++ coding). It is counter intuitive but 2 is better and bigger then 3 in this case. Especially since you'll need the more "exotic" parts like audio handling (something very few PBX support!) to make an IVR.