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.

375 lines
9.6 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. * CDirectSoundPlaybackBuffer.
  9. *
  10. * History:
  11. * Date By Reason
  12. * ==== == ======
  13. * 07/16/99 rodtoll Created
  14. * 08/04/99 rodtoll Updated to take dsound ranges for volume
  15. * 08/27/99 rodtoll Updated CreateBuffer call to remove DX7 dependencies.
  16. * 09/07/99 rodtoll Added 3d caps to buffer
  17. * 09/20/99 rodtoll Added memory allocation failure checks
  18. * 10/05/99 rodtoll Added DPF_MODNAMEs
  19. * 11/02/99 pnewson Fix: Bug #116365 - using wrong DSBUFFERDESC
  20. * 11/12/99 rodtoll Modified abstraction for new waveOut support.
  21. * Now abstracted types look almost like dsound objects
  22. * 01/27/2000 rodtoll Updated sound classes to accept playback flags,
  23. * buffer structures and DSBUFFERDESC instead of DSBUFFERDESC1
  24. * 04/17/2000 rodtoll Fix: Bug #32215 - Session Lost after resuming from hibernation
  25. * 07/12/2000 rodtoll Bug #31468 - Add diagnostic spew to logfile to show what is failing the HW Wizard
  26. * 08/03/2000 rodtoll Bug #41457 - DPVOICE: need way to discover which specific dsound call failed when returning DVERR_SOUNDINITFAILURE
  27. * 10/04/2000 rodtoll Bug #43510 - DPVOICE: Apps receive a DVMSGID_SESSIONLOST w/DVERR_LOCKEDBUFFER
  28. ***************************************************************************/
  29. #include "dxvutilspch.h"
  30. #undef DPF_SUBCOMP
  31. #define DPF_SUBCOMP DN_SUBCOMP_VOICE
  32. #define DSOUND_STARTUPLATENCY 1
  33. #undef DPF_MODNAME
  34. #define DPF_MODNAME "CDirectSoundPlaybackBuffer::CDirectSoundPlaybackBuffer"
  35. CDirectSoundPlaybackBuffer::CDirectSoundPlaybackBuffer(
  36. LPDIRECTSOUNDBUFFER lpdsBuffer
  37. ): CAudioPlaybackBuffer(), m_dwLastPosition(0), m_dwPriority(0),m_dwFlags(0),m_fPlaying(FALSE)
  38. {
  39. HRESULT hr;
  40. hr = lpdsBuffer->QueryInterface( IID_IDirectSoundBuffer, (void **) &m_lpdsBuffer );
  41. if( FAILED( hr ) )
  42. {
  43. Diagnostics_Write(DVF_ERRORLEVEL, "Unable to get dsound buffer interface" );
  44. m_lpdsBuffer = NULL;
  45. }
  46. }
  47. #undef DPF_MODNAME
  48. #define DPF_MODNAME "CDirectSoundPlaybackBuffer::CDirectSoundPlaybackBuffer"
  49. CDirectSoundPlaybackBuffer::~CDirectSoundPlaybackBuffer()
  50. {
  51. if( m_lpdsBuffer != NULL )
  52. {
  53. m_lpdsBuffer->Release();
  54. }
  55. }
  56. #undef DPF_MODNAME
  57. #define DPF_MODNAME "CDirectSoundPlaybackBuffer::Lock"
  58. HRESULT CDirectSoundPlaybackBuffer::Lock( DWORD dwWriteCursor, DWORD dwWriteBytes, LPVOID *lplpvBuffer1, LPDWORD lpdwSize1, LPVOID *lplpvBuffer2, LPDWORD lpdwSize2, DWORD dwFlags )
  59. {
  60. if( m_lpdsBuffer == NULL )
  61. {
  62. Diagnostics_Write(DVF_ERRORLEVEL, "No DirectSound Buffer Available" );
  63. return DVERR_NOTINITIALIZED;
  64. }
  65. HRESULT hr;
  66. while( 1 )
  67. {
  68. hr = m_lpdsBuffer->Lock( dwWriteCursor, dwWriteBytes, lplpvBuffer1, lpdwSize1, lplpvBuffer2, lpdwSize2, dwFlags );
  69. if( hr == DSERR_BUFFERLOST )
  70. {
  71. DPFX(DPFPREP, 0, "Buffer lost while locking buffer" );
  72. hr = Restore();
  73. }
  74. else
  75. {
  76. DSERTRACK_Update( "DSB::Lock()", hr );
  77. break;
  78. }
  79. if( hr == DSERR_BUFFERLOST )
  80. Sleep( 50 );
  81. }
  82. return hr;
  83. }
  84. #undef DPF_MODNAME
  85. #define DPF_MODNAME "CDirectSoundPlaybackBuffer::UnLock"
  86. HRESULT CDirectSoundPlaybackBuffer::UnLock( LPVOID lpvBuffer1, DWORD dwSize1, LPVOID lpvBuffer2, DWORD dwSize2 )
  87. {
  88. if( m_lpdsBuffer == NULL )
  89. {
  90. Diagnostics_Write(DVF_ERRORLEVEL, "No DirectSound Buffer Available" );
  91. return DVERR_NOTINITIALIZED;
  92. }
  93. HRESULT hr;
  94. hr = m_lpdsBuffer->Unlock( lpvBuffer1, dwSize1, lpvBuffer2, dwSize2 );
  95. if( hr == DSERR_BUFFERLOST )
  96. {
  97. hr = DS_OK;
  98. }
  99. DSERTRACK_Update( "DSB::UnLock()", hr );
  100. return hr;
  101. }
  102. #undef DPF_MODNAME
  103. #define DPF_MODNAME "CDirectSoundPlaybackBuffer::SetVolume"
  104. HRESULT CDirectSoundPlaybackBuffer::SetVolume( LONG lVolume )
  105. {
  106. if( m_lpdsBuffer == NULL )
  107. {
  108. Diagnostics_Write(DVF_ERRORLEVEL, "No DirectSound Buffer Available" );
  109. return DVERR_NOTINITIALIZED;
  110. }
  111. HRESULT hr;
  112. while( 1 )
  113. {
  114. hr = m_lpdsBuffer->SetVolume( lVolume );
  115. if( hr == DSERR_BUFFERLOST )
  116. {
  117. DPFX(DPFPREP, 0, "Buffer lost while setting volume" );
  118. hr = Restore();
  119. }
  120. else
  121. {
  122. break;
  123. }
  124. if( hr == DSERR_BUFFERLOST )
  125. Sleep( 50 );
  126. }
  127. return hr;
  128. }
  129. #undef DPF_MODNAME
  130. #define DPF_MODNAME "CDirectSoundPlaybackBuffer::GetCurrentPosition"
  131. HRESULT CDirectSoundPlaybackBuffer::GetCurrentPosition( LPDWORD lpdwPosition )
  132. {
  133. HRESULT hr;
  134. if( m_lpdsBuffer == NULL )
  135. {
  136. Diagnostics_Write(DVF_ERRORLEVEL, "No DirectSound Buffer Available" );
  137. return DVERR_NOTINITIALIZED;
  138. }
  139. while( 1 )
  140. {
  141. hr = m_lpdsBuffer->GetCurrentPosition( NULL, lpdwPosition );
  142. if( SUCCEEDED( hr ) )
  143. {
  144. DSERTRACK_Update( "DSB::GetCurrentPosition()", hr );
  145. m_dwLastPosition = *lpdwPosition;
  146. break;
  147. }
  148. else if( hr == DSERR_BUFFERLOST )
  149. {
  150. DPFX(DPFPREP, 0, "Buffer lost while getting current position" );
  151. hr = Restore();
  152. DPFX(DPFPREP, 0, "Restore --> 0x%x", hr );
  153. }
  154. else
  155. {
  156. DSERTRACK_Update( "DSB::GetCurrentPosition()", hr );
  157. break;
  158. }
  159. if( hr == DSERR_BUFFERLOST )
  160. Sleep( 50 );
  161. }
  162. return hr;
  163. }
  164. #undef DPF_MODNAME
  165. #define DPF_MODNAME "CDirectSoundPlaybackBuffer::SetCurrentPosition"
  166. HRESULT CDirectSoundPlaybackBuffer::SetCurrentPosition( DWORD dwPosition )
  167. {
  168. HRESULT hr;
  169. if( m_lpdsBuffer == NULL )
  170. {
  171. Diagnostics_Write(DVF_ERRORLEVEL, "No DirectSound Buffer Available" );
  172. return DVERR_NOTINITIALIZED;
  173. }
  174. while( 1 )
  175. {
  176. hr = m_lpdsBuffer->SetCurrentPosition( dwPosition );
  177. if( SUCCEEDED( hr ) )
  178. {
  179. DSERTRACK_Update( "DSB::SetCurrentPosition()", hr );
  180. m_dwLastPosition = dwPosition;
  181. break;
  182. }
  183. else if( hr == DSERR_BUFFERLOST )
  184. {
  185. DPFX(DPFPREP, 0, "Buffer lost while setting position" );
  186. hr = Restore();
  187. }
  188. else
  189. {
  190. DSERTRACK_Update( "DSB::SetCurrentPosition()", hr );
  191. break;
  192. }
  193. if( hr == DSERR_BUFFERLOST )
  194. Sleep( 50 );
  195. }
  196. return hr;
  197. }
  198. #undef DPF_MODNAME
  199. #define DPF_MODNAME "CDirectSoundPlaybackBuffer::Get3DBuffer"
  200. HRESULT CDirectSoundPlaybackBuffer::Get3DBuffer( LPDIRECTSOUND3DBUFFER *lplpds3dBuffer )
  201. {
  202. if( m_lpdsBuffer == NULL )
  203. {
  204. Diagnostics_Write(DVF_ERRORLEVEL, "No DirectSound Buffer Available" );
  205. return DVERR_NOTINITIALIZED;
  206. }
  207. return m_lpdsBuffer->QueryInterface( IID_IDirectSound3DBuffer, (void **) lplpds3dBuffer );
  208. }
  209. #undef DPF_MODNAME
  210. #define DPF_MODNAME "CDirectSoundPlaybackBuffer::Play"
  211. HRESULT CDirectSoundPlaybackBuffer::Play( DWORD dwPriority, DWORD dwFlags )
  212. {
  213. if( m_lpdsBuffer == NULL )
  214. {
  215. Diagnostics_Write(DVF_ERRORLEVEL, "No DirectSound Buffer Available" );
  216. return DVERR_NOTINITIALIZED;
  217. }
  218. HRESULT hr;
  219. m_dwPriority = dwPriority ;
  220. m_dwFlags = dwFlags;
  221. while( 1 )
  222. {
  223. hr = m_lpdsBuffer->Play( 0, dwPriority, dwFlags );
  224. if( hr == DSERR_BUFFERLOST )
  225. {
  226. DPFX(DPFPREP, 0, "Error playing buffer" );
  227. hr = Restore();
  228. }
  229. else
  230. {
  231. break;
  232. }
  233. if( hr == DSERR_BUFFERLOST )
  234. Sleep( 50 );
  235. }
  236. m_fPlaying = TRUE;
  237. return hr;
  238. }
  239. #undef DPF_MODNAME
  240. #define DPF_MODNAME "CDirectSoundPlaybackBuffer::Stop"
  241. HRESULT CDirectSoundPlaybackBuffer::Stop()
  242. {
  243. if( m_lpdsBuffer == NULL )
  244. {
  245. Diagnostics_Write(DVF_ERRORLEVEL, "No DirectSound Buffer Available" );
  246. return DVERR_NOTINITIALIZED;
  247. }
  248. HRESULT hr;
  249. while( 1 )
  250. {
  251. hr = m_lpdsBuffer->Stop( );
  252. m_fPlaying = FALSE;
  253. if( hr == DSERR_BUFFERLOST )
  254. {
  255. DPFX(DPFPREP, 0, "Error stopping buffer" );
  256. hr = Restore();
  257. // If buffer is lost during restore, no need to stop
  258. break;
  259. }
  260. else
  261. {
  262. DSERTRACK_Update( "DSB::Stop()", hr );
  263. break;
  264. }
  265. if( hr == DSERR_BUFFERLOST )
  266. Sleep( 50 );
  267. }
  268. return hr;
  269. }
  270. #undef DPF_MODNAME
  271. #define DPF_MODNAME "CDirectSoundPlaybackBuffer::Restore"
  272. HRESULT CDirectSoundPlaybackBuffer::Restore()
  273. {
  274. if( m_lpdsBuffer == NULL )
  275. {
  276. Diagnostics_Write(DVF_ERRORLEVEL, "No DirectSound Buffer Available" );
  277. return DVERR_NOTINITIALIZED;
  278. }
  279. HRESULT hr = m_lpdsBuffer->Restore( );
  280. DPFX(DPFPREP, 0, "Restore result --> 0x%x", hr );
  281. if( SUCCEEDED( hr ) )
  282. {
  283. if( m_fPlaying )
  284. {
  285. // Attempt to restore current position as well
  286. hr = m_lpdsBuffer->SetCurrentPosition( m_dwLastPosition );
  287. if( FAILED( hr ) )
  288. {
  289. DPFX(DPFPREP, 0, "Error setting position after restore hr=0x%x", hr );
  290. return hr;
  291. }
  292. hr = Play(m_dwPriority, m_dwFlags);
  293. }
  294. }
  295. return hr;
  296. }
  297. #undef DPF_MODNAME
  298. #define DPF_MODNAME "CDirectSoundPlaybackBuffer::GetStartupLatency"
  299. DWORD CDirectSoundPlaybackBuffer::GetStartupLatency()
  300. {
  301. return DSOUND_STARTUPLATENCY;
  302. }