修改三方通话功能,在发起三方通话时,先保持住主叫,然后再拉回主叫到会议

Mixer.cpp 8.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. #include "StdAfx.h"
  2. #include "Mixer.h"
  3. #include "MC.h"
  4. #include "DspChannel.h"
  5. CMixer::CMixer(IMixerHost& Host) : m_Host(Host), m_pPlayDsp(NULL), m_pRecordDsp(NULL), m_pMonitorChan(NULL)
  6. {
  7. }
  8. CMixer::~CMixer(void)
  9. {
  10. }
  11. /*****************************************************************
  12. **【函数名称】 __attachDspCh
  13. **【函数功能】 关联放音DSP通道
  14. **【参数】
  15. **【返回值】 成功true,失败false
  16. ****************************************************************/
  17. bool CMixer::__attachPlayDsp( void )
  18. {
  19. CDspChannel* pDspCh = m_pPlayDsp;
  20. if(pDspCh == NULL)
  21. {
  22. pDspCh = CMC::GetInstance().allocDspCh(m_Host.node(), DEVICE_BRD_NO_ANY);
  23. ASSERT(pDspCh != NULL);
  24. if(pDspCh == NULL)
  25. return false;
  26. }
  27. if(ISX_nr_scroute(m_Host.mixHandle(), m_Host.normalType(), pDspCh->handle(), pDspCh->type(), SC_FULLDUP) == 0)
  28. {
  29. m_pPlayDsp = pDspCh;
  30. pDspCh->attach(this);
  31. return true;
  32. }
  33. return false;
  34. }
  35. /*****************************************************************
  36. **【函数名称】 __detachDsp
  37. **【函数功能】 解关联放音DSP通道
  38. **【参数】
  39. **【返回值】
  40. ****************************************************************/
  41. void CMixer::__detachPlayDsp( void )
  42. {
  43. if(m_pPlayDsp == NULL)
  44. return;
  45. m_pPlayDsp->attach(NULL);
  46. m_pPlayDsp->reset();
  47. ISX_nr_scunroute(m_Host.mixHandle(), m_Host.normalType(), m_pPlayDsp->handle(), m_pPlayDsp->type(), SC_FULLDUP);
  48. m_pPlayDsp = NULL;
  49. }
  50. /*****************************************************************
  51. **【函数名称】 __attachRecordDsp
  52. **【函数功能】 关联录音DSP通道
  53. **【参数】
  54. **【返回值】 成功true,失败false
  55. ****************************************************************/
  56. bool CMixer::__attachRecordDsp( void )
  57. {
  58. CDspChannel* pDspCh = m_pRecordDsp;
  59. if(pDspCh == NULL)
  60. {
  61. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{Mixer}:关联录音,查找空闲DSP通道,host.node[%d]"), m_Host.node());
  62. pDspCh = CMC::GetInstance().allocDspCh(m_Host.node(), DEVICE_BRD_NO_ANY);
  63. ASSERT(pDspCh != NULL);
  64. if(pDspCh == NULL)
  65. return false;
  66. }
  67. if(ISX_nr_scroute(m_Host.mixHandle(), m_Host.mixType(), pDspCh->handle(), pDspCh->type(), SC_HALFDUP) == 0)
  68. {
  69. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{Mixer}: 关联录音DSP通道成功,Host[%d],type[%d],[%d], DSP[%d-%d-%d],type[%d],[%d]"),
  70. m_Host.node(), m_Host.mixType(), m_Host.mixHandle(), pDspCh->nodeNo(), pDspCh->boardNo(), pDspCh->chanNo(), pDspCh->type(), pDspCh->handle());
  71. m_pRecordDsp = pDspCh;
  72. pDspCh->attach(this);
  73. return true;
  74. }else {
  75. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Mixer}: 关联录音DSP通道失败,ErrorMessage=%s"), ISX_ATDV_ERRMSGP(m_Host.mixHandle()));
  76. LOGGER(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Mixer}: 关联录音DSP通道失败,dspch,ErrorMessage=%s"), ISX_ATDV_ERRMSGP(pDspCh->handle()));
  77. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{Mixer}: 关联录音DSP通道失败,Host[%d],type[%d],[%d], DSP[%d-%d-%d],type[%d],[%d]"),
  78. m_Host.node(), m_Host.mixType(), m_Host.mixHandle(), pDspCh->nodeNo(), pDspCh->boardNo(), pDspCh->chanNo(), pDspCh->type(), pDspCh->handle());
  79. }
  80. return false;
  81. }
  82. /*****************************************************************
  83. **【函数名称】 __detachDsp
  84. **【函数功能】 解关联录音DSP通道
  85. **【参数】
  86. **【返回值】
  87. ****************************************************************/
  88. void CMixer::__detachRecordDsp( void )
  89. {
  90. if(m_pRecordDsp == NULL)
  91. return;
  92. m_pRecordDsp->attach(NULL);
  93. m_pRecordDsp->reset();
  94. ISX_nr_scunroute(m_Host.mixHandle(), m_Host.mixType(), m_pRecordDsp->handle(), m_pRecordDsp->type(), SC_HALFDUP);
  95. m_pRecordDsp = NULL;
  96. }
  97. /*****************************************************************
  98. **【函数名称】 playSound
  99. **【函数功能】 放音
  100. **【参数】
  101. **【返回值】
  102. ****************************************************************/
  103. bool CMixer::playSound( PlayVoiceContent* pContent )
  104. {
  105. if(!__attachPlayDsp())
  106. return false;
  107. return m_pPlayDsp->playSound(pContent);
  108. }
  109. /*****************************************************************
  110. **【函数名称】 playTone
  111. **【函数功能】 播放信号音
  112. **【参数】 Type 信号音类型
  113. **【返回值】
  114. ****************************************************************/
  115. bool CMixer::playTone( int Type )
  116. {
  117. if(Type == CHANNEL_TONE_NULL)
  118. {
  119. if(m_pPlayDsp == NULL)
  120. return false;
  121. __detachPlayDsp();
  122. return true;
  123. }
  124. else
  125. {
  126. if(!__attachPlayDsp())
  127. return false;
  128. return m_pPlayDsp->playTone(Type);
  129. }
  130. }
  131. /*****************************************************************
  132. **【函数名称】 playStop
  133. **【函数功能】 停止放音
  134. **【参数】
  135. **【返回值】
  136. ****************************************************************/
  137. bool CMixer::playStop( void )
  138. {
  139. if(m_pPlayDsp == NULL)
  140. return false;
  141. __detachPlayDsp();
  142. return true;
  143. }
  144. /*****************************************************************
  145. **【函数名称】 startRecord
  146. **【函数功能】 开始录音
  147. **【参数】
  148. **【返回值】
  149. ****************************************************************/
  150. bool CMixer::startRecord( RecordContent* pContent )
  151. {
  152. ASSERT(pContent != NULL);
  153. if(m_pRecordDsp == NULL)
  154. if(!__attachRecordDsp())
  155. return false;
  156. return m_pRecordDsp->startRecord(pContent);
  157. }
  158. /*****************************************************************
  159. **【函数名称】 stopRecord
  160. **【函数功能】 停止录音
  161. **【参数】
  162. **【返回值】
  163. ****************************************************************/
  164. bool CMixer::stopRecord( void )
  165. {
  166. if(m_pRecordDsp == NULL)
  167. return false;
  168. return m_pRecordDsp->stopRecord();
  169. }
  170. /*****************************************************************
  171. **【函数名称】 release
  172. **【函数功能】 释放资源
  173. **【参数】
  174. **【返回值】
  175. ****************************************************************/
  176. void CMixer::release( void )
  177. {
  178. if(m_pMonitorChan != NULL)
  179. {
  180. ISX_nr_scunroute(m_Host.mixHandle(), m_Host.normalType(), m_pMonitorChan->handle(), m_pMonitorChan->type(), SC_HALFDUP);
  181. m_pMonitorChan = NULL;
  182. }
  183. __detachPlayDsp();
  184. __detachRecordDsp();
  185. }
  186. /*****************************************************************
  187. **【函数名称】 setupMonitor
  188. **【函数功能】 建立监听
  189. **【参数】
  190. **【返回值】
  191. ****************************************************************/
  192. bool CMixer::setupMonitor( CChannelResource* pMonitorParty )
  193. {
  194. ASSERT(pMonitorParty != NULL);
  195. if(m_pRecordDsp == NULL){
  196. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{Mixer}: 建立监听,Host[%d],type[%d],[%d],录音DSP通道空闲"),
  197. m_Host.node(), m_Host.mixType(), m_Host.mixHandle());
  198. }
  199. else {
  200. LOGGER(LOG_CLASS_DEV, LOG_LEVEL_NORMAL, _T("{Mixer}: 建立监听,Host[%d],type[%d],[%d], RecordDSP[%d-%d-%d],type[%d],[%d]"),
  201. m_Host.node(), m_Host.mixType(), m_Host.mixHandle(), m_pRecordDsp->nodeNo(), m_pRecordDsp->boardNo(), m_pRecordDsp->chanNo(), m_pRecordDsp->type(), m_pRecordDsp->handle());
  202. }
  203. //ASSERT(m_pRecordDsp == NULL); // 录音DSP必须为空,否则混音线路的+R端非空闲,则无法实现监听
  204. if(ISX_nr_scroute(m_Host.mixHandle(), m_Host.mixType(), pMonitorParty->handle(), pMonitorParty->type(), SC_HALFDUP) == 0)
  205. //if(ISX_nr_scroute(m_Host.mixHandle(), m_Host.normalType(), pMonitorParty->handle(), pMonitorParty->type(), SC_HALFDUP) == 0)
  206. {
  207. m_pMonitorChan = pMonitorParty;
  208. return true;
  209. }
  210. return false;
  211. }
  212. /*****************************************************************
  213. **【函数名称】 undoMonitor
  214. **【函数功能】 撤销监听
  215. **【参数】
  216. **【返回值】
  217. ****************************************************************/
  218. bool CMixer::undoMonitor( CChannelResource* pMonitorParty )
  219. {
  220. if(m_pMonitorChan != NULL)
  221. {
  222. ASSERT(m_pMonitorChan == pMonitorParty);
  223. ISX_nr_scunroute(m_Host.mixHandle(), m_Host.mixType(), m_pMonitorChan->handle(), m_pMonitorChan->type(), SC_HALFDUP);
  224. //ISX_nr_scunroute(m_Host.mixHandle(), m_Host.normalType(), m_pMonitorChan->handle(), m_pMonitorChan->type(), SC_HALFDUP);
  225. m_pMonitorChan = NULL;
  226. return true;
  227. }
  228. return false;
  229. }
  230. /*****************************************************************
  231. **【函数名称】 onPlayEnd
  232. **【函数功能】 放音完毕的处理函数
  233. **【参数】
  234. **【返回值】
  235. ****************************************************************/
  236. void CMixer::onPlayEnd( LPCTSTR lpDtmf )
  237. {
  238. //__detachPlayDsp(); 因为毅航设备DTMF检测不建议随机使用DSP通道,故中继线路转坐席之前如要放音则使用同一DSP通道
  239. m_Host.onPlayEnd(lpDtmf);
  240. }
  241. /*****************************************************************
  242. **【函数名称】 undoMonitor
  243. **【函数功能】 录音完毕的处理函数
  244. **【参数】
  245. **【返回值】
  246. ****************************************************************/
  247. void CMixer::onRecEnd( UINT TaskId )
  248. {
  249. __detachRecordDsp();
  250. m_Host.onRecEnd(TaskId);
  251. }
  252. /*****************************************************************
  253. **【函数名称】 undoMonitor
  254. **【函数功能】 Tone音完毕的处理函数
  255. **【参数】
  256. **【返回值】
  257. ****************************************************************/
  258. void CMixer::onToneEnd( int ToneTp )
  259. {
  260. __detachPlayDsp();
  261. m_Host.onToneEnd(ToneTp);
  262. }