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

📄 hcentralmanager.cpp

📁 一个使用tapi实现的自动语音应答的例子
💻 CPP
字号:
 /*****************************************************************
 * HCentralManager.cpp: implementation of the CHCentralManager
 * class.
 *
 * Auther: Hamed.M.
 * eMail : HamedMosavi @ hotmail.com
 *		   HamedMosavi @ gmail.com
 *****************************************************************/

#include "stdafx.h"
#include "HCentralManager.h"
#include "HSettings.h"
#include "HDevices.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

/*********************************************************************
 * Globals & Statics
 ********************************************************************/
						   /* A handle to main communication thread */
extern unsigned long	g_lMngrThread;
										/* Saves programme settings */
extern CHSettings		g_settings;
										   /* Device list inventory */
extern CHDevices		g_devices;
					   /* Will keep the phone#, if got successfully */
extern CString			g_phoneNumber;
							   /* Program executable folder address */
extern CString			g_path;

BOOL CHCentralManager::s_threadTerminate = FALSE;

/*********************************************************************
 * Construction: CHCentralManager class
 ********************************************************************/
CHCentralManager::CHCentralManager()
{
	g_lMngrThread = 0;
	m_pThread = NULL;
	s_threadTerminate = FALSE;
}

/*********************************************************************
 * Destruction: CHCentralManager class
 ********************************************************************/
CHCentralManager::~CHCentralManager()
{
									  /* Terminating Message Thread */
	s_threadTerminate = TRUE;
	Sleep(200);						 /* Give time to thread to exit */
}

/*********************************************************************
 * Will get all messages and process them.
 ********************************************************************/
void CHCentralManager::ProcessMessage(MSG msg)
{
	switch (msg.message) {

	case WM_DTMF:				   /* New DTMF code pressed by user */
		if (m_pWParent)
			m_pWParent->PostMessage(
				WM_STATUS_CHNGD,msg.lParam,ST_DTMF);
										 /* Play him/her a response */
		OnProcessDtmf(msg.lParam);
		break;
									   /* Playlist playback is done 
						(& we already asked the sound to inform us)*/
	case WM_SOUND_DONE:
		// UNDONE : Restart the line, perhaps.
		break;

						/* Line status changed, do appropriate job. */
	case WM_STATUS_CHNGD:
							    /* If TAPI Failed, cleanup and exit */
		if (msg.lParam==ST_FAILED) {
			OnFailed();
			break;
		} else if (msg.wParam == ST_PICKED_UP && 
				   msg.lParam == ST_BUSY) {
			OnAnswerTheCall();
			break;
		}
							  /* Update UI (Inform the UI manager!) */
//		ASSERT(m_pWParent);
		if (m_pWParent)
			m_pWParent->PostMessage(
				WM_STATUS_CHNGD,msg.wParam,msg.lParam);
		else {
						 /* If this class has not any parent window */
		// UNDONE : Inform developer.
		}
		break;

									  /* If users callerId received */
	case WM_CALLERID:
		g_phoneNumber = m_line.GetCallerID();
												   /* Inform parent */
		m_pWParent->PostMessage(WM_STATUS_CHNGD,0,ST_CALLER_ID);
		break;

	default : break;
	}
}

/*********************************************************************
 * Wakes up all managers!
 ********************************************************************/
BOOL CHCentralManager::WakeUp()
{
	try {

		/* Begin a message thread so that others can communicate us */
		m_pThread = AfxBeginThread(
			MessageThread,
			(LPVOID)this,
			THREAD_PRIORITY_BELOW_NORMAL,
			0,
			NULL,
			0);
										 /* If we can't run manager */
		if (!m_pThread) return FALSE;
											 /* Set global variable */
		g_lMngrThread = m_pThread->m_nThreadID;

				/* Run a message thread to get sound class messages */
		m_pSoundThread = AfxBeginThread(
			SoundThread,
			(LPVOID)this,
			THREAD_PRIORITY_BELOW_NORMAL,
			0,
			NULL,
			0);
										 /* If we can't run manager */
		if (!m_pSoundThread) return FALSE;
											 /* Set global variable */
					   /* Run a message thread to get DTMF Messages */
		m_pDTMFThread = AfxBeginThread(
			DTMFThread,
			(LPVOID)this,
			THREAD_PRIORITY_NORMAL,
			0,
			NULL,
			0);
										 /* If we can't run manager */
		if (!m_pDTMFThread) return FALSE;
												/* Set sound's boss */
		m_soundManager.SetManager(m_pSoundThread->m_nThreadID);
		m_soundManager.Reset();

								/* Set athread to get DTMF messages */
		m_line.SetBossMessenger(m_pDTMFThread->m_nThreadID);

					 /* Check to conform with user defined settings */
		if (g_settings.m_ringCount!=0) {
			m_line.SetRingCount(g_settings.m_ringCount);
		} else {
			g_settings.m_ringCount = 2;
			m_line.SetRingCount(2);
		}
									   /* Statr the line operations */
		m_line.Start();
										  /* Statr the phone device */
		m_phone.Start();

								  /* Handle line & phone exceptions */
	} catch (CTapiObj::TEx e) {

		CHErrLogger::LogError(e);
		if (g_lMngrThread)
			PostThreadMessage(
			g_lMngrThread,WM_STATUS_CHNGD,0,ST_FAILED);
		return FALSE;
										 /* Handle other exceptions */
	} catch ( ... ) {
		CHErrLogger::LogError(_T("Unknown error in waking up")
			_T("line manager. source: Central Manager"));
							   /* There was an error, inform parent */
		if (g_lMngrThread)
			PostThreadMessage(
			g_lMngrThread,WM_STATUS_CHNGD,0,ST_FAILED);

		return FALSE;
	}

	return TRUE;
}

/*********************************************************************
 * Update parent pointer
 ********************************************************************/
void CHCentralManager::SetParent(CWnd *pWParent)
{
	m_pWParent = pWParent;
}

/*********************************************************************
 * A thread to receive message from other managers
 *********************************************************************
 * A pointer to this thread will be available globaly, so that others
 * can access central manager.
 * TAPI classes (line & phone) will send their message to this thread
 * either.
 ********************************************************************/
UINT CHCentralManager::MessageThread (LPVOID pParam)
{
	CHCentralManager* pCM = (CHCentralManager*) pParam;
	MSG msg;

	while (1) {
		if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
					  /* New Message arrived -> process it please!! */
			pCM->ProcessMessage(msg);
		} else {
						 /* Chaeck message queue every 10 M.Seconds */
			Sleep(10);

								   /* Are we permitted to continue? */
			if (s_threadTerminate) {
				break;
			}
		};
	}
												  /* We are exiting */
	s_threadTerminate = FALSE;
	return 0;
}

/*********************************************************************
 * Reset sound playback
 ********************************************************************/
void CHCentralManager::ResetSound()
{
	// Don't blame me with a function calling 1 other function!
	// In my app. it had more duties!!!
	// This is just some pieces of it.
	m_soundManager.Close();
}

/*********************************************************************
 * Restart everythings
 ********************************************************************/
void CHCentralManager::Restart()
{
											   /* Shutdown the line */
	m_line.ShutDown();
											  /* Shutdown the phone */
	m_phone.ShutDown();
											   /* Empty device list */
	g_devices.Restart();

	try {
												  /* Start the line */
		m_line.Start();
												 /* Start the Phone */
		m_phone.Start();
												    /* Catch errors */
	} catch ( ... ) {
		CHErrLogger::LogError(_T("Unknown error in waking up")
			_T("line manager. source: Central Manager"));
								
										/* We failed, inform parent */
		PostThreadMessage(g_lMngrThread,WM_STATUS_CHNGD,0,ST_FAILED);

		return;
	}
}

/*********************************************************************
 * Does reverse of wakeup! Freezes everythings
 ********************************************************************/
void CHCentralManager::SleepAll()
{
											   /* Shutdown the line */
	m_line.ShutDown();
											  /* Shutdown the phone */
	m_phone.ShutDown();
											   /* Empty device list */
	g_devices.Restart();

	if (m_pThread) {				   /* If thread already started */
										/* Terminate Message Thread */
		s_threadTerminate = TRUE;
										/* Sleep while thread exits */
		if ( WaitForSingleObject(m_pThread->m_hThread,300) == 
			WAIT_TIMEOUT) {

			TerminateThread(m_pThread->m_hThread, 0);
		}
										/* Sleep while thread exits */
		if ( WaitForSingleObject(m_pSoundThread->m_hThread,300) == 
			WAIT_TIMEOUT) {

			TerminateThread(m_pSoundThread->m_hThread, 0);
		}
										/* Sleep while thread exits */
		if ( WaitForSingleObject(m_pDTMFThread->m_hThread,300) == 
			WAIT_TIMEOUT) {

			TerminateThread(m_pDTMFThread->m_hThread, 0);
		}
	}
}

