| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113 |
- #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:
- __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;
- }
|