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

📄 tapiline.cpp.svn-base

📁 一个使用TAPI函数写的电话应用的Demo
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
// TapiLine.cpp: implementation of the CTapiLine class.
// Author: T.Yogaramanan
// Include this header if you use any part of the code from this file 
/////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "TAPISample.h"
#include "TapiLine.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CTapiLine::CTapiLine()
{
	m_hEventFromThread = NULL;
	m_hLineMsgThread = NULL;   // TAPI Event monitoring thread.
	m_bStopLineEventThread = true; 
	m_lEventThreadResult = 0; 
	m_dwLineMsg= 0;
	m_nDevID = 0;
	m_hLineApp = NULL;
	m_hLine = NULL;
	m_hCall = NULL;
	m_bConnected = false;

}

CTapiLine::~CTapiLine()
{
	Close();
}

// if nMode = 0 then it is data/fax calls
//    nMode = 1 then it is data/fax/voice calls
int CTapiLine::Open(int nMode)
{
	LINEINITIALIZEEXPARAMS stInitParams;
	LINEDEVCAPS *lpDevCaps =NULL;
	LONG lRet;
	
	DWORD dwMediaMode;
	DWORD dwNumDevs =0;
	DWORD dwTAPIVer =TAPI_CURRENT_VERSION;;
	DWORD dwTmpVer =0;
	LINEEXTENSIONID stExtID;

	if(!nMode)
		dwMediaMode = LINEMEDIAMODE_DATAMODEM; // data/fax this should be
	else
		dwMediaMode = LINEMEDIAMODE_AUTOMATEDVOICE;// for voice this should be

	memset(&stInitParams, 0, sizeof(LINEINITIALIZEEXPARAMS));
	// set the options...
	stInitParams.dwTotalSize = sizeof(LINEINITIALIZEEXPARAMS);
	stInitParams.dwOptions = LINEINITIALIZEEXOPTION_USEEVENT;
	
	// Initialize TAPI.
	lRet = lineInitializeEx(&m_hLineApp, NULL, NULL, "CallAnswer", &dwNumDevs, &dwTAPIVer, &stInitParams);
	if(lRet)  //error
		return lRet;

	// Got the event handle...
	m_hLineEvent = stInitParams.Handles.hEvent;

	m_nDevID = -1;
	// go through the device list and select the appropriate device to transfer voice
	for(int i=0;i<dwNumDevs;i++)
	{
		lRet = lineNegotiateAPIVersion(m_hLineApp, i, dwTAPIVer, dwTAPIVer,	&dwTmpVer, &stExtID);
		if(lRet != 0)
			continue;
				
		lpDevCaps = (LINEDEVCAPS *)malloc(sizeof(LINEDEVCAPS)+1024);// Allocate a little extra memory...

		memset(lpDevCaps, 0, sizeof(LINEDEVCAPS)+1024);
		lpDevCaps->dwTotalSize = sizeof(LINEDEVCAPS)+1024;

		lRet = lineGetDevCaps(m_hLineApp, i, dwTmpVer, 0, lpDevCaps);
		
		if(lRet)  //error
		{
			free(lpDevCaps);
			lpDevCaps=NULL;
			continue;
		}
		
		char *szText = ((char*)lpDevCaps) + lpDevCaps->dwLineNameOffset;// FOR DEBUGGING
		// for more refer LINEMEDIAMODE_ Constants in MSDN

		if(lpDevCaps->dwMediaModes & dwMediaMode) 
		{
			free(lpDevCaps);
			m_nDevID = i;
			break;
		}
		free(lpDevCaps);
	}
	if(m_nDevID < 0)
		return LINEERR_BADDEVICEID; // no device available

	// Open the line...
	lRet = lineOpen(m_hLineApp, m_nDevID, &m_hLine, dwTAPIVer, 0x00000000, 1,LINECALLPRIVILEGE_OWNER,dwMediaMode,NULL);
	if(lRet)
	{
		lineShutdown(m_hLineApp);
		return lRet;
	}
	
	// We want to be notified for everything
	lRet = lineSetStatusMessages(m_hLine, 0x1ffffff, 0);
	if(lRet)
	{	
		lineShutdown(m_hLineApp);
		return lRet;	
	}
	m_bStopLineEventThread = false;
	m_hLineMsgThread = CreateThread(NULL,NULL,LineEventThread,this,NULL,0);
	m_hEventFromThread = CreateEvent(NULL,0,0,NULL);
	return 0;
}

int CTapiLine::Close()
{
	LINECALLSTATUS stLineStatus;
	LONG lRet;

	if(m_hCall)  // Call might be in progress...
	{
		memset(&stLineStatus, 0, sizeof(LINECALLSTATUS));

		lRet = lineGetCallStatus(m_hCall, &stLineStatus); 
			// Technically, lineGetCallStatus returns more info than 
			// there is in the structure.  Since we don't care about it,
			// We just go on our merry way...
		if(!lRet) // If it didn't fail, there's at least a call that needs to be droped.
			lineDrop(m_hCall, NULL, 0);
	}
	m_hCall = NULL;

	if(m_hLine)
		lineClose(m_hLine);
	m_hLine = NULL;

	if(m_hLineMsgThread)
	{
		m_bStopLineEventThread = true;  // stop the event waiting thread
		WaitForSingleObject(m_hLineMsgThread, INFINITE); // Wait for it to comit suicide..
		CloseHandle(m_hLineMsgThread);
		CloseHandle(m_hEventFromThread);
	}
	if(m_hLineApp)	
		lineShutdown(m_hLineApp);
	m_hLineApp = NULL;

	m_hLineMsgThread = NULL;
	m_hEventFromThread = NULL;
	m_hLineMsgThread = NULL;

	m_lEventThreadResult = 0; 
	m_dwLineMsg= 0;
	m_nDevID = -1;
	m_bConnected= false;
	return 0;
}


int CTapiLine::GetIncomingCall()
{
	long lRet;
	
	// set the ring b4 receiving the call
	lRet = lineSetNumRings(m_hLine,0,5);
	if(lRet)
		return lRet;
	
	// Now we wait for notification.
	switch(WaitForSingleObject(m_hEventFromThread, INFINITE))
	{
	case WAIT_OBJECT_0:
		if(m_dwLineMsg == LINECALLSTATE_OFFERING)
		{
			lRet = lineAnswer(m_hCall, NULL, 0);
			lRet = (lRet>0)?0:lRet;

			if(lRet)
				Close();
			return lRet;
		}
		break;
	case WAIT_TIMEOUT:
		return ERROR_TIMEOUT;
	};
	return 0xffffffff; // unknown error
}

int CTapiLine::PickupIncomingCall()
{
	long lRet;

	lRet = linePickup(m_hLine,0,&m_hCall,NULL,NULL);

	return (lRet>=0)?0:lRet;
}


int CTapiLine::MakeOutgoingCall(const char *szAddress)
{
	long lRet;

	LPLINECALLPARAMS lpCallParams;

	lpCallParams = (LPLINECALLPARAMS)malloc(sizeof(LINECALLPARAMS)+1024);
	
	memset(lpCallParams,0,sizeof(LINECALLPARAMS)+1024);

	lpCallParams->dwTotalSize = sizeof(LINECALLPARAMS)+1024;

	    // This is where we configure the line for DATAMODEM usage.
    lpCallParams->dwBearerMode = LINEBEARERMODE_VOICE;
    lpCallParams->dwMediaMode  = LINEMEDIAMODE_DATAMODEM;

    // This specifies that we want to use only IDLE calls and
    // don't want to cut into a call that might not be IDLE (ie, in use).
    lpCallParams->dwCallParamFlags = LINECALLPARAMFLAGS_IDLE;
                                    
    // if there are multiple addresses on line, use first anyway.
    // It will take a more complex application than a simple tty app
    // to use multiple addresses on a line anyway.
    lpCallParams->dwAddressMode = LINEADDRESSMODE_ADDRESSID;
    lpCallParams->dwAddressID = 0;

    // Address we are dialing.
    lpCallParams->dwDisplayableAddressOffset = sizeof(LINECALLPARAMS);
    lpCallParams->dwDisplayableAddressSize = strlen(szAddress);
    strcpy((LPSTR)lpCallParams+sizeof(LINECALLPARAMS), szAddress);
	
	lRet = lineMakeCall(m_hLine, &m_hCall, szAddress, 0, lpCallParams);

	return (lRet>=0)?0:lRet;
}

