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

📄 tapiobj.cpp

📁 一个使用tapi实现的自动语音应答的例子
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*********************************************************************
 * 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 + -