📄 tapiutils.cpp
字号:
//
// TAPIUTILS.CPP
//
// This module implements the CTapiConnection class.
//
#include "stdafx.h"
#include <string.h>
#include "TapiUtils.h"
// All TAPI line functions return 0 for SUCCESS, so define it.
#define SUCCESS 0
// TAPI version that this sample is designed to use.
#define SAMPLE_TAPI_VERSION 0x00010004
// Early TAPI version
#define EARLY_TAPI_VERSION 0x00010003
// Possible return error for resynchronization functions.
#define WAITERR_WAITABORTED 1
// A pointer to my class because TAPI needs a callback
CTapiConnection *MyThis;
#if FALSE
// Structures needed to handle special non-dialable characters.
#define g_sizeofNonDialable (sizeof(g_sNonDialable)/sizeof(g_sNonDialable[0]))
typedef struct {
LONG lError;
DWORD dwDevCapFlag;
LPSTR szToken;
LPSTR szMsg;
} NONDIALTOKENS;
NONDIALTOKENS g_sNonDialable[] = {
{LINEERR_DIALBILLING, LINEDEVCAPFLAGS_DIALBILLING, "$",
"Wait for the credit card bong tone" },
{LINEERR_DIALDIALTONE, LINEDEVCAPFLAGS_DIALDIALTONE, "W",
"Wait for the second dial tone" },
{LINEERR_DIALDIALTONE, LINEDEVCAPFLAGS_DIALDIALTONE, "w",
"Wait for the second dial tone" },
{LINEERR_DIALQUIET, LINEDEVCAPFLAGS_DIALQUIET, "@",
"Wait for the remote end to answer" },
{LINEERR_DIALPROMPT, 0, "?",
"Press OK when you are ready to continue dialing"},
};
#endif
//
// Constructor
//
CTapiConnection::CTapiConnection()
{
m_bShuttingDown = FALSE;
m_bStoppingCall = FALSE;
m_bInitializing = FALSE;
m_bTapiInUse = FALSE;
m_dwNumDevs = 0;
m_hCall = NULL;
m_hLine = NULL;
m_dwDeviceID = 0;
m_hLineApp = NULL;
MyThis = this;
};
//
// Destructor
//
CTapiConnection::~CTapiConnection()
{
m_bInitialized = FALSE;
};
//
// FUNCTION: BOOL Create()
//
// PURPOSE: Initializes TAPI
//
BOOL CTapiConnection::Create(char *szPhoneNumber)
{
long lReturn;
// If we're already initialized, then initialization succeeds.
if (m_hLineApp)
return TRUE;
// If we're in the middle of initializing, then fail, we're not done.
if (m_bInitializing)
return FALSE;
m_bInitializing = TRUE;
// Initialize TAPI
do
{
lReturn = ::lineInitialize(&m_hLineApp,
AfxGetInstanceHandle(),
lineCallbackFunc,
"DialIt",
&m_dwNumDevs);
if (m_dwNumDevs == 0)
{
AfxMessageBox("There are no telephony devices installed.");
m_bInitializing = FALSE;
return FALSE;
}
if (HandleLineErr(lReturn))
continue;
else
{
OutputDebugString("lineInitialize unhandled error\n");
m_bInitializing = FALSE;
return FALSE;
}
}
while(lReturn != SUCCESS);
OutputDebugString("Tapi initialized.\n");
// If the user furnished a phone number copy it over.
if (szPhoneNumber)
strcpy(m_szPhoneNumber, szPhoneNumber);
m_bInitializing = FALSE;
return TRUE;
}
//
// FUNCTION: DialCall()
//
// PURPOSE: Get a number from the user and dial it.
//
BOOL CTapiConnection::DialCall(char *szPhoneNumber)
{
long lReturn;
LPLINEDEVCAPS lpLineDevCaps = NULL;
if (m_bTapiInUse)
{
AfxMessageBox("A call is already being handled.");
return FALSE;
}
// Make sure TAPI is initialized properly
if (!m_hLineApp)
{
if (!Create(NULL))
return FALSE;
}
// If there are no line devices installed on the machine, quit.
if (m_dwNumDevs < 1)
return FALSE;
// We now have a call active. Prevent future calls.
m_bTapiInUse = TRUE;
// Get a phone number from the user.
if (szPhoneNumber == (char *)NULL)
{
if (m_szPhoneNumber == (char *)NULL)
{
HangupCall();
goto DeleteBuffers;
}
}
else
strcpy(m_szPhoneNumber, szPhoneNumber);
// Get the line to use
lpLineDevCaps = GetDeviceLine(&m_dwAPIVersion, lpLineDevCaps);
// Need to check the DevCaps to make sure this line is usable.
if (lpLineDevCaps == NULL)
{
OutputDebugString("Error on Requested line\n");
goto DeleteBuffers;
}
if (!(lpLineDevCaps->dwBearerModes & LINEBEARERMODE_VOICE ))
{
AfxMessageBox("The selected line doesn't support VOICE capabilities");
goto DeleteBuffers;
}
// Does this line have the capability to make calls?
if (!(lpLineDevCaps->dwLineFeatures & LINEFEATURE_MAKECALL))
{
AfxMessageBox("The selected line doesn't support MAKECALL capabilities");
goto DeleteBuffers;
}
// Does this line have the capability for interactive voice?
if (!(lpLineDevCaps->dwMediaModes & LINEMEDIAMODE_INTERACTIVEVOICE))
{
AfxMessageBox("The selected line doesn't support INTERACTIVE VOICE capabilities");
goto DeleteBuffers;
}
// Open the Line for an outgoing call.
do
{
lReturn = ::lineOpen(m_hLineApp, m_dwDeviceID, &m_hLine,
m_dwAPIVersion, 0, 0,
LINECALLPRIVILEGE_NONE, 0, 0);
if((lReturn == LINEERR_ALLOCATED)||(lReturn == LINEERR_RESOURCEUNAVAIL))
{
HangupCall();
OutputDebugString("Line is already in use by a non-TAPI application "
"or by another TAPI Service Provider.\n");
goto DeleteBuffers;
}
if (HandleLineErr(lReturn))
continue;
else
{
OutputDebugString("Unable to Use Line\n");
HangupCall();
goto DeleteBuffers;
}
}
while(lReturn != SUCCESS);
// Start dialing the number
if( MakeTheCall(lpLineDevCaps, m_szPhoneNumber))
OutputDebugString("lineMakeCall succeeded.\n");
else
{
OutputDebugString("lineMakeCall failed.\n");
HangupCall();
}
DeleteBuffers:
if (lpLineDevCaps)
LocalFree(lpLineDevCaps);
return m_bTapiInUse;
}
//
// FUNCTION: void GetDeviceLine()
//
// PURPOSE: Gets the first available line device.
//
//
LPLINEDEVCAPS CTapiConnection::GetDeviceLine(DWORD *pdwAPIVersion, LPLINEDEVCAPS lpLineDevCaps)
{
DWORD dwDeviceID;
char szLineUnavail[] = "Line Unavailable";
char szLineUnnamed[] = "Line Unnamed";
char szLineNameEmpty[] = "Line Name is Empty";
LPSTR lpszLineName;
long lReturn;
char buf[MAX_PATH];
LINEEXTENSIONID lineExtID;
BOOL bDone = FALSE;
for (dwDeviceID = 0; (dwDeviceID < m_dwNumDevs) && !bDone; dwDeviceID ++)
{
lReturn = ::lineNegotiateAPIVersion(m_hLineApp, dwDeviceID,
EARLY_TAPI_VERSION, SAMPLE_TAPI_VERSION,
pdwAPIVersion, &lineExtID);
if ((HandleLineErr(lReturn))&&(*pdwAPIVersion))
{
lpLineDevCaps = MylineGetDevCaps(lpLineDevCaps, dwDeviceID, *pdwAPIVersion);
if ((lpLineDevCaps -> dwLineNameSize) &&
(lpLineDevCaps -> dwLineNameOffset) &&
(lpLineDevCaps -> dwStringFormat == STRINGFORMAT_ASCII))
{
// This is the name of the device.
lpszLineName = ((char *) lpLineDevCaps) +
lpLineDevCaps -> dwLineNameOffset;
sprintf(buf, "Name of device is: %s\n", lpszLineName);
OutputDebugString(buf);
}
else // DevCaps doesn't have a valid line name. Unnamed.
lpszLineName = szLineUnnamed;
}
else // Couldn't NegotiateAPIVersion. Line is unavail.
lpszLineName = szLineUnavail;
// If this line is usable and we don't have a default initial
// line yet, make this the initial line.
if ((lpszLineName != szLineUnavail) &&
(lReturn == SUCCESS ))
{
m_dwDeviceID = dwDeviceID;
bDone = TRUE;
}
else
m_dwDeviceID = MAXDWORD;
}
return (lpLineDevCaps);
}
//
// FUNCTION: MylineGetDevCaps(LPLINEDEVCAPS, DWORD , DWORD)
//
// PURPOSE: Gets a LINEDEVCAPS structure for the specified line.
//
// COMMENTS:
//
// This function is a wrapper around lineGetDevCaps to make it easy
// to handle the variable sized structure and any errors received.
//
// The returned structure has been allocated with LocalAlloc,
// so LocalFree has to be called on it when you're finished with it,
// or there will be a memory leak.
//
// Similarly, if a lpLineDevCaps structure is passed in, it *must*
// have been allocated with LocalAlloc and it could potentially be
// LocalFree()d.
//
// If lpLineDevCaps == NULL, then a new structure is allocated. It is
// normal to pass in NULL for this parameter unless you want to use a
// lpLineDevCaps that has been returned by a previous I_lineGetDevCaps
// call.
//
//
LPLINEDEVCAPS CTapiConnection::MylineGetDevCaps(
LPLINEDEVCAPS lpLineDevCaps,
DWORD dwDeviceID, DWORD dwAPIVersion)
{
// Allocate enough space for the structure plus 1024.
size_t sizeofLineDevCaps = 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) CheckAndReAllocBuffer(
(LPVOID) lpLineDevCaps, // Pointer to existing buffer, if any
sizeofLineDevCaps); // Minimum size the buffer should be
if (lpLineDevCaps == NULL)
return NULL;
// Make the call to fill the structure.
do
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -