Source code of Windows XP (NT5)
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.

589 lines
15 KiB

  1. /*++
  2. Copyright (c) 1998-1999 Microsoft Corporation
  3. Module Name:
  4. waveaddr.cpp
  5. Abstract:
  6. This module contains implementation of CWaveMSP.
  7. Author:
  8. Zoltan Szilagyi (zoltans) September 7, 1998
  9. --*/
  10. #include "stdafx.h"
  11. ///////////////////////////////////////////////////////////////////////////////
  12. ///////////////////////////////////////////////////////////////////////////////
  13. //
  14. CWaveMSP::CWaveMSP()
  15. {
  16. LOG((MSP_TRACE, "CWaveMSP::CWaveMSP entered."));
  17. m_fHaveWaveIDs = FALSE;
  18. m_dwWaveInID = 0xfeedface;
  19. m_dwWaveOutID = 0xfeedface;
  20. m_fdSupport = FDS_UNKNOWN;
  21. m_pFilterMapper = NULL;
  22. LOG((MSP_TRACE, "CWaveMSP::CWaveMSP exited."));
  23. }
  24. ///////////////////////////////////////////////////////////////////////////////
  25. ///////////////////////////////////////////////////////////////////////////////
  26. //
  27. CWaveMSP::~CWaveMSP()
  28. {
  29. LOG((MSP_TRACE, "CWaveMSP::~CWaveMSP entered."));
  30. if ( m_pFilterMapper )
  31. {
  32. m_pFilterMapper->Release();
  33. }
  34. LOG((MSP_TRACE, "CWaveMSP::~CWaveMSP exited."));
  35. }
  36. ///////////////////////////////////////////////////////////////////////////////
  37. ///////////////////////////////////////////////////////////////////////////////
  38. //
  39. ULONG CWaveMSP::MSPAddressAddRef(void)
  40. {
  41. return MSPAddRefHelper(this);
  42. }
  43. ULONG CWaveMSP::MSPAddressRelease(void)
  44. {
  45. return MSPReleaseHelper(this);
  46. }
  47. ///////////////////////////////////////////////////////////////////////////////
  48. ///////////////////////////////////////////////////////////////////////////////
  49. //
  50. STDMETHODIMP CWaveMSP::CreateMSPCall(
  51. IN MSP_HANDLE htCall,
  52. IN DWORD dwReserved,
  53. IN DWORD dwMediaType,
  54. IN IUnknown * pOuterUnknown,
  55. OUT IUnknown ** ppMSPCall
  56. )
  57. {
  58. LOG((MSP_TRACE, "CWaveMSP::CreateMSPCall - enter"));
  59. CWaveMSPCall * pCWaveMSPCall;
  60. HRESULT hr = CreateMSPCallHelper<CWaveMSPCall>(this,
  61. htCall,
  62. dwReserved,
  63. dwMediaType,
  64. pOuterUnknown,
  65. ppMSPCall,
  66. &pCWaveMSPCall);
  67. //
  68. // pCWaveMSPCall is not addrefed; no need to release.
  69. //
  70. if ( FAILED(hr) )
  71. {
  72. LOG((MSP_ERROR, "CWaveMSP::CreateMSPCall - template helper returned"
  73. "0x%08x", hr));
  74. return hr;
  75. }
  76. //
  77. // If we know the wave IDs, tell the call. If we don't know the wave IDs
  78. // or if the setting fails, we still successfully create the call; we will
  79. // just get failure events during streaming.
  80. //
  81. if ( m_fHaveWaveIDs )
  82. {
  83. pCWaveMSPCall->SetWaveIDs( m_dwWaveInID, m_dwWaveOutID );
  84. }
  85. LOG((MSP_TRACE, "CWaveMSP::CreateMSPCall - exit S_OK"));
  86. return S_OK;
  87. }
  88. ///////////////////////////////////////////////////////////////////////////////
  89. ///////////////////////////////////////////////////////////////////////////////
  90. //
  91. STDMETHODIMP CWaveMSP::ShutdownMSPCall (
  92. IN IUnknown * pMSPCall
  93. )
  94. {
  95. LOG((MSP_TRACE, "CWaveMSP::ShutdownMSPCall - enter"));
  96. CWaveMSPCall * pCWaveMSPCall;
  97. HRESULT hr = ShutdownMSPCallHelper<CWaveMSPCall>(pMSPCall,
  98. &pCWaveMSPCall);
  99. //
  100. // pCWaveMSPCall is not addrefed; no need to release.
  101. //
  102. if ( FAILED(hr) )
  103. {
  104. LOG((MSP_ERROR, "CWaveMSP::ShutdownMSPCall - template helper returned"
  105. "0x%08x", hr));
  106. return hr;
  107. }
  108. LOG((MSP_TRACE, "CWaveMSP::ShutdownMSPCall - exit S_OK"));
  109. return S_OK;
  110. }
  111. ///////////////////////////////////////////////////////////////////////////////
  112. ///////////////////////////////////////////////////////////////////////////////
  113. //
  114. // Mandatory CMSPAddress override. This indicates the media types that
  115. // we support.
  116. //
  117. DWORD CWaveMSP::GetCallMediaTypes(void)
  118. {
  119. return (DWORD) TAPIMEDIATYPE_AUDIO;
  120. }
  121. ///////////////////////////////////////////////////////////////////////////////
  122. ///////////////////////////////////////////////////////////////////////////////
  123. //
  124. // Optional CMSPAddress override. Used to find out the wave id's before any
  125. // calls are created, allowing us to exclude our own wave devices from our
  126. // enumeration of static terminals.
  127. //
  128. // We now also use these as the wave ids for all our calls on this address.
  129. // We must get one of these messages before we make any calls -- these
  130. // messages are sent while tapi is initializing the address, and it is
  131. // done synchronously.
  132. //
  133. HRESULT CWaveMSP::ReceiveTSPAddressData(
  134. IN PBYTE pBuffer,
  135. IN DWORD dwSize
  136. )
  137. {
  138. LOG((MSP_TRACE, "CWaveMSP::ReceiveTSPAddressData - enter"));
  139. //
  140. // Check that the buffer is as big as advertised.
  141. //
  142. if ( IsBadWritePtr(pBuffer, sizeof(BYTE) * dwSize) )
  143. {
  144. LOG((MSP_ERROR, "CWaveMSP::ReceiveTSPAddressData - "
  145. "bad buffer - exit E_POINTER"));
  146. return E_POINTER;
  147. }
  148. //
  149. // Check if we have a command DWORD.
  150. //
  151. if ( dwSize < sizeof(DWORD) )
  152. {
  153. LOG((MSP_ERROR, "CWaveMSP::ReceiveTSPAddressData - "
  154. "need a DWORD for command - exit E_INVALIDARG"));
  155. return E_INVALIDARG;
  156. }
  157. int i;
  158. HRESULT hr;
  159. //
  160. // Based on the command, take action:
  161. //
  162. switch ( ((DWORD *) pBuffer) [0] )
  163. {
  164. case 3: // use wave IDs to hide terminals
  165. {
  166. if ( dwSize < 3 * sizeof(DWORD) )
  167. {
  168. LOG((MSP_ERROR, "CWaveMSP::ReceiveTSPAddressData - "
  169. "need 3 DWORDs for SetWaveID command - "
  170. "exit E_INVALIDARG"));
  171. return E_INVALIDARG;
  172. }
  173. m_TerminalDataLock.Lock();
  174. _ASSERTE( m_fTerminalsUpToDate == FALSE );
  175. m_fHaveWaveIDs = TRUE;
  176. m_dwWaveInID = ((DWORD *) pBuffer) [1];
  177. m_dwWaveOutID = ((DWORD *) pBuffer) [2];
  178. m_TerminalDataLock.Unlock();
  179. LOG((MSP_INFO, "CWaveMSP::ReceiveTSPAddressData - "
  180. "setting WaveInID=%d, WaveOutID=%d",
  181. m_dwWaveInID, m_dwWaveOutID));
  182. }
  183. break;
  184. case 4: // don't use wave IDs to hide terminals
  185. {
  186. _ASSERTE( m_fTerminalsUpToDate == FALSE );
  187. LOG((MSP_INFO, "CWaveMSP::ReceiveTSPAddressData - "
  188. "got command 4 - not setting wave IDs"));
  189. // m_fHaveWaveIDs remains FALSE
  190. }
  191. break;
  192. case 8:
  193. {
  194. if ( dwSize < 2 * sizeof(DWORD) )
  195. {
  196. LOG((MSP_INFO, "CWaveMSP::ReceiveTSPAddressData - "
  197. "need 2 DWORDS for set duplex support command - "
  198. "exit E_INVALIDARG"));
  199. return E_INVALIDARG;
  200. }
  201. m_TerminalDataLock.Lock();
  202. if ( 1 == ((DWORD *) pBuffer) [1] )
  203. {
  204. m_fdSupport = FDS_SUPPORTED;
  205. LOG((MSP_INFO, "CWaveMSP::ReceiveTSPAddressData - "
  206. "Full Duplex supported"));
  207. }
  208. else
  209. {
  210. m_fdSupport = FDS_NOTSUPPORTED;
  211. LOG((MSP_INFO, "CWaveMSP::ReceiveTSPAddressData - "
  212. "Full Duplex not supported"));
  213. }
  214. m_TerminalDataLock.Unlock();
  215. }
  216. break;
  217. default:
  218. LOG((MSP_ERROR, "CWaveMSP::ReceiveTSPAddressData - "
  219. "invalid command - exit E_INVALIDARG"));
  220. return E_INVALIDARG;
  221. }
  222. LOG((MSP_TRACE, "CWaveMSP::ReceiveTSPAddressData - exit S_OK"));
  223. return S_OK;
  224. }
  225. ///////////////////////////////////////////////////////////////////////////////
  226. ///////////////////////////////////////////////////////////////////////////////
  227. //
  228. // Optional CMSPAddress override. Used to remove our own wave devices from
  229. // the list of static terminals.
  230. //
  231. HRESULT CWaveMSP::UpdateTerminalList(void)
  232. {
  233. LOG((MSP_TRACE, "CWaveMSP::UpdateTerminalList - enter"));
  234. //
  235. // Call the base class method. This builds up the list of terminals.
  236. //
  237. HRESULT hr = CMSPAddress::UpdateTerminalList();
  238. if ( FAILED(hr) )
  239. {
  240. LOG((MSP_ERROR, "CWaveMSP::UpdateTerminalList - "
  241. "base class method failed - exit 0x%08x", hr));
  242. return hr;
  243. }
  244. m_TerminalDataLock.Lock();
  245. if ( m_fHaveWaveIDs )
  246. {
  247. int iSize = m_Terminals.GetSize();
  248. for ( int i = 0; i < iSize; i++ )
  249. {
  250. ITTerminal * pTerminal = m_Terminals[i];
  251. long lMediaType;
  252. if ( SUCCEEDED( pTerminal->get_MediaType( & lMediaType ) ) )
  253. {
  254. if ( lMediaType == TAPIMEDIATYPE_AUDIO )
  255. {
  256. TERMINAL_DIRECTION dir;
  257. if ( SUCCEEDED( pTerminal->get_Direction( & dir ) ) )
  258. {
  259. if ( TerminalHasWaveID( dir == TD_CAPTURE,
  260. pTerminal,
  261. m_dwWaveOutID ) )
  262. {
  263. pTerminal->Release();
  264. m_Terminals.RemoveAt(i);
  265. i--;
  266. iSize--;
  267. }
  268. } // if direction is available
  269. } // if audio
  270. } // if media type is available
  271. } // for each terminal
  272. } // if we have wave ids
  273. m_TerminalDataLock.Unlock();
  274. LOG((MSP_TRACE, "CWaveMSP::UpdateTerminalList - exit S_OK"));
  275. return S_OK;
  276. }
  277. ///////////////////////////////////////////////////////////////////////////////
  278. ///////////////////////////////////////////////////////////////////////////////
  279. //
  280. // Private helpers to check if a terminal has a given wave IDs.
  281. //
  282. BOOL CWaveMSP::TerminalHasWaveID(
  283. IN BOOL fCapture,
  284. IN ITTerminal * pTerminal,
  285. IN DWORD dwWaveID
  286. )
  287. {
  288. LOG((MSP_TRACE, "CWaveMSP::TerminalHasWaveID - enter"));
  289. _ASSERTE( ! IsBadReadPtr(pTerminal, sizeof(ITTerminal) ) );
  290. IMoniker * pMoniker;
  291. //
  292. // Cast to the correct type of terminal and get the moniker.
  293. //
  294. if ( fCapture )
  295. {
  296. CAudioCaptureTerminal * pCaptureTerminal;
  297. pCaptureTerminal = dynamic_cast<CAudioCaptureTerminal *> (pTerminal);
  298. if ( pCaptureTerminal == NULL )
  299. {
  300. LOG((MSP_ERROR, "CWaveMSP::TerminalHasWaveID - "
  301. "dynamic cast (capture) failed - exit FALSE"));
  302. return FALSE;
  303. }
  304. pMoniker = pCaptureTerminal->m_pMoniker;
  305. }
  306. else
  307. {
  308. CAudioRenderTerminal * pRenderTerminal;
  309. pRenderTerminal = dynamic_cast<CAudioRenderTerminal *> (pTerminal);
  310. if ( pRenderTerminal == NULL )
  311. {
  312. LOG((MSP_ERROR, "CWaveMSP::TerminalHasWaveID - "
  313. "dynamic cast (render) failed - exit FALSE"));
  314. return FALSE;
  315. }
  316. pMoniker = pRenderTerminal->m_pMoniker;
  317. }
  318. //
  319. // Check the moniker pointer.
  320. //
  321. if ( IsBadWritePtr( pMoniker, sizeof(IMoniker) ) )
  322. {
  323. LOG((MSP_ERROR, "CWaveMSP::TerminalHasWaveID - "
  324. "bad moniker pointer - exit FALSE"));
  325. return FALSE;
  326. }
  327. //
  328. // Get a property bag from the moniker.
  329. //
  330. IPropertyBag * pBag;
  331. HRESULT hr = pMoniker->BindToStorage(0,
  332. 0,
  333. IID_IPropertyBag,
  334. (void **) &pBag);
  335. if (FAILED(hr))
  336. {
  337. LOG((MSP_ERROR, "CWaveMSP::TerminalHasWaveID - "
  338. "can't get property bag - exit FALSE"));
  339. return FALSE;
  340. }
  341. //
  342. // Get the ID from the property bag.
  343. //
  344. WCHAR * pwszWaveID;
  345. if ( fCapture )
  346. {
  347. pwszWaveID = L"WaveInId";
  348. }
  349. else
  350. {
  351. pwszWaveID = L"WaveOutId";
  352. }
  353. VARIANT var;
  354. var.vt = VT_I4;
  355. hr = pBag->Read(pwszWaveID, &var, 0);
  356. pBag->Release();
  357. if (FAILED(hr))
  358. {
  359. LOG((MSP_ERROR, "CWaveMSP::TerminalHasWaveID - "
  360. "can't read wave ID - exit FALSE"));
  361. return FALSE;
  362. }
  363. if ( var.lVal == (long) dwWaveID )
  364. {
  365. LOG((MSP_TRACE, "CWaveMSP::TerminalHasWaveID - "
  366. "matched wave ID (%d) - exit TRUE", var.lVal));
  367. return TRUE;
  368. }
  369. else
  370. {
  371. LOG((MSP_TRACE, "CWaveMSP::TerminalHasWaveID - "
  372. "didn't match wave ID (%d) - exit FALSE", var.lVal));
  373. return FALSE;
  374. }
  375. }
  376. ///////////////////////////////////////////////////////////////////////////////
  377. ///////////////////////////////////////////////////////////////////////////////
  378. //
  379. // Public method for creating and saving a reference to the DShow filter
  380. // mapper object on an intelligent connect. Called by the stream/call when an
  381. // intelligent connection is attempted. Does nothing if the cache has already
  382. // been created.
  383. //
  384. HRESULT CWaveMSP::CreateFilterMapper(void)
  385. {
  386. LOG((MSP_TRACE, "CWaveMSP::CreateFilterMapper - enter"));
  387. if ( m_pFilterMapper != NULL )
  388. {
  389. LOG((MSP_TRACE, "CWaveMSP::CreateFilterMapper - "
  390. "mapper cache already created - doing nothing"));
  391. }
  392. else
  393. {
  394. //
  395. // Create an extra filter mapper to keep the filter mapper cache around,
  396. // and create the cache up front, This speeds up DShow's performance
  397. // when we do intelligent connects.
  398. //
  399. HRESULT hr;
  400. hr = CoCreateInstance(CLSID_FilterMapper,
  401. NULL,
  402. CLSCTX_INPROC_SERVER,
  403. IID_IFilterMapper,
  404. (void**) & m_pFilterMapper
  405. );
  406. if ( FAILED(hr) )
  407. {
  408. LOG((MSP_WARN, "CWaveMSP::CreateFilterMapper - "
  409. "failed to create filter mapper - 0x%08x - continuing", hr));
  410. m_pFilterMapper = NULL; // just to be safe
  411. }
  412. //
  413. // No need to enumerate filters on the mapper cache, because this is
  414. // called at connection time anyway, so there is nothing to be gained
  415. // that way -- the intelligent connection will just do it.
  416. //
  417. }
  418. LOG((MSP_TRACE, "CWaveMSP::CreateFilterMapper - exit S_OK"));
  419. return S_OK;
  420. }
  421. ///////////////////////////////////////////////////////////////////////////////
  422. ///////////////////////////////////////////////////////////////////////////////
  423. //
  424. // Returns full duplex support on this device
  425. //
  426. HRESULT CWaveMSP::IsFullDuplex( FULLDUPLEX_SUPPORT * pSupport )
  427. {
  428. LOG((MSP_TRACE, "CWaveMSP::IsFullDuplex - enter"));
  429. if (IsBadWritePtr( pSupport, sizeof(FULLDUPLEX_SUPPORT) ))
  430. {
  431. LOG((MSP_TRACE, "CWaveMSP::IsFullDuplex - bad pointer"));
  432. return E_POINTER;
  433. }
  434. m_TerminalDataLock.Lock();
  435. *pSupport = m_fdSupport;
  436. m_TerminalDataLock.Unlock();
  437. LOG((MSP_TRACE, "CWaveMSP::IsFullDuplex - exit S_OK"));
  438. return S_OK;
  439. }
  440. // eof