📄 tapiline.cpp.svn-base
字号:
// 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 + -