升龙物业 老版本 ocx IPO, 加密狗 转值班电话

CallSession.cpp 31KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113
  1. #include "StdAfx.h"
  2. #include "CallSession.h"
  3. #include "MC.h"
  4. #include "ProxyShell.h"
  5. #include "ConsultSession.h"
  6. #include "MeetingSession.h"
  7. #include "DirectSession.h"
  8. #include "TransferSession.h"
  9. #include "TrunkSession.h"
  10. #include "Config.h"
  11. #include "VirtualProxy.h"
  12. CCallSession::CCallSession(long SessionId) : m_Id(SessionId), m_SubCallIndex(0)
  13. {
  14. ZeroMemory(&m_MeetingId, sizeof(MeetingInfo));
  15. m_MeetingId.MeetingId = MEETING_ID_INVALID;
  16. }
  17. CCallSession::~CCallSession(void)
  18. {
  19. __clearSubSession();
  20. }
  21. /*****************************************************************
  22. **【函数名称】 __isLineMine
  23. **【函数功能】 指定线路是否属于当前会话
  24. **【参数】 LineId 要查找的线路ID
  25. **【返回值】
  26. *****************************************************************/
  27. CALL_PARTY_TYPE CCallSession::__isLineMine( CRDRID LineId )
  28. {
  29. int Type;
  30. if(m_LineMap.Lookup(LineId, Type))
  31. return (CALL_PARTY_TYPE)Type;
  32. else
  33. return CALL_PARTY_UNKNOWN;
  34. }
  35. /*****************************************************************
  36. **【函数名称】 __GetSubCall
  37. **【函数功能】 通过待处理线路ID查找子呼叫
  38. **【参数】 PendingLine 通话待处理线路ID
  39. **【返回值】
  40. *****************************************************************/
  41. CSubSession* CCallSession::__getSubSession(CRDRID PendingLine)
  42. {
  43. UINT SubCall = 0;
  44. CSubSession* pSubCall = NULL;
  45. // 找到子呼叫的ID
  46. if(!m_PendingLineMap.Lookup(PendingLine, SubCall))
  47. return NULL;
  48. // 查找子呼叫指针
  49. m_SubCallMap.Lookup(SubCall, pSubCall);
  50. return pSubCall;
  51. }
  52. /*****************************************************************
  53. **【函数名称】 __clearSubSession
  54. **【函数功能】 释放所有子会话
  55. **【参数】
  56. **【返回值】
  57. *****************************************************************/
  58. void CCallSession::__clearSubSession( void )
  59. {
  60. UINT Key = 0;
  61. CSubSession* pSub = NULL;
  62. POSITION pos = m_SubCallMap.GetStartPosition();
  63. while(pos != NULL)
  64. {
  65. m_SubCallMap.GetNextAssoc(pos, Key, pSub);
  66. ASSERT(pSub != NULL);
  67. delete pSub;
  68. } // end while
  69. m_SubCallMap.RemoveAll();
  70. }
  71. /*****************************************************************
  72. **【函数名称】 __notifySubSessionLineFree
  73. **【函数功能】 通知子会话相关线路空闲
  74. **【参数】
  75. **【返回值】
  76. *****************************************************************/
  77. void CCallSession::__notifySubSessionLineFree( CRDRID LineId )
  78. {
  79. UINT Key = 0;
  80. CSubSession* pSub = NULL;
  81. POSITION pos = m_SubCallMap.GetStartPosition();
  82. while(pos != NULL)
  83. {
  84. m_SubCallMap.GetNextAssoc(pos, Key, pSub);
  85. ASSERT(pSub != NULL);
  86. if(pSub->getSubHostLine() == LineId)
  87. pSub->onHostLineStateFree();
  88. else if(pSub->getSubPeerLine() == LineId)
  89. pSub->onPeerLineStateFree();
  90. } // end while
  91. }
  92. /*****************************************************************
  93. **【函数名称】 __lineDoRecord
  94. **【函数功能】 执行录音操作
  95. **【参数】 HostLine 录音线路
  96. lpFileName 录音文件名
  97. **【返回值】
  98. *****************************************************************/
  99. bool CCallSession::__lineRecord(CRDRID HostLine, LPCTSTR lpFileName)
  100. {
  101. // 填充录音参数
  102. RecordContent content;
  103. memset(&content, 0, sizeof(RecordContent));
  104. lstrcpy(content.szFileName, lpFileName);
  105. content.nTaskId = RECORD_TASK_ID_NORMAL;
  106. CALL_PARTY_TYPE Party = __isLineMine(HostLine);
  107. switch(Party)
  108. {
  109. case CALL_PARTY_HOST: // 主控线路
  110. {
  111. content.nModel = RECORD_MODE_NORMAL;
  112. content.nPeerLine = m_LinePeer;
  113. }
  114. break;
  115. case CALL_PARTY_PEER: // 对端线路
  116. {
  117. content.nModel = RECORD_MODE_NORMAL;
  118. content.nPeerLine = m_LineHost;
  119. }
  120. break;
  121. case CALL_PARTY_MEETING: // 会议线路
  122. {
  123. content.nModel = RECORD_MODE_MEETING;
  124. }
  125. break;
  126. case CALL_PARTY_PENDING:
  127. {
  128. content.nModel = RECORD_MODE_NORMAL;
  129. CSubSession * pSubCall = __getSubSession(HostLine);
  130. content.nPeerLine = pSubCall->getSubHostLine();
  131. }
  132. break;
  133. } // end switch
  134. // 启动录音
  135. return CMC::GetInstance().startRecord(HostLine, &content);
  136. }
  137. /*****************************************************************
  138. **【函数名称】 __LineDoMute
  139. **【函数功能】 线路静音操作
  140. **【参数】 HostLine 静音线路
  141. IsBegin 静音启动/结束
  142. **【返回值】
  143. *****************************************************************/
  144. bool CCallSession::__lineMute(CRDRID HostLine, bool IsOn)
  145. {
  146. // 查询对端线路
  147. DEV_RES_ID AssoLine = getPeerLine(HostLine);
  148. if(AssoLine.isEmpty())
  149. return false;
  150. // 静音控制
  151. if(IsOn)
  152. {
  153. // 断开通话
  154. CMC::GetInstance().bridgeDevice(HostLine, AssoLine, false);
  155. // 对端线路播放保持音
  156. CMC::GetInstance().playTone(AssoLine, CHANNEL_TONE_HOLD);
  157. }
  158. else
  159. {
  160. // 停止放音
  161. CMC::GetInstance().playStop(AssoLine);
  162. // 重连通话
  163. CMC::GetInstance().bridgeDevice(HostLine, AssoLine, true);
  164. } // end if
  165. return true;
  166. }
  167. /*****************************************************************
  168. **【函数名称】 __meetingMute
  169. **【函数功能】 会议静音操作
  170. **【参数】 HostLine 静音线路
  171. IsBegin 静音启动/结束
  172. **【返回值】
  173. *****************************************************************/
  174. bool CCallSession::__meetingMute(CRDRID HostLine, bool IsOn)
  175. {
  176. return CMC::GetInstance().meetingMute(HostLine, m_MeetingId, !IsOn);
  177. }
  178. /*****************************************************************
  179. **【函数名称】 __line2Link
  180. **【函数功能】 线路进入双向通话
  181. **【参数】 LineId 要进入通话的线路ID
  182. LinePeeer 要进行通话的对端线路
  183. **【返回值】
  184. *****************************************************************/
  185. bool CCallSession::__line2Link(CRDRID LineId, CRDRID LinePeer)
  186. {
  187. CString strRecFile;
  188. // 当前录音采用混音模式,原线路在录音时不影响线路之间通话的建立,故不需停止当前录音,
  189. // 因此注释一下三行。
  190. //// 停止当前录音
  191. //if(m_RecordMap.Lookup(LinePeer, strRecFile))
  192. // CMC::GetInstance().stopRecord(LinePeer);
  193. // 线路双向连通
  194. return CMC::GetInstance().bridgeDevice(LineId, LinePeer, true);
  195. }
  196. /*****************************************************************
  197. **【函数名称】 __detachListen
  198. **【函数功能】 解除指定线路的监听
  199. **【参数】 HostLine 当前挂机的线路
  200. **【返回值】
  201. *****************************************************************/
  202. void CCallSession::__detachListen(CRDRID HostLine)
  203. {
  204. POSITION pos = m_ListenLineMap.GetStartPosition();
  205. while(pos != NULL)
  206. {
  207. DEV_RES_ID DevId;
  208. DEV_RES_ID LineListen;
  209. m_ListenLineMap.GetNextAssoc(pos, LineListen, DevId);
  210. if(DevId == HostLine)
  211. CMC::GetInstance().dropCall(LineListen, false); // 监听线路挂机
  212. }
  213. }
  214. /*****************************************************************
  215. **【函数名称】 getPeerLine
  216. **【函数功能】 获取当前线路关联的对端线路
  217. **【参数】 LineId 要查询的线路
  218. **【返回值】 0 -> 无对端线路
  219. *****************************************************************/
  220. DEV_RES_ID CCallSession::getPeerLine(CRDRID LineId)
  221. {
  222. // 当前线路在会话中的职责
  223. DEV_RES_ID AssoLine;
  224. CALL_PARTY_TYPE Party = __isLineMine(LineId);
  225. switch(Party)
  226. {
  227. case CALL_PARTY_HOST: // 主控线路
  228. AssoLine = m_LinePeer;
  229. break;
  230. case CALL_PARTY_PEER: // 对端线路
  231. AssoLine = m_LineHost;
  232. break;
  233. default: // 其它线路
  234. break;
  235. } // end switch
  236. return AssoLine;
  237. }
  238. /*****************************************************************
  239. **【函数名称】 IsExist
  240. **【函数功能】 指定职责的线路是否在会话中
  241. **【参数】 LineId 要查询的线路ID
  242. PartyType 线路在会话中的职责
  243. **【返回值】
  244. *****************************************************************/
  245. bool CCallSession::isExist(CRDRID LineId, CALL_PARTY_TYPE PartyType)
  246. {
  247. int Type;
  248. if(m_LineMap.Lookup(LineId, Type))
  249. {
  250. return PartyType == (CALL_PARTY_TYPE)Type;
  251. }
  252. else
  253. {
  254. return false;
  255. }
  256. }
  257. /*****************************************************************
  258. **【函数名称】 onLineStateChanged
  259. **【函数功能】 线路状态变化事件处理
  260. **【参数】 LineId 状态变化的线路ID
  261. LineState 线路当前状态
  262. lpCallerNum 主叫号码
  263. lpCallerNum 被叫号码
  264. **【返回值】
  265. *****************************************************************/
  266. void CCallSession::onLineStateChanged(CRDRID LineId, VIRTUAL_LINE_STATE LineState, LPCTSTR lpCallerNum, LPCTSTR lpCalleeNum)
  267. {
  268. // 根据线路物理状态进行分类处理
  269. switch(LineState)
  270. {
  271. case VIRTUAL_LINE_STATE_FREE:
  272. __onLineStateFree(LineId, lpCallerNum, lpCalleeNum);
  273. break;
  274. case VIRTUAL_LINE_STATE_INIT:
  275. case VIRTUAL_LINE_STATE_DIALING:
  276. case VIRTUAL_LINE_STATE_DISABLED:
  277. CProxyShell::GetInstance().onLineStateUpdated(LineId, m_Id, SESSION_INVALID_SUB_CALL, LineState, lpCallerNum, lpCalleeNum);
  278. break;
  279. case VIRTUAL_LINE_STATE_RING_BACK:
  280. __onLineStateRingBack(LineId, lpCallerNum, lpCalleeNum);
  281. break;
  282. case VIRTUAL_LINE_STATE_ALERTING:
  283. __onLineStateAlerting(LineId, lpCallerNum, lpCalleeNum);
  284. break;
  285. case VIRTUAL_LINE_STATE_PROGRESSING:
  286. __onLineStateProgressing(LineId, lpCallerNum, lpCalleeNum);
  287. break;
  288. case VIRTUAL_LINE_STATE_TALKING:
  289. __onLineStateTalking(LineId, lpCallerNum, lpCalleeNum);
  290. break;
  291. } // end switch
  292. }
  293. /*****************************************************************
  294. **【函数名称】 onRecordStop
  295. **【函数功能】 录音停止事件
  296. **【参数】 LineId 录音停止的线路ID
  297. TaskId 录音启动时的任务ID
  298. **【返回值】
  299. *****************************************************************/
  300. void CCallSession::onRecordStop(CRDRID LineId, UINT TaskId)
  301. {
  302. if(TaskId == RECORD_TASK_ID_LEAVEWORD)
  303. CProxyShell::GetInstance().onDevChannelEvent(LineId, DEV_CH_EVT_REC_END, NULL, 0);
  304. }
  305. /*****************************************************************
  306. **【函数名称】 __onLineStateFree
  307. **【函数功能】 线路状态处理【空闲】
  308. **【参数】 nLineId 状态变化的线路ID
  309. lpCallerNum 主叫号码
  310. lpCallerNum 被叫号码
  311. **【返回值】
  312. *****************************************************************/
  313. void CCallSession::__onLineStateFree(CRDRID LineId, LPCTSTR lpCallerNum, LPCTSTR lpCalleeNum)
  314. {
  315. // 获取线路在会话中的职责
  316. CALL_PARTY_TYPE Type = __isLineMine(LineId);
  317. // 清除线路录音
  318. m_RecordMap.RemoveKey(LineId);
  319. // 根据线路在会话中的职责进行分类处理
  320. switch(Type)
  321. {
  322. case CALL_PARTY_HOST: // 主控线路
  323. case CALL_PARTY_PEER: // 对端线路
  324. {
  325. removeLine(LineId, Type); // 从会话中删除线路
  326. CProxyShell::GetInstance().onLineStateUpdated(LineId, m_Id, SESSION_INVALID_SUB_CALL, VIRTUAL_LINE_STATE_FREE);
  327. // 对端线路挂机
  328. DEV_RES_ID AssoLine = (Type == CALL_PARTY_HOST) ? m_LinePeer : m_LineHost;
  329. if(!AssoLine.isEmpty())
  330. CMC::GetInstance().dropCall(AssoLine, true);
  331. }
  332. break;
  333. case CALL_PARTY_PENDING: // 操作待处理线路
  334. {
  335. CSubSession* pSubCall = __getSubSession(LineId);
  336. ASSERT(pSubCall != NULL);
  337. removeLine(LineId, Type); // 从会话中删除线路
  338. if(pSubCall != NULL)
  339. pSubCall->onPendingLineState(VIRTUAL_LINE_STATE_FREE);
  340. }
  341. break;
  342. case CALL_PARTY_LISTEN: // 通话的监听线路
  343. {
  344. removeLine(LineId, Type); // 从会话中删除线路
  345. CProxyShell::GetInstance().onLineStateUpdated(LineId, m_Id, SESSION_INVALID_SUB_CALL, VIRTUAL_LINE_STATE_FREE);
  346. }
  347. break;
  348. case CALL_PARTY_MEETING: // 会议中的线路
  349. {
  350. removeLine(LineId, Type); // 从会话中删除线路
  351. CProxyShell::GetInstance().onLineStateUpdated(LineId, m_Id, SESSION_INVALID_SUB_CALL, VIRTUAL_LINE_STATE_FREE);
  352. // 如果会议中只剩下一条线路,线路中可能存在监听线路
  353. if(lineCount() == 1 && m_ListenLineMap.GetSize() > 0)
  354. {
  355. const CMap<DEV_RES_ID, CRDRID, DEV_RES_ID, CRDRID>::CPair* pLastListenLine = m_ListenLineMap.PGetFirstAssoc();
  356. ASSERT(pLastListenLine != NULL);
  357. // 挂断此线路
  358. CMC::GetInstance().dropCall(pLastListenLine->key, true);
  359. } // end if
  360. }
  361. break;
  362. default:
  363. CProxyShell::GetInstance().onLineStateUpdated(LineId, m_Id, SESSION_INVALID_SUB_CALL, VIRTUAL_LINE_STATE_FREE, lpCallerNum, lpCalleeNum);
  364. break;
  365. } // end switch
  366. __notifySubSessionLineFree(LineId);
  367. CMC::GetInstance().freeChanResource(LineId);
  368. }
  369. /*****************************************************************
  370. **【函数名称】 __onLineStateAlerting
  371. **【函数功能】 线路状态处理【来电振铃】
  372. **【参数】 LineId 状态变化的线路ID
  373. lpCallerNum 主叫号码
  374. lpCallerNum 被叫号码
  375. **【返回值】
  376. *****************************************************************/
  377. void CCallSession::__onLineStateAlerting(CRDRID LineId, LPCTSTR lpCallerNum, LPCTSTR lpCalleeNum)
  378. {
  379. // 获取线路在会话中的职责
  380. CALL_PARTY_TYPE Type = __isLineMine(LineId);
  381. switch(Type)
  382. {
  383. case CALL_PARTY_HOST: // 主控线路
  384. {
  385. CProxyShell::GetInstance().onLineStateUpdated(LineId, m_Id, SESSION_INVALID_SUB_CALL, VIRTUAL_LINE_STATE_ALERTING, lpCallerNum, lpCalleeNum);
  386. }
  387. break;
  388. case CALL_PARTY_PEER: // 通话对端线路
  389. break;
  390. case CALL_PARTY_LISTEN: // 通话的监听线路
  391. break;
  392. case CALL_PARTY_PENDING: // 操作待处理线路
  393. {
  394. CSubSession* pSubCall = __getSubSession(LineId);
  395. ASSERT(pSubCall != NULL);
  396. pSubCall->onPendingLineState(VIRTUAL_LINE_STATE_ALERTING);
  397. }
  398. break;
  399. case CALL_PARTY_MEETING: // 会议中的线路
  400. break;
  401. default:
  402. ASSERT(FALSE);
  403. break;
  404. } // end switch
  405. }
  406. /*****************************************************************
  407. **【函数名称】 __onLineStateProgressing
  408. **【函数功能】 线路状态处理【通话进展】
  409. **【参数】 LineId 状态变化的线路ID
  410. lpCallerNum 主叫号码
  411. lpCallerNum 被叫号码
  412. **【返回值】
  413. *****************************************************************/
  414. void CCallSession::__onLineStateProgressing( CRDRID LineId, LPCTSTR lpCallerNum, LPCTSTR lpCalleeNum )
  415. {
  416. // 获取线路在会话中的职责
  417. CALL_PARTY_TYPE Type = __isLineMine(LineId);
  418. if(Type == CALL_PARTY_PENDING)
  419. {
  420. CSubSession* pSubCall = __getSubSession(LineId);
  421. ASSERT(pSubCall != NULL);
  422. pSubCall->onPendingLineState(VIRTUAL_LINE_STATE_PROGRESSING);
  423. }
  424. }
  425. /*****************************************************************
  426. **【函数名称】 __onLineStateRingBack
  427. **【函数功能】 线路状态处理【呼出振铃】
  428. **【参数】 LineId 状态变化的线路ID
  429. lpCallerNum 主叫号码
  430. lpCallerNum 被叫号码
  431. **【返回值】
  432. *****************************************************************/
  433. void CCallSession::__onLineStateRingBack(CRDRID LineId, LPCTSTR lpCallerNum, LPCTSTR lpCalleeNum)
  434. {
  435. // 获取线路在会话中的职责
  436. CALL_PARTY_TYPE Type = __isLineMine(LineId);
  437. // 根据线路在会话中的职责进行分类处理
  438. switch(Type)
  439. {
  440. case CALL_PARTY_HOST: // 主控线路
  441. {
  442. CProxyShell::GetInstance().onLineStateUpdated(LineId, m_Id, SESSION_INVALID_SUB_CALL, VIRTUAL_LINE_STATE_RING_BACK, lpCallerNum, lpCalleeNum);
  443. }
  444. break;
  445. case CALL_PARTY_PEER: // 对端线路
  446. break;
  447. case CALL_PARTY_LISTEN: // 通话的监听线路
  448. break;
  449. case CALL_PARTY_PENDING: // 操作待处理线路
  450. {
  451. CSubSession* pSubCall = __getSubSession(LineId);
  452. ASSERT(pSubCall != NULL);
  453. pSubCall->onPendingLineState(VIRTUAL_LINE_STATE_RING_BACK);
  454. }
  455. break;
  456. case CALL_PARTY_MEETING: // 会议中的线路
  457. break;
  458. default:
  459. ASSERT(FALSE);
  460. } // end switch
  461. }
  462. /*****************************************************************
  463. **【函数名称】 __onLineStateTalking
  464. **【函数功能】 线路状态处理【通话】
  465. **【参数】 LineId 状态变化的线路ID
  466. lpCallerNum 主叫号码
  467. lpCallerNum 被叫号码
  468. **【返回值】
  469. *****************************************************************/
  470. void CCallSession::__onLineStateTalking(CRDRID LineId, LPCTSTR lpCallerNum, LPCTSTR lpCalleeNum)
  471. {
  472. // 获取线路在会话中的职责
  473. CALL_PARTY_TYPE Type = __isLineMine(LineId);
  474. switch(Type)
  475. {
  476. case CALL_PARTY_HOST: // 主控线路
  477. {
  478. CProxyShell::GetInstance().onLineStateUpdated(LineId, m_Id, SESSION_INVALID_SUB_CALL, VIRTUAL_LINE_STATE_TALKING, lpCallerNum, lpCalleeNum);
  479. }
  480. break;
  481. case CALL_PARTY_PEER: // 通话对端线路
  482. break;
  483. case CALL_PARTY_LISTEN: // 通话的监听线路
  484. break;
  485. case CALL_PARTY_PENDING: // 操作待处理线路
  486. {
  487. CSubSession* pSubCall = __getSubSession(LineId);
  488. ASSERT(pSubCall != NULL);
  489. pSubCall->onPendingLineState(VIRTUAL_LINE_STATE_TALKING);
  490. }
  491. break;
  492. case CALL_PARTY_MEETING: // 会议中的线路
  493. break;
  494. default:
  495. ASSERT(FALSE);
  496. break;
  497. } // end switch
  498. }
  499. /*****************************************************************
  500. **【函数名称】 insertLine
  501. **【函数功能】 添加待定线路到会话
  502. **【参数】 LineId 要添加的线路ID
  503. PartyType 新增线路在会话中的职责
  504. Info 附加信息
  505. IsLink 是否作通道连接
  506. **【返回值】
  507. *****************************************************************/
  508. bool CCallSession::insertLine(CRDRID LineId, UINT SessionId, bool IsLink)
  509. {
  510. // 通知当前线路关联呼叫
  511. CMC::GetInstance().setSessionInfo2Line(LineId, m_Id);
  512. CProxyShell::GetInstance().onNewCall(LineId, m_Id, SESSION_INVALID_SUB_CALL);
  513. m_LineMap[LineId] = CALL_PARTY_PENDING;
  514. m_PendingLineMap[LineId] = SessionId;
  515. return true;
  516. }
  517. /*****************************************************************
  518. **【函数名称】 insertLine
  519. **【函数功能】 添加指定线路到会话
  520. **【参数】 LineId 要添加的线路ID
  521. PartyType 新增线路在会话中的职责
  522. IsLink 是否作通道连接
  523. **【返回值】
  524. *****************************************************************/
  525. bool CCallSession::insertLine( CRDRID LineId, CALL_PARTY_TYPE PartyType, bool IsLink )
  526. {
  527. // 通知当前线路关联呼叫
  528. CMC::GetInstance().setSessionInfo2Line(LineId, m_Id);
  529. CProxyShell::GetInstance().onNewCall(LineId, m_Id, SESSION_INVALID_SUB_CALL);
  530. // 根据职责保存线路到指定位置
  531. switch(PartyType)
  532. {
  533. case CALL_PARTY_HOST: // 主控线路
  534. {
  535. m_LineHost = LineId;
  536. m_LineMap[LineId] = CALL_PARTY_HOST;
  537. if(!m_LinePeer.isEmpty() && IsLink)
  538. {
  539. if(!__line2Link(LineId, m_LinePeer))
  540. return false;
  541. }
  542. }
  543. break;
  544. case CALL_PARTY_PEER: // 通话对端线路
  545. {
  546. m_LinePeer = LineId;
  547. m_LineMap[LineId] = CALL_PARTY_PEER;
  548. if(!m_LineHost.isEmpty() && IsLink)
  549. {
  550. if(!__line2Link(LineId, m_LineHost))
  551. return false;
  552. }
  553. }
  554. break;
  555. case CALL_PARTY_MEETING: // 会议中的线路
  556. {
  557. m_LineMap[LineId] = CALL_PARTY_MEETING;
  558. if(!CMC::GetInstance().move2Meeting(LineId, m_MeetingId, false))
  559. return false;
  560. }
  561. break;
  562. } // end switch
  563. return true;
  564. }
  565. /*****************************************************************
  566. **【函数名称】 insertLine
  567. **【函数功能】 添加监听线路到会话
  568. **【参数】 LineId 要添加的线路ID
  569. PartyType 新增线路在会话中的职责
  570. IsLink 是否作通道连接
  571. **【返回值】
  572. *****************************************************************/
  573. bool CCallSession::insertLine( CRDRID HostLineId, CRDRID SrcLineId, bool IsLink )
  574. {
  575. // 通知当前线路关联呼叫
  576. CMC::GetInstance().setSessionInfo2Line(HostLineId, m_Id);
  577. CProxyShell::GetInstance().onNewCall(HostLineId, m_Id, SESSION_INVALID_SUB_CALL);
  578. m_LineMap[HostLineId] = CALL_PARTY_LISTEN;
  579. m_ListenLineMap[HostLineId] = SrcLineId;
  580. CALL_PARTY_TYPE Type = __isLineMine(SrcLineId);
  581. if (Type == CALL_PARTY_MEETING)
  582. {
  583. if(!CMC::GetInstance().meetingListen(HostLineId, m_MeetingId, true))
  584. return false;
  585. }
  586. else
  587. {
  588. DEV_RES_ID PeerId = getPeerLine(SrcLineId);
  589. if(!CMC::GetInstance().channelListen(SrcLineId, PeerId, HostLineId, true))
  590. return false;
  591. }
  592. return true;
  593. }
  594. /*****************************************************************
  595. **【函数名称】 removeLine
  596. **【函数功能】 从会话中删除指定线路
  597. **【参数】 LineId 要删除的线路ID
  598. PartyType 要删除的线路在会话中的职责
  599. **【返回值】
  600. *****************************************************************/
  601. void CCallSession::removeLine(CRDRID LineId, CALL_PARTY_TYPE PartyType, PENDING_CALL_TYPE CallType /*= PENDING_CALL_DIRECT*/)
  602. {
  603. // 根据职责保存线路到指定位置
  604. switch(PartyType)
  605. {
  606. case CALL_PARTY_HOST: // 主控线路
  607. {
  608. if(!m_LinePeer.isEmpty())
  609. CMC::GetInstance().bridgeDevice(m_LineHost, m_LinePeer, false);
  610. m_LineHost.reset();
  611. if(CallType != PENDING_CALL_MEETING)
  612. __detachListen(LineId); // 监听线路挂机
  613. }
  614. break;
  615. case CALL_PARTY_PEER: // 通话对端线路
  616. {
  617. if(!m_LineHost.isEmpty())
  618. CMC::GetInstance().bridgeDevice(m_LineHost, m_LinePeer, false);
  619. m_LinePeer.reset();
  620. if(CallType != PENDING_CALL_MEETING)
  621. __detachListen(LineId); // 监听线路挂机
  622. }
  623. break;
  624. case CALL_PARTY_LISTEN: // 通话的监听线路
  625. {
  626. // 关闭监听
  627. DEV_RES_ID DestLine;
  628. if(m_ListenLineMap.Lookup(LineId, DestLine))
  629. {
  630. CALL_PARTY_TYPE Type = __isLineMine(DestLine);
  631. if (Type == CALL_PARTY_MEETING)
  632. {
  633. CMC::GetInstance().meetingListen(LineId, m_MeetingId, false);
  634. }
  635. else
  636. {
  637. DEV_RES_ID PeerId = getPeerLine(DestLine);
  638. CMC::GetInstance().channelListen(DestLine, PeerId, LineId, false);
  639. }
  640. // 清除线路
  641. m_ListenLineMap.RemoveKey(LineId);
  642. }
  643. }
  644. break;
  645. case CALL_PARTY_PENDING: // 操作待处理线路
  646. {
  647. m_PendingLineMap.RemoveKey(LineId);
  648. }
  649. break;
  650. case CALL_PARTY_MEETING: // 会议中的线路
  651. {
  652. int Type;
  653. if(m_LineMap.Lookup(LineId, Type))
  654. {
  655. ASSERT(Type == CALL_PARTY_MEETING);
  656. CMC::GetInstance().removeFromMeeting(LineId, m_MeetingId);
  657. if(CallType != PENDING_CALL_MEETING)
  658. __detachListen(LineId); // 监听线路挂机
  659. }
  660. }
  661. break;
  662. } // end switch
  663. m_LineMap.RemoveKey(LineId);
  664. }
  665. /*****************************************************************
  666. **【函数名称】 setupPendingCall
  667. **【函数功能】 启动待处理呼叫
  668. **【参数】 SubCall 新生成的子会话ID(回传参数)
  669. pInfo 呼叫内容
  670. **【返回值】 启动呼叫时否成功
  671. *****************************************************************/
  672. bool CCallSession::setupPendingCall(long& SubCall, PendingCallInfo* pInfo)
  673. {
  674. // 是否为会话中的通话线路
  675. CALL_PARTY_TYPE HostLineParty = __isLineMine(pInfo->nHostLine);
  676. if(HostLineParty != CALL_PARTY_HOST &&
  677. HostLineParty != CALL_PARTY_PEER &&
  678. HostLineParty != CALL_PARTY_MEETING)
  679. {
  680. return false;
  681. }
  682. // 添加待处理线路到会话
  683. if(!insertLine(pInfo->nAssoLine, m_SubCallIndex + 1, true))
  684. return false;
  685. // 生成子呼叫
  686. CSubSession* pSubCall = NULL;
  687. switch(pInfo->nCallType)
  688. {
  689. case PENDING_CALL_DIRECT:
  690. pSubCall = new CDirectSession(this, ++m_SubCallIndex, pInfo);
  691. break;
  692. case PENDING_CALL_TRANSFER:
  693. pSubCall = new CTransferSession(this, ++m_SubCallIndex, pInfo);
  694. break;
  695. case PENDING_CALL_MEETING:
  696. pSubCall = new CMeetingSession(this, ++m_SubCallIndex, pInfo);
  697. break;
  698. case PENDING_CALL_TRUNK:
  699. pSubCall = new CTrunkSession(this, ++m_SubCallIndex, pInfo);
  700. break;
  701. case PENDING_CALL_CONSULT:
  702. pSubCall = new CConsultSession(this, ++m_SubCallIndex, pInfo);
  703. break;
  704. } // end if
  705. SubCall = m_SubCallIndex; // 回传参数
  706. m_SubCallMap.SetAt(m_SubCallIndex, pSubCall);
  707. // 启动操作
  708. return pSubCall->begin(HostLineParty);
  709. }
  710. /*****************************************************************
  711. **【函数名称】 lineLeave
  712. **【函数功能】 指定线路退出会话且挂机
  713. **【参数】 LineId 要退出会话的线路ID
  714. **【返回值】
  715. *****************************************************************/
  716. bool CCallSession::lineLeave(CRDRID LineId)
  717. {
  718. CALL_PARTY_TYPE nParty = __isLineMine(LineId);
  719. // 此操作序列不会关联对端线路挂机
  720. removeLine(LineId, nParty);
  721. m_RecordMap.RemoveKey(LineId); // 释放录音关联
  722. return CMC::GetInstance().dropCall(LineId, false);
  723. }
  724. /*****************************************************************
  725. **【函数名称】 LineInstead
  726. **【函数功能】 代接指定线路
  727. **【参数】 HostLine 申请代接的线路
  728. PeerLine 被代接的线路
  729. ExtNum 申请代接线路的分机号
  730. **【返回值】
  731. *****************************************************************/
  732. bool CCallSession::lineInstead(CRDRID HostLine, CRDRID PeerLine, UINT ExtNum)
  733. {
  734. // 被代接线路是否还在子会话中
  735. CSubSession* pSubCall = __getSubSession(PeerLine);
  736. if(pSubCall == NULL)
  737. return false;
  738. // 执行替换操作
  739. return pSubCall->replace(HostLine, PeerLine, ExtNum);
  740. }
  741. /*****************************************************************
  742. **【函数名称】 lineIntercept
  743. **【函数功能】 替换指定线路
  744. **【参数】 HostLine 要进入会话的线路
  745. PeerLine 要退出会话的线路
  746. **【返回值】
  747. *****************************************************************/
  748. bool CCallSession::lineIntercept(CRDRID HostLine, CRDRID PeerLine)
  749. {
  750. // 读取被替换线路在会话中的职责
  751. CALL_PARTY_TYPE Party = __isLineMine(PeerLine);
  752. if(Party != CALL_PARTY_HOST &&
  753. Party != CALL_PARTY_PEER &&
  754. Party != CALL_PARTY_MEETING)
  755. {
  756. return false;
  757. } // end if
  758. // 目标线路退出会话
  759. removeLine(PeerLine, Party);
  760. if(!CMC::GetInstance().dropCall(PeerLine, true))
  761. return false;
  762. // 主控线路加入会话
  763. if(!insertLine(HostLine, Party, true))
  764. return false;
  765. CString strCallerNum, strCalleeNum;
  766. // 获取代接线路绑定的分机号
  767. CVirtualProxy* pHostProxy = CProxyShell::GetInstance().getProxy(HostLine.toIntId());
  768. ASSERT(pHostProxy != NULL);
  769. if(pHostProxy != NULL)
  770. pHostProxy->getAssoExtenNo(strCalleeNum);
  771. // 获取被代接线路当前的主叫号码
  772. CVirtualProxy* pPeerProxy = CProxyShell::GetInstance().getProxy(PeerLine.toIntId());
  773. ASSERT(pPeerProxy != NULL);
  774. if(pPeerProxy != NULL)
  775. strCallerNum = pPeerProxy->callerNum();
  776. CProxyShell::GetInstance().onLineStateUpdated(HostLine, m_Id, SESSION_INVALID_SUB_CALL, VIRTUAL_LINE_STATE_TALKING, strCallerNum, strCalleeNum);
  777. return true;
  778. }
  779. /*****************************************************************
  780. **【函数名称】 lineInsert
  781. **【函数功能】 插入线路到会话
  782. **【参数】 HostLine 要进入会话的线路
  783. **【返回值】
  784. *****************************************************************/
  785. bool CCallSession::lineInsert(CRDRID HostLine, CRDRID PeerLine)
  786. {
  787. // 如果当前会话不是会议
  788. if(m_MeetingId.MeetingId == MEETING_ID_INVALID)
  789. {
  790. if(m_LineHost.isEmpty() || m_LinePeer.isEmpty())
  791. return false;
  792. // 将原通话转为会议
  793. if(!trans2Meeting(m_LineHost))
  794. return false;
  795. } // end if
  796. // 将主控线路添加到会议
  797. if(!insertLine(HostLine, CALL_PARTY_MEETING, true))
  798. return false;
  799. CString strCallerNum, strCalleeNum;
  800. // 获取插入线路绑定的分机号
  801. CVirtualProxy* pHostProxy = CProxyShell::GetInstance().getProxy(HostLine.toIntId());
  802. ASSERT(pHostProxy != NULL);
  803. if(pHostProxy != NULL)
  804. pHostProxy->getAssoExtenNo(strCallerNum);
  805. // 获取被插入线路绑定的分机号
  806. CVirtualProxy* pPeerProxy = CProxyShell::GetInstance().getProxy(PeerLine.toIntId());
  807. ASSERT(pPeerProxy != NULL);
  808. if(pPeerProxy != NULL)
  809. pPeerProxy->getAssoExtenNo(strCalleeNum);
  810. CProxyShell::GetInstance().onLineStateUpdated(HostLine, m_Id, SESSION_INVALID_SUB_CALL, VIRTUAL_LINE_STATE_TALKING, strCallerNum, strCalleeNum);
  811. return true;
  812. }
  813. /*****************************************************************
  814. **【函数名称】 lineListen
  815. **【函数功能】 监听指定线路
  816. **【参数】 HostLine 主控线路
  817. PeerLine 被监听线路
  818. **【返回值】
  819. *****************************************************************/
  820. bool CCallSession::lineListen(CRDRID HostLine, CRDRID PeerLine)
  821. {
  822. // 被监听线路是否还在会话中
  823. CALL_PARTY_TYPE Party = __isLineMine(PeerLine);
  824. if(Party == CALL_PARTY_HOST ||
  825. Party == CALL_PARTY_PEER ||
  826. Party == CALL_PARTY_MEETING)
  827. {
  828. if(!insertLine(HostLine, PeerLine, true)) // 添加线路到会话
  829. return false;
  830. CString strCallerNum, strCalleeNum;
  831. // 获取监听线路绑定的分机号
  832. CVirtualProxy* pHostProxy = CProxyShell::GetInstance().getProxy(HostLine.toIntId());
  833. ASSERT(pHostProxy != NULL);
  834. if(pHostProxy != NULL)
  835. pHostProxy->getAssoExtenNo(strCallerNum);
  836. // 获取被监听线路绑定的分机号
  837. CVirtualProxy* pPeerProxy = CProxyShell::GetInstance().getProxy(PeerLine.toIntId());
  838. ASSERT(pPeerProxy != NULL);
  839. if(pPeerProxy != NULL)
  840. pPeerProxy->getAssoExtenNo(strCalleeNum);
  841. CProxyShell::GetInstance().onLineStateUpdated(HostLine, m_Id, SESSION_INVALID_SUB_CALL, VIRTUAL_LINE_STATE_TALKING, strCallerNum, strCalleeNum);
  842. return true;
  843. } // end if
  844. return false;
  845. }
  846. /*****************************************************************
  847. **【函数名称】 lineRecord
  848. **【函数功能】 线路录音启动
  849. **【参数】 HostLine 主控线路
  850. lpFileName 录音文件名
  851. **【返回值】
  852. *****************************************************************/
  853. bool CCallSession::lineRecord(CRDRID HostLine, LPCTSTR lpFileName)
  854. {
  855. // 如果当前线路已在录音
  856. CString strRecFile;
  857. if(m_RecordMap.Lookup(HostLine, strRecFile))
  858. return false;
  859. // 启动录音
  860. if(__lineRecord(HostLine, lpFileName))
  861. {
  862. m_RecordMap.SetAt(HostLine, lpFileName);
  863. return true;
  864. } // end if
  865. return false;
  866. }
  867. /*****************************************************************
  868. **【函数名称】 lineLeaveWord
  869. **【函数功能】 线路留言启动
  870. **【参数】 HostLine 主控线路
  871. pContent 留言参数
  872. **【返回值】
  873. *****************************************************************/
  874. bool CCallSession::lineLeaveWord(CRDRID HostLine, RecordContent* pContent)
  875. {
  876. if(__isLineMine(HostLine) == CALL_PARTY_UNKNOWN)
  877. return false;
  878. // 启动留言
  879. pContent->nModel = RECORD_MODE_LEAVEWORD;
  880. return CMC::GetInstance().startRecord(HostLine, pContent);
  881. }
  882. /*****************************************************************
  883. **【函数名称】 lineMute
  884. **【函数功能】 线路静音控制
  885. **【参数】 HostLine 主控线路
  886. IsBegin 是启动还是结束
  887. **【返回值】
  888. *****************************************************************/
  889. bool CCallSession::lineMute(CRDRID HostLine, bool IsOn)
  890. {
  891. // 是否对会议中的线路静音
  892. CALL_PARTY_TYPE Type = __isLineMine(HostLine);
  893. bool IsMeetingMute = Type == CALL_PARTY_MEETING ? true : false;
  894. if (IsMeetingMute)
  895. {
  896. return __meetingMute(HostLine, IsOn);
  897. }
  898. else
  899. {
  900. return __lineMute(HostLine, IsOn);
  901. }
  902. }
  903. /*****************************************************************
  904. **【函数名称】 lineConsultConfirm
  905. **【函数功能】 协商呼叫确认
  906. **【参数】 PeerLine 协商呼叫的被叫线路
  907. Type 呼叫类型
  908. **【返回值】
  909. *****************************************************************/
  910. bool CCallSession::lineConsultConfirm(CRDRID PeerLine, UINT Type)
  911. {
  912. // 被代接线路是否还在子会话中
  913. CSubSession* pSubCall = __getSubSession(PeerLine);
  914. if(pSubCall == NULL)
  915. return false;
  916. // 执行替换操作
  917. return pSubCall->resume(Type);
  918. }
  919. /*****************************************************************
  920. **【函数名称】 line2Meeting
  921. **【函数功能】 通话线路转入会议
  922. **【参数】 LineId 要转入会议的线路ID
  923. Party 要进入会议的线路在原会话中的职责
  924. **【返回值】
  925. *****************************************************************/
  926. bool CCallSession::line2Meeting(DEV_RES_ID LineId, CALL_PARTY_TYPE Party)
  927. {
  928. removeLine(LineId, Party, PENDING_CALL_MEETING);
  929. // 线路转入会议
  930. return insertLine(LineId, CALL_PARTY_MEETING, true);
  931. }
  932. /*****************************************************************
  933. **【函数名称】 trans2Meeting
  934. **【函数功能】 将当前会话转换为会议
  935. **【参数】 HostLineId 发起会议的主控线路
  936. **【返回值】
  937. *****************************************************************/
  938. bool CCallSession::trans2Meeting(CRDRID HostLineId)
  939. {
  940. if(m_MeetingId.MeetingId != MEETING_ID_INVALID)
  941. return true;
  942. if(!CMC::GetInstance().createMeeting(HostLineId, m_MeetingId))
  943. {
  944. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Session}: 会话环境转换为会议失败, HostLine = %u, PeerLine = %u"),
  945. m_LineHost.toIntId(), m_LinePeer.toIntId());
  946. return false;
  947. }
  948. bool HostTrans2MeetingResult = false;
  949. // 原通话线路职责转换
  950. if(!m_LineHost.isEmpty())
  951. {
  952. HostTrans2MeetingResult = line2Meeting(m_LineHost, CALL_PARTY_HOST);
  953. if(!HostTrans2MeetingResult) // 若主线路转为会议不成功,就说明DSP资源枯竭,此次会议就宣告失败
  954. {
  955. CMC::GetInstance().deleteMeeting(m_MeetingId);
  956. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Session}: 主线路转换为会议失败, HostLine = %u, PeerLine = %u"),
  957. m_LineHost.toIntId(), m_LinePeer.toIntId());
  958. return false;
  959. }
  960. }
  961. if(!m_LinePeer.isEmpty())
  962. {
  963. if(!line2Meeting(m_LinePeer, CALL_PARTY_PEER))
  964. {
  965. if(!HostTrans2MeetingResult)
  966. {
  967. // 运行到此,说明主线路为空(即:m_LineHost == 0),因此要删除以创建的会议,
  968. // 但若主线路成功转为会议则不删除,因为主线路挂机后会自动删除。
  969. CMC::GetInstance().deleteMeeting(m_MeetingId);
  970. }
  971. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Session}: 对端线路转换为会议失败, HostLine = %u, PeerLine = %u"),
  972. m_LineHost.toIntId(), m_LinePeer.toIntId());
  973. return false;
  974. }
  975. }
  976. return true;
  977. }