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; jGetNextAssoc(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"