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.

831 lines
24 KiB

  1. /*++
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. Module Name:
  4. msptrmac.cpp
  5. Abstract:
  6. MSP base classes: implementation of audio capture terminal.
  7. --*/
  8. #include "precomp.h"
  9. #pragma hdrstop
  10. #define MAX_LONG 0xefffffff
  11. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  12. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  13. CAudioCaptureTerminal::CAudioCaptureTerminal()
  14. {
  15. m_TerminalDirection = TD_CAPTURE;
  16. m_TerminalType = TT_STATIC;
  17. m_bResourceReserved = false;
  18. LOG((MSP_TRACE, "CAudioCaptureTerminal::CAudioCaptureTerminal() finished"));
  19. }
  20. CAudioCaptureTerminal::~CAudioCaptureTerminal()
  21. {
  22. LOG((MSP_TRACE, "CAudioCaptureTerminal::~CAudioCaptureTerminal() finished"));
  23. }
  24. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  25. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  26. HRESULT CAudioCaptureTerminal::CreateTerminal(
  27. IN CComPtr<IMoniker> pMoniker,
  28. IN MSP_HANDLE htAddress,
  29. OUT ITTerminal **ppTerm
  30. )
  31. {
  32. // Enable ATL string conversion macros.
  33. USES_CONVERSION;
  34. LOG((MSP_TRACE, "CAudioCaptureTerminal::CreateTerminal : enter"));
  35. //
  36. // Validate the parameters
  37. //
  38. if ( MSPB_IsBadWritePtr(ppTerm, sizeof(ITTerminal *) ) )
  39. {
  40. LOG((MSP_ERROR, "CAudioCaptureTerminal::CreateTerminal : "
  41. "bad terminal pointer; returning E_POINTER"));
  42. return E_POINTER;
  43. }
  44. if ( IsBadReadPtr(pMoniker, sizeof(IMoniker) ) )
  45. {
  46. LOG((MSP_ERROR, "CAudioCaptureTerminal::CreateTerminal : "
  47. "bad moniker pointer; returning E_POINTER"));
  48. return E_POINTER;
  49. }
  50. //
  51. // We return a NULL terminal if there is an error.
  52. //
  53. *ppTerm = NULL;
  54. HRESULT hr;
  55. //
  56. // Bind the moniker to storage as a property bag.
  57. //
  58. CComPtr<IPropertyBag> pBag;
  59. hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
  60. if (FAILED(hr))
  61. {
  62. LOG((MSP_ERROR, "CAudioCaptureTerminal::CreateTerminal (IMoniker::BindToStorage) - returning %8x", hr));
  63. return hr;
  64. }
  65. VARIANT var;
  66. //
  67. // Get the wave ID from the property bag.
  68. // Skip this terminal if it doesn't have a wave ID.
  69. // (Needed because WDM devices don't work, and we don't want more than one
  70. // terminal per device.)
  71. //
  72. var.vt = VT_I4;
  73. hr = pBag->Read(L"WaveInId", &var, 0);
  74. if (FAILED(hr))
  75. {
  76. LOG((MSP_INFO, "CAudioCaptureTerminal::CreateTerminal - "
  77. "IPropertyBag::Read failed on WaveID - "
  78. "skipping terminal (not cause for alarm) - "
  79. "returning 0x%08x", hr));
  80. return hr;
  81. }
  82. //
  83. // Get the name for this filter out of the property bag.
  84. // Skip this terminal if it doesn't have a name.
  85. //
  86. var.vt = VT_BSTR;
  87. hr = pBag->Read(L"FriendlyName", &var, 0);
  88. if (FAILED(hr))
  89. {
  90. LOG((MSP_INFO, "CAudioCaptureTerminal::CreateTerminal - "
  91. "IPropertyBag::Read failed on FriendlyName - "
  92. "skipping terminal (not cause for alarm) - "
  93. "returning 0x%08x", hr));
  94. return hr;
  95. }
  96. //
  97. // Create the filter.
  98. //
  99. CMSPComObject<CAudioCaptureTerminal> *pLclTerm = new CMSPComObject<CAudioCaptureTerminal>;
  100. if (pLclTerm == NULL)
  101. {
  102. LOG((MSP_ERROR, "CAudioCaptureTerminal::CreateTerminal - returning E_OUTOFMEMORY"));
  103. return E_OUTOFMEMORY;
  104. }
  105. //
  106. // Save some stuff in the terminal.
  107. //
  108. pLclTerm->m_pMoniker = pMoniker;
  109. lstrcpyn(pLclTerm->m_szName, OLE2T(var.bstrVal), MAX_PATH);
  110. SysFreeString(var.bstrVal);
  111. //
  112. // Get the ITTerminal interface that we were asked for.
  113. //
  114. hr = pLclTerm->_InternalQueryInterface(IID_ITTerminal, (void**)ppTerm);
  115. if ( FAILED(hr) )
  116. {
  117. LOG((MSP_ERROR, "CAudioCaptureTerminal::CreateTerminal - "
  118. "Internal QI failed; returning 0x%08x", hr));
  119. delete pLclTerm;
  120. *ppTerm = NULL; // just in case
  121. return hr;
  122. }
  123. //
  124. // Finish initializing the terminal.
  125. //
  126. hr = pLclTerm->Initialize(CLSID_MicrophoneTerminal,
  127. TAPIMEDIATYPE_AUDIO,
  128. TD_CAPTURE,
  129. htAddress
  130. );
  131. if ( FAILED(hr) )
  132. {
  133. LOG((MSP_ERROR, "CAudioCaptureTerminal::CreateTerminal - "
  134. "Initialize failed; returning 0x%08x", hr));
  135. (*ppTerm)->Release();
  136. *ppTerm = NULL;
  137. return hr;
  138. }
  139. LOG((MSP_TRACE, "CAudioCaptureTerminal::CreateTerminal - exit S_OK"));
  140. return S_OK;
  141. }
  142. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  143. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  144. // Create the filters used by this terminal
  145. HRESULT CAudioCaptureTerminal::CreateFilters(void)
  146. {
  147. LOG((MSP_TRACE, "CAudioCaptureTerminal::CreateFilters() called"));
  148. //
  149. // This should only be called atmost once in the lifetime of this instance
  150. //
  151. if ( (m_pIFilter != NULL) ||
  152. (m_pIPin != NULL) ||
  153. (m_pIAMAudioInputMixer != NULL) )
  154. {
  155. LOG((MSP_ERROR, "CAudioCaptureTerminal::CreateFilters() : we've already been called; returning E_FAIL"));
  156. return E_FAIL;
  157. }
  158. //
  159. // Create the filter.
  160. //
  161. HRESULT hr = m_pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void**)&m_pIFilter);
  162. if ( FAILED(hr) || (m_pIFilter == NULL) )
  163. {
  164. LOG((MSP_ERROR, "CAudioCaptureTerminal::CreateFilters() : BindToObject failed 0x%08x", hr));
  165. m_pIFilter = NULL; // we are being extra careful...
  166. return hr;
  167. }
  168. //
  169. // Get the basic audio (mixer) interface for the filter.
  170. //
  171. hr = m_pIFilter->QueryInterface(IID_IAMAudioInputMixer,
  172. (void **) &m_pIAMAudioInputMixer);
  173. if ( FAILED(hr) || (m_pIAMAudioInputMixer == NULL) )
  174. {
  175. //
  176. // The filter doesn't support the mixer interface. This is not catastrophic;
  177. // all it means is that subsequent mixer operations on the terminal will fail.
  178. //
  179. LOG((MSP_WARN, "CAudioCaptureTerminal::CreateFilters() : mixer QI failed 0x%08x", hr));
  180. m_pIAMAudioInputMixer = NULL;
  181. }
  182. //
  183. // Find the output pin (this is a private method on the terminal).
  184. //
  185. hr = FindTerminalPin();
  186. if ( FAILED(hr) || (m_pIPin == NULL) )
  187. {
  188. LOG((MSP_ERROR, "CAudioCaptureTerminal::CreateFilters() : FindTerminalPin failed 0x%08x", hr));
  189. //
  190. // Clean up our mess.
  191. //
  192. if (m_pIAMAudioInputMixer != NULL)
  193. {
  194. m_pIAMAudioInputMixer = NULL; // implicit release
  195. }
  196. m_pIFilter = NULL; // implicit release
  197. return hr;
  198. }
  199. LOG((MSP_TRACE, "CAudioCaptureTerminal::CreateFilters() succeeded"));
  200. return S_OK;
  201. }
  202. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  203. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  204. HRESULT
  205. CAudioCaptureTerminal::FindTerminalPin(
  206. )
  207. {
  208. LOG((MSP_TRACE, "CAudioCaptureTerminal::FindTerminalPin - enter"));
  209. // We must not do CreateFiltersIfRequired here because that would
  210. // result in a recursive call to us again.
  211. if (m_pIPin != NULL)
  212. {
  213. LOG((MSP_ERROR, "CAudioCaptureTerminal::FindTerminalPin - "
  214. "we've alread got a pin; returning E_UNEXPECTED"));
  215. return E_UNEXPECTED;
  216. }
  217. HRESULT hr;
  218. CComPtr<IEnumPins> pIEnumPins;
  219. ULONG cFetched;
  220. //
  221. // Find the capture pin for the filter.
  222. //
  223. if (FAILED(hr = m_pIFilter->EnumPins(&pIEnumPins)))
  224. {
  225. LOG((MSP_ERROR,
  226. "CAudioCaptureTerminal::FindTerminalPin - can't enum pins %8x",
  227. hr));
  228. return hr;
  229. }
  230. IPin * pIPin;
  231. // Enumerate all the pins and break on the
  232. // first pin that meets requirement.
  233. for (;;)
  234. {
  235. if (pIEnumPins->Next(1, &pIPin, &cFetched) != S_OK)
  236. {
  237. LOG((MSP_ERROR,
  238. "CAudioCaptureTerminal::FindTerminalPin - can't get a pin %8x",
  239. hr));
  240. return (hr == S_FALSE) ? E_FAIL : hr;
  241. }
  242. if (0 == cFetched)
  243. {
  244. LOG((MSP_ERROR, "CAudioCaptureTerminal::FindTerminalPin - got zero pins"));
  245. return E_FAIL;
  246. }
  247. PIN_DIRECTION dir;
  248. if (FAILED(hr = pIPin->QueryDirection(&dir)))
  249. {
  250. LOG((MSP_ERROR,
  251. "CAudioCaptureTerminal::FindTerminalPin - can't query pin direction %8x",
  252. hr));
  253. pIPin->Release();
  254. return hr;
  255. }
  256. if (PINDIR_OUTPUT == dir)
  257. {
  258. break;
  259. }
  260. pIPin->Release();
  261. }
  262. m_pIPin = pIPin;
  263. LOG((MSP_TRACE, "CAudioCaptureTerminal::FindTerminalPin - exit S_OK"));
  264. return S_OK;
  265. }
  266. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  267. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  268. HRESULT CAudioCaptureTerminal::AddFiltersToGraph(
  269. )
  270. {
  271. LOG((MSP_TRACE, "CAudioCaptureTerminal::AddFiltersToGraph - enter"));
  272. if (m_pGraph == NULL)
  273. {
  274. LOG((MSP_ERROR, "CAudioCaptureTerminal::AddFiltersToGraph - "
  275. "we don't have a filter graph; returning E_UNEXPECTED"));
  276. return E_UNEXPECTED;
  277. }
  278. HRESULT hr = CreateFiltersIfRequired();
  279. if ( FAILED(hr) )
  280. {
  281. LOG((MSP_ERROR, "CAudioCaptureTerminal::AddFiltersToGraph - "
  282. "CreateFiltersIfRequired failed; returning hr = 0x%08x", hr));
  283. return hr;
  284. }
  285. if (m_pIFilter == NULL)
  286. {
  287. LOG((MSP_ERROR, "CAudioCaptureTerminal::AddFiltersToGraph - "
  288. "we don't have a filter; returning E_UNEXPECTED"));
  289. return E_UNEXPECTED;
  290. }
  291. //
  292. // Add the filter to the graph.
  293. //
  294. // A word about names:
  295. // If a filter has already been added with the same name (which will
  296. // happen if we have more than one audio capture terminal in the same
  297. // graph) then that will return VFW_S_DUPLICATE_NAME, which is not
  298. // a failure.
  299. //
  300. hr = m_pGraph->AddFilter(m_pIFilter, WAVEIN_NAME);
  301. if ( FAILED(hr) )
  302. {
  303. LOG((MSP_ERROR, "CAudioCaptureTerminal::AddFiltersToGraph - "
  304. "AddFilter failed; returning hr = 0x%08x", hr));
  305. return hr;
  306. }
  307. LOG((MSP_TRACE, "CAudioCaptureTerminal::AddFiltersToGraph - exit S_OK"));
  308. return S_OK;
  309. }
  310. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  311. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  312. HRESULT CAudioCaptureTerminal::CompleteConnectTerminal(void)
  313. {
  314. CLock lock(m_CritSec);
  315. LOG((MSP_TRACE, "CAudioCaptureTerminal::CompleteConnectTerminal - enter"));
  316. // By default, we need not unreserve later.
  317. m_bResourceReserved = false;
  318. HRESULT hr = CSingleFilterTerminal::CompleteConnectTerminal();
  319. if (FAILED(hr))
  320. {
  321. LOG((MSP_ERROR, "CAudioCaptureTerminal::CompleteConnectTerminal: "
  322. "CSingleFilterTerminal method failed"));
  323. return hr;
  324. }
  325. // So here we are, after our filter has been added to the filter graph and connected up, but before
  326. // the MSP has told it to run.
  327. //////////////////////////////////////////////////////////////////////////
  328. // connect-time device reservation:
  329. // we must inform the filter that we want it to grab the wave device.
  330. // We do this after connecting because the filter needs to negotiate the
  331. // media type before it can open a wave device.
  332. CComPtr <IAMResourceControl> pIResource;
  333. hr = m_pIFilter->QueryInterface(IID_IAMResourceControl, (void **) &pIResource);
  334. if (FAILED(hr))
  335. {
  336. LOG((MSP_WARN, "CAudioCaptureTerminal::CompleteConnectTerminal - QI failed: %8x", hr));
  337. // This is a nonesential operation so we do not "return hr;" here.
  338. }
  339. else // QueryInterface didn't fail
  340. {
  341. hr = pIResource->Reserve(AMRESCTL_RESERVEFLAGS_RESERVE, NULL);
  342. if (hr != S_OK)
  343. {
  344. LOG((MSP_ERROR, "CAudioCaptureTerminal::CompleteConnectTerminal - "
  345. "device reservation failed: %8x", hr));
  346. return hr;
  347. }
  348. // We have succeeded in reserving, so we will want to unreserve later.
  349. m_bResourceReserved = true;
  350. }
  351. LOG((MSP_TRACE, "CAudioCaptureTerminal::CompleteConnectTerminal - exit S_OK"));
  352. return S_OK;
  353. }
  354. //////////////////////////////////////////////////////////////////////////////////
  355. // We override this here so we can unreserve the resource when we are done.
  356. // removes filters from the filter graph and resets member variables
  357. // Disconnect may be called anytime after Connect succeeds (it need not be called
  358. // if CompleteConnect fails)
  359. STDMETHODIMP CAudioCaptureTerminal::DisconnectTerminal(
  360. IN IGraphBuilder * pGraph,
  361. IN DWORD dwReserved
  362. )
  363. {
  364. LOG((MSP_TRACE, "CAudioCaptureTerminal::DisconnectTerminal - enter"));
  365. HRESULT hr;
  366. //
  367. // First call the base class method, to make sure we validate everything
  368. // and don't mess with our resource reservation unless this is a valid
  369. // disconnection (e.g., the filter graph pointersmatch).
  370. //
  371. hr = CSingleFilterTerminal::DisconnectTerminal(pGraph, dwReserved);
  372. if (FAILED(hr))
  373. {
  374. LOG((MSP_TRACE, "CAudioCaptureTerminal::DisconnectTerminal : "
  375. "CSingleFilterTerminal method failed; hr = %d", hr));
  376. return hr;
  377. }
  378. // if we need to unreserve the resource now
  379. if (m_bResourceReserved)
  380. {
  381. CComPtr <IAMResourceControl> pIResource;
  382. hr = m_pIFilter->QueryInterface(IID_IAMResourceControl,
  383. (void **) &pIResource);
  384. if (FAILED(hr))
  385. {
  386. LOG((MSP_WARN, "CAudioCaptureTerminal::DisconnectTerminal - "
  387. "QI failed: %8x", hr));
  388. // This is a nonesential operation so we do not "return hr;" here.
  389. }
  390. else
  391. {
  392. // QueryInterface didn't fail, so UNRESERVE now
  393. hr = pIResource->Reserve(AMRESCTL_RESERVEFLAGS_UNRESERVE, NULL);
  394. if (hr != S_OK)
  395. {
  396. LOG((MSP_WARN, "CAudioCaptureTerminal::DisconnectTerminal - "
  397. "device unreservation failed: %8x", hr));
  398. // no reason to completely die at this point, so we just continue
  399. }
  400. // if other things fail we may be called again, but we should not try
  401. // to unreserve again.
  402. m_bResourceReserved = false;
  403. } // {if QI succeeded}
  404. } // {if we need to release}
  405. LOG((MSP_TRACE, "CAudioCaptureTerminal::DisconnectTerminal - exit S_OK"));
  406. return S_OK;
  407. }
  408. ///////////////////////////////////////////////////////////////////////////////
  409. //***************************************************************************//
  410. //* *//
  411. //* NOTE: The input filter does not support IBasicAudio so we need to masage*//
  412. //* the parameters for the basic audio methods so that the will work *//
  413. //* for IAMAudioInputMixer. *//
  414. //* *//
  415. //*****************************************************************************
  416. ///////////////////////////////////////////////////////////////////////////////
  417. static const long TMGR_MIN_API_VOLUME = 0; // our terminal semantics
  418. static const long TMGR_MAX_API_VOLUME = 0xFFFF;
  419. static const double TMGR_MIN_CAPTURE_VOLUME = 0.0; // capture filter semantics
  420. static const double TMGR_MAX_CAPTURE_VOLUME = 1.0;
  421. STDMETHODIMP CAudioCaptureTerminal::get_Volume(long * plVolume)
  422. {
  423. CLock lock(m_CritSec);
  424. LOG((MSP_TRACE, "CAudioCaptureTerminal::get_Volume - enter"));
  425. //
  426. // Check parameters.
  427. //
  428. if ( MSPB_IsBadWritePtr(plVolume, sizeof(long)) )
  429. {
  430. LOG((MSP_ERROR, "CAudioCaptureTerminal::get_Volume - "
  431. "invalid pointer passed in - returning E_POINTER"));
  432. return E_POINTER;
  433. }
  434. //
  435. // Create the filters if required. This protects us if the creation fails.
  436. //
  437. HRESULT hr = CreateFiltersIfRequired();
  438. if ( FAILED(hr) )
  439. {
  440. LOG((MSP_ERROR, "CAudioCaptureTerminal::get_Volume - "
  441. "CreateFiltersIfRequired failed; returning hr = 0x%08x", hr));
  442. return hr;
  443. }
  444. //
  445. // Check if CreateFiltersIfRequired was able to get us the mixer interface.
  446. // If not, we must fail.
  447. //
  448. if (m_pIAMAudioInputMixer == NULL)
  449. {
  450. LOG((MSP_ERROR, "CAudioCaptureTerminal::get_Volume - "
  451. "filter does not support mixer interface - returning E_FAIL"));
  452. return E_FAIL;
  453. }
  454. //
  455. // Perform the call on the filter.
  456. //
  457. double dVolume;
  458. hr = m_pIAMAudioInputMixer->get_MixLevel(&dVolume);
  459. if (FAILED(hr))
  460. {
  461. LOG((MSP_ERROR, "CAudioCaptureTerminal::get_Volume "
  462. "(get_MixLevel) - returning %8x", hr));
  463. return hr;
  464. }
  465. //
  466. // Massage ranges to convert between disparate semantics.
  467. //
  468. // Our argument is a pointer to a long in the range 0 - 0xFFFF.
  469. // We need to output that based on a double ranging from 0.0 to 1.0.
  470. if (dVolume < TMGR_MIN_CAPTURE_VOLUME)
  471. {
  472. LOG((MSP_ERROR, "CAudioCaptureTerminal::get_Volume - observed "
  473. "volume %d < %d; returning E_INVALIDARG",
  474. dVolume, TMGR_MIN_CAPTURE_VOLUME));
  475. return E_INVALIDARG;
  476. }
  477. if (dVolume > TMGR_MAX_CAPTURE_VOLUME)
  478. {
  479. LOG((MSP_ERROR, "CAudioCaptureTerminal::get_Volume - observed "
  480. "volume %d > %d; returning E_INVALIDARG",
  481. dVolume, TMGR_MAX_CAPTURE_VOLUME));
  482. return E_INVALIDARG;
  483. }
  484. // Convert the volume from whatever range of doubles the filter uses
  485. // to the range 0 - 1. Right now this does nothing but makes the code more general.
  486. dVolume = ( dVolume - TMGR_MIN_CAPTURE_VOLUME )
  487. / ( TMGR_MAX_CAPTURE_VOLUME - TMGR_MIN_CAPTURE_VOLUME );
  488. // Convert the volume from the range 0 - 1 to the API's range.
  489. *plVolume = TMGR_MIN_API_VOLUME +
  490. (long) (( TMGR_MAX_API_VOLUME - TMGR_MIN_API_VOLUME ) * dVolume);
  491. LOG((MSP_TRACE, "CAudioCaptureTerminal::get_Volume - exit S_OK"));
  492. return S_OK;
  493. }
  494. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  495. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  496. STDMETHODIMP CAudioCaptureTerminal::put_Volume(long lVolume)
  497. {
  498. CLock lock(m_CritSec);
  499. LOG((MSP_TRACE, "CAudioCaptureTerminal::put_Volume - enter"));
  500. //
  501. // Create the filters if required. This protects us if the creation fails.
  502. //
  503. HRESULT hr = CreateFiltersIfRequired();
  504. if ( FAILED(hr) )
  505. {
  506. LOG((MSP_ERROR, "CAudioCaptureTerminal::put_Volume - "
  507. "CreateFiltersIfRequired failed; returning hr = 0x%08x", hr));
  508. return hr;
  509. }
  510. //
  511. // Check if CreateFiltersIfRequired was able to get us the mixer interface.
  512. // If not, we must fail.
  513. //
  514. if (m_pIAMAudioInputMixer == NULL)
  515. {
  516. LOG((MSP_ERROR, "CAudioCaptureTerminal::put_Volume - "
  517. "filter does not support mixer interface - returning E_FAIL"));
  518. return E_FAIL;
  519. }
  520. //
  521. // Massage ranges to convert between disparate semantics.
  522. //
  523. // Our argument is a long in the range 0 - 0xFFFF. We need to convert it
  524. // to a double ranging from 0.0 to 1.0.
  525. if (lVolume < TMGR_MIN_API_VOLUME)
  526. {
  527. LOG((MSP_ERROR, "CAudioCaptureTerminal::put_Volume - requested "
  528. "volume %d < %d; returning E_INVALIDARG",
  529. lVolume, TMGR_MIN_API_VOLUME));
  530. return E_INVALIDARG;
  531. }
  532. if (lVolume > TMGR_MAX_API_VOLUME)
  533. {
  534. LOG((MSP_ERROR, "CAudioCaptureTerminal::put_Volume - requested "
  535. "volume %d > %d; returning E_INVALIDARG",
  536. lVolume, TMGR_MAX_API_VOLUME));
  537. return E_INVALIDARG;
  538. }
  539. // Convert to the range 0 to 1.
  540. double dVolume =
  541. ( (double) ( lVolume - TMGR_MIN_API_VOLUME ) )
  542. / ( (double) ( TMGR_MAX_API_VOLUME - TMGR_MIN_API_VOLUME ) );
  543. // Convert the volume to whatever range of doubles the filter uses
  544. // from the range 0 - 1. Right now this does nothing but makes the code
  545. // more general.
  546. dVolume = TMGR_MIN_CAPTURE_VOLUME +
  547. ( TMGR_MAX_CAPTURE_VOLUME - TMGR_MIN_CAPTURE_VOLUME ) * dVolume;
  548. hr = m_pIAMAudioInputMixer->put_MixLevel(dVolume);
  549. LOG((MSP_TRACE, "CAudioCaptureTerminal::put_Volume - exit 0x%08x", hr));
  550. return hr;
  551. }
  552. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  553. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  554. STDMETHODIMP CAudioCaptureTerminal::get_Balance(long * plBalance)
  555. {
  556. HRESULT hr = E_NOTIMPL;
  557. LOG((MSP_TRACE, "CAudioCaptureTerminal::get_Balance - enter"));
  558. LOG((MSP_TRACE, "CAudioCaptureTerminal::get_Balance - exit 0x%08x", hr));
  559. return hr;
  560. }
  561. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  562. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  563. STDMETHODIMP CAudioCaptureTerminal::put_Balance(long lBalance)
  564. {
  565. HRESULT hr = E_NOTIMPL;
  566. LOG((MSP_TRACE, "CAudioCaptureTerminal::put_Balance - enter"));
  567. LOG((MSP_TRACE, "CAudioCaptureTerminal::put_Balance - exit 0x%08x", hr));
  568. return hr;
  569. }
  570. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  571. //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  572. STDMETHODIMP
  573. CAudioCaptureTerminal::get_WaveId(
  574. OUT long * plWaveId
  575. )
  576. {
  577. LOG((MSP_TRACE, "CAudioCaptureTerminal::get_WaveId - enter"));
  578. CLock lock(m_CritSec);
  579. //
  580. // Parameter checks.
  581. //
  582. if ( MSPB_IsBadWritePtr(plWaveId, sizeof(long)) )
  583. {
  584. LOG((MSP_ERROR, "CAudioCaptureTerminal::get_WaveId - "
  585. "bad pointer argument"));
  586. return E_POINTER;
  587. }
  588. //
  589. // Check the moniker pointer.
  590. //
  591. if ( IsBadReadPtr( m_pMoniker, sizeof(IMoniker) ) )
  592. {
  593. LOG((MSP_ERROR, "CAudioCaptureTerminal::get_WaveId - "
  594. "bad moniker pointer - exit E_UNEXPECTED"));
  595. return E_UNEXPECTED;
  596. }
  597. //
  598. // Get a property bag from the moniker.
  599. //
  600. IPropertyBag * pBag;
  601. HRESULT hr = m_pMoniker->BindToStorage(0,
  602. 0,
  603. IID_IPropertyBag,
  604. (void **) &pBag);
  605. if ( FAILED(hr) )
  606. {
  607. LOG((MSP_ERROR, "CAudioCaptureTerminal::get_WaveId - "
  608. "can't get property bag - exit 0x%08x", hr));
  609. return hr;
  610. }
  611. //
  612. // Get the ID from the property bag.
  613. //
  614. VARIANT var;
  615. var.vt = VT_I4;
  616. hr = pBag->Read(
  617. L"WaveInId",
  618. &var,
  619. 0);
  620. pBag->Release();
  621. if ( FAILED(hr) )
  622. {
  623. LOG((MSP_ERROR, "CAudioCaptureTerminal::get_WaveId - "
  624. "can't read wave ID - exit 0x%08x", hr));
  625. return hr;
  626. }
  627. *plWaveId = (long) var.lVal;
  628. LOG((MSP_TRACE, "CAudioCaptureTerminal::get_WaveId - exit S_OK"));
  629. return S_OK;
  630. }