首頁(yè)>>廠商>>CT中間件廠商>>朗深技術(shù)

使用C++Builder快速實(shí)現(xiàn)自己的專用IVR

2009/06/04

1.涉及的組件
  CTIX控件。

2.應(yīng)用環(huán)境
  使用C++Builder開發(fā)固定流程的IVR。

3.目標(biāo)功能
  來(lái)話后放音,循環(huán)放音完成后掛機(jī)。

4.主要代碼片段
////////////////////////////////////////////////////////////

Part 1: 主窗口類

class TFrmCTIX : public TForm
{
__published:
TCTI *CTI1; //CTIX實(shí)例

void __fastcall FormDestroy(TObject *Sender);
void __fastcall FormCreate(TObject *Sender);
void __fastcall CTI1CallIncome(TObject *Sender, int Tag,
CALL *ACall, BSTR Ano, BSTR Bno);
void __fastcall CTI1CallEnd(TObject *Sender, int Tag,
CALL *ACall);

private:
SCPMANAGER *m_pMainSCPManager; //主SCPMANAGER
};

//Form創(chuàng)建
void __fastcall TFrmCTIX::FormCreate(TObject *Sender)
{
//COM 環(huán)境初始化
CoInitialize(NULL);

//創(chuàng)建線程管理器
g_pThreadManager = new CThreadManager();

//連接到CTI引擎
CTI1->Start(WideString("192.168.1.131").c_bstr(), 10088);

//獲得主SCPMANAGER,CTI1是CTIX的實(shí)例
m_pMainSCPManager = CTI1->GetSCPManager();
}

//Form銷毀
void __fastcall TFrmCTIX::FormDestroy(TObject *Sender)
{
//釋放獲得的SCPMANAGER
m_pMainSCPManager->Free();

//從CTI引擎斷開連接
CTI1->Stop();

//釋放CTIX內(nèi)存
CTI1->Finalize();

delete g_pThreadManager;

//COM環(huán)境釋放
CoUninitialize();
}

//來(lái)話通知事件處理函數(shù)
void __fastcall TFrmCTIX::CTI1CallIncome(TObject *Sender, int Tag,
CALL *ACall, BSTR Ano, BSTR Bno)
{
TAnswerCallThread* pThd = NULL;

//以掛起方式創(chuàng)建應(yīng)答線程,傳入CallID
pThd = new TAnswerCallThread(true, ACall->CallID);
//線程開始運(yùn)行
pThd->Resume();
}

//掛機(jī)通知事件處理函數(shù)
void __fastcall TFrmCTIX::CTI1CallEnd(TObject *Sender, int Tag,
CALL *ACall)
{
//Tag是CALL關(guān)聯(lián)的線程ID
//(線程ID在AnswerCallThread中通過(guò)SetCurrentProcess方法設(shè)置)

//通過(guò)線程ID找到線程
TThread *pThd = g_pThreadManager->FindThreadByThreadID(Tag);
if (pThd != NULL)
{
//調(diào)用線程結(jié)束方法,結(jié)束線程
pThd->Terminate();
}
}

////////////////////////////////////////////////////////////////////////

Part 2:業(yè)務(wù)線程類

class TAnswerCallThread : public TThread
{
private:
SCPMANAGER *m_pThreadSCPManager; //線程用的SCPMANAGER
int OriginalCallID; //保存線程構(gòu)造時(shí)傳入的CallID
CALL *m_pOriginalCall; //保存線程對(duì)應(yīng)的CALL

protected:
void __fastcall Execute();

public:
__fastcall TAnswerCallThread(bool CreateSuspended, int callid);

};

//線程構(gòu)造函數(shù)
__fastcall TAnswerCallThread::TAnswerCallThread(
bool CreateSuspended, int callid) : TThread(CreateSuspended)
{
m_pThreadSCPManager = NULL;

//保存線程構(gòu)造時(shí)傳入的CallID
m_OriginalCallID = callid;

//結(jié)束后釋放線程
FreeOnTerminate = true;

//將線程加入到線程管理器
g_pThreadManager->AddThread(this);
}

//線程主執(zhí)行函數(shù)
void __fastcall TAnswerCallThread::Execute()
{
int ret;
BSTR errstr = NULL;

//準(zhǔn)備線程COM環(huán)境
CoInitialize(NULL);

//-------------- 應(yīng)答過(guò)程 ----------------------
try
{
//獲得線程的SCPMANAGER
m_pThreadSCPManager = FrmCTIX->CTI1->GetSCPManager();
if (m_pThreadSCPManager == NULL)
{
throw Exception("GetSCPManager fail.");
}

//獲得線程關(guān)聯(lián)的呼叫
m_pOriginalCall = m_pThreadSCPManager->
FindCallByID(m_OriginalCallID);
if (m_pOriginalCall == NULL)
{
throw Exception("FindCallByID fail.");
}

//設(shè)置呼叫關(guān)聯(lián)的線程ID
ret = m_pOriginalCall->AttachCurrentProcess(ThreadID);
if (ret != rtSUCC)
{
BSTR errstr = m_pOriginalCall->LastErrStr;
throw Exception(AnsiString("設(shè)置關(guān)聯(lián)線程錯(cuò)誤:")
+ AnsiString(errstr));
}

//應(yīng)答來(lái)話
ret = m_pOriginalCall->Answer();
if (ret != rtSUCC)
{
BSTR errstr = m_pOriginalCall->LastErrStr;
throw Exception(AnsiString("應(yīng)答來(lái)話錯(cuò)誤:")
+ AnsiString(errstr));
}
}
catch(Exception& e)
{
if (errstr != NULL)
{
//COM返回的BSTR由用戶釋放
SysFreeString(errstr);
}
//輸出錯(cuò)誤消息e.Message
}


//-------------- 業(yè)務(wù)過(guò)程 ----------------------
errstr = NULL;
try
{
int taskid;

//異步循環(huán)放音,直到StopOP或掛機(jī)
ret = m_pOriginalCall->Play(true, true,
WideString("D:\\vox\\welcome.vox").c_bstr(), &taskid);
if (ret != rtSUCC)
{
BSTR errstr = m_pOriginalCall->LastErrStr;
throw Exception(AnsiString("放音錯(cuò)誤:")
+ AnsiString(errstr));
}

//等待30秒
Sleep(30000L);

//停止放音
ret = m_pOriginalCall->StopOP(taskid);
if (ret != rtSUCC)
{
BSTR errstr = m_pOriginalCall->LastErrStr;
throw Exception(AnsiString("停止放音錯(cuò)誤:")
+ AnsiString(errstr));
}
}
catch(Exception& e)
{
if (errstr != NULL)
{
//COM返回的BSTR由用戶釋放
SysFreeString(errstr);
}
//輸出錯(cuò)誤消息e.Message
}

//呼叫掛機(jī)
ret = m_pOriginalCall->OnHook();

//-------------- 等待掛機(jī)事件 ------------------
while (Terminated == false)
{
Sleep(100L);
}

//-------------- 清理獲得的COM對(duì)象 --------------
if (m_pThreadSCPManager != NULL)
{
//釋放線程的SCPMANAGER
m_pThreadSCPManager->Free();
}
if (m_pOriginalCall != NULL)
{
//釋放線程關(guān)聯(lián)的CALL對(duì)象
m_pOriginalCall->Free();
}

//將線程從線程管理器中刪除
g_pThreadManager->RemoveThreadByThreadID(ThreadID);

//釋放線程COM環(huán)境
CoUninitialize();

}

///////////////////////////////////////////////////////////////////////

Part 3 線程管理器類

class CThreadManager
{
private:
TBucketList *m_pThreadList; //線程列表哈希表
TCriticalSection *m_pListLocker; //線程鎖

public:
CThreadManager();
~CThreadManager();

//將線程加入線程表
void AddThread(TThread *pThd);
//根據(jù)線程ID從線程中移除
void RemoveThreadByThreadID(int ThreadID);
//根據(jù)線程ID查找線程對(duì)象
TThread *FindThreadByThreadID(int ThreadID);
};


//線程管理器構(gòu)造
CThreadManager::CThreadManager()
{
m_pThreadList = new TBucketList(bl16);
m_pListLocker = new TCriticalSection();
}

//線程管理器析構(gòu)
CThreadManager::~CThreadManager()
{
delete m_pThreadList;
delete m_pListLocker;
}


//加入線程列表
void CThreadManager::AddThread(TThread *pThd)
{
//多線程訪問(wèn)列表,需要加鎖
m_pListLocker->Acquire();
try
{
m_pThreadList->Add((void*)(pThd->ThreadID), pThd);
}
catch(...)
{
}
m_pListLocker->Release();
}

//從線程列表中刪除
void CThreadManager::RemoveThreadByThreadID(int ThreadID)
{
//多線程訪問(wèn)列表,需要加鎖
m_pListLocker->Acquire();
try
{
TThread *pThd = NULL;
if (m_pThreadList->Find((void*)ThreadID, (void*)pThd))
{
m_pThreadList->Remove((void*)ThreadID);
}
}
catch(...)
{
}
m_pListLocker->Release();
}

//根據(jù)線程ID查找線程
TThread * CThreadManager::FindThreadByThreadID(int ThreadID)
{
TThread *pRetThd = NULL;

//多線程訪問(wèn)列表,需要加鎖
m_pListLocker->Acquire();
try
{
TThread *pThd = NULL;
if (m_pThreadList->Find((void*)ThreadID, (void*)pThd))
{
pRetThd = pThd;
}
}
catch(...)
{
}
m_pListLocker->Release();
return pRetThd;
}

CTI論壇報(bào)道


相關(guān)鏈接:
UniMedia Script++常用對(duì)象及使用 2009-06-03
UniMedia MSIX座席控件的使用 2009-06-02
UniMedia MSIX座席控件Delphi調(diào)用實(shí)例解析 2009-06-01
UniMedia IDE集成環(huán)境文件操作實(shí)例解析 2009-05-22
UniMedia IDE集成環(huán)境調(diào)用DLL動(dòng)態(tài)庫(kù)實(shí)例解析 2009-05-22