/*********************************************************************
 * A function added in a very very time, to transfer line to phone
 * so that you can speak in your microphone and here in your headphone
 * If your modem supports this.
 ********************************************************************/
long CHCentralManager::EnableSpeakerHook()
{
	long lResult;

	if (lResult = m_phone.SwichToMicSpk()){
		
		TRACE(_T("\n\n\n  %x"),lResult);
	};
	return 0;
}

/*********************************************************************
 * Will be called uppon a failier
 ********************************************************************/
void CHCentralManager::OnFailed()
{
	g_settings.m_deviceId = -1;
	g_settings.m_ringCount = 2;
	
	m_line.ShutDown();
	m_phone.ShutDown();
	g_devices.Restart();
	AfxMessageBox(_T("Can't open device, device is")
		_T("not ready for voice or ..."));
}

/*********************************************************************
 * Start playing first sentences(welcome message)
 ********************************************************************/
void CHCentralManager::OnAnswerTheCall()
{
										  /* Add a file to playlist */
	m_soundManager.AddToPlayList(g_path + 
		_T("Voices\\CP_IVR_WELCOME.wav"));
												  /* Start playback */
	m_soundManager.PlayList(m_line.GetDevWavID(),FALSE,TRUE);
}

/*********************************************************************
 * On each DTMF arrival
 ********************************************************************/
void CHCentralManager::OnProcessDtmf(UINT dtmfCode)
{
	CString str = _T("");
									 /* Make sure nothing's playing */
	m_soundManager.Reset();
										  /* Add a file to playlist */
	str.Format(g_path + _T("Voices\\%d.wav"),dtmfCode);
	m_soundManager.AddToPlayList(str);
												  /* Start playback */
	m_soundManager.PlayList(m_line.GetDevWavID());
}

/*********************************************************************
 * A thread to receive message from DTMF manager
 *********************************************************************
 * A thread to receive DTMF messages. Don't try to mix this message
 * thread with MessageThread. The reason I separated these two is
 * to be able to detect and respond to line messages more quickly and
 * independent to current status of the other thread. Think about a 
 * chicky user who pressed 100 digits one after the other and then 
 * disconnected, calling parent's ProcessMessage() function directly, 
 * make us busy the line untill all button process completed and then
 * process disconnect message.(It's a queue). But separating these 2
 * ensures that line messages will be processed as soon as comming.
 ********************************************************************/
UINT CHCentralManager::DTMFThread (LPVOID pParam)
{
	CHCentralManager* pCM = (CHCentralManager*) pParam;
	MSG msg;

	while (1) {
		if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
					  /* New Message arrived -> process it please!! */
			pCM->ProcessMessage(msg);
		} else {
						 /* Chaeck message queue every 10 M.Seconds */
			Sleep(5);

								   /* Are we permitted to continue? */
			if (s_threadTerminate) {
				break;
			}
		};
	}
												  /* We are exiting */
	s_threadTerminate = FALSE;
	return 0;
}

/*********************************************************************
 * A thread to receive message from Sound manager
 *********************************************************************
 * Will receive messages regurding to sound class
 * In this sample app just 1 message!! It had more duties in my own
 * The message here says that a playlist playback is done, and you
 * asked in your PlayList() call that I inform you! perhaps you want
 * to terminate the session now?!
 ********************************************************************/
UINT CHCentralManager::SoundThread (LPVOID pParam)
{
	CHCentralManager* pCM = (CHCentralManager*) pParam;
	MSG msg;

	while (1) {
		if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
					  /* New Message arrived -> process it please!! */
			pCM->ProcessMessage(msg);
		} else {
						 /* Chaeck message queue every 10 M.Seconds */
			Sleep(10);

								   /* Are we permitted to continue? */
			if (s_threadTerminate) {
				break;
			}
		};
	}
												  /* We are exiting */
	s_threadTerminate = FALSE;
	return 0;
}

/*********************************************************************
 * End of Central manager :)
 ********************************************************************/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -