📄 tapiobj.cpp
字号:
/*********************************************************************
* TapiObj.cpp:
* implementation of the
* CTapiObj,
* CLine,
* CPhone classes
* WARNINGS:
* - Just 1 and only 1 instance of these class must be
* created.
*
* Auther: Hamed.M.
* eMail : HamedMosavi @ hotmail.com
* HamedMosavi @ gmail.com
********************************************************************/
#include "stdafx.h"
#include "TapiObj.h"
#include "HSettings.h"
#include "HDevices.h"
#include "HErrLogger.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
/*********************************************************************
* Globals
********************************************************************/
/* To post event messages to central manager */
extern unsigned long g_lMngrThread;
/* To load some initialdata from a prefrences list */
extern CHSettings g_settings;
/* To store a list of telephony devices */
extern CHDevices g_devices;
/*********************************************************************
* Construction: Parent class
********************************************************************/
CTapiObj::CTapiObj()
{
/* Our application name. CP stands for Code Project ;) */
m_appName = _T("CP_IVR");
/* This application is going to use TAPI 2.1 */
/* For more information about versionning look at MSDN */
m_version = 0x00020001;
/* We are going to place a communication of the type voice */
m_mediaMode = LINEMEDIAMODE_AUTOMATEDVOICE;
}
/*********************************************************************
* Destruction: Parent class
********************************************************************/
CTapiObj::~CTapiObj()
{
}
/*********************************************************************
* Construction: Exception class, to be thrown!
********************************************************************/
CTapiObj::TEx::TEx(int id, CString res, CString dt, CString tm)
{
code=id;
result=res;
date=dt;
time=tm;
}
/*********************************************************************
* CLine class
*********************************************************************
* This class impelements a line and defines main operations on it *
* A line will be automatically answered (picked up), and app waits *
* and detects codes that user presses at the other end of the line *
* CallerID of the user will be receiver. *
* It informs the outside world of what's happenning at any time by *
* posting a message to any hread, whoes handle is placed in *
* 'g_lMngrThread' global variable. *
********************************************************************/
/*********************************************************************
*Constructor: CLine class (Up to line # 810)
********************************************************************/
CLine::CLine()
{
/* To receive device capabilities info. */
m_pLineDevCaps = NULL;
/* To keep the ID of the current device, it can be used later to
* to open other devices, in a multiline application. Line class
* Starts searching ID's greater than this ID, So after Finding
* the first line ID, you can give this 'that value +1' to search
* for the next device. */
m_lBossThreadID = 0;
m_ID = 0;
m_cid = _T("");
/* The line has not been initialized yet */
m_bInitialized = FALSE;
/* The line has not been opened yet */
m_bOpened = FALSE;
/* Thread should not stop after starting */
m_bContinueEventThread = TRUE;
/* TAPI variables */
m_hLineApp = NULL;
m_hLine = NULL;
m_hCall = NULL;
m_hLineEvent = NULL;
m_hLineMsgThread = NULL;
m_hWOut = NULL;
memset(&m_extID,NULL,sizeof(LINEEXTENSIONID));
m_dwApiVersion = 0;
m_dwWaveOutID = 0;
m_dwRingCnt = 0;
/* Will be filled by the number of available TAPI devices */
m_nLineCnt = 0;
}
/*********************************************************************
* Destructor: CLine class
********************************************************************/
CLine::~CLine()
{
ShutDown();
}
/*********************************************************************
* Initialize the line, (~ 200 lines)
********************************************************************/
long CLine::Init()
{
PostThreadMessage(g_lMngrThread,WM_STATUS_CHNGD,0,ST_INIT);
long ret = -1;
/* To be able to control loops. It will keep track of the numbers
a loop continued, so after a maximum, we are in trouble=> break */
int patience = 0;
/* Working with memory in TAPI is a hell! */
BOOL noMem;
/* Allocate memory for line parameters */
LINEINITIALIZEEXPARAMS *lineParams =
(LINEINITIALIZEEXPARAMS *) calloc(1,
sizeof(LINEINITIALIZEEXPARAMS));
memset(lineParams,NULL,sizeof(LINEINITIALIZEEXPARAMS));
/* We are going to receive TAPI events using an event thread */
lineParams->dwOptions = LINEINITIALIZEEXOPTION_USEEVENT;
lineParams->dwTotalSize = sizeof(LINEINITIALIZEEXPARAMS);
/* Try to initilize line */
/* We need a loop untill needed memory is alocated */
do {
/* We have not memory shortage yet */
noMem = FALSE;
/* First TAPI call in the sequence */
ret = lineInitializeEx(
&m_hLineApp,
AfxGetInstanceHandle(),
NULL,
m_appName,
&m_nLineCnt,
&m_version,
lineParams );
/* Didn't Itell you about memory hell? Here it starts
If more memory is needed, Realocate */
/* Re alocate memory if more is needed */
if ( lineParams->dwNeededSize > lineParams->dwTotalSize ) {
int needed = lineParams->dwNeededSize;
noMem = TRUE;
free(lineParams);
lineParams = NULL;
lineParams = (LINEINITIALIZEEXPARAMS *) calloc(1,needed);
if (!lineParams) {
ThrowErr(0,
_T("TapiObj.cpp, Ln 186, can't alocate memory"));
}
memset(lineParams,NULL,needed);
lineParams->dwOptions = LINEINITIALIZEEXOPTION_USEEVENT;
lineParams->dwTotalSize = needed;
}
/* If this loop ran 1000 times!!, there must be a problem */
if (++patience> 1000) {
if (lineParams) free(lineParams);
ThrowErr(1,_T(
"TapiObj.cpp, Ln 199, Recovered from unlimited loop"));
};
/* Sleep 5 mili seconds and re run the loop again */
Sleep(5);
/* Repeat untill everythings go right */
} while ( (ret==LINEERR_REINIT) || (noMem==TRUE) );
/* Get a handle for thread waking up */
m_hLineEvent = (lineParams->Handles.hEvent);
/* Free unused memory */
if (lineParams) free(lineParams);
/* Catch errors */
if (ret != 0) {
CString str;
str.Format(_T("%d"),ret);
ThrowErr(ret,_T("TapiObj.cpp, Ln 217, ret=")+str);
}
/* Create an array of devices */
g_devices.Reset();
/* Place to hold the true device id */
int trueDeviceId = 0;
/* Time to negotiate! for a good device */
for (int i=m_ID;(unsigned)i<m_nLineCnt;i++) {
ret = lineNegotiateAPIVersion(
m_hLineApp,
i,
m_version,
m_version,
&m_dwApiVersion,
&m_extID );
if (ret !=0 ) continue;
/* Warning: this line MUST be before calling GetDevCaps */
m_ID = i;
/* Check device capabilities */
ret = GetDevCaps();
/* Catch errors */
if (ret != 0) {
CString sr;
sr.Format(_T("%d"),ret);
ThrowErr(ret,_T("TapiObj.cpp, Ln 248, ret=")+sr);
}
/* Add information to device array */
int nSize = (m_pLineDevCaps->dwLineNameSize/sizeof(TCHAR))+
sizeof(TCHAR);
TCHAR *sname = new TCHAR[nSize];
memset(sname,NULL,nSize);
wcsncpy(sname,
(LPCTSTR)((LPBYTE)m_pLineDevCaps +
m_pLineDevCaps->dwLineNameOffset),
nSize);
g_devices.Add(i,sname);
delete []sname;
/* Is device demanding? Can it support answering machine? */
if (m_pLineDevCaps->dwMediaModes &
LINEMEDIAMODE_AUTOMATEDVOICE
&& m_pLineDevCaps->dwMonitorToneMaxNumFreq > 0) {
trueDeviceId = i;
}
}
/* If we were asked to open a particular device */
if (g_settings.m_deviceId!=-1) {
/* If true device ID is NOT equal to the requested ID */
if ( g_settings.m_deviceId!=trueDeviceId ) {
/* Better NOT to throw an error, and try openning it,
because user asked to! */
}
m_ID = g_settings.m_deviceId;
g_devices.SetDefaultItem(g_settings.m_deviceId);
} else { /* If no default device id defined */
g_settings.m_deviceId = trueDeviceId;
g_devices.SetDefaultItem(trueDeviceId);
m_ID = g_settings.m_deviceId;
}
/* Now we got a list of all devices. */
/* Try to re negotiate the true device. */
ret = lineNegotiateAPIVersion(
m_hLineApp,
m_ID,
m_version,
m_version,
&m_dwApiVersion,
&m_extID );
/* Catch errors */
if (ret != 0) {
CString sr;
sr.Format(_T("%d"),ret);
ThrowErr(ret,_T("TapiObj.cpp, Ln 302, ret=")+sr);
}
/* Ask for cpabilities of the true device */
ret = GetDevCaps();
/* Catch errors */
if (ret != 0) {
CString sr;
sr.Format(_T("%d"),ret);
ThrowErr(ret,_T("TapiObj.cpp, Ln 312, ret=")+sr);
}
if ((unsigned)trueDeviceId<=m_nLineCnt && ret==0 &&
m_pLineDevCaps->dwMediaModes & LINEMEDIAMODE_AUTOMATEDVOICE &&
m_pLineDevCaps->dwMonitorToneMaxNumFreq > 0)
m_bInitialized = TRUE;
else {
/* Now we are sure, we can't do that! */
/* Device is not able to do what we ask */
PostThreadMessage(g_lMngrThread,WM_STATUS_CHNGD,0,ST_FAILED);
}
/* Line initialization is done. */
return TRUE;
}
/*********************************************************************
* Openning the line
********************************************************************/
long CLine::Open()
{
long ret = -1;
/* Inform parent about a open process start */
PostThreadMessage(
g_lMngrThread,WM_STATUS_CHNGD,0,ST_OPEN);
/* If line has not been initialized yet */
if (!m_bInitialized) return ret;
/* Open line, another call to TAPI */
ret = lineOpen(m_hLineApp,
m_ID,
&m_hLine,
m_dwApiVersion,
0, 0, LINECALLPRIVILEGE_OWNER,
LINEMEDIAMODE_AUTOMATEDVOICE,
NULL);
/* Check for errors */
if (ret !=0 ) {
return ret;
}
m_bOpened = TRUE;
/* Pickup after ? rings */
lineSetNumRings (m_hLine, 0, m_dwRingCnt);
/* I want to receive all messages and events appropriate to me! */
ret = lineSetStatusMessages(
m_hLine,
m_pLineDevCaps->dwLineStates,
0);
/* Start a thread to listen to events from this line */
m_bContinueEventThread = TRUE;
m_hLineMsgThread = CreateThread(
NULL,
NULL,
EventThread,
(LPVOID)this,
NULL,
0);
/* Well! We are ready now, everythings OK */
PostThreadMessage(g_lMngrThread,WM_STATUS_CHNGD,0,ST_READY);
return ret;
}
/*********************************************************************
* Asks TAPI for device capabilities
********************************************************************/
long CLine::GetDevCaps()
{
long ret = -1;
int patience = 0;
DWORD dwRealSize = 0;
/* Free the memory that possibly alocated from last calls */
if (m_pLineDevCaps) free(m_pLineDevCaps);
m_pLineDevCaps = NULL;
/* Try to alocate minimum possible memory */
m_pLineDevCaps = (LINEDEVCAPS*) calloc(1,sizeof(LINEDEVCAPS));
if (!m_pLineDevCaps)
return IDS_LINEERR_NOMEM;
/* Clean memory */
memset(m_pLineDevCaps,NULL,sizeof(LINEDEVCAPS));
m_pLineDevCaps->dwTotalSize = sizeof(LINEDEVCAPS);
/* Run a loop untill enough memory alocated */
do {
ret = lineGetDevCaps (m_hLineApp,
m_ID,
m_dwApiVersion,
0,
m_pLineDevCaps);
/* Check memory size and realocate, if nessesery */
dwRealSize = m_pLineDevCaps->dwNeededSize;
if (m_pLineDevCaps->dwTotalSize < dwRealSize) {
free(m_pLineDevCaps);
m_pLineDevCaps = NULL;
/* Try to alocate minimum posible memory */
m_pLineDevCaps = (LINEDEVCAPS*) calloc(1,dwRealSize);
if (!m_pLineDevCaps)
return IDS_LINEERR_NOMEM;
/* Clean memory */
memset(m_pLineDevCaps,NULL,dwRealSize);
m_pLineDevCaps->dwTotalSize = dwRealSize;
} else break;
/* We'll not encounter unlimited loops */
if (++patience> 1000) {
if (m_pLineDevCaps) free(m_pLineDevCaps);
ThrowErr(3,_T("TapiObj.cpp, Ln 430,")
_T("Recovered from unlimited loop"));
break;
};
} while (1);
return ret;
}
/*********************************************************************
* Processes events received from TAPI (~ 180 lines)
********************************************************************/
void CLine::ProcessEvent()
{
LINEMESSAGE stLineMsg;
DWORD dwTimeout = 10;// Miliseconds
long ret=0;
CString tmp,st;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -