⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tapiapp.cpp

📁 TAPI编程应用
💻 CPP
字号:
// tapiapp.cpp : Defines the class behaviors for the TAPI application.
// (c) Dialogic corp 1995, 1996

#include "stdafx.h"
#include <tapi.h>
#include "tapiapp.h"

#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif

//CMap<DWORD, DWORD, ASYNCCALL, ASYNCCALL&> 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<nCount && pos != NULL; j++)		// iterate thru list, delete all
			{
				m_pAsyncList->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"

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -