首页>>厂商>>CT中间件厂商>>朗深技术

使用C++Builder快速实现自己的专用IVR

2009/06/04

1.涉及的组件
  CTIX控件。

2.应用环境
  使用C++Builder开发固定流程的IVR。

3.目标功能
  来话后放音,循环放音完成后挂机。

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

Part 1: 主窗口类

class TFrmCTIX : public TForm
{
__published:
TCTI *CTI1; //CTIX实例

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创建
void __fastcall TFrmCTIX::FormCreate(TObject *Sender)
{
//COM 环境初始化
CoInitialize(NULL);

//创建线程管理器
g_pThreadManager = new CThreadManager();

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

//获得主SCPMANAGER,CTI1是CTIX的实例
m_pMainSCPManager = CTI1->GetSCPManager();
}

//Form销毁
void __fastcall TFrmCTIX::FormDestroy(TObject *Sender)
{
//释放获得的SCPMANAGER
m_pMainSCPManager->Free();

//从CTI引擎断开连接
CTI1->Stop();

//释放CTIX内存
CTI1->Finalize();

delete g_pThreadManager;

//COM环境释放
CoUninitialize();
}

//来话通知事件处理函数
void __fastcall TFrmCTIX::CTI1CallIncome(TObject *Sender, int Tag,
CALL *ACall, BSTR Ano, BSTR Bno)
{
TAnswerCallThread* pThd = NULL;

//以挂起方式创建应答线程,传入CallID
pThd = new TAnswerCallThread(true, ACall->CallID);
//线程开始运行
pThd->Resume();
}

//挂机通知事件处理函数
void __fastcall TFrmCTIX::CTI1CallEnd(TObject *Sender, int Tag,
CALL *ACall)
{
//Tag是CALL关联的线程ID
//(线程ID在AnswerCallThread中通过SetCurrentProcess方法设置)

//通过线程ID找到线程
TThread *pThd = g_pThreadManager->FindThreadByThreadID(Tag);
if (pThd != NULL)
{
//调用线程结束方法,结束线程
pThd->Terminate();
}
}

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

Part 2:业务线程类

class TAnswerCallThread : public TThread
{
private:
SCPMANAGER *m_pThreadSCPManager; //线程用的SCPMANAGER
int OriginalCallID; //保存线程构造时传入的CallID
CALL *m_pOriginalCall; //保存线程对应的CALL

protected:
void __fastcall Execute();

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

};

//线程构造函数
__fastcall TAnswerCallThread::TAnswerCallThread(
bool CreateSuspended, int callid) : TThread(CreateSuspended)
{
m_pThreadSCPManager = NULL;

//保存线程构造时传入的CallID
m_OriginalCallID = callid;

//结束后释放线程
FreeOnTerminate = true;

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

//线程主执行函数
void __fastcall TAnswerCallThread::Execute()
{
int ret;
BSTR errstr = NULL;

//准备线程COM环境
CoInitialize(NULL);

//-------------- 应答过程 ----------------------
try
{
//获得线程的SCPMANAGER
m_pThreadSCPManager = FrmCTIX->CTI1->GetSCPManager();
if (m_pThreadSCPManager == NULL)
{
throw Exception("GetSCPManager fail.");
}

//获得线程关联的呼叫
m_pOriginalCall = m_pThreadSCPManager->
FindCallByID(m_OriginalCallID);
if (m_pOriginalCall == NULL)
{
throw Exception("FindCallByID fail.");
}

//设置呼叫关联的线程ID
ret = m_pOriginalCall->AttachCurrentProcess(ThreadID);
if (ret != rtSUCC)
{
BSTR errstr = m_pOriginalCall->LastErrStr;
throw Exception(AnsiString("设置关联线程错误:")
+ AnsiString(errstr));
}

//应答来话
ret = m_pOriginalCall->Answer();
if (ret != rtSUCC)
{
BSTR errstr = m_pOriginalCall->LastErrStr;
throw Exception(AnsiString("应答来话错误:")
+ AnsiString(errstr));
}
}
catch(Exception& e)
{
if (errstr != NULL)
{
//COM返回的BSTR由用户释放
SysFreeString(errstr);
}
//输出错误消息e.Message
}


//-------------- 业务过程 ----------------------
errstr = NULL;
try
{
int taskid;

//异步循环放音,直到StopOP或挂机
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("放音错误:")
+ AnsiString(errstr));
}

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

//停止放音
ret = m_pOriginalCall->StopOP(taskid);
if (ret != rtSUCC)
{
BSTR errstr = m_pOriginalCall->LastErrStr;
throw Exception(AnsiString("停止放音错误:")
+ AnsiString(errstr));
}
}
catch(Exception& e)
{
if (errstr != NULL)
{
//COM返回的BSTR由用户释放
SysFreeString(errstr);
}
//输出错误消息e.Message
}

//呼叫挂机
ret = m_pOriginalCall->OnHook();

//-------------- 等待挂机事件 ------------------
while (Terminated == false)
{
Sleep(100L);
}

//-------------- 清理获得的COM对象 --------------
if (m_pThreadSCPManager != NULL)
{
//释放线程的SCPMANAGER
m_pThreadSCPManager->Free();
}
if (m_pOriginalCall != NULL)
{
//释放线程关联的CALL对象
m_pOriginalCall->Free();
}

//将线程从线程管理器中删除
g_pThreadManager->RemoveThreadByThreadID(ThreadID);

//释放线程COM环境
CoUninitialize();

}

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

Part 3 线程管理器类

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

public:
CThreadManager();
~CThreadManager();

//将线程加入线程表
void AddThread(TThread *pThd);
//根据线程ID从线程中移除
void RemoveThreadByThreadID(int ThreadID);
//根据线程ID查找线程对象
TThread *FindThreadByThreadID(int ThreadID);
};


//线程管理器构造
CThreadManager::CThreadManager()
{
m_pThreadList = new TBucketList(bl16);
m_pListLocker = new TCriticalSection();
}

//线程管理器析构
CThreadManager::~CThreadManager()
{
delete m_pThreadList;
delete m_pListLocker;
}


//加入线程列表
void CThreadManager::AddThread(TThread *pThd)
{
//多线程访问列表,需要加锁
m_pListLocker->Acquire();
try
{
m_pThreadList->Add((void*)(pThd->ThreadID), pThd);
}
catch(...)
{
}
m_pListLocker->Release();
}

//从线程列表中删除
void CThreadManager::RemoveThreadByThreadID(int ThreadID)
{
//多线程访问列表,需要加锁
m_pListLocker->Acquire();
try
{
TThread *pThd = NULL;
if (m_pThreadList->Find((void*)ThreadID, (void*)pThd))
{
m_pThreadList->Remove((void*)ThreadID);
}
}
catch(...)
{
}
m_pListLocker->Release();
}

//根据线程ID查找线程
TThread * CThreadManager::FindThreadByThreadID(int ThreadID)
{
TThread *pRetThd = NULL;

//多线程访问列表,需要加锁
m_pListLocker->Acquire();
try
{
TThread *pThd = NULL;
if (m_pThreadList->Find((void*)ThreadID, (void*)pThd))
{
pRetThd = pThd;
}
}
catch(...)
{
}
m_pListLocker->Release();
return pRetThd;
}

CTI论坛报道


相关链接:
UniMedia Script++常用对象及使用 2009-06-03
UniMedia MSIX座席控件的使用 2009-06-02
UniMedia MSIX座席控件Delphi调用实例解析 2009-06-01
UniMedia IDE集成环境文件操作实例解析 2009-05-22
UniMedia IDE集成环境调用DLL动态库实例解析 2009-05-22