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.

442 lines
10 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1999 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: dscrecb.cpp
  6. * Content:
  7. * This module contains the implementation of the
  8. * CDirectSoundCaptureRecordBuffer.
  9. *
  10. * History:
  11. * Date By Reason
  12. * ==== == ======
  13. * 11/04/99 rodtoll Created
  14. * 11/22/99 rodtoll Added code to allow specification of wave device ID
  15. * 11/23/99 rodtoll Updated to use waveIn device ID or DSound 7.1 when they are avail
  16. * rodtoll Updated with new Microphone select member
  17. * 12/08/99 rodtoll Bug #115783 - Will always adjust volume of default device
  18. * Now uses new CMixerLine class for adjusting volumes/selecting mic
  19. * 12/08/99 rodtoll Bug #121054 - DirectX 7.1 support.
  20. * - Added hwndOwner param for capture focus support
  21. * - Added lpfLostFocus param to GetCurrentPosition so upper
  22. * layers can detect lost focus.
  23. * 01/28/2000 rodtoll Bug #130465: Record Mute/Unmute must call YieldFocus() / ClaimFocus()
  24. * 02/10/2000 rodtoll Removed more capture focus code
  25. * 04/19/2000 rodtoll Re-enabled capture focus behaviour
  26. * 08/03/2000 rodtoll Bug #41457 - DPVOICE: need way to discover which specific dsound call failed when returning DVERR_SOUNDINITFAILURE
  27. * 04/22/2001 rodtoll Fixed bug in lockup simulation code (TESTING PURPOSES ONLY)
  28. *
  29. ***************************************************************************/
  30. #include "dxvutilspch.h"
  31. #undef DPF_SUBCOMP
  32. #define DPF_SUBCOMP DN_SUBCOMP_VOICE
  33. #define DSC_STARTUP_LATENCY 1
  34. #undef DPF_MODNAME
  35. #define DPF_MODNAME "CDirectSoundCaptureRecordBuffer::CDirectSoundCaptureRecordBuffer"
  36. CDirectSoundCaptureRecordBuffer::CDirectSoundCaptureRecordBuffer(
  37. LPDIRECTSOUNDCAPTUREBUFFER lpdscBuffer, HWND hwndOwner, const GUID &guidDevice, UINT uiWaveDeviceID, LPDSCBUFFERDESC lpdsBufferDesc
  38. ): CAudioRecordBuffer(), m_lpwfxRecordFormat(NULL), m_lpdscBuffer7(NULL),
  39. m_guidDevice(guidDevice), m_uiWaveDeviceID(uiWaveDeviceID),
  40. #ifdef LOCKUP_SIMULATION
  41. m_dwNumSinceLastLockup(0), m_dwLastPosition(0),
  42. #endif
  43. m_hwndOwner(hwndOwner), m_fUseCaptureFocus( FALSE )
  44. {
  45. HRESULT hr;
  46. DWORD dwSize;
  47. if( lpdsBufferDesc->dwFlags & DSCBCAPS_FOCUSAWARE )
  48. {
  49. DPFX(DPFPREP, 1, "Enabling focus" );
  50. m_fUseCaptureFocus = TRUE;
  51. }
  52. else
  53. {
  54. DPFX(DPFPREP, 1, "Disabling focus" );
  55. m_fUseCaptureFocus = FALSE;
  56. }
  57. hr = lpdscBuffer->QueryInterface( IID_IDirectSoundCaptureBuffer, (void **) &m_lpdscBuffer );
  58. if( FAILED( hr ) )
  59. {
  60. DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to get dsound buffer interface" );
  61. m_lpdscBuffer = NULL;
  62. }
  63. hr = lpdscBuffer->QueryInterface( IID_IDirectSoundCaptureBuffer7_1, (void **) &m_lpdscBuffer7 );
  64. if( FAILED( hr ) )
  65. {
  66. DPFX(DPFPREP, DVF_WARNINGLEVEL, "Could not retrieve new interface hr=0x%x.", hr );
  67. hr = m_mixerLine.Initialize( m_uiWaveDeviceID );
  68. if( FAILED( hr ) )
  69. {
  70. DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to acquire volume controls hr=0x%x", hr );
  71. DNASSERT( FALSE );
  72. }
  73. }
  74. else
  75. {
  76. if( m_fUseCaptureFocus )
  77. {
  78. hr = m_lpdscBuffer7->SetFocusHWND( hwndOwner );
  79. if( FAILED( hr ) )
  80. {
  81. DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to set the focus window hr = 0x%x", hr );
  82. DNASSERT( FALSE );
  83. }
  84. }
  85. }
  86. hr = lpdscBuffer->GetFormat( NULL, 0, &dwSize );
  87. m_lpwfxRecordFormat = (LPWAVEFORMATEX) new BYTE[dwSize];
  88. if( m_lpwfxRecordFormat == NULL )
  89. {
  90. DPFX(DPFPREP, DVF_ERRORLEVEL, "Unable to allocate space for record format" );
  91. DNASSERT( FALSE );
  92. }
  93. hr = lpdscBuffer->GetFormat( m_lpwfxRecordFormat, dwSize, NULL );
  94. if( FAILED( hr ) )
  95. {
  96. delete [] ((LPBYTE) m_lpwfxRecordFormat);
  97. m_lpwfxRecordFormat = NULL;
  98. }
  99. }
  100. #undef DPF_MODNAME
  101. #define DPF_MODNAME "CDirectSoundCaptureRecordBuffer::CDirectSoundCaptureRecordBuffer"
  102. CDirectSoundCaptureRecordBuffer::~CDirectSoundCaptureRecordBuffer()
  103. {
  104. if( m_lpdscBuffer7 != NULL )
  105. {
  106. m_lpdscBuffer7->Release();
  107. }
  108. if( m_lpdscBuffer != NULL )
  109. {
  110. m_lpdscBuffer->Release();
  111. }
  112. if( m_lpwfxRecordFormat != NULL )
  113. {
  114. delete [] ((LPBYTE) m_lpwfxRecordFormat);
  115. }
  116. }
  117. #undef DPF_MODNAME
  118. #define DPF_MODNAME "CDirectSoundCaptureRecordBuffer::Lock"
  119. HRESULT CDirectSoundCaptureRecordBuffer::Lock( DWORD dwWriteCursor, DWORD dwWriteBytes, LPVOID *lplpvBuffer1, LPDWORD lpdwSize1, LPVOID *lplpvBuffer2, LPDWORD lpdwSize2, DWORD dwFlags )
  120. {
  121. HRESULT hr;
  122. if( m_lpdscBuffer == NULL )
  123. {
  124. DPFX(DPFPREP, DVF_ERRORLEVEL, "No DirectSoundCapture Buffer Available" );
  125. return DVERR_NOTINITIALIZED;
  126. }
  127. hr = m_lpdscBuffer->Lock( dwWriteCursor, dwWriteBytes, lplpvBuffer1, lpdwSize1, lplpvBuffer2, lpdwSize2, dwFlags );
  128. DSERTRACK_Update( "DSCB::Lock()", hr );
  129. return hr;
  130. }
  131. #undef DPF_MODNAME
  132. #define DPF_MODNAME "CDirectSoundCaptureRecordBuffer::UnLock"
  133. HRESULT CDirectSoundCaptureRecordBuffer::UnLock( LPVOID lpvBuffer1, DWORD dwSize1, LPVOID lpvBuffer2, DWORD dwSize2 )
  134. {
  135. HRESULT hr;
  136. if( m_lpdscBuffer == NULL )
  137. {
  138. DPFX(DPFPREP, DVF_ERRORLEVEL, "No DirectSoundCapture Buffer Available" );
  139. return DVERR_NOTINITIALIZED;
  140. }
  141. hr = m_lpdscBuffer->Unlock( lpvBuffer1, dwSize1, lpvBuffer2, dwSize2 );
  142. return hr;
  143. }
  144. #undef DPF_MODNAME
  145. #define DPF_MODNAME "CDirectSoundCaptureRecordBuffer::SetVolume"
  146. HRESULT CDirectSoundCaptureRecordBuffer::SetVolume( LONG lVolume )
  147. {
  148. if( m_lpdscBuffer == NULL )
  149. {
  150. DPFX(DPFPREP, DVF_ERRORLEVEL, "No DirectSoundCapture Buffer Available" );
  151. return DVERR_NOTINITIALIZED;
  152. }
  153. HRESULT hr;
  154. if( m_lpdscBuffer7 != NULL )
  155. {
  156. hr = m_lpdscBuffer7->SetVolume( lVolume );
  157. }
  158. else
  159. {
  160. hr = m_mixerLine.SetMasterRecordVolume( lVolume );
  161. }
  162. // This is only a warning condition
  163. if( FAILED( hr ) )
  164. {
  165. DPFX(DPFPREP, DVF_INFOLEVEL, "Could not set master volume hr=0x%x", hr );
  166. }
  167. if( m_lpdscBuffer7 != NULL )
  168. {
  169. hr = m_lpdscBuffer7->SetMicVolume( lVolume );
  170. }
  171. else
  172. {
  173. hr = m_mixerLine.SetMicrophoneVolume( lVolume );
  174. }
  175. if( FAILED( hr ) )
  176. {
  177. DPFX(DPFPREP, DVF_INFOLEVEL, "Unable to set Microphone volume hr=0x%x", hr );
  178. return hr;
  179. }
  180. return DV_OK;
  181. }
  182. #undef DPF_MODNAME
  183. #define DPF_MODNAME "CDirectSoundCaptureRecordBuffer::GetVolume"
  184. HRESULT CDirectSoundCaptureRecordBuffer::GetVolume( LPLONG lplVolume )
  185. {
  186. if( m_lpdscBuffer == NULL )
  187. {
  188. DPFX(DPFPREP, DVF_ERRORLEVEL, "No DirectSoundCapture Buffer Available" );
  189. return DVERR_NOTINITIALIZED;
  190. }
  191. HRESULT hr;
  192. if( m_lpdscBuffer7 != NULL )
  193. {
  194. hr = m_lpdscBuffer7->GetMicVolume( lplVolume );
  195. }
  196. else
  197. {
  198. hr = m_mixerLine.GetMicrophoneVolume( lplVolume );
  199. }
  200. if( FAILED( hr ) )
  201. {
  202. DPFX(DPFPREP, DVF_WARNINGLEVEL, "Unable to get Microphone volume hr=0x%x", hr );
  203. if( m_lpdscBuffer7 != NULL )
  204. {
  205. hr = m_lpdscBuffer7->GetVolume( lplVolume );
  206. }
  207. else
  208. {
  209. hr = m_mixerLine.GetMasterRecordVolume( lplVolume );
  210. }
  211. // This is only a warning condition
  212. if( FAILED( hr ) )
  213. {
  214. DPFX(DPFPREP, DVF_WARNINGLEVEL, "Could not get master record volume hr=0x%x", hr );
  215. return hr;
  216. }
  217. return hr;
  218. }
  219. return hr;
  220. }
  221. #undef DPF_MODNAME
  222. #define DPF_MODNAME "CDirectSoundCaptureRecordBuffer::GetCurrentPosition"
  223. HRESULT CDirectSoundCaptureRecordBuffer::GetCurrentPosition( LPDWORD lpdwPosition, LPBOOL lpfLostFocus )
  224. {
  225. if( m_lpdscBuffer == NULL )
  226. {
  227. DPFX(DPFPREP, DVF_ERRORLEVEL, "No DirectSoundCapture Buffer Available" );
  228. return DVERR_NOTINITIALIZED;
  229. }
  230. #ifdef LOCKUP_SIMULATION
  231. m_dwNumSinceLastLockup++;
  232. if( m_dwNumSinceLastLockup > LOCKUP_NUM_CALLS_BEFORE_LOCKUP )
  233. {
  234. *lpdwPosition = m_dwLastPosition;
  235. *lpfLostFocus = FALSE;
  236. return DV_OK;
  237. }
  238. #endif
  239. HRESULT hr;
  240. if( m_lpdscBuffer7 != NULL && m_fUseCaptureFocus )
  241. {
  242. DWORD dwStatus;
  243. hr = m_lpdscBuffer7->GetStatus( &dwStatus );
  244. if( FAILED( hr ) )
  245. {
  246. DPFX(DPFPREP, DVF_ERRORLEVEL, "Error getting status hr=0x%x", hr );
  247. *lpfLostFocus = FALSE;
  248. }
  249. else
  250. {
  251. *lpfLostFocus = (dwStatus & DSCBSTATUS_LOSTFOCUS) ? TRUE : FALSE;
  252. }
  253. }
  254. else
  255. {
  256. *lpfLostFocus = FALSE;
  257. }
  258. hr = m_lpdscBuffer->GetCurrentPosition( NULL, lpdwPosition );
  259. #ifdef LOCKUP_SIMULATION
  260. m_dwLastPosition = *lpdwPosition;
  261. #endif
  262. DSERTRACK_Update( "DSCB::GetCurrentPosition()", hr );
  263. return hr;
  264. }
  265. #undef DPF_MODNAME
  266. #define DPF_MODNAME "CDirectSoundCaptureRecordBuffer::Play"
  267. HRESULT CDirectSoundCaptureRecordBuffer::Record( BOOL fLooping )
  268. {
  269. if( m_lpdscBuffer == NULL )
  270. {
  271. DPFX(DPFPREP, DVF_ERRORLEVEL, "No DirectSound Buffer Available" );
  272. return DVERR_NOTINITIALIZED;
  273. }
  274. HRESULT hr;
  275. hr = m_lpdscBuffer->Start( (fLooping) ? DSCBSTART_LOOPING : 0 );
  276. #ifdef LOCKUP_SIMULATION
  277. #ifdef LOCKUP_STOPFAIL
  278. if( m_dwNumSinceLastLockup > LOCKUP_NUM_CALLS_BEFORE_LOCKUP )
  279. {
  280. hr = DSERR_GENERIC;
  281. }
  282. #else
  283. m_dwNumSinceLastLockup = 0;
  284. #endif
  285. #endif
  286. DSERTRACK_Update( "DSCB::Start()", hr );
  287. return hr;
  288. }
  289. #undef DPF_MODNAME
  290. #define DPF_MODNAME "CDirectSoundCaptureRecordBuffer::Stop"
  291. HRESULT CDirectSoundCaptureRecordBuffer::Stop()
  292. {
  293. if( m_lpdscBuffer == NULL )
  294. {
  295. DPFX(DPFPREP, DVF_ERRORLEVEL, "No DirectSound Buffer Available" );
  296. return DVERR_NOTINITIALIZED;
  297. }
  298. HRESULT hr;
  299. hr = m_lpdscBuffer->Stop( );
  300. #ifdef LOCKUP_SIMULATION
  301. #ifdef LOCKUP_STOPFAIL
  302. if( m_dwNumSinceLastLockup > LOCKUP_NUM_CALLS_BEFORE_LOCKUP )
  303. {
  304. hr = DSERR_GENERIC;
  305. }
  306. #endif
  307. #endif
  308. DSERTRACK_Update( "DSCB::Stop()", hr );
  309. return hr;
  310. }
  311. #undef DPF_MODNAME
  312. #define DPF_MODNAME "CDirectSoundCaptureRecordBuffer::GetStartupLatency"
  313. DWORD CDirectSoundCaptureRecordBuffer::GetStartupLatency()
  314. {
  315. return DSC_STARTUP_LATENCY;
  316. }
  317. #undef DPF_MODNAME
  318. #define DPF_MODNAME "CDirectSoundCaptureRecordBuffer::GetRecordFormat"
  319. LPWAVEFORMATEX CDirectSoundCaptureRecordBuffer::GetRecordFormat()
  320. {
  321. return m_lpwfxRecordFormat;
  322. }
  323. #undef DPF_MODNAME
  324. #define DPF_MODNAME "CDirectSoundCaptureRecordBuffer::SelectMicrophone"
  325. HRESULT CDirectSoundCaptureRecordBuffer::SelectMicrophone( BOOL fSelect )
  326. {
  327. if( m_lpdscBuffer7 != NULL )
  328. {
  329. return m_lpdscBuffer7->EnableMic( fSelect );
  330. }
  331. else
  332. {
  333. return m_mixerLine.EnableMicrophone( fSelect );
  334. }
  335. }
  336. #undef DPF_MODNAME
  337. #define DPF_MODNAME "CDirectSoundCaptureRecordBuffer::ClaimFocus"
  338. HRESULT CDirectSoundCaptureRecordBuffer::ClaimFocus( )
  339. {
  340. if( m_lpdscBuffer7 != NULL && m_fUseCaptureFocus)
  341. {
  342. return m_lpdscBuffer7->ClaimFocus();
  343. }
  344. else
  345. {
  346. return DVERR_NOTSUPPORTED;
  347. }
  348. }
  349. #undef DPF_MODNAME
  350. #define DPF_MODNAME "CDirectSoundCaptureRecordBuffer::YieldFocus"
  351. HRESULT CDirectSoundCaptureRecordBuffer::YieldFocus( )
  352. {
  353. if( m_lpdscBuffer7 != NULL && m_fUseCaptureFocus )
  354. {
  355. return m_lpdscBuffer7->YieldFocus();
  356. }
  357. else
  358. {
  359. return DVERR_NOTSUPPORTED;
  360. }
  361. }