📄 hcentralmanager.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 + -