#include "StdAfx.h" #include "LineOpImplement.h" #include "Line.h" #include "LineAudio.h" #include "DeviceMgr.h" #include "Config.h" #include "DevFax.h" #include "NetworkVs.h" #include "LineRecordAna.h" #include "LineRecordDig.h" #include "../IVR/IvrSysInc.h" #include "../TtsInterface/TtsInterface.h" SINGLETON_IMPLEMENT(CLineOpImplement) CLineOpImplement::CLineOpImplement(void) { } CLineOpImplement::~CLineOpImplement(void) { } /***************************************************************** **【函数名称】 __createFilePath **【函数功能】 创建文件路径 **【参数】 FilePath: 文件路径 **【返回值】 ****************************************************************/ bool CLineOpImplement::__createFilePath( LPCTSTR FilePath ) { CString tmpPath = FilePath; int index = tmpPath.ReverseFind('\\'); if (index == -1) index = tmpPath.ReverseFind('/'); tmpPath = tmpPath.Left(index + 1); return SHCreateDirectoryEx(NULL, tmpPath, NULL) == ERROR_SUCCESS; } /***************************************************************** **【函数名称】 __startPlay **【函数功能】 放音/放音收号 **【参数】 pLine: 放音线路 PlayContent: 放音内容(指定音乐文件路径) **【返回值】 成功true, 失败false ****************************************************************/ bool CLineOpImplement::__startPlay( CLine *pLine, LPCTSTR PlayContent ) { int LineID = pLine->id(); //获取通道状态 int Res= SsmGetChState(LineID); if (Res == -1) { char Buf[DEV_OP_BUF_LEN] = { 0 }; SsmGetLastErrMsg(Buf); ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_ERROR, _T("{LineOP}: 线路[%d]放音时获取通道状态失败, %s"), LineID, Buf); return false; } if (Res != S_CALL_TALKING) { ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{LineOP}: 线路[%d]未处于连接状态不能放音"), LineID); return false; } if (SsmCheckPlay(LineID) == 0) { ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{LineOP}: 线路[%d]正在放音, 将终止当前放音"), LineID); //先停止,保证下面的正常操作 SsmStopPlayFile(LineID); } //设置收到DTMF是否停止放音 if ( SsmSetDtmfStopPlay(LineID, TRUE) == -1) { char Buf[DEV_OP_BUF_LEN] = { 0 }; SsmGetLastErrMsg(Buf); ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_ERROR, _T("{LineOP}: 线路[%d]设置按键停止放音出错, %s"), LineID, Buf); return false; } //清空DTMF缓冲区 if(SsmClearRxDtmfBuf(LineID) == -1) { char Buf[DEV_OP_BUF_LEN] = { 0 }; SsmGetLastErrMsg(Buf); ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_ERROR, _T("{LineOP}: 线路[%d]清空DTMF缓冲出错, %s"), LineID, Buf); return false; } //开始放音 Res = SsmPlayFile(LineID, PlayContent, 6, 0,-1); if (Res == -1) { char Buf[DEV_OP_BUF_LEN] = { 0 }; SsmGetLastErrMsg(Buf); ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_ERROR, _T("{LineOP}: 线路[%d]放音失败, %s"), LineID, Buf); return false; } ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{LineOP}: 线路[%d]开始放音"), LineID); return true; } /***************************************************************** **【函数名称】 __stopPlay **【函数功能】 停止放音及收号 **【参数】 LineID: 指定线路ID **【返回值】 ****************************************************************/ void CLineOpImplement::__stopPlay( CLine *pLine ) { CPduEntity* pCmdPduEntity = pLine->getCmd(); if(pCmdPduEntity != NULL && pCmdPduEntity->GetCmdType() == PDU_CMD_IVR_PLAY_DTMF) { // 若存在此命令说明是在放音结束前就要停止放音,则通知CTI放音失败。 pCmdPduEntity->SetToExecReturn(); pCmdPduEntity->SetDataBool(0, false); CNetworkVs::GetInstance().sendPduToCti(pCmdPduEntity); pLine->freeCmd(); } int LineID = pLine->id(); if (SsmCheckPlay(LineID) == 0) { //查看该通道是否在录音 int Res = SsmCheckRecord(LineID); if ((Res == 5) || (Res == 0)) { SsmStopRecToFile(LineID); ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{LineOP}: 线路[%d]停止录音"), LineID); } if(SsmStopPlayFile(LineID) == 0) ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{LineOP}: 线路[%d]停止放音"), LineID); else { char Buf[DEV_OP_BUF_LEN] = { 0 }; SsmGetLastErrMsg(Buf); ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{LineOP}: 线路[%d]停止放音失败, %s"), LineID, Buf); } } TCHAR Dtmf[DEV_OP_BUF_LEN] = { 0 }; if(SsmChkWaitDtmf(LineID, Dtmf) == 0) { if(SsmCancelWaitDtmf(LineID) == 0) ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{LineOP}: 线路[%d]停止接收DTMF"), LineID); } } /***************************************************************** **【函数名称】 __waitForDtmf **【函数功能】 设置等待收号 **【参数】 pLine:指定线路指针 DtmfLen:接收DTMF的最大长度 szEndFlag:结束字符 DtmfSpan:按键间隔 **【返回值】 成功TRUE,失败FALSE ****************************************************************/ bool CLineOpImplement::__waitForDtmf( CLine *pLine, int DtmfLen, char EndFlag, int DtmfSpan ) { int LineID = pLine->id(); if (SsmGetChState(LineID) == S_CALL_TALKING) //通道状态为接通 { if(DtmfLen > 0) //收号位数大于0 { int iDtmfMixTime = DtmfLen * DtmfSpan; if (SsmSetWaitDtmf(LineID, iDtmfMixTime, DtmfLen, EndFlag, FALSE) == 0) return true; } } else { ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{LineOP}: 线路[%d]未处于连接状态不能收号"), LineID); } return false; } /***************************************************************** **【函数名称】 __linkFax **【函数功能】 关联一传真资源 **【参数】 pLine: 放音线路指针 **【返回值】 成功TRUE, 失败FALSE ****************************************************************/ bool CLineOpImplement::__linkFax( CLineAudio *pLine ) { CDevFax * pDevFax = CDeviceMgr::GetInstance().getFreeDevFax(); if(pDevFax == NULL) { ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{LineOP}: 线路[%d]关联传真资源失败, 没有空闲传真资源"), pLine->id()); return false; } pLine->setFax(pDevFax); pDevFax->setAssoLine(pLine); //显示关联的传真资源ID pLine->show(); return true; } /***************************************************************** **【函数名称】 __unLinkFax **【函数功能】 释放一传真资源 **【参数】 pLine: 放音线路指针 **【返回值】 ****************************************************************/ void CLineOpImplement::__unLinkFax( CLineAudio *pLine ) { CDevFax *pDevFax = pLine->getFax(); if(pDevFax == NULL) return; //判断是否收发传真时启动录音 if(CConfig::recordFax()) __stopRecord(pLine); pDevFax->stopFax(); pDevFax->setAssoLine(NULL); pLine->freeFax(); //显示关联的传真资源ID为空 pLine->show(); } /***************************************************************** **【函数名称】 __hangUp **【函数功能】 放音线路挂机 **【参数】 LineID: 线路ID **【返回值】 ****************************************************************/ void CLineOpImplement::__hangUp( int LineID ) { //挂机执行 if (SsmHangup(LineID) == -1) { char Buf[DEV_OP_BUF_LEN] = { 0 }; SsmGetLastErrMsg(Buf); ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{LineOP}: 线路[%d]挂机失败, %s"), LineID, Buf); } else { ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{LineOP}: 线路[%d]挂机"), LineID); } } /***************************************************************** **【函数名称】 __startRecord **【函数功能】 录音 **【参数】 pLine: 录音线路 FileName: 录音文件完全路径 FinishKey: 结束符 LeaveTime: 留言时间 **【返回值】 成功TRUE, 失败FALSE ****************************************************************/ bool CLineOpImplement::__startRecord( CLine *pLine, LPCTSTR FileName, char FinishKey, int LeaveTime ) { ASSERT(pLine != NULL); //创建文件路径 __createFilePath(FileName); DEV_VS_TYPE LineType = pLine->type(); int LineID = pLine->id(); //开启自动增益 SsmSetRecAGC(LineID, TRUE); //查看该通道是否在录音 if (SsmGetRecType(LineID) != 0) { //先停止,下面的才能开始录音 if(LineType == DEV_VS_TYPE_RECDIG) SpyStopRecToFile(LineID); else SsmStopRecToFile(LineID); ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{LineOP}: 线路[%d]录音终止, 开始新的录音"), LineID); } if (LeaveTime <= 0) // 录音结束时间不可用,发生在为传真录音时 { LeaveTime = 0xFFFFFF; } else { LeaveTime = LeaveTime * 1000; TCHAR FinishKeySet[2] = { 0 }; FinishKeySet[0] = FinishKey; //设置结束标志 if (SsmSetDTMFStopRecCharSet(LineID, FinishKeySet) == -1) { char Buf[DEV_OP_BUF_LEN] = { 0 }; SsmGetLastErrMsg(Buf); ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_ERROR,_T("{LineOP}: 线路[%d]设置录音结束按键出错, %s"), LineID, Buf); return false; } } //开始执行录音. int nReturn = -1; if (LineType == DEV_VS_TYPE_RECDIG) //数字录音 { char RecordFile[MAX_PATH] = { 0 }; _snprintf_s(RecordFile, MAX_PATH, _TRUNCATE, _T("%s"), FileName); nReturn = SpyRecToFile(LineID, 2, RecordFile, 6, 0, 0xffffffff, LeaveTime, 1); } else nReturn = SsmRecToFile(LineID, FileName, 6, 0, 0xffffffff, LeaveTime, 1); if (nReturn == 0) { ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_NORMAL,_T("{LineOP}: 线路[%d]开始录音, FileName = %s"), LineID, FileName); return true; } else { char Buf[DEV_OP_BUF_LEN] = { 0 }; SsmGetLastErrMsg(Buf); ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_ERROR, _T("{LineOP}: 线路[%d]录音出错, %s"), LineID, Buf); return false; } } /***************************************************************** **【函数名称】 __stopRecord **【函数功能】 停止留言 **【参数】 pLine: 线路 **【返回值】 ****************************************************************/ void CLineOpImplement::__stopRecord( CLine *pLine ) { ASSERT(pLine != NULL); CString strInfo; int LineID = pLine->id(); int LineType = pLine->type(); int nReturnIsRec = SsmGetRecType(LineID); // 当坐席外呼时,挂机后通道先变为空闲,实际上通道上还有录音任务 // 获取通道类型失败(-1),则直接返回不进行停止录音处理 if(-1 == nReturnIsRec) { ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_ERROR, _T("{LineOP}: 线路[%d]停止录音时获取录音状态出错"), LineID); return; } if (LineType == DEV_VS_TYPE_RECANA || LineType == DEV_VS_TYPE_RECDIG) { int nReturn = 0; if (LineType == DEV_VS_TYPE_RECANA ) { if (nReturnIsRec != 0) nReturn = SsmStopRecToFile(LineID); } else { nReturn = SpyStopRecToFile(LineID); } if (0 != nReturn) { char Buf[DEV_OP_BUF_LEN] = { 0 }; SsmGetLastErrMsg(Buf); ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_ERROR, _T("{LineOP}: 线路[%d]停止录音失败, %s"), LineID, Buf); } else { ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{LineOP}: 线路[%d]已停止录音"), LineID); } } } /***************************************************************** **【函数名称】 __pauseRecord **【函数功能】 暂停录音 **【参数】 LineID 线路ID **【返回值】 成功TRUE, 失败FALSE ****************************************************************/ bool CLineOpImplement::__pauseRecord( int LineID ) { // 检查通道上是否有录音任务 /*int Res = SsmCheckRecord(LineID); if(Res > 0 && Res < 7) { ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{LineOP}: 线路[%d]未进行录音或录音已暂停"), LineID); return false; }*/ //暂停录音 if (SsmPauseRecToFile(LineID) == 0) { ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{LineOP}: 线路[%d]录音暂停"), LineID); return true; } else { char Buf[DEV_OP_BUF_LEN] = { 0 }; SsmGetLastErrMsg(Buf); ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_ERROR, _T("{LineOP}: 线路[%d]暂停录音失败, %s"), LineID, Buf); return false; } } /***************************************************************** **【函数名称】 __resumeRecord **【函数功能】 继续录音 **【参数】 LineID 线路ID **【返回值】 成功TRUE, 失败FALSE ****************************************************************/ bool CLineOpImplement::__resumeRecord( int LineID ) { if(SsmCheckRecord(LineID) != 5) { ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{LineOP}: 线路[%d]没有被暂停的录音任务"), LineID); return false; } if (SsmRestartRecToFile(LineID) == -1) { char Buf[DEV_OP_BUF_LEN] = { 0 }; SsmGetLastErrMsg(Buf); ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{LineOP}: 线路[%d]恢复录音失败, %s"), LineID, Buf); return false; } else { ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{LineOP}: 线路[%d]已恢复录音"), LineID); return true; } } /***************************************************************** **【函数名称】 __pickUp **【函数功能】 摘机执行 **【参数】 LineID: 线路ID **【返回值】 ****************************************************************/ void CLineOpImplement::__pickUp( int LineID ) { int nReturnState= SsmGetChState(LineID); switch(nReturnState) { case S_CALL_RINGING: //振铃 { int nReturn = SsmPickup(LineID); if (nReturn == -1) { char Buf[DEV_OP_BUF_LEN] = { 0 }; SsmGetLastErrMsg(Buf); ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{LineOP}: 线路[%d]摘机失败, %s"), LineID, Buf); } else { ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{LineOP}: 线路[%d]摘机成功"), LineID); } } break; case S_CALL_TALKING: //通话 ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{LineOP}: 线路[%d]已处于通话状态, 不需摘机"), LineID); break; default: ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{LineOP}: 线路[%d]未处于振铃状态, 无法执行摘机操作"), LineID); break; } } /***************************************************************** **【函数名称】 onCmdLinePlay **【函数功能】 放音命令处理 **【参数】 CLinePlay *pLine 放音线路指针 CPduEntity* pPduEntity 命令指针 **【返回值】 ****************************************************************/ void CLineOpImplement::onCmdLinePlay( CLineAudio *pLine, CPduEntity* pPduEntity ) { ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{LineOP}: 线路[%d]收到放音收按键命令"), pLine->id()); bool Result = false; int PlayMode = pPduEntity->GetDataInt(4); switch(PlayMode) { case PVM_PLAY_WAIT_DIGIT: case PVM_PLAY_ONLY: { char szFileName[MAX_PATH] = { 0 }; switch(pPduEntity->GetDataInt(5)) { default: case PLAY_CONTENT_AUDIO: // 不使用TTS { lstrcpy(szFileName, pPduEntity->GetDataString(15)); Result = true; } break; case PLAY_CONTENT_TTS_STR: // TTS文本 { ITtsInterface::getInstance().setTTSParam(pPduEntity->GetDataInt(6), pPduEntity->GetDataInt(8), pPduEntity->GetDataInt(9)); Result = ITtsInterface::getInstance().string2Audio(pPduEntity->GetDataString(15).GetBuffer(0), szFileName, MAX_PATH); } break; case PLAY_CONTENT_TTS_FILE: // TTS文件 { ITtsInterface::getInstance().setTTSParam(pPduEntity->GetDataInt(6), pPduEntity->GetDataInt(8), pPduEntity->GetDataInt(9)); Result = ITtsInterface::getInstance().file2Audio(pPduEntity->GetDataString(15).GetBuffer(0), szFileName, 512); } break; } if(Result) Result = __startPlay(pLine, szFileName); } break; case PVM_WAIT_DIGIT: { int DTMFLen = pPduEntity->GetDataInt(10); char szEndFlag=(pPduEntity->GetDataString(11)).GetAt(0); int DtmfSpan = pPduEntity->GetDataInt(12); // 按键间隔 Result = __waitForDtmf(pLine, DTMFLen, szEndFlag, DtmfSpan); } break; case PVM_STOP_PLAY: { if(pLine->getCmd() != NULL) pLine->freeCmd(); } return; default: ASSERT(FALSE); break; } if(!Result) { pPduEntity->SetToExecReturn(); pPduEntity->SetDataBool(0, false); CNetworkVs::GetInstance().sendPduToCti(pPduEntity); } else { pLine->setCmd(pPduEntity); } } /***************************************************************** **【函数名称】 CLineOpImplement::GetInstance() **【函数功能】 线路控制命令处理 **【参数】 CLinePlay *pLine 放音线路指针 CPduEntity* pPduEntity 命令指针 **【返回值】 ****************************************************************/ void CLineOpImplement::onCmdLinePlayControl( CLineAudio *pLine, CPduEntity* pPduEntity ) { int lineControl = pPduEntity->GetDataInt(1); if(lineControl == IVR_LINE_HANG_UP) { ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{LineOP}: 线路[%d]收到挂机控制命令"), pLine->id()); //停止留言 __stopRecord(pLine); //停止放音及收号 __stopPlay(pLine); //挂机操作 __hangUp(pLine->id()); } } /***************************************************************** **【函数名称】 onCmdFax **【函数功能】 传真操作命令处理 **【参数】 CLinePlay *pLine 放音线路指针 CPduEntity* pPduEntity 命令指针 **【返回值】 ****************************************************************/ void CLineOpImplement::onCmdFax( CLineAudio *pLine, CPduEntity* pPduEntity ) { int Direction = pPduEntity->GetDataUInt(4); CString strFaxFileName = pPduEntity->GetDataString(5); ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{LineOP}: 线路[%d]收到%s传真命令, FaxFile = %s") , pLine->id(), (Direction == 0 ? _T("发送") : _T("接收")), strFaxFileName); // 查找一空闲传真资源 __linkFax(pLine); // 开始发送或者接收传真的时候是否启动录音 if(CConfig::recordFax()) __startRecord(pLine, strFaxFileName, '\0', -1); // 执行结果标志 bool bResult = false; CDevFax* pFax = pLine->getFax(); if(pFax != NULL) { if(Direction == 0) //发送传真 { bResult = pFax->sendFax(strFaxFileName); } else //接收传真 { bResult = pFax->recvFax(strFaxFileName); } } if(bResult) { //保存传真操作命令,等待传真操作设备回调事件的返回 pLine->setCmd(pPduEntity); } else { pPduEntity->SetToExecReturn(); pPduEntity->SetDataBool(0,FALSE); CNetworkVs::GetInstance().sendPduToCti(pPduEntity); __unLinkFax(pLine); //释放传真资源 } } /***************************************************************** **【函数名称】 onCmdLeaveWord **【函数功能】 留言操作处理 **【参数】 CLinePlay *pLine 放音线路指针 CPduEntity* pPduEntity 命令指针 **【返回值】 ****************************************************************/ void CLineOpImplement::onCmdLeaveWord( CLineAudio *pLine, CPduEntity* pPduEntity ) { //命令参数解析 CString szRecFileName = pPduEntity->GetDataString(6); //录音文件名 char szEndFlag = pPduEntity->GetDataString(5).GetAt(0); //结束标志 int LeaveTime = pPduEntity->GetDataUInt(4); //留言时长 ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{LineOP}: 线路[%d]收到留言命令, RecordFile = %s") , pLine->id(), szRecFileName); if(__startRecord(pLine, szRecFileName, szEndFlag, LeaveTime)) { //如果函数执行成功,等待留言结束回调事件的返回 pLine->setCmd(pPduEntity); } else { pPduEntity->SetToExecReturn(); pPduEntity->SetDataBool(0,FALSE); CNetworkVs::GetInstance().sendPduToCti(pPduEntity); } } /***************************************************************** **【函数名称】 onCmdLineHangUp **【函数功能】 挂机操作 **【参数】 CLinePlay *pLine 放音线路指针 **【返回值】 ****************************************************************/ void CLineOpImplement::onCmdLineHangUp( CLineAudio *pLine ) { int LineID = pLine->id(); ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{LineOP}: 线路[%d]收到挂机命令"), LineID); //挂机执行 if (SsmHangup(LineID) == -1) { char szBuf[DEV_OP_BUF_LEN] = { 0 }; SsmGetLastErrMsg(szBuf); ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{LineOP}: 线路[%d]挂机失败, ErrorMsg = %s"), LineID, szBuf); } } /***************************************************************** **【函数名称】 onCmdLineRecord **【函数功能】 录音线路命令处理 **【参数】 CLinePlay *pLine 放音线路指针 CPduEntity* pPduEntity 命令指针 **【返回值】 ****************************************************************/ void CLineOpImplement::onCmdLineRecord( CLine *pLine, CPduEntity * pPduEntity ) { CString szRecFileName = pPduEntity->GetDataString(3); //录音文件名 switch(pPduEntity->GetDataInt(2)) { case RECORD_CONTROL_BEGIN: // 录音开始 { char szEndFlag = pPduEntity->GetDataString(4).GetAt(0); //结束标志 int LeaveTime = pPduEntity->GetDataLong(5); //留言时长 __startRecord(pLine, szRecFileName, szEndFlag, LeaveTime); ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{LineOP}: 录音线路[%d]收到开始录音命令, RecFile = %s"), pLine->id(), szRecFileName); } break; case RECORD_CONTROL_END: // 停止录音 { __stopRecord(pLine); ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{LineOP}: 录音线路[%d]收到停止录音命令, RecFile = %s"), pLine->id(), szRecFileName); } break; case RECORD_CONTROL_PAUSE: // 暂停录音 { __pauseRecord(pLine->id()); ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{LineOP}: 录音线路[%d]收到暂停录音命令, RecFile = %s"), pLine->id(), szRecFileName); } break; case RECORD_CONTROL_RESUME: // 继续录音 { __resumeRecord(pLine->id()); ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{LineOP}: 录音线路[%d]收到继续录音命令, RecFile = %s"), pLine->id(), szRecFileName); } break; } // end switch } /***************************************************************** **【函数名称】 onCmdLineRecControl **【函数功能】 录音线路控制命令处理 **【参数】 CLinePlay *pLine 放音线路指针 CPduEntity* pPduEntity 命令指针 **【返回值】 ****************************************************************/ void CLineOpImplement::onCmdLineRecControl( CLine *pLine, CPduEntity * pPduEntity ) { int lineControl = pPduEntity->GetDataInt(1); if(lineControl == IVR_LINE_HANG_UP) { ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{LineOP}: 录音线路[%d]收到挂机控制命令"), pLine->id()); //仅仅停止录音,不用挂机 __stopRecord(pLine); } } /***************************************************************** **【函数名称】 onCmdStopRecord **【函数功能】 停止录音 **【参数】 CLine *pLine 指定线路指针 **【返回值】 ****************************************************************/ void CLineOpImplement::onCmdStopRecord( CLine *pLine ) { __stopRecord(pLine); } /***************************************************************** **【函数名称】 onMsgReturnRecord **【函数功能】 录音完成或留言事件 **【参数】 CLinePlay *pLine 放音线路指针 **【返回值】 ****************************************************************/ void CLineOpImplement::onMsgReturnRecord( CLineAudio *pLine ) { CPduEntity* pCmdPduEntity = pLine->getCmd(); if(pCmdPduEntity != NULL) { // 命令存在说明是留言而不是录音执行,只有留言执行才保存命令 pCmdPduEntity->SetToExecReturn(); pCmdPduEntity->SetDataBool(0, true); CNetworkVs::GetInstance().sendPduToCti(pCmdPduEntity); pLine->freeCmd(); ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{LineOP}: 线路[%d]完成留言录音"), pLine->id()); } } /***************************************************************** **【函数名称】 onMsgPlayState **【函数功能】 放音线路状态处理 **【参数】 CLinePlay *pLine 放音线路指针 int nState 状态类型 **【返回值】 ****************************************************************/ void CLineOpImplement::onMsgPlayState( CLineAudio *pLine, int State ) { ASSERT(pLine != NULL); pLine->state() = State; switch(State) { case S_CALL_RINGING: //振铃 pLine->show(); ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{LineOP}: 线路[%d]来电呼入"), pLine->id()); __pickUp(pLine->id()); break; case S_CALL_STANDBY: //空闲 case S_CALL_PICKUPED: //摘机 case S_CALL_TALKING: //连接 case S_CALL_ANALOG_WAITDIALTONE: //等待拨号音 pLine->show(); break; case S_CALL_OFFLINE: //断开 pLine->show(); ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{LineOP}: 线路[%d]断开"), pLine->id()); break; } } /***************************************************************** **【函数名称】 onMsgReturnPlay **【函数功能】 结束放音 **【参数】 pLine 放音线路指针 **【返回值】 ****************************************************************/ void CLineOpImplement::onMsgReturnPlay( CLineAudio *pLine ) { int LineID = pLine->id(); CPduEntity *pPduEntity = pLine->getCmd(); if(pPduEntity == NULL) { ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{LineOP}: 线路[%d]放音完成, 当前没有关联命令"), LineID); return; } bool Back = false; int PlayMode = pPduEntity->GetDataInt(4); if (PlayMode == PVM_PLAY_ONLY) // 只放音 { ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{LineOP}: 线路[%d]放音完成, 无需收号"), LineID); Back = true; } else if(PlayMode == PVM_PLAY_WAIT_DIGIT) // 放音收号 { int DtmfLen = pPduEntity->GetDataInt(10); char szEndFlag=(pPduEntity->GetDataString(11)).GetAt(0); int DtmfSpan = pPduEntity->GetDataInt(12); if(!__waitForDtmf(pLine, DtmfLen, szEndFlag, DtmfSpan)) { ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_WARNING, _T("{LineOP}: 线路[%d]放音完成, 但设置收号功能失败"), LineID); Back = true; } else { ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{LineOP}: 线路[%d]放音完成, 等待收号"), LineID); } } if(Back) { pPduEntity->SetToExecReturn(); pPduEntity->SetDataBool(0, true); // 若设置收号功能失败,但放音完毕,仍正常返回上层 CNetworkVs::GetInstance().sendPduToCti(pPduEntity); pLine->freeCmd(); } } /***************************************************************** **【函数名称】 onMsgReturnDTMF **【函数功能】 DTMF结束 **【参数】 pLine 放音线路指针 **【返回值】 ****************************************************************/ void CLineOpImplement::onMsgReturnDTMF( CLineAudio *pLine ) { char szBuff[DEV_OP_BUF_LEN]; memset(szBuff, 0, sizeof(szBuff)); int LineID = pLine->id(); // 获取收到的DTMF值 SsmChkWaitDtmf(LineID, szBuff); ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{LineOP}: 线路[%d]收号完成, DTMF = %s"), LineID, szBuff); // 判断是否向同一平台返回 CPduEntity *pPduEntity = pLine->getCmd(); if (pPduEntity != NULL) { pPduEntity->SetToExecReturn(); pPduEntity->SetDataBool(0, true); pPduEntity->SetDataString(16, szBuff); CNetworkVs::GetInstance().sendPduToCti(pPduEntity); pLine->freeCmd(); } //停止放音及重置收号状态 __stopPlay(pLine); } /***************************************************************** **【函数名称】 onMsgReturnFax **【函数功能】 传真结束事件 **【参数】 pLine 放音线路指针 Return 传真事件是否成功 **【返回值】 ****************************************************************/ void CLineOpImplement::onMsgReturnFax( CLineAudio *pLine, int Return ) { bool Result = Return == 1 ? true : false; CDevFax* pFax = pLine->getFax(); ASSERT(pFax != NULL); ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{LineOP}: 线路[%d]完成传真收发任务%s, DevFax = %d"), pLine->id(), (Result ? _T("成功") : _T("失败")), pFax->id()); __unLinkFax(pLine); //取消绑定 CPduEntity *pCmdEntity = pLine->getCmd(); if(pCmdEntity != NULL) { pCmdEntity->SetToExecReturn(); pCmdEntity->SetDataBool(0, Result); CNetworkVs::GetInstance().sendPduToCti(pCmdEntity); pLine->freeCmd(); } } /***************************************************************** **【函数名称】 onMsgDigState **【函数功能】 数字录音线路事件处理 **【参数】 pLine 数字录音线路指针 State 状态类型 **【返回值】 ****************************************************************/ void CLineOpImplement::onMsgDigState( CLineRecordDig *pLine, int State ) { ASSERT(pLine != NULL); pLine->state() = State; switch(State) { case S_SPY_STANDBY: //空闲 case S_SPY_RINGING: //振铃 case S_SPY_TALKING: //通话 case S_SPY_SS1RESET : //电路复原 case S_CALL_UNAVAILABLE: pLine->show(); break; } // end switch } /***************************************************************** **【函数名称】 MsgDigState **【函数功能】 模拟录音线路事件处理 **【参数】 CLineRecordAna *pLine 模拟录音线路指针 int State 状态类型 **【返回值】 ****************************************************************/ void CLineOpImplement::onMsgAnaState( CLineRecordAna *pLine, int State ) { ASSERT(pLine != NULL); pLine->state() = State; switch(State) { case S_CALL_STANDBY: // 空闲 case S_CALL_PICKUPED: // 摘机 case S_CALL_RINGING: // 振铃 case S_CALL_TALKING: // 连接 case S_CALL_ANALOG_WAITDIALTONE: // 等待拨号音 case S_CALL_ANALOG_TXPHONUM: // 拨号 case S_CALL_OFFLINE: // 断开 pLine->show(); break; } }