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.

1156 lines
28 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. IPConfaudt.cpp
  5. Abstract:
  6. IPConfMSP implementation of audio capture terminal and render terminal
  7. Author:
  8. Zoltan Szilagyi (zoltans) September 6,1998
  9. Mu Han (muhan) June 6, 1999
  10. --*/
  11. #include "stdafx.h"
  12. #define MAX_LONG 0xefffffff
  13. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  14. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  15. CIPConfAudioCaptureTerminal::CIPConfAudioCaptureTerminal()
  16. : m_WaveID(0),
  17. m_DSoundGuid(GUID_NULL),
  18. m_pIAMAudioInputMixer(NULL)
  19. {
  20. LOG((MSP_TRACE, "CIPConfAudioCaptureTerminal::CIPConfAudioCaptureTerminal"));
  21. m_TerminalClassID = CLSID_MicrophoneTerminal;
  22. m_TerminalDirection = TD_CAPTURE;
  23. m_TerminalType = TT_STATIC;
  24. m_TerminalState = TS_NOTINUSE;
  25. m_dwMediaType = TAPIMEDIATYPE_AUDIO;
  26. }
  27. CIPConfAudioCaptureTerminal::~CIPConfAudioCaptureTerminal()
  28. {
  29. LOG((MSP_TRACE, "CIPConfAudioCaptureTerminal::~CIPConfAudioCaptureTerminal"));
  30. if (m_pIAMAudioInputMixer)
  31. {
  32. m_pIAMAudioInputMixer->Release();
  33. }
  34. }
  35. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  36. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  37. HRESULT CIPConfAudioCaptureTerminal::CreateTerminal(
  38. IN AudioDeviceInfo *pAudioDevieInfo,
  39. IN MSP_HANDLE htAddress,
  40. OUT ITTerminal **ppTerm
  41. )
  42. /*++
  43. Routine Description:
  44. This method creates a terminal object base on the device info.
  45. Arguments:
  46. pAudioDevieInfo - a pointer to an AudioDevieInfo data structure.
  47. htAddress - the handle to the address object.
  48. ppTerm - memory to store the returned terminal pointer.
  49. Return Value:
  50. S_OK
  51. E_POINTER
  52. --*/
  53. {
  54. ENTER_FUNCTION("CIPConfAudioCaptureTerminal::CreateTerminal");
  55. LOG((MSP_TRACE, "%s, htAddress:%x", __fxName, htAddress));
  56. _ASSERT(!IsBadWritePtr(ppTerm, sizeof(ITTerminal *)));
  57. HRESULT hr;
  58. //
  59. // Create the terminal.
  60. //
  61. CMSPComObject<CIPConfAudioCaptureTerminal> *pTerminal = NULL;
  62. hr = ::CreateCComObjectInstance(&pTerminal);
  63. if (FAILED(hr))
  64. {
  65. LOG((MSP_ERROR,
  66. "%s can't create the terminal object hr = %8x", __fxName, hr));
  67. return hr;
  68. }
  69. // query for the ITTerminal interface
  70. ITTerminal *pITTerminal;
  71. hr = pTerminal->_InternalQueryInterface(__uuidof(ITTerminal), (void**)&pITTerminal);
  72. if (FAILED(hr))
  73. {
  74. LOG((MSP_ERROR,
  75. "%s, query terminal interface failed, %x", __fxName, hr));
  76. delete pTerminal;
  77. return hr;
  78. }
  79. // initialize the terminal
  80. hr = pTerminal->Initialize(
  81. pAudioDevieInfo,
  82. htAddress
  83. );
  84. if ( FAILED(hr) )
  85. {
  86. LOG((MSP_ERROR,
  87. "%s, Initialize failed; returning 0x%08x", __fxName, hr));
  88. pITTerminal->Release();
  89. return hr;
  90. }
  91. LOG((MSP_TRACE, "%s, Terminal %p(%ws) created",
  92. __fxName, pITTerminal, pAudioDevieInfo->szDeviceDescription));
  93. *ppTerm = pITTerminal;
  94. return S_OK;
  95. }
  96. HRESULT CIPConfAudioCaptureTerminal::Initialize(
  97. IN AudioDeviceInfo *pAudioDevieInfo,
  98. IN MSP_HANDLE htAddress
  99. )
  100. {
  101. m_DSoundGuid = pAudioDevieInfo->DSoundGUID;
  102. m_WaveID = pAudioDevieInfo->WaveID;
  103. return CIPConfBaseTerminal::Initialize(
  104. pAudioDevieInfo->szDeviceDescription, htAddress
  105. );
  106. }
  107. HRESULT CIPConfAudioCaptureTerminal::CreateFilter(void)
  108. /*++
  109. Routine Description:
  110. This method creates the filter in this terminal. It creates the tapi audio
  111. capture filter and configures the device it uses.
  112. Arguments:
  113. nothing.
  114. Return Value:
  115. S_OK
  116. --*/
  117. {
  118. ENTER_FUNCTION("CIPConfAudioCaptureTerminal::CreateFilter");
  119. LOG((MSP_TRACE, "%s, entered", __fxName));
  120. // This should only be called atmost once in the lifetime of this instance
  121. _ASSERT(m_pFilter == NULL);
  122. _ASSERT(m_pIAMAudioInputMixer == NULL);
  123. IBaseFilter *pICaptureFilter;
  124. // Create the filter.
  125. HRESULT hr = CoCreateInstance(
  126. __uuidof(TAPIAudioCapture),
  127. NULL,
  128. CLSCTX_INPROC_SERVER | CLSCTX_NO_CODE_DOWNLOAD,
  129. __uuidof(IBaseFilter),
  130. (void **)&pICaptureFilter
  131. );
  132. if (FAILED(hr))
  133. {
  134. LOG((MSP_ERROR,
  135. "%s, CoCreate filter failed, %x", __fxName, hr));
  136. return hr;
  137. }
  138. // get the config interface.
  139. IAudioDeviceConfig *pIAudioDeviceConfig;
  140. hr = pICaptureFilter->QueryInterface(
  141. __uuidof(IAudioDeviceConfig),
  142. (void **)&pIAudioDeviceConfig
  143. );
  144. if (FAILED(hr))
  145. {
  146. pICaptureFilter->Release();
  147. LOG((MSP_ERROR,
  148. "%s, can't get the IAudioDeviceConfig interface, %x",
  149. __fxName, hr));
  150. return hr;
  151. }
  152. // tell the filter the device IDs.
  153. hr = pIAudioDeviceConfig->SetDeviceID(m_DSoundGuid, m_WaveID);
  154. pIAudioDeviceConfig->Release();
  155. if (FAILED(hr))
  156. {
  157. pICaptureFilter->Release();
  158. LOG((MSP_ERROR,
  159. "%s, set device ID failed, %x", __fxName, hr));
  160. return hr;
  161. }
  162. // remember the filter, keep the refcount as well.
  163. m_pFilter = pICaptureFilter;
  164. // Get the basic audio (mixer) interface for the filter.
  165. IAMAudioInputMixer *pIAMAudioInputMixer;
  166. hr = m_pFilter->QueryInterface(
  167. __uuidof(IAMAudioInputMixer),
  168. (void **) &pIAMAudioInputMixer
  169. );
  170. if (FAILED(hr))
  171. {
  172. // The filter doesn't support the mixer interface. This is not catastrophic;
  173. // all it means is that subsequent mixer operations on the terminal will fail.
  174. LOG((MSP_WARN, "%s, mixer QI failed %x", __fxName, hr));
  175. m_pIAMAudioInputMixer = NULL;
  176. }
  177. else
  178. {
  179. m_pIAMAudioInputMixer = pIAMAudioInputMixer;
  180. }
  181. LOG((MSP_TRACE, "%s succeeded", __fxName));
  182. return S_OK;
  183. }
  184. HRESULT CIPConfAudioCaptureTerminal::GetExposedPins(
  185. IN IPin ** ppPins,
  186. IN DWORD dwNumPins
  187. )
  188. /*++
  189. Routine Description:
  190. This method returns the output pins of the audio capture filter.
  191. Arguments:
  192. ppPins - memory buffer to store the returned pins.
  193. dwNumPins - the number pins asked.
  194. Return Value:
  195. S_OK
  196. --*/
  197. {
  198. ENTER_FUNCTION("CIPConfAudioRenderTerminal::GetExposedPins");
  199. LOG((MSP_TRACE, "%s entered, dwNumPins:%d", __fxName, dwNumPins));
  200. _ASSERT(m_pFilter != NULL);
  201. _ASSERT(dwNumPins != 0);
  202. _ASSERT(!IsBadWritePtr(ppPins, sizeof (IPin*) * dwNumPins));
  203. // Get the enumerator of pins on the filter.
  204. IEnumPins * pIEnumPins;
  205. HRESULT hr = m_pFilter->EnumPins(&pIEnumPins);
  206. if (FAILED(hr))
  207. {
  208. LOG((MSP_ERROR,
  209. "%s enumerate pins on the filter failed. hr=%x", __fxName, hr));
  210. return hr;
  211. }
  212. // TODO: get only the outptu pins.
  213. // get the pins.
  214. DWORD dwFetched;
  215. hr = pIEnumPins->Next(dwNumPins, ppPins, &dwFetched);
  216. pIEnumPins->Release();
  217. if (FAILED(hr))
  218. {
  219. LOG((MSP_ERROR,
  220. "%s IEnumPins->Next failed. hr=%x", __fxName, hr));
  221. return hr;
  222. }
  223. _ASSERT(dwFetched == dwNumPins);
  224. return S_OK;
  225. }
  226. STDMETHODIMP
  227. CIPConfAudioCaptureTerminal::DisconnectTerminal(
  228. IN IGraphBuilder * pGraph,
  229. IN DWORD dwReserved
  230. )
  231. /*++
  232. Routine Description:
  233. This function is called by the MSP while trying to disconnect the filter in
  234. the terminal from the rest of the graph in the MSP. It adds the removes the
  235. filter from the graph and set the terminal free.
  236. Arguments:
  237. pGraph - The filter graph. It is used for validation, to make sure the
  238. terminal is disconnected from the same graph that it was
  239. originally connected to.
  240. dwReserved - A reserved dword.
  241. Return Value:
  242. S_OK
  243. E_INVALIDARG - wrong graph.
  244. --*/
  245. {
  246. ENTER_FUNCTION("CIPConfBaseTerminal::DisconnectTerminal");
  247. LOG((MSP_TRACE,
  248. "%s entered, pGraph:%p, dwReserved:%d", __fxName, pGraph, dwReserved));
  249. Lock();
  250. HRESULT hr;
  251. hr = CIPConfBaseTerminal::DisconnectTerminal(pGraph, dwReserved);
  252. if (SUCCEEDED(hr))
  253. {
  254. if (m_pIAMAudioInputMixer)
  255. {
  256. m_pIAMAudioInputMixer->Release();
  257. m_pIAMAudioInputMixer = NULL;
  258. }
  259. }
  260. Unlock();
  261. return hr;
  262. }
  263. ///////////////////////////////////////////////////////////////////////////////
  264. //***************************************************************************//
  265. //* *//
  266. //* NOTE: The input filter does not support IBasicAudio so we need to masage*//
  267. //* the parameters for the basic audio methods so that the will work *//
  268. //* for IAMAudioInputMixer. *//
  269. //* *//
  270. //*****************************************************************************
  271. ///////////////////////////////////////////////////////////////////////////////
  272. STDMETHODIMP CIPConfAudioCaptureTerminal::get_Volume(long * plVolume)
  273. {
  274. ENTER_FUNCTION("CIPConfAudioCaptureTerminal::get_Volume");
  275. LOG((MSP_TRACE, "%s entered", __fxName));
  276. // Check parameters.
  277. if ( IsBadWritePtr(plVolume, sizeof(long)) )
  278. {
  279. LOG((MSP_ERROR, "%s bad pointer, plVolume:%p", __fxName, plVolume));
  280. return E_POINTER;
  281. }
  282. Lock();
  283. HRESULT hr;
  284. if (m_pFilter == NULL)
  285. {
  286. hr = CreateFilter();
  287. if ( FAILED(hr) )
  288. {
  289. Unlock();
  290. return hr;
  291. }
  292. }
  293. if (m_pIAMAudioInputMixer == NULL)
  294. {
  295. Unlock();
  296. return E_FAIL;
  297. }
  298. double dVolume;
  299. hr = m_pIAMAudioInputMixer->get_MixLevel(&dVolume);
  300. Unlock();
  301. if (FAILED(hr))
  302. {
  303. LOG((MSP_ERROR, "%s (get_MixLevel) failed, hr=%x", __fxName, hr));
  304. return hr;
  305. }
  306. //
  307. // Massage ranges to convert between disparate semantics.
  308. //
  309. _ASSERT(dVolume >= MIXER_MIN_VOLUME);
  310. _ASSERT(dVolume <= MIXER_MAX_VOLUME);
  311. // Convert the volume from whatever range of doubles the filter uses
  312. // to the range 0 - 1. Right now this does nothing but makes the code
  313. // more general.
  314. dVolume = ( dVolume - MIXER_MIN_VOLUME )
  315. / ( MIXER_MAX_VOLUME - MIXER_MIN_VOLUME );
  316. // Convert the volume from the range 0 - 1 to the API's range.
  317. *plVolume = MIN_VOLUME +
  318. (long) (( MAX_VOLUME - MIN_VOLUME ) * dVolume);
  319. LOG((MSP_TRACE, "%s exits S_OK", __fxName));
  320. return S_OK;
  321. }
  322. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  323. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  324. STDMETHODIMP CIPConfAudioCaptureTerminal::put_Volume(long lVolume)
  325. {
  326. ENTER_FUNCTION("CIPConfAudioCaptureTerminal::put_Volume");
  327. LOG((MSP_TRACE, "%s entered, lVolume:%d", __fxName, lVolume));
  328. // Our argument is a long in the range 0 - 0xFFFF. We need to convert it
  329. // to a double ranging from 0.0 to 1.0.
  330. if (lVolume < MIN_VOLUME)
  331. {
  332. LOG((MSP_ERROR,
  333. "%s volume %d < %d; returning E_INVALIDARG",
  334. __fxName, lVolume, MIN_VOLUME));
  335. return E_INVALIDARG;
  336. }
  337. if (lVolume > MAX_VOLUME)
  338. {
  339. LOG((MSP_ERROR,
  340. "%s volume %d > %d; returning E_INVALIDARG",
  341. __fxName, lVolume, MAX_VOLUME));
  342. return E_INVALIDARG;
  343. }
  344. Lock();
  345. HRESULT hr;
  346. if (m_pFilter == NULL)
  347. {
  348. hr = CreateFilter();
  349. if ( FAILED(hr) )
  350. {
  351. Unlock();
  352. return hr;
  353. }
  354. }
  355. if (m_pIAMAudioInputMixer == NULL)
  356. {
  357. Unlock();
  358. return E_FAIL;
  359. }
  360. // Convert to the range 0 to 1.
  361. double dVolume =
  362. ( (double) ( lVolume - MIN_VOLUME ) )
  363. / ( (double) ( MAX_VOLUME - MIN_VOLUME ) );
  364. // Convert the volume to whatever range of doubles the filter uses
  365. // from the range 0 - 1. Right now this does nothing but makes the code
  366. // more general.
  367. dVolume = MIXER_MIN_VOLUME +
  368. ( MIXER_MAX_VOLUME - MIXER_MIN_VOLUME ) * dVolume;
  369. hr = m_pIAMAudioInputMixer->put_MixLevel(dVolume);
  370. Unlock();
  371. LOG((MSP_TRACE, "%s exits. hr=%x", __fxName, hr));
  372. return hr;
  373. }
  374. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  375. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  376. STDMETHODIMP CIPConfAudioCaptureTerminal::get_Balance(long * plBalance)
  377. {
  378. ENTER_FUNCTION("CIPConfAudioCaptureTerminal::get_Balance");
  379. LOG((MSP_TRACE, "%s entered, plBalance:%p", __fxName, plBalance));
  380. if ( IsBadWritePtr(plBalance, sizeof(long) ) )
  381. {
  382. LOG((MSP_ERROR, "%s, bad pointer", __fxName));
  383. return E_POINTER;
  384. }
  385. Lock();
  386. HRESULT hr;
  387. if (m_pFilter == NULL)
  388. {
  389. hr = CreateFilter();
  390. if ( FAILED(hr) )
  391. {
  392. Unlock();
  393. return hr;
  394. }
  395. }
  396. if (m_pIAMAudioInputMixer == NULL)
  397. {
  398. Unlock();
  399. return E_FAIL;
  400. }
  401. double dBalance;
  402. hr = m_pIAMAudioInputMixer->get_Pan(&dBalance);
  403. Unlock();
  404. if (FAILED(hr))
  405. {
  406. LOG((MSP_ERROR, "%s (get_Pan) failed, hr=%x", __fxName, hr));
  407. return hr;
  408. }
  409. *plBalance = (LONG) (dBalance * MAX_LONG);
  410. LOG((MSP_TRACE, "%s exits S_OK", __fxName));
  411. return hr;
  412. }
  413. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  414. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  415. STDMETHODIMP CIPConfAudioCaptureTerminal::put_Balance(long lBalance)
  416. {
  417. ENTER_FUNCTION("CIPConfAudioCaptureTerminal::put_Balance");
  418. LOG((MSP_TRACE, "%s entered, lBalance:%d", __fxName, lBalance));
  419. Lock();
  420. HRESULT hr;
  421. if (m_pFilter == NULL)
  422. {
  423. hr = CreateFilter();
  424. if ( FAILED(hr) )
  425. {
  426. Unlock();
  427. return hr;
  428. }
  429. }
  430. if (m_pIAMAudioInputMixer == NULL)
  431. {
  432. Unlock();
  433. return E_FAIL;
  434. }
  435. hr = m_pIAMAudioInputMixer->put_Pan(lBalance / MAX_LONG);
  436. Unlock();
  437. LOG((MSP_TRACE, "%s exits. hr=%x", __fxName, hr));
  438. return hr;
  439. }
  440. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  441. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  442. STDMETHODIMP CIPConfAudioCaptureTerminal::get_WaveId(
  443. OUT long * plWaveId
  444. )
  445. {
  446. ENTER_FUNCTION("CIPConfAudioCaptureTerminal::get_WaveId");
  447. LOG((MSP_TRACE, "%s, plWaveId:%p", __fxName, plWaveId));
  448. if ( IsBadWritePtr(plWaveId, sizeof(long)) )
  449. {
  450. LOG((MSP_ERROR, "%s, bad pointer argument", __fxName));
  451. return E_POINTER;
  452. }
  453. *plWaveId = (LONG)m_WaveID;
  454. LOG((MSP_TRACE, "%s, returning wave id:%d", __fxName, m_WaveID));
  455. return S_OK;
  456. }
  457. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  458. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  459. // Audio Render Terminal
  460. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  461. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  462. CIPConfAudioRenderTerminal::CIPConfAudioRenderTerminal()
  463. : m_WaveID(0),
  464. m_DSoundGuid(GUID_NULL),
  465. m_pIBasicAudio(NULL)
  466. {
  467. LOG((MSP_TRACE, "CIPConfAudioRenderTerminal::CIPConfAudioRenderTerminal"));
  468. m_TerminalClassID = CLSID_SpeakersTerminal;
  469. m_TerminalDirection = TD_RENDER;
  470. m_TerminalType = TT_STATIC;
  471. m_TerminalState = TS_NOTINUSE;
  472. m_dwMediaType = TAPIMEDIATYPE_AUDIO;
  473. }
  474. CIPConfAudioRenderTerminal::~CIPConfAudioRenderTerminal()
  475. {
  476. LOG((MSP_TRACE, "CIPConfAudioRenderTerminal::~CIPConfAudioRenderTerminal"));
  477. if (m_pIBasicAudio)
  478. {
  479. m_pIBasicAudio->Release();
  480. }
  481. }
  482. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  483. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  484. HRESULT CIPConfAudioRenderTerminal::CreateTerminal(
  485. IN AudioDeviceInfo *pAudioDevieInfo,
  486. IN MSP_HANDLE htAddress,
  487. OUT ITTerminal **ppTerm
  488. )
  489. /*++
  490. Routine Description:
  491. This method creates a terminal object base on the info in the moniker.
  492. Arguments:
  493. pAudioDevieInfo - a pointer to an AudioDevieInfo data structure.
  494. htAddress - the handle to the address object.
  495. ppTerm - memory to store the returned terminal pointer.
  496. Return Value:
  497. S_OK
  498. E_POINTER
  499. --*/
  500. {
  501. ENTER_FUNCTION("CIPConfAudioRenderTerminal::CreateTerminal");
  502. LOG((MSP_TRACE, "%s, htAddress:%x", __fxName, htAddress));
  503. _ASSERT(!IsBadWritePtr(ppTerm, sizeof(ITTerminal *)));
  504. HRESULT hr;
  505. //
  506. // Create the filter.
  507. //
  508. CMSPComObject<CIPConfAudioRenderTerminal> *pTerminal = NULL;
  509. hr = ::CreateCComObjectInstance(&pTerminal);
  510. if (FAILED(hr))
  511. {
  512. LOG((MSP_ERROR,
  513. "%s can't create the terminal object hr = %8x", __fxName, hr));
  514. return hr;
  515. }
  516. // query for the ITTerminal interface
  517. ITTerminal *pITTerminal;
  518. hr = pTerminal->_InternalQueryInterface(__uuidof(ITTerminal), (void**)&pITTerminal);
  519. if (FAILED(hr))
  520. {
  521. LOG((MSP_ERROR,
  522. "%s, query terminal interface failed, %x", __fxName, hr));
  523. delete pTerminal;
  524. return hr;
  525. }
  526. // initialize the terminal
  527. hr = pTerminal->Initialize(
  528. pAudioDevieInfo,
  529. htAddress
  530. );
  531. if ( FAILED(hr) )
  532. {
  533. LOG((MSP_ERROR,
  534. "%s, Initialize failed; returning 0x%08x", __fxName, hr));
  535. pITTerminal->Release();
  536. return hr;
  537. }
  538. LOG((MSP_TRACE, "%s, Terminal %p(%ws) created",
  539. __fxName, pITTerminal, pAudioDevieInfo->szDeviceDescription));
  540. *ppTerm = pITTerminal;
  541. return S_OK;
  542. }
  543. HRESULT CIPConfAudioRenderTerminal::Initialize(
  544. IN AudioDeviceInfo *pAudioDevieInfo,
  545. IN MSP_HANDLE htAddress
  546. )
  547. {
  548. m_DSoundGuid = pAudioDevieInfo->DSoundGUID;
  549. m_WaveID = pAudioDevieInfo->WaveID;
  550. return CIPConfBaseTerminal::Initialize(
  551. pAudioDevieInfo->szDeviceDescription, htAddress
  552. );
  553. }
  554. HRESULT CIPConfAudioRenderTerminal::CreateFilter(void)
  555. /*++
  556. Routine Description:
  557. This method creates the filter in this terminal. It creates the tapi audio
  558. render filter and configures the device it uses.
  559. Arguments:
  560. nothing.
  561. Return Value:
  562. S_OK
  563. E_POINTER
  564. --*/
  565. {
  566. ENTER_FUNCTION("CIPConfAudioRenderTerminal::CreateFilters");
  567. LOG((MSP_TRACE, "%s, entered", __fxName));
  568. // This should only be called atmost once in the lifetime of this instance
  569. _ASSERT(m_pFilter == NULL);
  570. IBaseFilter *pICaptureFilter;
  571. // Create the filter.
  572. HRESULT hr = CoCreateInstance(
  573. __uuidof(TAPIAudioRender),
  574. NULL,
  575. CLSCTX_INPROC_SERVER | CLSCTX_NO_CODE_DOWNLOAD,
  576. __uuidof(IBaseFilter),
  577. (void **)&pICaptureFilter
  578. );
  579. if (FAILED(hr))
  580. {
  581. LOG((MSP_ERROR,
  582. "%s, CoCreate filter failed, %x", __fxName, hr));
  583. return hr;
  584. }
  585. // get the config interface.
  586. IAudioDeviceConfig *pIAudioDeviceConfig;
  587. hr = pICaptureFilter->QueryInterface(
  588. __uuidof(IAudioDeviceConfig),
  589. (void **)&pIAudioDeviceConfig
  590. );
  591. if (FAILED(hr))
  592. {
  593. pICaptureFilter->Release();
  594. LOG((MSP_ERROR,
  595. "%s, can't get the IAudioDeviceConfig interface, %x",
  596. __fxName, hr));
  597. return hr;
  598. }
  599. // tell the filter the device IDs.
  600. hr = pIAudioDeviceConfig->SetDeviceID(m_DSoundGuid, m_WaveID);
  601. pIAudioDeviceConfig->Release();
  602. if (FAILED(hr))
  603. {
  604. pICaptureFilter->Release();
  605. LOG((MSP_ERROR,
  606. "%s, set device ID failed, %x", __fxName, hr));
  607. return hr;
  608. }
  609. // remember the filter, keep the refcount as well.
  610. m_pFilter = pICaptureFilter;
  611. // Get the basic audio interface for the filter.
  612. IBasicAudio *pIBasicAudio;
  613. hr = m_pFilter->QueryInterface(
  614. __uuidof(IBasicAudio),
  615. (void **) &pIBasicAudio
  616. );
  617. if (FAILED(hr))
  618. {
  619. LOG((MSP_ERROR, "%s, IBasicAudio QI failed 0x%08x", __fxName, hr));
  620. m_pIBasicAudio = NULL;
  621. }
  622. else
  623. {
  624. m_pIBasicAudio = pIBasicAudio;
  625. }
  626. LOG((MSP_TRACE, "%s succeeded", __fxName));
  627. return S_OK;
  628. }
  629. HRESULT CIPConfAudioRenderTerminal::GetExposedPins(
  630. IN IPin ** ppPins,
  631. IN DWORD dwNumPins
  632. )
  633. /*++
  634. Routine Description:
  635. This method returns the input pins of the audio render filter.
  636. Arguments:
  637. ppPins - memory buffer to store the returned pins.
  638. dwNumPins - the number pins asked.
  639. Return Value:
  640. S_OK
  641. --*/
  642. {
  643. ENTER_FUNCTION("CIPConfAudioRenderTerminal::GetExposedPins");
  644. LOG((MSP_TRACE, "%s entered, dwNumPins:%d", __fxName, dwNumPins));
  645. _ASSERT(m_pFilter != NULL);
  646. _ASSERT(dwNumPins != 0);
  647. _ASSERT(!IsBadWritePtr(ppPins, sizeof (IPin*) * dwNumPins));
  648. // Get the enumerator of pins on the filter.
  649. IEnumPins * pIEnumPins;
  650. HRESULT hr = m_pFilter->EnumPins(&pIEnumPins);
  651. if (FAILED(hr))
  652. {
  653. LOG((MSP_ERROR,
  654. "%s enumerate pins on the filter failed. hr=%x", __fxName, hr));
  655. return hr;
  656. }
  657. // get the pins.
  658. DWORD dwFetched;
  659. hr = pIEnumPins->Next(dwNumPins, ppPins, &dwFetched);
  660. pIEnumPins->Release();
  661. if (FAILED(hr))
  662. {
  663. LOG((MSP_ERROR,
  664. "%s IEnumPins->Next failed. hr=%x", __fxName, hr));
  665. return hr;
  666. }
  667. _ASSERT(dwFetched == dwNumPins);
  668. return S_OK;
  669. }
  670. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  671. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  672. // TODO: Fix the range
  673. STDMETHODIMP CIPConfAudioRenderTerminal::get_Volume(long * plVolume)
  674. {
  675. ENTER_FUNCTION("CIPConfAudioRenderTerminal::get_Volume");
  676. LOG((MSP_TRACE, "%s entered", __fxName));
  677. if ( IsBadWritePtr(plVolume, sizeof(long)) )
  678. {
  679. LOG((MSP_ERROR, "%s bad pointer, plVolume:%p", __fxName, plVolume));
  680. return E_POINTER;
  681. }
  682. Lock();
  683. HRESULT hr;
  684. if (m_pFilter == NULL)
  685. {
  686. hr = CreateFilter();
  687. if ( FAILED(hr) )
  688. {
  689. Unlock();
  690. return hr;
  691. }
  692. }
  693. if (m_pIBasicAudio == NULL)
  694. {
  695. Unlock();
  696. return E_FAIL;
  697. }
  698. hr = m_pIBasicAudio->get_Volume(plVolume);
  699. Unlock();
  700. if (FAILED(hr))
  701. {
  702. LOG((MSP_ERROR, "%s (get_Volume) failed, hr=%x", __fxName, hr));
  703. return hr;
  704. }
  705. LOG((MSP_TRACE, "%s exits S_OK", __fxName));
  706. return S_OK;
  707. }
  708. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  709. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  710. STDMETHODIMP CIPConfAudioRenderTerminal::put_Volume(long lVolume)
  711. {
  712. ENTER_FUNCTION("CIPConfAudioRenderTerminal::put_Volume");
  713. LOG((MSP_TRACE, "%s entered, lVolume:%d", __fxName, lVolume));
  714. // Our argument is a long in the range 0 - 0xFFFF. We need to convert it
  715. // to a double ranging from 0.0 to 1.0.
  716. if (lVolume < MIN_VOLUME)
  717. {
  718. LOG((MSP_ERROR,
  719. "%s volume %d < %d; returning E_INVALIDARG",
  720. __fxName, lVolume, MIN_VOLUME));
  721. return E_INVALIDARG;
  722. }
  723. if (lVolume > MAX_VOLUME)
  724. {
  725. LOG((MSP_ERROR,
  726. "%s volume %d > %d; returning E_INVALIDARG",
  727. __fxName, lVolume, MAX_VOLUME));
  728. return E_INVALIDARG;
  729. }
  730. Lock();
  731. HRESULT hr;
  732. if (m_pFilter == NULL)
  733. {
  734. hr = CreateFilter();
  735. if ( FAILED(hr) )
  736. {
  737. Unlock();
  738. return hr;
  739. }
  740. }
  741. if (m_pIBasicAudio == NULL)
  742. {
  743. Unlock();
  744. return E_FAIL;
  745. }
  746. hr = m_pIBasicAudio->put_Volume(lVolume);
  747. Unlock();
  748. LOG((MSP_TRACE, "%s exits. hr=%x", __fxName, hr));
  749. return hr;
  750. }
  751. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  752. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  753. STDMETHODIMP CIPConfAudioRenderTerminal::get_Balance(long * plBalance)
  754. {
  755. ENTER_FUNCTION("CIPConfAudioRenderTerminal::get_Balance");
  756. LOG((MSP_TRACE, "%s entered, plBalance:%p", __fxName, plBalance));
  757. if ( IsBadWritePtr(plBalance, sizeof(long) ) )
  758. {
  759. LOG((MSP_ERROR, "%s, bad pointer", __fxName));
  760. return E_POINTER;
  761. }
  762. Lock();
  763. HRESULT hr;
  764. if (m_pFilter == NULL)
  765. {
  766. hr = CreateFilter();
  767. if ( FAILED(hr) )
  768. {
  769. Unlock();
  770. return hr;
  771. }
  772. }
  773. if (m_pIBasicAudio == NULL)
  774. {
  775. Unlock();
  776. return E_FAIL;
  777. }
  778. hr = m_pIBasicAudio->get_Balance(plBalance);
  779. Unlock();
  780. if (FAILED(hr))
  781. {
  782. LOG((MSP_ERROR, "%s (get_Balance) failed, hr=%x", __fxName, hr));
  783. return hr;
  784. }
  785. LOG((MSP_TRACE, "%s exits S_OK", __fxName));
  786. return hr;
  787. }
  788. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  789. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  790. STDMETHODIMP CIPConfAudioRenderTerminal::put_Balance(long lBalance)
  791. {
  792. ENTER_FUNCTION("CIPConfAudioRenderTerminal::put_Balance");
  793. LOG((MSP_TRACE, "%s entered, lBalance:%d", __fxName, lBalance));
  794. Lock();
  795. HRESULT hr;
  796. if (m_pFilter == NULL)
  797. {
  798. hr = CreateFilter();
  799. if ( FAILED(hr) )
  800. {
  801. Unlock();
  802. return hr;
  803. }
  804. }
  805. if (m_pIBasicAudio == NULL)
  806. {
  807. Unlock();
  808. return E_FAIL;
  809. }
  810. hr = m_pIBasicAudio->put_Balance(lBalance);
  811. Unlock();
  812. LOG((MSP_TRACE, "%s exits. hr=%x", __fxName, hr));
  813. return hr;
  814. }
  815. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  816. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  817. STDMETHODIMP CIPConfAudioRenderTerminal::get_WaveId(
  818. OUT long * plWaveId
  819. )
  820. {
  821. ENTER_FUNCTION("CIPConfAudioRenderTerminal::get_WaveId");
  822. LOG((MSP_TRACE, "%s, plWaveId:%p", __fxName, plWaveId));
  823. if ( IsBadWritePtr(plWaveId, sizeof(long)) )
  824. {
  825. LOG((MSP_ERROR, "%s, bad pointer argument", __fxName));
  826. return E_POINTER;
  827. }
  828. *plWaveId = (LONG)m_WaveID;
  829. LOG((MSP_TRACE, "%s, returning wave id:%d", __fxName, m_WaveID));
  830. return S_OK;
  831. }
  832. STDMETHODIMP
  833. CIPConfAudioRenderTerminal::DisconnectTerminal(
  834. IN IGraphBuilder * pGraph,
  835. IN DWORD dwReserved
  836. )
  837. /*++
  838. Routine Description:
  839. This function is called by the MSP while trying to disconnect the filter in
  840. the terminal from the rest of the graph in the MSP. It adds the removes the
  841. filter from the graph and set the terminal free.
  842. Arguments:
  843. pGraph - The filter graph. It is used for validation, to make sure the
  844. terminal is disconnected from the same graph that it was
  845. originally connected to.
  846. dwReserved - A reserved dword.
  847. Return Value:
  848. S_OK
  849. E_INVALIDARG - wrong graph.
  850. --*/
  851. {
  852. ENTER_FUNCTION("CIPConfBaseTerminal::DisconnectTerminal");
  853. LOG((MSP_TRACE,
  854. "%s entered, pGraph:%p, dwReserved:%d", __fxName, pGraph, dwReserved));
  855. Lock();
  856. HRESULT hr;
  857. hr = CIPConfBaseTerminal::DisconnectTerminal(pGraph, dwReserved);
  858. if (SUCCEEDED(hr))
  859. {
  860. if (m_pIBasicAudio)
  861. {
  862. m_pIBasicAudio->Release();
  863. m_pIBasicAudio = NULL;
  864. }
  865. }
  866. Unlock();
  867. return hr;
  868. }