#include "StdAfx.h" #include "DeviceMgr.h" #include "DevFax.h" #include "NetworkVs.h" #include "LineAudio.h" #include "LineRecordAna.h" #include "LineRecordDig.h" #include "LineRecordIpra.h" #include "LineRecordIprr.h" #include "Config.h" #include "IprControl.h" SINGLETON_IMPLEMENT(CDeviceMgr) CDeviceMgr::CDeviceMgr(void) { } CDeviceMgr::~CDeviceMgr(void) { __release(); } /***************************************************************** **【函数名称】 __release **【函数功能】 释放资源 **【参数】 **【返回值】 ****************************************************************/ void CDeviceMgr::__release( void ) { for(int i = 0; i < m_LineArray.GetCount(); ++i) { ASSERT(m_LineArray[i] != NULL); delete m_LineArray[i]; } m_LineArray.RemoveAll(); while(!m_FaxList.IsEmpty()) delete m_FaxList.RemoveHead(); } /***************************************************************** **【函数名称】 __initLineObject **【函数功能】 初始化线路对象 **【参数】 **【返回值】 ****************************************************************/ void CDeviceMgr::__initLineObject( void ) { // 初始化线路对象 int nTotalCH = SsmGetMaxCh(); // 系统通道总数 for (int i = 0; i < nTotalCH; ++i) { int nType = SsmGetChType(i); switch(nType) { case CONST_CH_AUDIO_ANA: //模拟放音线路 { CLineAudio * pLine = new CLineAudio(i); m_LineArray.Add(pLine); CMsgCenter::GetInstance().pushMsg(VS_MSG_LINE_STATE_UPDATE, reinterpret_cast(i)); } break; case CONST_CH_REC_ANA: //模拟录音线路 { CLineRecordAna* pLine = new CLineRecordAna(i); m_LineArray.Add(pLine); CMsgCenter::GetInstance().pushMsg(VS_MSG_LINE_STATE_UPDATE, reinterpret_cast(i)); } break; case CONST_CH_REC_DIG: //数字录音线路 { int nCicID = SpyChToCic(i); if (-1 == nCicID) break; if (NULL == __findLineByCicID(nCicID)) { CLineRecordDig *pLine = new CLineRecordDig(i); m_LineArray.Add(pLine); CMsgCenter::GetInstance().pushMsg(VS_MSG_LINE_STATE_UPDATE, reinterpret_cast(i)); } } break; case CONST_CH_FAX: // 传真资源 { CDevFax * pDevFax = new CDevFax(i); m_FaxList.AddTail(pDevFax); CMsgCenter::GetInstance().pushMsg(VS_MSG_DEV_FAX_STATE_UPDAET, reinterpret_cast(i)); } break; case CONST_CH_REC_IPR: { CIprControl::GetInstance().newIprrLine(i); } break; case CONST_CH_REC_IPA: { CIprControl::GetInstance().newIpraLine(i); } break; } } // end for } /***************************************************************** **【函数名称】 __findLineByCicID **【函数功能】 根据数字线路的逻辑编号查找指定数字中继线路 **【参数】 int nCic 数字中继线路的逻辑编号 **【返回值】 ****************************************************************/ CLine* CDeviceMgr::__findLineByCicID( int CicId ) { int Count = m_LineArray.GetCount(); for (int i = 0; i < Count; ++i) { CLine* pLine = m_LineArray[i]; ASSERT(pLine != NULL); if(pLine->type() == DEV_VS_TYPE_RECDIG && pLine->cicId() == CicId) return pLine; } return NULL; } /***************************************************************** **【函数名称】 __findLineByIPOLineID **【函数功能】 根据IPO的线路ID查找线路 **【参数】 **【返回值】 ****************************************************************/ CLine* CDeviceMgr::__findLineByIPOLineID( int IpoLineID ) { int Count = m_LineArray.GetCount(); for (int i = 0; i < Count; ++i) { CLine* pLine = m_LineArray[i]; ASSERT(pLine != NULL); if (pLine->assoIpoId() == IpoLineID) return pLine; } return CIprControl::GetInstance().findLineByIPOLineID(IpoLineID); } /***************************************************************** **【函数名称】 __callBackProc **【函数功能】 回调函数 **【参数】 wEvent:系统当前触发的事件,nReference:通道逻辑号,dwParam:事件输出参数dwUser:用户自定义参数 **【返回值】 ****************************************************************/ void CDeviceMgr::__callBackProc( PSSM_EVENT pEvent ) { CLine* pLine = NULL; switch(pEvent->wEventCode) { case E_CHG_ChState: //通道状态发生变化 case E_PROC_PlayEnd: //放音任务完成 case E_CHG_BusyTone: //检测到忙音,即挂机 case E_PROC_WaitDTMF: //WaitDTMF任务完成 case E_PROC_RecordEnd: //录音任务终止 pLine = findLineByID(pEvent->nReference); break; case E_CHG_FaxPages: { int FaxEnd = SsmFaxCheckEnd(pEvent->nReference); if (FaxEnd == 3) // 已经完成全部传真的接收与发送,正在断开 { CDevFax* pDevFax = getFaxByID(pEvent->nReference); ASSERT(pDevFax != NULL); pLine = pDevFax->getAssoLine(); pEvent->dwParam = 1; } ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{DevMgr}: 传真设备[%d]结束第%d页收发, Result = %d"), pEvent->nReference, pEvent->dwParam, FaxEnd); } break; case E_PROC_FaxEnd: //传真操作结束事件 { CDevFax * pDevFax = getFaxByID(pEvent->nReference); pLine = pDevFax->getAssoLine(); ILogger::getInstance().log(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{DevMgr}: 传真设备[%d]结束传真收发, Result = %d"), pEvent->nReference, pEvent->dwParam); } break; case E_CHG_SpyState: { pLine = __findLineByCicID(pEvent->nReference); } break; case E_IPR_LINK_REC_SLAVER_CONNECTED: CIprControl::GetInstance().onEventSlaverConnected(pEvent); break; case E_IPR_LINK_REC_SLAVER_DISCONNECTED: CIprControl::GetInstance().onEventSlaverDisconnected(pEvent); break; case E_IPR_START_SLAVER_CB: CIprControl::GetInstance().onEventStartSlaverCb(pEvent); break; case E_IPR_CLOSE_SLAVER_CB: CIprControl::GetInstance().onEventCloseSlaverCb(pEvent); break; // IP录音相关 case E_IPR_START_REC_CB: case E_IPR_STOP_REC_CB: case E_IPR_PAUSE_REC_CB: case E_IPR_RESTART_REC_CB: case E_IPR_ACTIVE_SESSION_CB: case E_IPR_DEACTIVE_SESSION_CB: case E_IPR_ACTIVE_AND_REC_CB: case E_IPR_DEACTIVE_AND_STOPREC_CB: case E_RCV_IPR_MEDIA_SESSION_STARTED: case E_RCV_IPR_MEDIA_SESSION_STOPED: case E_RCV_IPR_AUX_MEDIA_SESSION_STARTED: case E_RCV_IPR_AUX_MEDIA_SESSION_STOPED: pLine = findLineByID(pEvent->nReference); break; case E_RCV_IPR_DONGLE_REMOVED: case E_RCV_IPA_DONGLE_REMOVED: CIprControl::GetInstance().onEventUsbKeyRemoved(pEvent); break; case E_RCV_IPR_AUTH_OVERFLOW: CIprControl::GetInstance().onEventAuthOverflow(pEvent); break; case E_RCV_IPR_STATION_ADDED: CIprControl::GetInstance().onEventStationAdd(pEvent); break; case E_RCV_IPR_STATION_REMOVED: CIprControl::GetInstance().onEventStationRemoved(pEvent); break; case E_CHG_CIDExBuf: //收到主叫号码 case E_CHG_RcvDTMF: case E_SYS_ActualPickup: //摘机命令执行完毕 break; } if(pLine != NULL) pLine->procDevMsg(pEvent); } /***************************************************************** **【函数名称】 __eventCallBackProc **【函数功能】 回调函数 **【参数】 wEvent:系统当前触发的事件,nReference:通道逻辑号,dwParam:事件输出参数dwUser:用户自定义参数 **【返回值】 ****************************************************************/ int CALLBACK CDeviceMgr::__eventCallBackProc( PSSM_EVENT pEvent ) { CDeviceMgr* pDevManager = (CDeviceMgr*)pEvent->dwUser; pDevManager->__callBackProc(pEvent); return 1; } /***************************************************************** **【函数名称】 getFreeDevFax **【函数功能】 获取一空闲传真资源 **【参数】 **【返回值】 ****************************************************************/ CDevFax* CDeviceMgr::getFreeDevFax( void ) { static POSITION posFaxStatic = m_FaxList.GetHeadPosition(); for(int i= 0; i< m_FaxList.GetCount(); i++) { CDevFax * pDevFax = m_FaxList.GetNext(posFaxStatic); if(posFaxStatic == NULL) posFaxStatic = m_FaxList.GetHeadPosition(); if(!pDevFax->isBusy()) return pDevFax; } return NULL; } /***************************************************************** **【函数名称】 getFaxByID **【函数功能】 通过传真资源ID获取传真资源对象 **【参数】 **【返回值】 ****************************************************************/ CDevFax* CDeviceMgr::getFaxByID( int DevID ) { POSITION pos = m_FaxList.GetHeadPosition(); while(pos != NULL) { CDevFax * pDevFax = m_FaxList.GetNext(pos); if(pDevFax->id() == DevID) return pDevFax; } return NULL; } /***************************************************************** **【函数名称】 getDevType **【函数功能】 获取设备类型 **【参数】 **【返回值】 ****************************************************************/ int CDeviceMgr::getDevType( void ) { int type = 0; int Count = m_LineArray.GetCount(); for (int i = 0; i < Count; ++i) { CLine* pLine = m_LineArray[i]; ASSERT(pLine != NULL); if (pLine->type() == DEV_VS_TYPE_AUDIO) //包含有放音模块 { type = type | PDU_DEV_TYPE_VS_PLAY; } if ((pLine->type() == DEV_VS_TYPE_RECANA) || (pLine->type() == DEV_VS_TYPE_RECDIG)) //包含的是录音模块 { type = type | PDU_DEV_TYPE_VS_REC; } } if(CIprControl::GetInstance().getIprrLineCount() > 0) type = type | PDU_DEV_TYPE_VS_REC; return type; } /***************************************************************** **【函数名称】 findLineByID **【函数功能】 根据通道逻辑号查找线路对象 **【参数】 LineID:通道逻辑号 **【返回值】 线路对象 ****************************************************************/ CLine* CDeviceMgr::findLineByID( int LineID ) { int Count = m_LineArray.GetCount(); for (int i = 0; i < Count; ++i) { CLine* pLine = m_LineArray[i]; ASSERT(pLine != NULL); if (pLine->id() == LineID) return pLine; } return CIprControl::GetInstance().findLineByID(LineID); } /***************************************************************** **【函数名称】 initDev **【函数功能】 设备初始化 **【参数】 **【返回值】 初始化成功或失败 ****************************************************************/ bool CDeviceMgr::initDev( void ) { //设置事件回调类型 EVENT_SET_INFO EventSet; EventSet.dwWorkMode = EVENT_CALLBACKA; EventSet.lpHandlerParam = __eventCallBackProc; EventSet.dwUser = (DWORD)this; // 系统初始化 int IsSsmStartCtiOK = SsmStartCtiEx(SH_SSM_CFG_FILE, SH_IDX_CFG_FILE, TRUE, &EventSet); if(IsSsmStartCtiOK != 0) { char szErrMsg[DEV_OP_BUF_LEN]; SsmGetLastErrMsg(szErrMsg); AfxMessageBox(szErrMsg, MB_OK, 0); return false; } // 是否所有板卡都初始化成功 if(SsmGetMaxUsableBoard() != SsmGetMaxCfgBoard()) { char szErrMsg[DEV_OP_BUF_LEN]; SsmGetLastErrMsg(szErrMsg); CString ErrContent; ErrContent.Format(_T("警告:板卡总数=%d, 初始化成功板卡数=%d!\n 错误信息=\"%s\""), SsmGetMaxCfgBoard(), SsmGetMaxUsableBoard(), szErrMsg); AfxMessageBox(szErrMsg, MB_OK, 0); SsmCloseCti(); return false; } //初始化线路对象 __initLineObject(); CIprControl::GetInstance().init(); //设置回调事件 初始化已由SsmStartCti改为SsmStartCtiEx,后者包含了事件输出的设定,故该函数调用暂被注释 //if(SsmSetEvent(0xffff, -1, TRUE, &EventSet) == -1) //Designates event //{ // char szErrMsg[DEV_OP_BUF_LEN]; // SsmGetLastErrMsg(szErrMsg); //Get wrong message // AfxMessageBox(szErrMsg, MB_OK, 0); // closeDev(); // return false; //} ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{DevMgr}: 设备初始化成功")); return true; } /***************************************************************** **【函数名称】 closeDev **【函数功能】 关闭设备 **【参数】 **【返回值】 ****************************************************************/ void CDeviceMgr::closeDev( void ) { CIprControl::GetInstance().release(); if (SsmCloseCti() != 1) ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{DevMgr}: 关闭设备时出错")); __release(); ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{DevMgr}: 设备关闭")); } /***************************************************************** **【函数名称】 procCmd **【函数功能】 处理网络命令 **【参数】 **【返回值】 ****************************************************************/ void CDeviceMgr::procCmd( CPduEntity* a_pPduEntity ) { CLine* pLine = NULL; switch(a_pPduEntity->GetCmdType()) { case PDU_CMD_IVR_PLAY_DTMF: // 放音收号 { pLine = __findLineByIPOLineID(a_pPduEntity->GetDataUInt(3)); if(pLine == NULL) { a_pPduEntity->SetToExecReturn(); a_pPduEntity->SetDataBool(0, false); CNetworkVs::GetInstance().sendPduToCti(a_pPduEntity); ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{DevMgr}: 收到放音收号命令, 但未找到对应VS线路[%d], 请确定FirstStep中配置是否正确"), a_pPduEntity->GetDataUInt(3)); } } break; case PDU_CMD_IVR_LEAVE_WORD: // 留言 { pLine = __findLineByIPOLineID(a_pPduEntity->GetDataUInt(3)); if(pLine == NULL) { a_pPduEntity->SetToExecReturn(); a_pPduEntity->SetDataBool(0, false); CNetworkVs::GetInstance().sendPduToCti(a_pPduEntity); ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{DevMgr}: 收到留言命令, 但未找到对应VS线路[%d], 请确定FirstStep中配置是否正确"), a_pPduEntity->GetDataUInt(3)); } } break; case PDU_CMD_IVR_FAX: // 传真 { pLine = __findLineByIPOLineID(a_pPduEntity->GetDataUInt(3)); if(pLine == NULL) { a_pPduEntity->SetToExecReturn(); a_pPduEntity->SetDataBool(0, false); CNetworkVs::GetInstance().sendPduToCti(a_pPduEntity); ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{DevMgr}: 收到传真命令, 但未找到对应VS线路[%d], 请确定FirstStep中配置是否正确"), a_pPduEntity->GetDataUInt(3)); } } break; case PDU_CMD_CTI_VS_RECORD: // 录音 { pLine = __findLineByIPOLineID(a_pPduEntity->GetDataUInt(1)); if(pLine == NULL) { a_pPduEntity->SetToExecReturn(); a_pPduEntity->SetDataBool(0, false); CNetworkVs::GetInstance().sendPduToCti(a_pPduEntity); ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{DevMgr}: 收到录音命令, 但未找到对应VS线路[%d], 请确定FirstStep中配置是否正确"), a_pPduEntity->GetDataUInt(1)); } } break; case PDU_CMD_CTI_VS_LINECONTROL: { pLine = __findLineByIPOLineID(a_pPduEntity->GetDataUInt(0)); if(pLine == NULL) { ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{DevMgr}: 收到线路控制命令, 但未找到对应VS线路[%d], 请确定FirstStep中配置是否正确"), a_pPduEntity->GetDataUInt(0)); } } break; } if(pLine != NULL) pLine->procCmd(a_pPduEntity); } /***************************************************************** **【函数名称】 hangupAllLine **【函数功能】 对所有线路进行挂机操作 **【参数】 **【返回值】 ****************************************************************/ void CDeviceMgr::hangupAllLine( void ) { int Count = m_LineArray.GetCount(); for (int i = 0; i < Count; ++i) { CLine* pLine = m_LineArray[i]; ASSERT(pLine != NULL); CPduEntity cmd(PDU_CMD_CTI_VS_LINECONTROL); cmd.SetDataInt(1, IVR_LINE_HANG_UP); pLine->procCmd(&cmd); } }