| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132 |
- #include "StdAfx.h"
- #include "CallSession.h"
- #include "MC.h"
- #include "ProxyShell.h"
- #include "ConsultSession.h"
- #include "MeetingSession.h"
- #include "DirectSession.h"
- #include "TransferSession.h"
- #include "TrunkSession.h"
- #include "Config.h"
- #include "VirtualProxy.h"
- CCallSession::CCallSession(long SessionId) : m_Id(SessionId), m_SubCallIndex(0)
- {
- ZeroMemory(&m_MeetingId, sizeof(MeetingInfo));
- m_MeetingId.MeetingId = MEETING_ID_INVALID;
- }
- CCallSession::~CCallSession(void)
- {
- __clearSubSession();
- }
- /*****************************************************************
- **【函数名称】 __isLineMine
- **【函数功能】 指定线路是否属于当前会话
- **【参数】 LineId 要查找的线路ID
- **【返回值】
- *****************************************************************/
- CALL_PARTY_TYPE CCallSession::__isLineMine( CRDRID LineId )
- {
- int Type;
- if(m_LineMap.Lookup(LineId, Type))
- return (CALL_PARTY_TYPE)Type;
- else
- return CALL_PARTY_UNKNOWN;
- }
- /*****************************************************************
- **【函数名称】 __GetSubCall
- **【函数功能】 通过待处理线路ID查找子呼叫
- **【参数】 PendingLine 通话待处理线路ID
- **【返回值】
- *****************************************************************/
- CSubSession* CCallSession::__getSubSession(CRDRID PendingLine)
- {
- UINT SubCall = 0;
- CSubSession* pSubCall = NULL;
- // 找到子呼叫的ID
- if(!m_PendingLineMap.Lookup(PendingLine, SubCall))
- return NULL;
- // 查找子呼叫指针
- m_SubCallMap.Lookup(SubCall, pSubCall);
- return pSubCall;
- }
- /*****************************************************************
- **【函数名称】 __clearSubSession
- **【函数功能】 释放所有子会话
- **【参数】
- **【返回值】
- *****************************************************************/
- void CCallSession::__clearSubSession( void )
- {
- UINT Key = 0;
- CSubSession* pSub = NULL;
- POSITION pos = m_SubCallMap.GetStartPosition();
- while(pos != NULL)
- {
- m_SubCallMap.GetNextAssoc(pos, Key, pSub);
- ASSERT(pSub != NULL);
- delete pSub;
- } // end while
- m_SubCallMap.RemoveAll();
- }
- /*****************************************************************
- **【函数名称】 __notifySubSessionLineFree
- **【函数功能】 通知子会话相关线路空闲
- **【参数】
- **【返回值】
- *****************************************************************/
- void CCallSession::__notifySubSessionLineFree( CRDRID LineId )
- {
- UINT Key = 0;
- CSubSession* pSub = NULL;
- POSITION pos = m_SubCallMap.GetStartPosition();
- while(pos != NULL)
- {
- m_SubCallMap.GetNextAssoc(pos, Key, pSub);
- ASSERT(pSub != NULL);
- if(pSub->getSubHostLine() == LineId)
- pSub->onHostLineStateFree();
- else if(pSub->getSubPeerLine() == LineId)
- pSub->onPeerLineStateFree();
- } // end while
- }
- /*****************************************************************
- **【函数名称】 __lineDoRecord
- **【函数功能】 执行录音操作
- **【参数】 HostLine 录音线路
- lpFileName 录音文件名
- **【返回值】
- *****************************************************************/
- bool CCallSession::__lineRecord(CRDRID HostLine, LPCTSTR lpFileName)
- {
- // 填充录音参数
- RecordContent content;
- memset(&content, 0, sizeof(RecordContent));
- lstrcpy(content.szFileName, lpFileName);
- content.nTaskId = RECORD_TASK_ID_NORMAL;
- CALL_PARTY_TYPE Party = __isLineMine(HostLine);
- switch(Party)
- {
- case CALL_PARTY_HOST: // 主控线路
- {
- content.nModel = RECORD_MODE_NORMAL;
- content.nPeerLine = m_LinePeer;
- }
- break;
- case CALL_PARTY_PEER: // 对端线路
- {
- content.nModel = RECORD_MODE_NORMAL;
- content.nPeerLine = m_LineHost;
- }
- break;
- case CALL_PARTY_MEETING: // 会议线路
- {
- content.nModel = RECORD_MODE_MEETING;
- }
- break;
- case CALL_PARTY_PENDING:
- {
- content.nModel = RECORD_MODE_NORMAL;
- CSubSession * pSubCall = __getSubSession(HostLine);
- content.nPeerLine = pSubCall->getSubHostLine();
- }
- break;
- } // end switch
- // 启动录音
- return CMC::GetInstance().startRecord(HostLine, &content);
- }
- /*****************************************************************
- **【函数名称】 __LineDoMute
- **【函数功能】 线路静音操作
- **【参数】 HostLine 静音线路
- IsBegin 静音启动/结束
- **【返回值】
- *****************************************************************/
- bool CCallSession::__lineMute(CRDRID HostLine, bool IsOn)
- {
- // 查询对端线路
- DEV_RES_ID AssoLine = getPeerLine(HostLine);
- if(AssoLine.isEmpty())
- return false;
- // 静音控制
- if(IsOn)
- {
- // 断开通话
- CMC::GetInstance().bridgeDevice(HostLine, AssoLine, false);
- // 对端线路播放保持音
- CMC::GetInstance().playTone(AssoLine, CHANNEL_TONE_HOLD);
- }
- else
- {
- // 停止放音
- CMC::GetInstance().playStop(AssoLine);
- // 重连通话
- CMC::GetInstance().bridgeDevice(HostLine, AssoLine, true);
- } // end if
- return true;
- }
- /*****************************************************************
- **【函数名称】 __meetingMute
- **【函数功能】 会议静音操作
- **【参数】 HostLine 静音线路
- IsBegin 静音启动/结束
- **【返回值】
- *****************************************************************/
- bool CCallSession::__meetingMute(CRDRID HostLine, bool IsOn)
- {
- return CMC::GetInstance().meetingMute(HostLine, m_MeetingId, !IsOn);
- }
- /*****************************************************************
- **【函数名称】 __line2Link
- **【函数功能】 线路进入双向通话
- **【参数】 LineId 要进入通话的线路ID
- LinePeeer 要进行通话的对端线路
- **【返回值】
- *****************************************************************/
- bool CCallSession::__line2Link(CRDRID LineId, CRDRID LinePeer)
- {
- CString strRecFile;
- // 当前录音采用混音模式,原线路在录音时不影响线路之间通话的建立,故不需停止当前录音,
- // 因此注释一下三行。
- //// 停止当前录音
- //if(m_RecordMap.Lookup(LinePeer, strRecFile))
- // CMC::GetInstance().stopRecord(LinePeer);
- // 线路双向连通
- return CMC::GetInstance().bridgeDevice(LineId, LinePeer, true);
- }
- /*****************************************************************
- **【函数名称】 __detachListen
- **【函数功能】 解除指定线路的监听
- **【参数】 HostLine 当前挂机的线路
- **【返回值】
- *****************************************************************/
- void CCallSession::__detachListen(CRDRID HostLine)
- {
- POSITION pos = m_ListenLineMap.GetStartPosition();
- while(pos != NULL)
- {
- DEV_RES_ID DevId;
- DEV_RES_ID LineListen;
- m_ListenLineMap.GetNextAssoc(pos, LineListen, DevId);
- if(DevId == HostLine)
- CMC::GetInstance().dropCall(LineListen, false); // 监听线路挂机
- }
- }
- /*****************************************************************
- **【函数名称】 getPeerLine
- **【函数功能】 获取当前线路关联的对端线路
- **【参数】 LineId 要查询的线路
- **【返回值】 0 -> 无对端线路
- *****************************************************************/
- DEV_RES_ID CCallSession::getPeerLine(CRDRID LineId)
- {
- // 当前线路在会话中的职责
- DEV_RES_ID AssoLine;
- CALL_PARTY_TYPE Party = __isLineMine(LineId);
- switch(Party)
- {
- case CALL_PARTY_HOST: // 主控线路
- AssoLine = m_LinePeer;
- break;
- case CALL_PARTY_PEER: // 对端线路
- AssoLine = m_LineHost;
- break;
- default: // 其它线路
- break;
- } // end switch
- return AssoLine;
- }
- /*****************************************************************
- **【函数名称】 IsExist
- **【函数功能】 指定职责的线路是否在会话中
- **【参数】 LineId 要查询的线路ID
- PartyType 线路在会话中的职责
- **【返回值】
- *****************************************************************/
- bool CCallSession::isExist(CRDRID LineId, CALL_PARTY_TYPE PartyType)
- {
- int Type;
- if(m_LineMap.Lookup(LineId, Type))
- {
- return PartyType == (CALL_PARTY_TYPE)Type;
- }
- else
- {
- return false;
- }
- }
- /*****************************************************************
- **【函数名称】 onLineStateChanged
- **【函数功能】 线路状态变化事件处理
- **【参数】 LineId 状态变化的线路ID
- LineState 线路当前状态
- lpCallerNum 主叫号码
- lpCallerNum 被叫号码
- **【返回值】
- *****************************************************************/
- void CCallSession::onLineStateChanged(CRDRID LineId, VIRTUAL_LINE_STATE LineState, LPCTSTR lpCallerNum, LPCTSTR lpCalleeNum)
- {
- // 根据线路物理状态进行分类处理
- switch(LineState)
- {
- case VIRTUAL_LINE_STATE_FREE:
- __onLineStateFree(LineId, lpCallerNum, lpCalleeNum);
- break;
- case VIRTUAL_LINE_STATE_INIT:
- case VIRTUAL_LINE_STATE_DIALING:
- case VIRTUAL_LINE_STATE_DISABLED:
- CProxyShell::GetInstance().onLineStateUpdated(LineId, m_Id, SESSION_INVALID_SUB_CALL, LineState, lpCallerNum, lpCalleeNum);
- break;
- case VIRTUAL_LINE_STATE_RING_BACK:
- __onLineStateRingBack(LineId, lpCallerNum, lpCalleeNum);
- break;
- case VIRTUAL_LINE_STATE_ALERTING:
- __onLineStateAlerting(LineId, lpCallerNum, lpCalleeNum);
- break;
- case VIRTUAL_LINE_STATE_PROGRESSING:
- __onLineStateProgressing(LineId, lpCallerNum, lpCalleeNum);
- break;
- case VIRTUAL_LINE_STATE_TALKING:
- //__setTimer(0,1000*60*10); //鹤壁12345 通话不能超过10分钟
- __onLineStateTalking(LineId, lpCallerNum, lpCalleeNum);
- break;
- } // end switch
- }
- /*****************************************************************
- **【函数名称】 onRecordStop
- **【函数功能】 录音停止事件
- **【参数】 LineId 录音停止的线路ID
- TaskId 录音启动时的任务ID
- **【返回值】
- *****************************************************************/
- void CCallSession::onRecordStop(CRDRID LineId, UINT TaskId)
- {
- if(TaskId == RECORD_TASK_ID_LEAVEWORD)
- CProxyShell::GetInstance().onDevChannelEvent(LineId, DEV_CH_EVT_REC_END, NULL, 0);
- }
- /*****************************************************************
- **【函数名称】 __onLineStateFree
- **【函数功能】 线路状态处理【空闲】
- **【参数】 nLineId 状态变化的线路ID
- lpCallerNum 主叫号码
- lpCallerNum 被叫号码
- **【返回值】
- *****************************************************************/
- void CCallSession::__onLineStateFree(CRDRID LineId, LPCTSTR lpCallerNum, LPCTSTR lpCalleeNum)
- {
- // 获取线路在会话中的职责
- CALL_PARTY_TYPE Type = __isLineMine(LineId);
- // 清除线路录音
- m_RecordMap.RemoveKey(LineId);
- // 根据线路在会话中的职责进行分类处理
- switch(Type)
- {
- case CALL_PARTY_HOST: // 主控线路
- case CALL_PARTY_PEER: // 对端线路
- {
- removeLine(LineId, Type); // 从会话中删除线路
- CProxyShell::GetInstance().onLineStateUpdated(LineId, m_Id, SESSION_INVALID_SUB_CALL, VIRTUAL_LINE_STATE_FREE);
-
- // 对端线路挂机
- DEV_RES_ID AssoLine = (Type == CALL_PARTY_HOST) ? m_LinePeer : m_LineHost;
- if(!AssoLine.isEmpty())
- CMC::GetInstance().dropCall(AssoLine, true);
- }
- break;
- case CALL_PARTY_PENDING: // 操作待处理线路
- {
- CSubSession* pSubCall = __getSubSession(LineId);
- ASSERT(pSubCall != NULL);
- removeLine(LineId, Type); // 从会话中删除线路
- if(pSubCall != NULL)
- pSubCall->onPendingLineState(VIRTUAL_LINE_STATE_FREE);
- }
- break;
- case CALL_PARTY_LISTEN: // 通话的监听线路
- {
- removeLine(LineId, Type); // 从会话中删除线路
- CProxyShell::GetInstance().onLineStateUpdated(LineId, m_Id, SESSION_INVALID_SUB_CALL, VIRTUAL_LINE_STATE_FREE);
- }
- break;
- case CALL_PARTY_MEETING: // 会议中的线路
- {
- removeLine(LineId, Type); // 从会话中删除线路
- CProxyShell::GetInstance().onLineStateUpdated(LineId, m_Id, SESSION_INVALID_SUB_CALL, VIRTUAL_LINE_STATE_FREE);
- // 如果会议中只剩下一条线路,线路中可能存在监听线路
- if(lineCount() == 1 && m_ListenLineMap.GetSize() > 0)
- {
- const CMap<DEV_RES_ID, CRDRID, DEV_RES_ID, CRDRID>::CPair* pLastListenLine = m_ListenLineMap.PGetFirstAssoc();
- ASSERT(pLastListenLine != NULL);
-
- // 挂断此线路
- CMC::GetInstance().dropCall(pLastListenLine->key, true);
- } // end if
- }
- break;
- default:
- CProxyShell::GetInstance().onLineStateUpdated(LineId, m_Id, SESSION_INVALID_SUB_CALL, VIRTUAL_LINE_STATE_FREE, lpCallerNum, lpCalleeNum);
- break;
- } // end switch
- __notifySubSessionLineFree(LineId);
- CMC::GetInstance().freeChanResource(LineId);
- }
- /*****************************************************************
- **【函数名称】 __onLineStateAlerting
- **【函数功能】 线路状态处理【来电振铃】
- **【参数】 LineId 状态变化的线路ID
- lpCallerNum 主叫号码
- lpCallerNum 被叫号码
- **【返回值】
- *****************************************************************/
- void CCallSession::__onLineStateAlerting(CRDRID LineId, LPCTSTR lpCallerNum, LPCTSTR lpCalleeNum)
- {
- // 获取线路在会话中的职责
- CALL_PARTY_TYPE Type = __isLineMine(LineId);
- switch(Type)
- {
- case CALL_PARTY_HOST: // 主控线路
- {
- CProxyShell::GetInstance().onLineStateUpdated(LineId, m_Id, SESSION_INVALID_SUB_CALL, VIRTUAL_LINE_STATE_ALERTING, lpCallerNum, lpCalleeNum);
- }
- break;
- case CALL_PARTY_PEER: // 通话对端线路
- break;
- case CALL_PARTY_LISTEN: // 通话的监听线路
- break;
- case CALL_PARTY_PENDING: // 操作待处理线路
- {
- CSubSession* pSubCall = __getSubSession(LineId);
- ASSERT(pSubCall != NULL);
- pSubCall->onPendingLineState(VIRTUAL_LINE_STATE_ALERTING);
- }
- break;
- case CALL_PARTY_MEETING: // 会议中的线路
- break;
- default:
- ASSERT(FALSE);
- break;
- } // end switch
- }
- /*****************************************************************
- **【函数名称】 __onLineStateProgressing
- **【函数功能】 线路状态处理【通话进展】
- **【参数】 LineId 状态变化的线路ID
- lpCallerNum 主叫号码
- lpCallerNum 被叫号码
- **【返回值】
- *****************************************************************/
- void CCallSession::__onLineStateProgressing( CRDRID LineId, LPCTSTR lpCallerNum, LPCTSTR lpCalleeNum )
- {
- // 获取线路在会话中的职责
- CALL_PARTY_TYPE Type = __isLineMine(LineId);
- if(Type == CALL_PARTY_PENDING)
- {
- CSubSession* pSubCall = __getSubSession(LineId);
- ASSERT(pSubCall != NULL);
- pSubCall->onPendingLineState(VIRTUAL_LINE_STATE_PROGRESSING);
- }
- }
- /*****************************************************************
- **【函数名称】 __onLineStateRingBack
- **【函数功能】 线路状态处理【呼出振铃】
- **【参数】 LineId 状态变化的线路ID
- lpCallerNum 主叫号码
- lpCallerNum 被叫号码
- **【返回值】
- *****************************************************************/
- void CCallSession::__onLineStateRingBack(CRDRID LineId, LPCTSTR lpCallerNum, LPCTSTR lpCalleeNum)
- {
- // 获取线路在会话中的职责
- CALL_PARTY_TYPE Type = __isLineMine(LineId);
-
- // 根据线路在会话中的职责进行分类处理
- switch(Type)
- {
- case CALL_PARTY_HOST: // 主控线路
- {
- CProxyShell::GetInstance().onLineStateUpdated(LineId, m_Id, SESSION_INVALID_SUB_CALL, VIRTUAL_LINE_STATE_RING_BACK, lpCallerNum, lpCalleeNum);
- }
- break;
- case CALL_PARTY_PEER: // 对端线路
- break;
- case CALL_PARTY_LISTEN: // 通话的监听线路
- break;
- case CALL_PARTY_PENDING: // 操作待处理线路
- {
- CSubSession* pSubCall = __getSubSession(LineId);
- ASSERT(pSubCall != NULL);
- pSubCall->onPendingLineState(VIRTUAL_LINE_STATE_RING_BACK);
- }
- break;
- case CALL_PARTY_MEETING: // 会议中的线路
- break;
- default:
- ASSERT(FALSE);
- } // end switch
- }
- /*****************************************************************
- **【函数名称】 __onLineStateTalking
- **【函数功能】 线路状态处理【通话】
- **【参数】 LineId 状态变化的线路ID
- lpCallerNum 主叫号码
- lpCallerNum 被叫号码
- **【返回值】
- *****************************************************************/
- void CCallSession::__onLineStateTalking(CRDRID LineId, LPCTSTR lpCallerNum, LPCTSTR lpCalleeNum)
- {
- // 获取线路在会话中的职责
- CALL_PARTY_TYPE Type = __isLineMine(LineId);
- switch(Type)
- {
- case CALL_PARTY_HOST: // 主控线路
- {
- CProxyShell::GetInstance().onLineStateUpdated(LineId, m_Id, SESSION_INVALID_SUB_CALL, VIRTUAL_LINE_STATE_TALKING, lpCallerNum, lpCalleeNum);
- }
- break;
- case CALL_PARTY_PEER: // 通话对端线路
- break;
- case CALL_PARTY_LISTEN: // 通话的监听线路
- break;
- case CALL_PARTY_PENDING: // 操作待处理线路
- {
- CSubSession* pSubCall = __getSubSession(LineId);
- ASSERT(pSubCall != NULL);
- pSubCall->onPendingLineState(VIRTUAL_LINE_STATE_TALKING);
- }
- break;
- case CALL_PARTY_MEETING: // 会议中的线路
- break;
- default:
- ASSERT(FALSE);
- break;
- } // end switch
- }
- /*****************************************************************
- **【函数名称】 insertLine
- **【函数功能】 添加待定线路到会话
- **【参数】 LineId 要添加的线路ID
- PartyType 新增线路在会话中的职责
- Info 附加信息
- IsLink 是否作通道连接
- **【返回值】
- *****************************************************************/
- bool CCallSession::insertLine(CRDRID LineId, UINT SessionId, bool IsLink)
- {
- // 通知当前线路关联呼叫
- CMC::GetInstance().setSessionInfo2Line(LineId, m_Id);
- CProxyShell::GetInstance().onNewCall(LineId, m_Id, SESSION_INVALID_SUB_CALL);
- m_LineMap[LineId] = CALL_PARTY_PENDING;
- m_PendingLineMap[LineId] = SessionId;
- return true;
- }
- /*****************************************************************
- **【函数名称】 insertLine
- **【函数功能】 添加指定线路到会话
- **【参数】 LineId 要添加的线路ID
- PartyType 新增线路在会话中的职责
- IsLink 是否作通道连接
- **【返回值】
- *****************************************************************/
- bool CCallSession::insertLine( CRDRID LineId, CALL_PARTY_TYPE PartyType, bool IsLink )
- {
- // 通知当前线路关联呼叫
- CMC::GetInstance().setSessionInfo2Line(LineId, m_Id);
- CProxyShell::GetInstance().onNewCall(LineId, m_Id, SESSION_INVALID_SUB_CALL);
- // 根据职责保存线路到指定位置
- switch(PartyType)
- {
- case CALL_PARTY_HOST: // 主控线路
- {
- m_LineHost = LineId;
- m_LineMap[LineId] = CALL_PARTY_HOST;
- if(!m_LinePeer.isEmpty() && IsLink)
- {
- if(!__line2Link(LineId, m_LinePeer))
- return false;
- }
- }
- break;
- case CALL_PARTY_PEER: // 通话对端线路
- {
- m_LinePeer = LineId;
- m_LineMap[LineId] = CALL_PARTY_PEER;
- if(!m_LineHost.isEmpty() && IsLink)
- {
- if(!__line2Link(LineId, m_LineHost))
- return false;
- }
- }
- break;
- case CALL_PARTY_MEETING: // 会议中的线路
- {
- m_LineMap[LineId] = CALL_PARTY_MEETING;
- if(!CMC::GetInstance().move2Meeting(LineId, m_MeetingId, false))
- return false;
- }
- break;
- } // end switch
- return true;
- }
- /*****************************************************************
- **【函数名称】 insertLine
- **【函数功能】 添加监听线路到会话
- **【参数】 LineId 要添加的线路ID
- PartyType 新增线路在会话中的职责
- IsLink 是否作通道连接
- **【返回值】
- *****************************************************************/
- bool CCallSession::insertLine( CRDRID HostLineId, CRDRID SrcLineId, bool IsLink )
- {
- // 通知当前线路关联呼叫
- CMC::GetInstance().setSessionInfo2Line(HostLineId, m_Id);
- CProxyShell::GetInstance().onNewCall(HostLineId, m_Id, SESSION_INVALID_SUB_CALL);
- m_LineMap[HostLineId] = CALL_PARTY_LISTEN;
- m_ListenLineMap[HostLineId] = SrcLineId;
- CALL_PARTY_TYPE Type = __isLineMine(SrcLineId);
- if (Type == CALL_PARTY_MEETING)
- {
- if(!CMC::GetInstance().meetingListen(HostLineId, m_MeetingId, true))
- return false;
- }
- else
- {
- DEV_RES_ID PeerId = getPeerLine(SrcLineId);
- if(!CMC::GetInstance().channelListen(SrcLineId, PeerId, HostLineId, true))
- return false;
- }
- return true;
- }
- /*****************************************************************
- **【函数名称】 removeLine
- **【函数功能】 从会话中删除指定线路
- **【参数】 LineId 要删除的线路ID
- PartyType 要删除的线路在会话中的职责
- **【返回值】
- *****************************************************************/
- void CCallSession::removeLine(CRDRID LineId, CALL_PARTY_TYPE PartyType, PENDING_CALL_TYPE CallType /*= PENDING_CALL_DIRECT*/)
- {
- // 根据职责保存线路到指定位置
- switch(PartyType)
- {
- case CALL_PARTY_HOST: // 主控线路
- {
- if(!m_LinePeer.isEmpty())
- CMC::GetInstance().bridgeDevice(m_LineHost, m_LinePeer, false);
- m_LineHost.reset();
- if(CallType != PENDING_CALL_MEETING)
- __detachListen(LineId); // 监听线路挂机
- }
- break;
- case CALL_PARTY_PEER: // 通话对端线路
- {
- if(!m_LineHost.isEmpty())
- CMC::GetInstance().bridgeDevice(m_LineHost, m_LinePeer, false);
- m_LinePeer.reset();
- if(CallType != PENDING_CALL_MEETING)
- __detachListen(LineId); // 监听线路挂机
- }
- break;
- case CALL_PARTY_LISTEN: // 通话的监听线路
- {
- // 关闭监听
- DEV_RES_ID DestLine;
- if(m_ListenLineMap.Lookup(LineId, DestLine))
- {
- CALL_PARTY_TYPE Type = __isLineMine(DestLine);
- if (Type == CALL_PARTY_MEETING)
- {
- CMC::GetInstance().meetingListen(LineId, m_MeetingId, false);
- }
- else
- {
- DEV_RES_ID PeerId = getPeerLine(DestLine);
- CMC::GetInstance().channelListen(DestLine, PeerId, LineId, false);
- }
- // 清除线路
- m_ListenLineMap.RemoveKey(LineId);
- }
- }
- break;
- case CALL_PARTY_PENDING: // 操作待处理线路
- {
- m_PendingLineMap.RemoveKey(LineId);
- }
- break;
- case CALL_PARTY_MEETING: // 会议中的线路
- {
- int Type;
- if(m_LineMap.Lookup(LineId, Type))
- {
- ASSERT(Type == CALL_PARTY_MEETING);
- CMC::GetInstance().removeFromMeeting(LineId, m_MeetingId);
- if(CallType != PENDING_CALL_MEETING)
- __detachListen(LineId); // 监听线路挂机
- }
- }
- break;
- } // end switch
- m_LineMap.RemoveKey(LineId);
- }
- /*****************************************************************
- **【函数名称】 setupPendingCall
- **【函数功能】 启动待处理呼叫
- **【参数】 SubCall 新生成的子会话ID(回传参数)
- pInfo 呼叫内容
- **【返回值】 启动呼叫时否成功
- *****************************************************************/
- bool CCallSession::setupPendingCall(long& SubCall, PendingCallInfo* pInfo)
- {
- // 是否为会话中的通话线路
- CALL_PARTY_TYPE HostLineParty = __isLineMine(pInfo->nHostLine);
- if(HostLineParty != CALL_PARTY_HOST &&
- HostLineParty != CALL_PARTY_PEER &&
- HostLineParty != CALL_PARTY_MEETING)
- {
- return false;
- }
- // 添加待处理线路到会话
- if(!insertLine(pInfo->nAssoLine, m_SubCallIndex + 1, true))
- return false;
- // 生成子呼叫
- CSubSession* pSubCall = NULL;
- switch(pInfo->nCallType)
- {
- case PENDING_CALL_DIRECT:
- pSubCall = new CDirectSession(this, ++m_SubCallIndex, pInfo);
- break;
- case PENDING_CALL_TRANSFER:
- pSubCall = new CTransferSession(this, ++m_SubCallIndex, pInfo);
- break;
- case PENDING_CALL_MEETING:
- pSubCall = new CMeetingSession(this, ++m_SubCallIndex, pInfo);
- break;
- case PENDING_CALL_TRUNK:
- pSubCall = new CTrunkSession(this, ++m_SubCallIndex, pInfo);
- break;
- case PENDING_CALL_CONSULT:
- pSubCall = new CConsultSession(this, ++m_SubCallIndex, pInfo);
- break;
- } // end if
- SubCall = m_SubCallIndex; // 回传参数
- m_SubCallMap.SetAt(m_SubCallIndex, pSubCall);
- // 启动操作
- return pSubCall->begin(HostLineParty);
- }
- /*****************************************************************
- **【函数名称】 lineLeave
- **【函数功能】 指定线路退出会话且挂机
- **【参数】 LineId 要退出会话的线路ID
- **【返回值】
- *****************************************************************/
- bool CCallSession::lineLeave(CRDRID LineId)
- {
- CALL_PARTY_TYPE nParty = __isLineMine(LineId);
- // 此操作序列不会关联对端线路挂机
- removeLine(LineId, nParty);
- m_RecordMap.RemoveKey(LineId); // 释放录音关联
- return CMC::GetInstance().dropCall(LineId, false);
- }
- /*****************************************************************
- **【函数名称】 LineInstead
- **【函数功能】 代接指定线路
- **【参数】 HostLine 申请代接的线路
- PeerLine 被代接的线路
- ExtNum 申请代接线路的分机号
- **【返回值】
- *****************************************************************/
- bool CCallSession::lineInstead(CRDRID HostLine, CRDRID PeerLine, UINT ExtNum)
- {
- // 被代接线路是否还在子会话中
- CSubSession* pSubCall = __getSubSession(PeerLine);
- if(pSubCall == NULL)
- return false;
- // 执行替换操作
- return pSubCall->replace(HostLine, PeerLine, ExtNum);
- }
- /*****************************************************************
- **【函数名称】 lineIntercept
- **【函数功能】 替换指定线路
- **【参数】 HostLine 要进入会话的线路
- PeerLine 要退出会话的线路
- **【返回值】
- *****************************************************************/
- bool CCallSession::lineIntercept(CRDRID HostLine, CRDRID PeerLine)
- {
- // 读取被替换线路在会话中的职责
- CALL_PARTY_TYPE Party = __isLineMine(PeerLine);
- if(Party != CALL_PARTY_HOST &&
- Party != CALL_PARTY_PEER &&
- Party != CALL_PARTY_MEETING)
- {
- return false;
- } // end if
- // 目标线路退出会话
- removeLine(PeerLine, Party);
- if(!CMC::GetInstance().dropCall(PeerLine, true))
- return false;
- // 主控线路加入会话
- if(!insertLine(HostLine, Party, true))
- return false;
- CString strCallerNum, strCalleeNum;
- // 获取代接线路绑定的分机号
- CVirtualProxy* pHostProxy = CProxyShell::GetInstance().getProxy(HostLine.toIntId());
- ASSERT(pHostProxy != NULL);
- if(pHostProxy != NULL)
- pHostProxy->getAssoExtenNo(strCalleeNum);
- // 获取被代接线路当前的主叫号码
- CVirtualProxy* pPeerProxy = CProxyShell::GetInstance().getProxy(PeerLine.toIntId());
- ASSERT(pPeerProxy != NULL);
- if(pPeerProxy != NULL)
- strCallerNum = pPeerProxy->callerNum();
- CProxyShell::GetInstance().onLineStateUpdated(HostLine, m_Id, SESSION_INVALID_SUB_CALL, VIRTUAL_LINE_STATE_TALKING, strCallerNum, strCalleeNum);
- return true;
- }
- /*****************************************************************
- **【函数名称】 lineInsert
- **【函数功能】 插入线路到会话
- **【参数】 HostLine 要进入会话的线路
- **【返回值】
- *****************************************************************/
- bool CCallSession::lineInsert(CRDRID HostLine, CRDRID PeerLine)
- {
- // 如果当前会话不是会议
- if(m_MeetingId.MeetingId == MEETING_ID_INVALID)
- {
- if(m_LineHost.isEmpty() || m_LinePeer.isEmpty())
- return false;
- // 将原通话转为会议
- if(!trans2Meeting(m_LineHost))
- return false;
- } // end if
- // 将主控线路添加到会议
- if(!insertLine(HostLine, CALL_PARTY_MEETING, true))
- return false;
- CString strCallerNum, strCalleeNum;
- // 获取插入线路绑定的分机号
- CVirtualProxy* pHostProxy = CProxyShell::GetInstance().getProxy(HostLine.toIntId());
- ASSERT(pHostProxy != NULL);
- if(pHostProxy != NULL)
- pHostProxy->getAssoExtenNo(strCallerNum);
- // 获取被插入线路绑定的分机号
- CVirtualProxy* pPeerProxy = CProxyShell::GetInstance().getProxy(PeerLine.toIntId());
- ASSERT(pPeerProxy != NULL);
- if(pPeerProxy != NULL)
- pPeerProxy->getAssoExtenNo(strCalleeNum);
- CProxyShell::GetInstance().onLineStateUpdated(HostLine, m_Id, SESSION_INVALID_SUB_CALL, VIRTUAL_LINE_STATE_TALKING, strCallerNum, strCalleeNum);
- return true;
- }
- /*****************************************************************
- **【函数名称】 lineListen
- **【函数功能】 监听指定线路
- **【参数】 HostLine 主控线路
- PeerLine 被监听线路
- **【返回值】
- *****************************************************************/
- bool CCallSession::lineListen(CRDRID HostLine, CRDRID PeerLine)
- {
- // 被监听线路是否还在会话中
- CALL_PARTY_TYPE Party = __isLineMine(PeerLine);
- if(Party == CALL_PARTY_HOST ||
- Party == CALL_PARTY_PEER ||
- Party == CALL_PARTY_MEETING)
- {
- if(!insertLine(HostLine, PeerLine, true)) // 添加线路到会话
- return false;
- CString strCallerNum, strCalleeNum;
- // 获取监听线路绑定的分机号
- CVirtualProxy* pHostProxy = CProxyShell::GetInstance().getProxy(HostLine.toIntId());
- ASSERT(pHostProxy != NULL);
- if(pHostProxy != NULL)
- pHostProxy->getAssoExtenNo(strCallerNum);
- // 获取被监听线路绑定的分机号
- CVirtualProxy* pPeerProxy = CProxyShell::GetInstance().getProxy(PeerLine.toIntId());
- ASSERT(pPeerProxy != NULL);
- if(pPeerProxy != NULL)
- pPeerProxy->getAssoExtenNo(strCalleeNum);
- CProxyShell::GetInstance().onLineStateUpdated(HostLine, m_Id, SESSION_INVALID_SUB_CALL, VIRTUAL_LINE_STATE_TALKING, strCallerNum, strCalleeNum);
- return true;
- } // end if
- return false;
- }
- /*****************************************************************
- **【函数名称】 lineRecord
- **【函数功能】 线路录音启动
- **【参数】 HostLine 主控线路
- lpFileName 录音文件名
- **【返回值】
- *****************************************************************/
- bool CCallSession::lineRecord(CRDRID HostLine, LPCTSTR lpFileName)
- {
- // 如果当前线路已在录音
- CString strRecFile;
- if(m_RecordMap.Lookup(HostLine, strRecFile))
- return false;
- // 启动录音
- if(__lineRecord(HostLine, lpFileName))
- {
- m_RecordMap.SetAt(HostLine, lpFileName);
- return true;
- } // end if
- return false;
- }
- /*****************************************************************
- **【函数名称】 lineLeaveWord
- **【函数功能】 线路留言启动
- **【参数】 HostLine 主控线路
- pContent 留言参数
- **【返回值】
- *****************************************************************/
- bool CCallSession::lineLeaveWord(CRDRID HostLine, RecordContent* pContent)
- {
- if(__isLineMine(HostLine) == CALL_PARTY_UNKNOWN)
- return false;
- // 启动留言
- pContent->nModel = RECORD_MODE_LEAVEWORD;
- return CMC::GetInstance().startRecord(HostLine, pContent);
- }
- /*****************************************************************
- **【函数名称】 lineMute
- **【函数功能】 线路静音控制
- **【参数】 HostLine 主控线路
- IsBegin 是启动还是结束
- **【返回值】
- *****************************************************************/
- bool CCallSession::lineMute(CRDRID HostLine, bool IsOn)
- {
- // 是否对会议中的线路静音
- CALL_PARTY_TYPE Type = __isLineMine(HostLine);
- bool IsMeetingMute = Type == CALL_PARTY_MEETING ? true : false;
- if (IsMeetingMute)
- {
- return __meetingMute(HostLine, IsOn);
- }
- else
- {
- return __lineMute(HostLine, IsOn);
- }
- }
- /*****************************************************************
- **【函数名称】 lineConsultConfirm
- **【函数功能】 协商呼叫确认
- **【参数】 PeerLine 协商呼叫的被叫线路
- Type 呼叫类型
- **【返回值】
- *****************************************************************/
- bool CCallSession::lineConsultConfirm(CRDRID PeerLine, UINT Type)
- {
- // 被代接线路是否还在子会话中
- CSubSession* pSubCall = __getSubSession(PeerLine);
- if(pSubCall == NULL)
- return false;
- // 执行替换操作
- return pSubCall->resume(Type);
- }
- /*****************************************************************
- **【函数名称】 line2Meeting
- **【函数功能】 通话线路转入会议
- **【参数】 LineId 要转入会议的线路ID
- Party 要进入会议的线路在原会话中的职责
- **【返回值】
- *****************************************************************/
- bool CCallSession::line2Meeting(DEV_RES_ID LineId, CALL_PARTY_TYPE Party)
- {
- removeLine(LineId, Party, PENDING_CALL_MEETING);
- // 线路转入会议
- return insertLine(LineId, CALL_PARTY_MEETING, true);
- }
- /*****************************************************************
- **【函数名称】 trans2Meeting
- **【函数功能】 将当前会话转换为会议
- **【参数】 HostLineId 发起会议的主控线路
- **【返回值】
- *****************************************************************/
- bool CCallSession::trans2Meeting(CRDRID HostLineId)
- {
- if(m_MeetingId.MeetingId != MEETING_ID_INVALID)
- return true;
- if(!CMC::GetInstance().createMeeting(HostLineId, m_MeetingId))
- {
- LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Session}: 会话环境转换为会议失败, HostLine = %u, PeerLine = %u"),
- m_LineHost.toIntId(), m_LinePeer.toIntId());
- return false;
- }
- bool HostTrans2MeetingResult = false;
- // 原通话线路职责转换
- if(!m_LineHost.isEmpty())
- {
- HostTrans2MeetingResult = line2Meeting(m_LineHost, CALL_PARTY_HOST);
- if(!HostTrans2MeetingResult) // 若主线路转为会议不成功,就说明DSP资源枯竭,此次会议就宣告失败
- {
- CMC::GetInstance().deleteMeeting(m_MeetingId);
- LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Session}: 主线路转换为会议失败, HostLine = %u, PeerLine = %u"),
- m_LineHost.toIntId(), m_LinePeer.toIntId());
- return false;
- }
- }
- if(!m_LinePeer.isEmpty())
- {
- if(!line2Meeting(m_LinePeer, CALL_PARTY_PEER))
- {
- if(!HostTrans2MeetingResult)
- {
- // 运行到此,说明主线路为空(即:m_LineHost == 0),因此要删除以创建的会议,
- // 但若主线路成功转为会议则不删除,因为主线路挂机后会自动删除。
- CMC::GetInstance().deleteMeeting(m_MeetingId);
- }
- LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Session}: 对端线路转换为会议失败, HostLine = %u, PeerLine = %u"),
- m_LineHost.toIntId(), m_LinePeer.toIntId());
- return false;
- }
- }
- return true;
- }
- void CCallSession::__setTimer(UINT TimmerId, UINT Elapse)
- {
- m_SessionTimer.StopSafely();
- m_SessionTimer.SetTimedEvent(this, &CCallSession::__onTimerPostProcessing);
- m_SessionTimer.Start(Elapse, false, true, WT_EXECUTEDEFAULT);
- }
- void CCallSession::__onTimerPostProcessing(void)
- {
- CMC::GetInstance().dropCall(m_LineHost, true);
- }
|