www.pudn.com > tapi3.zip > TAPIAPP.CPP
// tapiapp.cpp : Defines the class behaviors for the TAPI application. // (c) Dialogic corp 1995, 1996 #include "stdafx.h" #include#include "tapiapp.h" #ifdef _DEBUG #undef THIS_FILE static char BASED_CODE THIS_FILE[] = __FILE__; #endif //CMap g_cmAsyncCalls; // globally defined ///////////////////////////////////////////////////////////////////////////// // CTapiApp BEGIN_MESSAGE_MAP(CTapiApp, CWinApp) //{{AFX_MSG_MAP(CTapiApp) // NOTE - the ClassWizard will add and remove mapping macros here. // DO NOT EDIT what you see in these blocks of generated code! //}}AFX_MSG ON_COMMAND(ID_HELP, CWinApp::OnHelp) END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CTalkApp construction CTapiApp::CTapiApp() { // TODO: add construction code here, // Place all significant initialization in InitInstance m_hApp = NULL; m_dwLines = 0L; m_hAsyncListSem = NULL; } ///////////////////////////////////////////////////////////////////////////// // CTapiApp initialization BOOL CTapiApp::InitInstance() { // Standard initialization; MUST be called by the child class & return TRUE // if success; the child decides what to do after Enable3dControls(); LoadStdProfileSettings(); // Load standard INI file options (including MRU) if(!InitTAPIApp()) // lineInit etc { MessageBox(NULL, "Failed to initialize TAPI", NULL, MB_ICONSTOP); return FALSE; } return TRUE; } int CTapiApp::ExitInstance() { CloseTAPIApp(); return CWinApp::ExitInstance(); } // Call lineInit BOOL CTapiApp::InitTAPIApp() { LONG lResult, i=0; while (LINEERR_REINIT == (lResult = lineInitialize(&m_hApp, m_hInstance, LineCallBackProc, "Talker32", &m_dwLines))) { Sleep(1000); i++; if(i > 10) return FALSE; } m_pAsyncList = new CMAPASYNC; // list of asynchronous calls if(lResult || m_pAsyncList == NULL) return FALSE; m_hAsyncListSem = CreateMutex(NULL, FALSE, "TALKER32_ASYNC_LIST"); if(m_hAsyncListSem == NULL) return FALSE; return TRUE; } // MUST be protected void CTapiApp::SetAsyncID(DWORD dwID, WORD wState, WORD wFunc, LPVOID pvLine, LPVOID pvCall) { DWORD dwrc; PASYNCCALL pAsync = new ASYNCCALL; if(!pAsync) return; TRACE("*** TALKER32 ***: Set ID #%d entering wait for sem\n", dwID); dwrc = WaitForSingleObject(m_hAsyncListSem, 15000); if(dwrc != WAIT_OBJECT_0) { TRACE("*** TALKER32 ***: Set ID #%d wait for sem failed rc=%lx\n", dwID, dwrc); return; } pAsync->dwID = dwID; pAsync->wState = wState; pAsync->wFunction = wFunc; pAsync->pvLine = pvLine; pAsync->pvCall = pvCall; m_pAsyncList->SetAt(pAsync->dwID, pAsync); TRACE("*** TALKER32 ***: Set ID #%d releasing mutex\n", dwID); ReleaseMutex(m_hAsyncListSem); } // MUST be protected PASYNCCALL CTapiApp::FindAsyncID(DWORD dwID, WORD wAction) { PASYNCCALL pAsync = NULL; ASSERT(m_pAsyncList != NULL); TRACE("*** TALKER32 ***: %s ID #%d entering wait for sem\n", wAction==FIND_ID?"find":"remove",dwID); DWORD dwrc = WaitForSingleObject(m_hAsyncListSem, 15000); if(dwrc != WAIT_OBJECT_0) { TRACE("*** TALKER32 ***: Find async ID #%d wait for sem failed rc=%lx\n",dwID, dwrc); return NULL; } if(m_pAsyncList->Lookup(dwID, pAsync)) { if(wAction == REMOVE_ID) { m_pAsyncList->RemoveKey(dwID); delete pAsync; TRACE("*** TALKER32 ***: ID#%d releasing mutex\n", dwID); ReleaseMutex(m_hAsyncListSem); return NULL; } } // if found, returns what found TRACE("*** TALKER32 ***: ID #%d releasing mutex\n", dwID); ReleaseMutex(m_hAsyncListSem); return pAsync; } void CTapiApp::CloseTAPIApp() { lineShutdown(m_hApp); PurgeAsyncQue(); CloseHandle(m_hAsyncListSem); m_hAsyncListSem = NULL; } // Delete the async requests queue; must be protected void CTapiApp::PurgeAsyncQue() { DWORD dwrc; if(m_pAsyncList != NULL) { TRACE("*** TALKER32 ***: Purge queue entering wait for sem\n"); dwrc = WaitForSingleObject(m_hAsyncListSem, 15000); if(dwrc != WAIT_OBJECT_0) { TRACE("*** TALKER32 ***: Purge async queue wait for sem failed rc=%lx\n", dwrc); return; } if(!m_pAsyncList->IsEmpty()) // list not empty, cleanup { PASYNCCALL pAsyncCall = NULL; DWORD dwID; int j; int nCount = m_pAsyncList->GetCount(); POSITION pos = m_pAsyncList->GetStartPosition(); for(j=0; j GetNextAssoc(pos, dwID, pAsyncCall); if(pAsyncCall) delete pAsyncCall; } } delete m_pAsyncList; m_pAsyncList = NULL; TRACE("*** TALKER32 ***: Purge queue releasing mutex\n"); ReleaseMutex(m_hAsyncListSem); } } void CTapiApp::OnLineReply(DWORD dwCallback, DWORD dwRequest, DWORD dwStatus) { // first, find the request PASYNCCALL pAC = FindAsyncID(dwRequest, FIND_ID); if(pAC == NULL) // not found for some reason (???) { TRACE1("*** TALKER32 *** :Request ID=%lx not found!\n", dwRequest); return; } ASSERT(pAC->dwID == dwRequest); // sanity check FindAsyncID(dwRequest, REMOVE_ID); // Done, remove the ID from list } // get info on incoming call LPLINECALLINFO CTapiApp::GetCallInfo(HCALL hCall) { LPLINECALLINFO lpCallInfo = NULL; LONG lrc = 0; DWORD dwSize = sizeof(LINECALLINFO)+1000; DWORD i; // keep trying until buffer is big enough for (i=0; i<2; i++) { lpCallInfo = (LPLINECALLINFO) new char[dwSize]; if (lpCallInfo == NULL) return NULL; lpCallInfo->dwTotalSize = dwSize; lrc = lineGetCallInfo(hCall,lpCallInfo); if(lrc < 0) goto FinishLineCallInfo; dwSize = lpCallInfo->dwNeededSize; if(dwSize <= lpCallInfo->dwTotalSize) break; // success delete (char *) lpCallInfo; } return lpCallInfo; FinishLineCallInfo: if (lpCallInfo != NULL) delete (LPBYTE) lpCallInfo; return NULL; } // get call status LPLINECALLSTATUS CTapiApp::GetCallStatus(HCALL hCall) { LPLINECALLSTATUS lpCallInfo = NULL; LONG lrc = 0; DWORD dwSize = sizeof(LINECALLSTATUS)+1000; DWORD i; // keep trying until buffer is big enough for (i=0; i<2; i++) { lpCallInfo = (LPLINECALLSTATUS) new char[dwSize]; if (lpCallInfo == NULL) return NULL; lpCallInfo->dwTotalSize = dwSize; lrc = lineGetCallStatus(hCall,lpCallInfo); if(lrc < 0) goto FinishLineCallStatus; dwSize = lpCallInfo->dwNeededSize; if(dwSize <= lpCallInfo->dwTotalSize) break; // success delete (char *) lpCallInfo; } return lpCallInfo; FinishLineCallStatus: if (lpCallInfo != NULL) delete (LPBYTE) lpCallInfo; return NULL; } extern "C" { VOID WINAPI LineCallBackProc(DWORD hDevice, DWORD dwMsg, DWORD dwCallbackInstance, DWORD dwParam1, DWORD dwParam2, DWORD dwParam3) { // char szDigit[2]={0,0}; TRACE("*** TALKER32 *** lineCallBack:Message=%ld,P1=%lx, P2=%lx, P3=%lx\n", dwMsg, dwParam1,dwParam2,dwParam3); switch (dwMsg) { case LINE_LINEDEVSTATE: if (dwParam1 & LINEDEVSTATE_REINIT) { TRACE("*** TALKER32 *** :LINEDEVSTATE_REINIT\n"); } // see DIALER if (dwParam1 & LINEDEVSTATE_TRANSLATECHANGE) { TRACE("*** TALKER32 *** :LINEDEVSTATE_TRANSLATECHANGE\n"); } // see DIALER if (dwParam1 & LINEDEVSTATE_CAPSCHANGE) { TRACE("*** TALKER32 *** :LINEDEVSTATE_CAPSCHANGE\n"); } // CAPSCHANGE, see DIALER if (dwParam1 & LINEDEVSTATE_REMOVED) { // treat removal like a request to close the line TRACE("*** TALKER32 *** :LINEDEVSTATE_REMOVED\n"); } // REMOVED, see DIALER break; case LINE_ADDRESSSTATE: TRACE("*** TALKER32 *** :LINE_ADDRESSSTATE\n"); break; // see DIALER // process state transition case LINE_CALLSTATE: TRACE("*** TALKER32 *** :LINE_CALLSTATE\n"); ((CTapiApp *)AfxGetApp())->OnCallState((HCALL) hDevice, dwCallbackInstance, dwParam1, dwParam2, dwParam3); break; // see DIALER case LINE_CREATE: // a new line is created TRACE("*** TALKER32 *** :LINE_CREATE\n"); break; case LINE_CLOSE: // see if the closed line is the line on which we have an active call // if it is, do what would have been done if that call went idle // if not, see if it is a line for which we have a monitoring handle // if it is, mark that line as closed // if any calls are being monitored on that line, stop monitoring TRACE("*** TALKER32 *** :LINE_CLOSE\n"); break; // handle simple tapi request case LINE_REQUEST: TRACE("*** TALKER32 *** :LINE_REQUEST\n"); break; // handle the async completion of TAPI functions // lineMakeCall/lineDropCall/lineAnswer case LINE_REPLY: TRACE("*** TALKER32 *** :LINE_REPLY\n"); ((CTapiApp *)AfxGetApp())->OnLineReply(dwCallbackInstance, dwParam1, dwParam2); // virtual handler break; // other messages that can be processed case LINE_CALLINFO: TRACE("*** TALKER32 *** :LINE_CALLINFO\n"); ((CTapiApp *)AfxGetApp())->OnLineCallInfo((HCALL)hDevice, dwCallbackInstance, dwParam1); break; case LINE_DEVSPECIFIC: TRACE("*** TALKER32 *** :LINE_DEVSPECIFIC\n"); ((CTapiApp *)AfxGetApp())->OnLineDevSpec(hDevice, dwCallbackInstance, dwParam1, dwParam2, dwParam3); break; case LINE_DEVSPECIFICFEATURE: TRACE("*** TALKER32 *** :LINE_DEVSPECIFICFEATURE\n"); break; case LINE_GATHERDIGITS: TRACE("*** TALKER32 *** :LINE_GATHERDIGITS\n"); ((CTapiApp *)AfxGetApp())->OnGatherDigits((HCALL)hDevice, dwCallbackInstance, dwParam1); break; case LINE_GENERATE: TRACE("*** TALKER32 *** :LINE_GENERATE\n"); break; case LINE_MONITORDIGITS: TRACE("*** TALKER32 *** :LINE_MONITORDIGITS\n"); ((CTapiApp *)AfxGetApp())->OnMonitorDigits((HCALL)hDevice, dwCallbackInstance, dwParam1, dwParam2); break; case LINE_MONITORMEDIA: TRACE("*** TALKER32 *** :LINE_MONITORMEDIA\n"); ((CTapiApp *)AfxGetApp())->OnMonitorMedia(hDevice, dwCallbackInstance, dwParam1, dwParam2, dwParam3); break; case LINE_MONITORTONE: TRACE("*** TALKER32 *** :LINE_MONITORTONE\n"); break; default: TRACE("*** TALKER32 *** :UNACCOUNTED LINE MESSAGE\n"); break; } /* switch */ } // LineCallBackProc } // extern "C"