📄 tapiline.cpp
字号:
// Written by JHCC
#include "stdafx.h"
#include "TAPIx.h"
#include "TAPIErr.h"
#include "comm.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// ---- CTAPILine ----
IMPLEMENT_SERIAL(CTAPILine, CObject, 0 /* schema number*/ )
CTAPILine::CTAPILine()
{
m_dwDeviceID = 0;
m_lpLineDevCaps = NULL;
m_hLine = 0;
m_dwAsyncID = (DWORD)-1;
m_WaitReplyType = REPLY_NONE;
m_hCall = (HCALL)-1;
m_bConnected = FALSE;
m_pComm = NULL;
}
CTAPILine::~CTAPILine()
{
if (m_lpLineDevCaps != NULL)
delete m_lpLineDevCaps;
}
BOOL CTAPILine::Create(DWORD dwDeviceID, DWORD dwAPILowVersion, DWORD dwAPIHighVersion)
{
m_dwDeviceID = dwDeviceID;
if ((m_dwAPIVersion = NegotiateLegacyAPIVersion(dwAPIHighVersion, dwAPIHighVersion)) == 0)
return FALSE;
if ((m_dwAPILegacyVersion = NegotiateLegacyAPIVersion(dwAPILowVersion, dwAPIHighVersion)) == 0)
return FALSE;
m_dwExtVersion = 0;
long lReturn = ::lineGetIcon(m_dwDeviceID, NULL/*comm*/, &m_hLineIcon);
if (lReturn != TAPISUCCESS)
m_hLineIcon = ::AfxGetApp()->LoadStandardIcon(IDI_QUESTION);
if ((m_lpLineDevCaps = I_lineGetDevCaps()) == NULL)
{
::MessageBox(NULL, "Error on Requested line",
"Unable to Use Line", MB_OK);
return FALSE;
}
return TRUE;
}
BOOL CTAPILine::IsSupportVoice(void)
{
return BOOL(m_lpLineDevCaps->dwBearerModes & LINEBEARERMODE_VOICE);
}
BOOL CTAPILine::IsSupportDataModem(void)
{
return BOOL(m_lpLineDevCaps->dwMediaModes & LINEMEDIAMODE_DATAMODEM);
}
BOOL CTAPILine::IsSupportMakeCall(void)
{
return BOOL(m_lpLineDevCaps->dwLineFeatures & LINEFEATURE_MAKECALL);
}
DWORD CTAPILine::GetDevCapFlags(void)
{
return m_lpLineDevCaps->dwDevCapFlags;
}
// Negotiate an API Version to use for a specific device.
// This wrapper function not only negotiates the API,
// but also handles LINEERR errors that can occur while negotiating.
DWORD CTAPILine::NegotiateLegacyAPIVersion(DWORD dwAPILowVersion, DWORD dwAPIHighVersion)
{
ASSERT(dwAPIHighVersion != 0);
ASSERT(dwAPILowVersion != 0);
DWORD dwLocalAPIVersion;
long lReturn;
do
{
LINEEXTENSIONID LineExtensionID;
lReturn = ::lineNegotiateAPIVersion(CTAPIConnection::m_hLineApp, m_dwDeviceID,
dwAPILowVersion, dwAPIHighVersion,
&dwLocalAPIVersion, &LineExtensionID);
switch (lReturn)
{
case LINEERR_INCOMPATIBLEAPIVERSION:
TRACE0("lineNegotiateAPIVersion, INCOMPATIBLEAPIVERSION.\n");
return 0;
default:
if (!CTAPIError::HandleLineErr(lReturn))
{
TRACE1("lineNegotiateAPIVersion unhandled error: %lx\n", lReturn);
return 0;
}
}
}
while (lReturn != TAPISUCCESS);
return dwLocalAPIVersion;
}
// Open the Line for an outgoing call.
BOOL CTAPILine::Open(void)
{
if (m_hLine) // line is not opened
{
TRACE0("Line is already Opened !\n");
return FALSE;
}
long lReturn;
do
{
lReturn = ::lineOpen(CTAPIConnection::m_hLineApp, m_dwDeviceID, &m_hLine,
m_dwAPIVersion, m_dwExtVersion, 0,
LINECALLPRIVILEGE_OWNER, LINEMEDIAMODE_DATAMODEM, NULL);
switch (lReturn)
{
case LINEERR_ALLOCATED:
case LINEERR_RESOURCEUNAVAIL:
::MessageBox(NULL,
"Line is already in use by a non-TAPI application "
"or by another TAPI Service Provider.",
"Unable to Use Line", MB_OK);
return FALSE;
default:
if (!CTAPIError::HandleLineErr(lReturn))
{
TRACE1("lineOpen unhandled error: %lu\n", lReturn);
::MessageBox(NULL,
"Error on Requested line",
"Unable to Use Line",MB_OK);
return FALSE;
}
break;
}
}
while (lReturn != TAPISUCCESS);
// Tell the service provider that we want all notifications that
// have anything to do with this line.
do
{
// Set the messages we are interested in.
// Note that while most applications aren't really interested
// in dealing with all of the possible messages, its interesting
// to see which come through the callback for testing purposes.
lReturn = ::lineSetStatusMessages(m_hLine,
LINEDEVSTATE_OTHER |
LINEDEVSTATE_RINGING |
LINEDEVSTATE_CONNECTED | // Important state!
LINEDEVSTATE_DISCONNECTED | // Important state!
LINEDEVSTATE_MSGWAITON |
LINEDEVSTATE_MSGWAITOFF |
LINEDEVSTATE_INSERVICE |
LINEDEVSTATE_OUTOFSERVICE | // Important state!
LINEDEVSTATE_MAINTENANCE | // Important state!
LINEDEVSTATE_OPEN |
LINEDEVSTATE_CLOSE |
LINEDEVSTATE_NUMCALLS |
LINEDEVSTATE_NUMCOMPLETIONS |
LINEDEVSTATE_TERMINALS |
LINEDEVSTATE_ROAMMODE |
LINEDEVSTATE_BATTERY |
LINEDEVSTATE_SIGNAL |
LINEDEVSTATE_DEVSPECIFIC |
LINEDEVSTATE_REINIT | // Not allowed to disable this.
LINEDEVSTATE_LOCK |
LINEDEVSTATE_CAPSCHANGE |
LINEDEVSTATE_CONFIGCHANGE |
LINEDEVSTATE_COMPLCANCEL,
LINEADDRESSSTATE_OTHER |
LINEADDRESSSTATE_DEVSPECIFIC |
LINEADDRESSSTATE_INUSEZERO |
LINEADDRESSSTATE_INUSEONE |
LINEADDRESSSTATE_INUSEMANY |
LINEADDRESSSTATE_NUMCALLS |
LINEADDRESSSTATE_FORWARD |
LINEADDRESSSTATE_TERMINALS |
LINEADDRESSSTATE_CAPSCHANGE);
if (CTAPIError::HandleLineErr(lReturn))
continue;
else
{
// If we do get an unhandled problem, we don't care.
// We just won't get notifications.
TRACE1("lineSetStatusMessages unhandled error: %lu\n", lReturn);
break;
}
}
while (lReturn != TAPISUCCESS);
return TRUE;
}
BOOL CTAPILine::Close(void)
{
if (m_hLine == 0)
return TRUE;
// if we have a line open, close it.
long lReturn;
do
{
lReturn = ::lineClose(m_hLine);
if (!CTAPIError::HandleLineErr(lReturn))
{
TRACE1("lineClose unhandled error: %lu\n", lReturn);
}
}
while (lReturn != TAPISUCCESS);
m_hLine = 0;
TRACE0("Line Closed.\n");
return TRUE;
}
// Allocates and fills a LINECALLPARAMS structure
// If a non-NULL lpCallParams is passed in, it must have been allocated
// with LocalAlloc, and can potentially be freed and reallocated. It must
// also have the dwTotalSize field correctly set.
LPLINECALLPARAMS CTAPILine::CreateCallParams(LPCTSTR lpszDisplayableAddress)
{
if (lpszDisplayableAddress == NULL)
lpszDisplayableAddress = _T("");
int nSizeDisplayableAddress = ::lstrlen(lpszDisplayableAddress) + 1;
LPLINECALLPARAMS lpCallParams = (LPLINECALLPARAMS)new BYTE[sizeof(LINECALLPARAMS) + nSizeDisplayableAddress];
if (lpCallParams == NULL)
return NULL;
memset(lpCallParams, 0, sizeof(LINECALLPARAMS));
lpCallParams->dwTotalSize = sizeof(LINECALLPARAMS) + nSizeDisplayableAddress;
// This is where we configure the line for DATAMODEM usage.
lpCallParams->dwBearerMode = LINEBEARERMODE_VOICE;
lpCallParams->dwMediaMode = LINEMEDIAMODE_DATAMODEM;//LINEMEDIAMODE_INTERACTIVEVOICE;
// 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;
// Since we don't know where we originated, leave these blank.
lpCallParams->dwOrigAddressSize = 0;
lpCallParams->dwOrigAddressOffset = 0;
// Unimodem ignores these values.
(lpCallParams->DialParams).dwDialSpeed = 0;
(lpCallParams->DialParams).dwDigitDuration = 0;
(lpCallParams->DialParams).dwDialPause = 0;
(lpCallParams->DialParams).dwWaitForDialtone = 0;
// Address we are dialing.
lpCallParams->dwDisplayableAddressOffset = sizeof(LINECALLPARAMS);
lpCallParams->dwDisplayableAddressSize = nSizeDisplayableAddress;
lstrcpy((LPSTR)lpCallParams + sizeof(LINECALLPARAMS),
lpszDisplayableAddress);
return lpCallParams;
}
//**************************************************
// line API Wrapper Functions.
//**************************************************
// Gets a LINEDEVCAPS structure for the specified line.
// This function is a wrapper around lineGetDevCaps to make it easy
// to handle the variable sized structure and any errors received.
LPLINEDEVCAPS CTAPILine::I_lineGetDevCaps(void)
{
// Allocate enough space for the structure plus 1024.
int nSizeLineDevCaps = sizeof(LINEDEVCAPS) + 1024;
long lReturn;
// Continue this loop until the structure is big enough.
while (TRUE)
{
// Make sure the buffer exists, is valid and big enough.
LPLINEDEVCAPS lpLineDevCaps = (LPLINEDEVCAPS)new BYTE[nSizeLineDevCaps];
if (lpLineDevCaps == NULL)
return NULL;
lpLineDevCaps->dwTotalSize = nSizeLineDevCaps;
// Make the call to fill the structure.
do
{
lReturn = ::lineGetDevCaps(CTAPIConnection::m_hLineApp,
m_dwDeviceID, m_dwAPIVersion,
m_dwExtVersion, lpLineDevCaps);
if (CTAPIError::HandleLineErr(lReturn))
continue;
else
{
TRACE0("lineGetDevCaps unhandled error\n");
delete lpLineDevCaps;
return NULL;
}
}
while (lReturn != TAPISUCCESS);
// If the buffer was big enough, then succeed.
if ((lpLineDevCaps->dwNeededSize) <= (lpLineDevCaps->dwTotalSize))
{
return lpLineDevCaps;
}
else
{
// Buffer wasn't big enough. Make it bigger and try again.
nSizeLineDevCaps = lpLineDevCaps->dwNeededSize;
delete lpLineDevCaps;
}
}
}
// Retrieve a LINEADDRESSSTATUS structure for the specified line.
// This function is a wrapper around lineGetAddressStatus to make it easy
// to handle the variable sized structure and any errors received.
LPLINEADDRESSSTATUS CTAPILine::I_lineGetAddressStatus(DWORD dwAddressID)
{
int nSizeLineAddressStatus = sizeof(LINEADDRESSSTATUS) + 1024;
long lReturn;
// Continue this loop until the structure is big enough.
while (TRUE)
{
// Make sure the buffer exists, is valid and big enough.
LPLINEADDRESSSTATUS lpLineAddressStatus =
(LPLINEADDRESSSTATUS)new BYTE[nSizeLineAddressStatus];
if (lpLineAddressStatus == NULL)
{
delete lpLineAddressStatus;
return NULL;
}
lpLineAddressStatus->dwTotalSize = nSizeLineAddressStatus;
// Make the call to fill the structure.
do
{
lReturn = ::lineGetAddressStatus(m_hLine, dwAddressID, lpLineAddressStatus);
if (CTAPIError::HandleLineErr(lReturn))
continue;
else
{
TRACE1("lineGetAddressStatus unhandled error: %lu\n", lReturn);
delete lpLineAddressStatus;
return NULL;
}
}
while (lReturn != TAPISUCCESS);
// If the buffer was big enough, then succeed.
if ((lpLineAddressStatus->dwNeededSize) <=
(lpLineAddressStatus->dwTotalSize))
{
return lpLineAddressStatus;
}
else
{
// Buffer wasn't big enough. Make it bigger and try again.
nSizeLineAddressStatus = lpLineAddressStatus->dwNeededSize;
delete lpLineAddressStatus;
}
}
}
// Retrieve a LINECALLSTATUS structure for the specified line.
// This function is a wrapper around lineGetCallStatus to make it easy
// to handle the variable sized structure and any errors received.
LPLINECALLSTATUS CTAPILine::I_lineGetCallStatus(HCALL hCall)
{
int nSizeLineCallStatus = sizeof(LINECALLSTATUS) + 1024;
long lReturn;
// Continue this loop until the structure is big enough.
while (TRUE)
{
// Make sure the buffer exists, is valid and big enough.
LPLINECALLSTATUS lpLineCallStatus =
(LPLINECALLSTATUS)new BYTE[nSizeLineCallStatus];
if (lpLineCallStatus == NULL)
return NULL;
lpLineCallStatus->dwTotalSize = nSizeLineCallStatus;
// Make the call to fill the structure.
do
{
lReturn = ::lineGetCallStatus(hCall, lpLineCallStatus);
if (!CTAPIError::HandleLineErr(lReturn))
{
TRACE1("lineGetCallStatus unhandled error: %lu", lReturn);
delete lpLineCallStatus;
return NULL;
}
}
while (lReturn != TAPISUCCESS);
// If the buffer was big enough, then succeed.
if ((lpLineCallStatus->dwNeededSize) <=
(lpLineCallStatus->dwTotalSize))
{
return lpLineCallStatus;
}
else
{
// Buffer wasn't big enough. Make it bigger and try again.
nSizeLineCallStatus = lpLineCallStatus->dwNeededSize;
delete lpLineCallStatus;
}
}
}
// Retrieve a LINEADDRESSCAPS structure for the specified line.
// This function is a wrapper around lineGetAddressCaps to make it easy
// to handle the variable sized structure and any errors received.
LPLINEADDRESSCAPS CTAPILine::I_lineGetAddressCaps(DWORD dwAddressID)
{
int nSizeLineAddressCaps = sizeof(LINEADDRESSCAPS) + 1024;
long lReturn;
// Continue this loop until the structure is big enough.
while (TRUE)
{
// Make sure the buffer exists, is valid and big enough.
LPLINEADDRESSCAPS lpLineAddressCaps =
(LPLINEADDRESSCAPS)new BYTE[nSizeLineAddressCaps];
if (lpLineAddressCaps == NULL)
return NULL;
lpLineAddressCaps->dwTotalSize = nSizeLineAddressCaps;
// Make the call to fill the structure.
do
{
lReturn = ::lineGetAddressCaps(CTAPIConnection::m_hLineApp,
m_dwDeviceID, dwAddressID,
m_dwAPIVersion, m_dwExtVersion,
lpLineAddressCaps);
if (CTAPIError::HandleLineErr(lReturn))
continue;
else
{
TRACE0("lineGetAddressCaps unhandled error\n");
delete lpLineAddressCaps;
return NULL;
}
}
while (lReturn != TAPISUCCESS);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -