6.示例程序
以C++Builder为例,示例实现了一个简单的来话处理,循环播放语音后挂机。
6.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();
9
//释放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();
}
}6.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();
11
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)
{
12
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();}6.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;
}