I have been able to create an application that (ab)uses TAPI3Lib and understands incoming calls, puts them on hold, rings an internal number, connects the line that is on hold with the target number.
Below is the code getting the caller number
private void tapi_ITTAPIEventNotification_Event_Event(TAPI3Lib.TAPI_EVENT TapiEvent, object pEvent)
{
try
{
switch (TapiEvent)
{
case TAPI3Lib.TAPI_EVENT.TE_CALLNOTIFICATION:
TAPI3Lib.ITCallNotificationEvent cln = pEvent as TAPI3Lib.ITCallNotificationEvent;
if (cln.Call.CallState == TAPI3Lib.CALL_STATE.CS_OFFERING)
{
string c = cln.Call.get_CallInfoString(TAPI3Lib.CALLINFO_STRING.CIS_CALLERIDNUMBER);
string target = cln.Call.Address.DialableAddress;
.
.
.
Here i run a MSSQL query to a database to identify who is the owner of the number. and i display a form on screen with the potential user that is calling. A button on the form allows you to ring internal numbers (this action automatically adds the current line on hold.
IEnumCall ec = ia[line].EnumerateCalls();
uint arg = 0;
ITCallInfo ici;
try
{
ec.Next(1, out ici, ref arg);
ITBasicCallControl bc = (ITBasicCallControl)ici;
bc.Hold(true);
}
catch (Exception exp)
{
System.Windows.Forms.MessageBox.Show("May not have any call to put on hold!\n\n" + exp.ToString(), "TAPI3");
}
IEnumCall ec1 = ia[line].EnumerateCalls();
uint arg1 = 0;
ITCallInfo ici1;
try
{
ec1.Next(1, out ici1, ref arg1);
ITBasicCallControl bc1 = ia[line].CreateCall("107",TapiConstants.LINEADDRESSTYPE_IPADDRESS, TapiConstants.TAPIMEDIATYPE_AUDIO);
bc1.Connect(false);
}
catch (Exception exp)
{
System.Windows.Forms.MessageBox.Show("Target looks unreachable!\n\n" + exp.ToString(), "TAPI3");
}
This part connects the current active line with the line on hold;
ITBasicCallControl callOnHold = null;
ITBasicCallControl callConnected = null;
IEnumCall enumCall = ia[line].EnumerateCalls();
ITCallInfo callInfo;
uint dummy = 0;
while (true)
{
enumCall.Next(1, out callInfo, ref dummy);
if (callInfo == null)
return;
if (callInfo.CallState == CALL_STATE.CS_HOLD)
callOnHold = (ITBasicCallControl)callInfo;
else if (callInfo.CallState == CALL_STATE.CS_CONNECTED)
callConnected = (ITBasicCallControl)callInfo;
if (callOnHold != null && callConnected != null)
break;
}
callOnHold.Transfer(callConnected, true);
callConnected.Finish(FINISH_MODE.FM_ASTRANSFER);
The initiation is as follows;
ITAddress[] ia = new TAPI3Lib.ITAddress[10];
...
try
{
tobj = new TAPIClass();
tobj.Initialize();
IEnumAddress ea = tobj.EnumerateAddresses();
ITAddress ln;
uint arg3 = 0;
lines = 0;
cn = new callnotification();
tobj.ITTAPIEventNotification_Event_Event += new TAPI3Lib.ITTAPIEventNotification_EventEventHandler(cn.Event);
tobj.EventFilter = (int)(TAPI_EVENT.TE_CALLNOTIFICATION |
TAPI_EVENT.TE_DIGITEVENT |
TAPI_EVENT.TE_PHONEEVENT |
TAPI_EVENT.TE_CALLSTATE |
TAPI_EVENT.TE_GENERATEEVENT |
TAPI_EVENT.TE_GATHERDIGITS |
TAPI_EVENT.TE_REQUEST);
for (int i = 0; i < 10; i++)
{
ea.Next(1, out ln, ref arg3);
ia[i] = ln;
if (ln != null)
{
lines++;
}
else
break;
}
}
catch (Exception e)
{
System.Windows.Forms.MessageBox.Show(e.ToString());
}
--Scenario
CallA: Incoming Call
CallB: Internal Call
Operator: The main answering operator
Bob: A user of this application
Alice: The caller of CallA
Bob uses his cellphone to call Alice's call center. The Operator sees a pop-up screen containing Bob's name and number and then picks up the phone. (CallA is stored). Bob requests to talk to Alice. The Operator clicks on "Alice" on the screen (CallA is now on Hold and the Operator's phone creates CallB which rings Alice's phone). Alice answers the line and agrees to take the call. The Operator clicks "Transfer" on screen and CallA and CallB are connected.
--End of Scenario
--Expected result
When the Operator calls Alice, the event sees that 100 called 107 (with 100 being the Operator's address on the PBX and 107 Alice's. When the Operator connects the 2 calls, I want to be able to pop-up the same screen that the Operator got that includes the information of the connected caller. What am i missing in order to fire that event? Because when i try to check the cln.Call.get_CallInfoString(TAPI3Lib.CALLINFO_STRING.CIS_CALLERIDNUMBER)
all i see is 100 which is the Operator that called Alice and that is correct. What is the check i need to do in order to identify that a call has been transferred thus → get the caller ID → pop up the screen
--End of Expected result
I wish i was able to describe it as i have it mind. Thank you for your time and excuse me for the lengthy post.
The TAPI3 lib may have a bit different naming but the fields you are looking for are called ConnectedId, RedirectingId and RedirectionId on TAPI itself. But it is very dependent on the PBX itself whether these fields get filled or not.
In a transfered call scenario "theoretically" you should see this in the call information:
But none of this enforced by TAPI so a PBX can fill in what it wants, and different vendors will :(