Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

494 lines
9.5 KiB

  1. // File: ichnlaud.cpp
  2. #include "precomp.h"
  3. #include "ichnlaud.h"
  4. static const IID * g_apiidCP[] =
  5. {
  6. {&IID_INmChannelNotify},
  7. {&IID_INmChannelAudioNotify}
  8. };
  9. CNmChannelAudio::CNmChannelAudio(BOOL fIncoming) :
  10. CConnectionPointContainer(g_apiidCP, ARRAY_ELEMENTS(g_apiidCP)),
  11. m_cMembers (0),
  12. m_dwFlags(0),
  13. m_pAudioChannel(NULL),
  14. m_pAudioDevice(NULL),
  15. m_pCommChannel(NULL),
  16. m_fIncoming(fIncoming),
  17. m_AudioControl(!fIncoming /* fLocal */),
  18. m_MediaFormat(INVALID_MEDIA_FORMAT)
  19. {
  20. IMediaChannel *pMC = NULL;
  21. HRESULT hr;
  22. if (NULL != g_pH323UI)
  23. {
  24. IMediaChannelBuilder * pMCProvider = g_pH323UI->GetStreamProvider();
  25. ASSERT(NULL != pMCProvider);
  26. // create the channel, and get the device interface
  27. pMCProvider->CreateMediaChannel(MCF_AUDIO | (fIncoming ? MCF_RECV : MCF_SEND), &pMC);
  28. if (NULL != pMC)
  29. {
  30. pMCProvider->QueryInterface(IID_IAudioDevice, (void**)&m_pAudioDevice);
  31. pMC->QueryInterface(IID_IAudioChannel, (void**)&m_pAudioChannel);
  32. ASSERT(m_pAudioChannel);
  33. ASSERT(m_pAudioDevice);
  34. pMC->Release();
  35. }
  36. else
  37. {
  38. WARNING_OUT(("CreateMediaChannel failed"));
  39. }
  40. pMCProvider->Release();
  41. }
  42. DbgMsg(iZONE_OBJECTS, "Obj: %08X created CNmChannelAudio", this);
  43. }
  44. CNmChannelAudio::~CNmChannelAudio()
  45. {
  46. if (NULL != m_pCommChannel)
  47. {
  48. m_pCommChannel->Release();
  49. }
  50. if (NULL != m_pAudioChannel)
  51. {
  52. m_pAudioChannel->Release();
  53. }
  54. if (NULL != m_pAudioDevice)
  55. {
  56. m_pAudioDevice->Release();
  57. }
  58. DbgMsg(iZONE_OBJECTS, "Obj: %08X destroyed CNmChannelAudio", this);
  59. }
  60. VOID CNmChannelAudio::CommChannelOpened(ICommChannel *pCommChannel)
  61. {
  62. ASSERT(NULL == m_pCommChannel);
  63. m_pCommChannel = pCommChannel;
  64. pCommChannel->AddRef();
  65. }
  66. VOID CNmChannelAudio::CommChannelActive(ICommChannel *pCommChannel)
  67. {
  68. ASSERT(m_pCommChannel == pCommChannel);
  69. }
  70. VOID CNmChannelAudio::CommChannelClosed()
  71. {
  72. if (NULL != m_pCommChannel)
  73. {
  74. m_pCommChannel->Release();
  75. m_pCommChannel = NULL;
  76. }
  77. }
  78. VOID CNmChannelAudio::OnMemberAdded(CNmMember *pMember)
  79. {
  80. // Don't add to the channel if we already belong.
  81. if (0 != (pMember->GetNmchCaps() & NMCH_AUDIO))
  82. {
  83. return;
  84. }
  85. ++m_cMembers;
  86. pMember->AddNmchCaps(NMCH_AUDIO);
  87. CConfObject *pco = ::GetConfObject();
  88. pco->OnMemberUpdated(pMember);
  89. NotifySink((INmMember *) pMember, OnNotifyChannelMemberAdded);
  90. }
  91. VOID CNmChannelAudio::OnMemberRemoved(CNmMember *pMember)
  92. {
  93. // If member does not belong to this channel, don't remove it.
  94. if (0 == (pMember->GetNmchCaps() & NMCH_AUDIO))
  95. {
  96. return;
  97. }
  98. --m_cMembers;
  99. pMember->RemoveNmchCaps(NMCH_AUDIO);
  100. CConfObject *pco = ::GetConfObject();
  101. pco->OnMemberUpdated(pMember);
  102. NotifySink((INmMember *) pMember, OnNotifyChannelMemberRemoved);
  103. }
  104. VOID CNmChannelAudio::OnMemberUpdated(CNmMember *pMember)
  105. {
  106. NotifySink((INmMember *) pMember, OnNotifyChannelMemberUpdated);
  107. }
  108. DWORD CNmChannelAudio::GetLevel()
  109. {
  110. UINT uLevel = 0;
  111. if (NULL != m_pAudioChannel)
  112. {
  113. m_pAudioChannel->GetSignalLevel(&uLevel);
  114. }
  115. return uLevel;
  116. }
  117. BOOL CNmChannelAudio::IsAutoMixing()
  118. {
  119. BOOL bOn=FALSE;
  120. if ((NULL != m_pAudioChannel) && (!m_fIncoming))
  121. {
  122. m_pAudioDevice->GetAutoMix(&bOn);
  123. }
  124. return bOn;
  125. }
  126. BOOL CNmChannelAudio::IsPaused()
  127. {
  128. BOOL fPaused = TRUE;
  129. if (NULL != m_pCommChannel)
  130. {
  131. DWORD dwOn = FALSE;
  132. UINT uSize = sizeof(dwOn);
  133. DWORD dwPropID = m_fIncoming ? PROP_PLAY_ON : PROP_RECORD_ON;
  134. m_pCommChannel->GetProperty(dwPropID, &dwOn, &uSize);
  135. fPaused = (0 == dwOn);
  136. }
  137. return fPaused;
  138. }
  139. VOID CNmChannelAudio::Open()
  140. {
  141. ASSERT(m_MediaFormat != INVALID_MEDIA_FORMAT);
  142. m_AudioControl.Open(m_MediaFormat);
  143. }
  144. VOID CNmChannelAudio::Close()
  145. {
  146. m_AudioControl.Close();
  147. }
  148. STDMETHODIMP_(ULONG) CNmChannelAudio::AddRef(void)
  149. {
  150. return RefCount::AddRef();
  151. }
  152. STDMETHODIMP_(ULONG) CNmChannelAudio::Release(void)
  153. {
  154. return RefCount::Release();
  155. }
  156. STDMETHODIMP CNmChannelAudio::QueryInterface(REFIID riid, PVOID *ppv)
  157. {
  158. HRESULT hr = S_OK;
  159. if ((riid == IID_INmChannelAudio) || (riid == IID_INmChannel) || (riid == IID_IUnknown))
  160. {
  161. *ppv = (INmChannel *)this;
  162. DbgMsgApi("CNmChannelAudio::QueryInterface()");
  163. }
  164. else if (riid == IID_IConnectionPointContainer)
  165. {
  166. *ppv = (IConnectionPointContainer *) this;
  167. DbgMsgApi("CNmChannelAudio::QueryInterface(): Returning IConnectionPointContainer.");
  168. }
  169. else
  170. {
  171. hr = E_NOINTERFACE;
  172. *ppv = NULL;
  173. DbgMsgApi("CNmChannelAudio::QueryInterface(): Called on unknown interface.");
  174. }
  175. if (S_OK == hr)
  176. {
  177. AddRef();
  178. }
  179. return hr;
  180. }
  181. STDMETHODIMP CNmChannelAudio::IsSameAs(INmChannel *pChannel)
  182. {
  183. return (((INmChannel *) this) == pChannel) ? S_OK : S_FALSE;
  184. }
  185. STDMETHODIMP CNmChannelAudio::IsActive()
  186. {
  187. return (NULL != m_pCommChannel) ? S_OK : S_FALSE;
  188. }
  189. STDMETHODIMP CNmChannelAudio::SetActive(BOOL fActive)
  190. {
  191. return E_FAIL;
  192. }
  193. STDMETHODIMP CNmChannelAudio::GetConference(INmConference **ppConference)
  194. {
  195. return ::GetConference(ppConference);
  196. }
  197. STDMETHODIMP CNmChannelAudio::GetInterface(IID *piid)
  198. {
  199. HRESULT hr = E_POINTER;
  200. if (NULL != piid)
  201. {
  202. *piid = IID_INmChannelAudio;
  203. hr = S_OK;
  204. }
  205. return hr;
  206. }
  207. STDMETHODIMP CNmChannelAudio::GetNmch(ULONG *puCh)
  208. {
  209. HRESULT hr = E_POINTER;
  210. if (NULL != puCh)
  211. {
  212. *puCh = NMCH_AUDIO;
  213. hr = S_OK;
  214. }
  215. return hr;
  216. }
  217. STDMETHODIMP CNmChannelAudio::EnumMember(IEnumNmMember **ppEnum)
  218. {
  219. HRESULT hr = E_POINTER;
  220. if (NULL != ppEnum)
  221. {
  222. int cMembers = 0;
  223. COBLIST MemberList;
  224. COBLIST* pPartList = ::GetMemberList();
  225. if (NULL != pPartList)
  226. {
  227. POSITION pos = pPartList->GetHeadPosition();
  228. while (pos)
  229. {
  230. CNmMember * pMember = (CNmMember *) pPartList->GetNext(pos);
  231. ASSERT(NULL != pMember);
  232. if (NMCH_AUDIO & pMember->GetNmchCaps())
  233. {
  234. MemberList.AddTail(pMember);
  235. pMember->AddRef();
  236. cMembers++;
  237. }
  238. }
  239. }
  240. *ppEnum = new CEnumNmMember(&MemberList, cMembers);
  241. while (!MemberList.IsEmpty())
  242. {
  243. INmMember *pMember = (INmMember *) (CNmMember *) MemberList.RemoveHead();
  244. pMember->Release();
  245. }
  246. hr = (NULL != *ppEnum)? S_OK : E_OUTOFMEMORY;
  247. }
  248. return hr;
  249. }
  250. STDMETHODIMP CNmChannelAudio::GetMemberCount(ULONG * puCount)
  251. {
  252. HRESULT hr = E_POINTER;
  253. if (NULL != puCount)
  254. {
  255. *puCount = m_cMembers;
  256. hr = S_OK;
  257. }
  258. return hr;
  259. }
  260. STDMETHODIMP CNmChannelAudio::IsIncoming(void)
  261. {
  262. return m_fIncoming ? S_OK : S_FALSE;
  263. }
  264. STDMETHODIMP CNmChannelAudio::GetState(NM_AUDIO_STATE *puState)
  265. {
  266. HRESULT hr = E_POINTER;
  267. if (NULL != puState)
  268. {
  269. if (NULL != m_pCommChannel)
  270. {
  271. if (IsPaused())
  272. {
  273. *puState = NM_AUDIO_LOCAL_PAUSED;
  274. }
  275. else
  276. {
  277. *puState = NM_AUDIO_TRANSFERRING;
  278. }
  279. }
  280. else
  281. {
  282. *puState = NM_AUDIO_IDLE;
  283. }
  284. hr = S_OK;
  285. }
  286. return hr;
  287. }
  288. IMediaChannel* CNmChannelAudio::GetMediaChannelInterface(void)
  289. {
  290. IMediaChannel *pMC=NULL;
  291. if (m_pAudioChannel)
  292. {
  293. m_pAudioChannel->QueryInterface(IID_IMediaChannel, (void**)&pMC);
  294. }
  295. return pMC;
  296. }
  297. STDMETHODIMP CNmChannelAudio::GetProperty(NM_AUDPROP uID, ULONG_PTR *puValue)
  298. {
  299. HRESULT hr = E_POINTER;
  300. if (NULL != puValue)
  301. {
  302. switch (uID)
  303. {
  304. case NM_AUDPROP_LEVEL:
  305. *puValue = GetLevel();
  306. hr = S_OK;
  307. break;
  308. case NM_AUDPROP_PAUSE:
  309. *puValue = IsPaused();
  310. hr = S_OK;
  311. break;
  312. case NM_AUDPROP_AUTOMIX:
  313. *puValue = IsAutoMixing();
  314. hr = S_OK;
  315. break;
  316. default:
  317. hr = E_FAIL;
  318. break;
  319. }
  320. }
  321. return hr;
  322. }
  323. HRESULT OnNotifyPropertyChanged(IUnknown *pAudioChannelNotify, PVOID pv, REFIID riid)
  324. {
  325. ASSERT(NULL != pAudioChannelNotify);
  326. ((INmChannelAudioNotify*)pAudioChannelNotify)->PropertyChanged((DWORD)((DWORD_PTR)pv));
  327. return S_OK;
  328. }
  329. HRESULT OnNotifyStateChanged(IUnknown *pAudioChannelNotify, PVOID pv, REFIID riid)
  330. {
  331. ASSERT(NULL != pAudioChannelNotify);
  332. ((INmChannelAudioNotify*)pAudioChannelNotify)->StateChanged(static_cast<NM_AUDIO_STATE>((DWORD)((DWORD_PTR)pv)));
  333. return S_OK;
  334. }
  335. STDMETHODIMP CNmChannelAudio::SetProperty(NM_AUDPROP uID, ULONG_PTR uValue)
  336. {
  337. HRESULT hr = E_FAIL;
  338. if ((NULL != m_pAudioDevice) && (NULL != m_pAudioChannel))
  339. {
  340. switch (uID)
  341. {
  342. case NM_AUDPROP_PAUSE:
  343. {
  344. DWORD dwOn = (0 == uValue);
  345. DWORD dwPropID = m_fIncoming ? PROP_PLAY_ON : PROP_RECORD_ON;
  346. if (m_pCommChannel)
  347. {
  348. hr = m_pCommChannel->SetProperty(dwPropID, &dwOn, sizeof(dwOn));
  349. if(S_OK == hr)
  350. {
  351. // The Mute state has changed
  352. NotifySink((void*)NM_AUDPROP_PAUSE, OnNotifyPropertyChanged);
  353. // The Channel state has changed
  354. NM_AUDIO_STATE uState;
  355. if(SUCCEEDED(GetState(&uState)))
  356. {
  357. NotifySink((void*)uState, OnNotifyStateChanged);
  358. }
  359. }
  360. }
  361. break;
  362. }
  363. case NM_AUDPROP_LEVEL:
  364. {
  365. hr = m_pAudioDevice->SetSilenceLevel(uValue);
  366. break;
  367. }
  368. case NM_AUDPROP_FULL_DUPLEX:
  369. {
  370. DWORD dwDuplex = uValue;
  371. hr = m_pAudioDevice->SetDuplex((BOOL)uValue);
  372. break;
  373. }
  374. case NM_AUDPROP_WAVE_DEVICE:
  375. {
  376. if (m_fIncoming)
  377. {
  378. hr = m_pAudioDevice->SetPlaybackID(uValue);
  379. }
  380. else
  381. {
  382. hr = m_pAudioDevice->SetRecordID(uValue);
  383. }
  384. break;
  385. }
  386. case NM_AUDPROP_AUTOMIX:
  387. {
  388. hr = m_pAudioDevice->SetAutoMix((BOOL)uValue);
  389. break;
  390. }
  391. case NM_AUDPROP_DTMF_DIGIT:
  392. {
  393. IDTMFSend *pDTMF=NULL;
  394. if (!m_fIncoming)
  395. {
  396. hr = m_pAudioChannel->QueryInterface(IID_IDTMFSend, (void**)&pDTMF);
  397. if (SUCCEEDED(hr))
  398. {
  399. hr = pDTMF->AddDigit((int)uValue);
  400. pDTMF->Release();
  401. }
  402. }
  403. }
  404. default:
  405. break;
  406. }
  407. }
  408. return hr;
  409. }
  410.