//Author: Ramanan.T
HANDLE CTapiLine::GetHandle(const char *szClassType, long *lError)
{
	if(!m_bConnected)
	{
		*lError = ERROR_DEVICE_NOT_CONNECTED;
		return NULL;
	}

	VARSTRING *pvarStrDevID = (VARSTRING *)malloc(sizeof(VARSTRING)+255);

	memset(pvarStrDevID,0,sizeof(VARSTRING)+255);
	pvarStrDevID->dwTotalSize = sizeof(VARSTRING)+255;
	
	long lRet = lineGetID(m_hLine,0,m_hCall,LINECALLSELECT_LINE,pvarStrDevID,szClassType);
	if(lRet)
	{
		*lError = lRet;
		return NULL;
	}

	*lError = 0;

	return *((LPHANDLE)((char *)pvarStrDevID + pvarStrDevID->dwStringOffset));
}

//Author: Ramanan.T
DWORD WINAPI CTapiLine::LineEventThread(LPVOID lpVoid)
{
	CTapiLine *pcTapiLine = (CTapiLine *)lpVoid;
	long lRet;
	LINEMESSAGE stLineMsg;
	LINECALLINFO *lpCallInfo;

	while(!pcTapiLine->m_bStopLineEventThread)
	{
		// Get a TAPI event if available, wait for 10ms just enough to give up quontum
		switch(WaitForSingleObject(pcTapiLine->m_hLineEvent, 10))
		{
		case WAIT_OBJECT_0:
			//TAPI's got something
			if ((lRet = lineGetMessage(pcTapiLine->m_hLineApp, &stLineMsg, 0)) != 0)
			{
				pcTapiLine->m_lEventThreadResult = lRet;
				return lRet;
			}
			// Process the retruned msg
			switch (stLineMsg.dwMessageID)
			{
			case LINE_REPLY: // Sent after lineMakeCall or lineDrop				
				pcTapiLine->m_lEventThreadResult = (LONG)stLineMsg.dwParam2;
				break;

			case LINE_CALLSTATE:  // Sent after change of call state
				switch (stLineMsg.dwParam1)
				{
					case LINECALLSTATE_OFFERING:	//Incoming call is offering.
						//  Get the call handle
						pcTapiLine->m_hCall = (HCALL)stLineMsg.hDevice;

						pcTapiLine->m_dwLineMsg = LINECALLSTATE_OFFERING;
						SetEvent(pcTapiLine->m_hEventFromThread);
						break;

					case LINECALLSTATE_IDLE:
						lineDrop(pcTapiLine->m_hCall, NULL, 0);
						pcTapiLine->m_hCall = NULL;
						break;

					case LINECALLSTATE_CONNECTED:
						
						if(stLineMsg.dwCallbackInstance == 1)
						{
							pcTapiLine->m_dwLineMsg = LINECALLSTATE_CONNECTED;
							SetEvent(pcTapiLine->m_hEventFromThread);
							pcTapiLine->m_bConnected = true;
						}

						break;

					case LINECALLSTATE_DISCONNECTED:
						switch (stLineMsg.dwParam2) 
						{// currently these r not handled separately
							case LINEDISCONNECTMODE_NORMAL:
							case LINEDISCONNECTMODE_UNKNOWN:
							case LINEDISCONNECTMODE_REJECT:
							case LINEDISCONNECTMODE_PICKUP:
							case LINEDISCONNECTMODE_FORWARDED:

⌨️ 快捷键说明

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