诸暨麻将添加redis
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 
 
 
 
 

298 líneas
8.1 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Copyright (C) 1998 by Jörg König
  3. // All rights reserved
  4. //
  5. // This file is part of the completely free tetris clone "CGTetris".
  6. //
  7. // This is free software.
  8. // You may redistribute it by any means providing it is not sold for profit
  9. // without the authors written consent.
  10. //
  11. // No warrantee of any kind, expressed or implied, is included with this
  12. // software; use at your own risk, responsibility for damages (if any) to
  13. // anyone resulting from the use of this software rests entirely with the
  14. // user.
  15. //
  16. // Send bug reports, bug fixes, enhancements, requests, flames, etc., and
  17. // I'll try to keep a version up to date. I can be reached as follows:
  18. // J.Koenig@adg.de (company site)
  19. // Joerg.Koenig@rhein-neckar.de (private site)
  20. /////////////////////////////////////////////////////////////////////////////
  21. // DirectSound.cpp: implementation of the CDirectSound class.
  22. //
  23. //////////////////////////////////////////////////////////////////////
  24. #include "stdafx.h"
  25. #include "DirectSound.h"
  26. // The following macro is defined since DirectX 5, but will work with
  27. // older versions too.
  28. #ifndef DSBLOCK_ENTIREBUFFER
  29. #define DSBLOCK_ENTIREBUFFER 0x00000002
  30. #endif
  31. #ifdef _DEBUG
  32. #undef THIS_FILE
  33. static char THIS_FILE[]=__FILE__;
  34. #define new DEBUG_NEW
  35. #endif
  36. static void DSError( HRESULT hRes ) {
  37. switch(hRes) {
  38. case DS_OK: TRACE0("NO ERROR\n"); break;
  39. case DSERR_ALLOCATED: TRACE0("ALLOCATED\n"); break;
  40. case DSERR_INVALIDPARAM: TRACE0("INVALIDPARAM\n"); break;
  41. case DSERR_OUTOFMEMORY: TRACE0("OUTOFMEMORY\n"); break;
  42. case DSERR_UNSUPPORTED: TRACE0("UNSUPPORTED\n"); break;
  43. case DSERR_NOAGGREGATION: TRACE0("NOAGGREGATION\n"); break;
  44. case DSERR_UNINITIALIZED: TRACE0("UNINITIALIZED\n"); break;
  45. case DSERR_BADFORMAT: TRACE0("BADFORMAT\n"); break;
  46. case DSERR_ALREADYINITIALIZED: TRACE0("ALREADYINITIALIZED\n"); break;
  47. case DSERR_BUFFERLOST: TRACE0("BUFFERLOST\n"); break;
  48. case DSERR_CONTROLUNAVAIL: TRACE0("CONTROLUNAVAIL\n"); break;
  49. case DSERR_GENERIC: TRACE0("GENERIC\n"); break;
  50. case DSERR_INVALIDCALL: TRACE0("INVALIDCALL\n"); break;
  51. case DSERR_OTHERAPPHASPRIO: TRACE0("OTHERAPPHASPRIO\n"); break;
  52. case DSERR_PRIOLEVELNEEDED: TRACE0("PRIOLEVELNEEDED\n"); break;
  53. default: TRACE1("%lu\n",hRes);break;
  54. }
  55. }
  56. //////////////////////////////////////////////////////////////////////
  57. // Construction/Destruction
  58. //////////////////////////////////////////////////////////////////////
  59. LPDIRECTSOUND CDirectSound::m_lpDirectSound;
  60. DWORD CDirectSound::m_dwInstances;
  61. CDirectSound::CDirectSound()
  62. {
  63. m_lpDirectSound = 0;
  64. m_pDsb = 0;
  65. m_pTheSound = 0;
  66. m_dwTheSound = 0;
  67. m_bEnabled = TRUE;
  68. ++m_dwInstances;
  69. }
  70. CDirectSound::~CDirectSound()
  71. {
  72. if( m_pDsb )
  73. m_pDsb->Release();
  74. if( !--m_dwInstances && m_lpDirectSound ) {
  75. m_lpDirectSound->Release();
  76. m_lpDirectSound = 0;
  77. }
  78. }
  79. BOOL CDirectSound::Create(LPCTSTR pszResource, CWnd * pWnd)
  80. {
  81. //////////////////////////////////////////////////////////////////
  82. // load resource
  83. HINSTANCE hApp = ::GetModuleHandle(0);
  84. ASSERT(hApp);
  85. HRSRC hResInfo = ::FindResource(hApp, pszResource, TEXT("WAVE"));
  86. if(hResInfo == 0)
  87. return FALSE;
  88. HGLOBAL hRes = ::LoadResource(hApp, hResInfo);
  89. if(hRes == 0)
  90. return FALSE;
  91. LPVOID pTheSound = ::LockResource(hRes);
  92. if(pTheSound == 0)
  93. return FALSE;
  94. return Create(pTheSound, pWnd);
  95. }
  96. BOOL CDirectSound :: Create(LPVOID pSoundData, CWnd * pWnd) {
  97. if(pWnd == 0)
  98. pWnd = AfxGetApp()->GetMainWnd();
  99. ASSERT(pWnd != 0);
  100. ASSERT(::IsWindow(pWnd->GetSafeHwnd()));
  101. ASSERT(pSoundData != 0);
  102. //////////////////////////////////////////////////////////////////
  103. // create direct sound object
  104. if( m_lpDirectSound == 0 ) {
  105. // Someone might use sounds for starting apps. This may cause
  106. // DirectSoundCreate() to fail because the driver is used by
  107. // anyone else. So wait a little before starting with the work ...
  108. HRESULT hRes = DS_OK;
  109. short nRes = 0;
  110. do {
  111. if( nRes )
  112. ::Sleep(500);
  113. hRes = ::DirectSoundCreate(0, &m_lpDirectSound, 0);
  114. ++nRes;
  115. } while( nRes < 10 && (hRes == DSERR_ALLOCATED || hRes == DSERR_NODRIVER) );
  116. if( hRes != DS_OK )
  117. return FALSE;
  118. m_lpDirectSound->SetCooperativeLevel(pWnd->GetSafeHwnd(), DSSCL_NORMAL);
  119. }
  120. ASSERT(m_lpDirectSound != 0);
  121. WAVEFORMATEX * pcmwf;
  122. if( ! GetWaveData(pSoundData, pcmwf, m_pTheSound, m_dwTheSound) ||
  123. ! CreateSoundBuffer(pcmwf) ||
  124. ! SetSoundData(m_pTheSound, m_dwTheSound) )
  125. return FALSE;
  126. return TRUE;
  127. }
  128. BOOL CDirectSound :: GetWaveData(void * pRes, WAVEFORMATEX * & pWaveHeader, void * & pbWaveData, DWORD & cbWaveSize) {
  129. pWaveHeader = 0;
  130. pbWaveData = 0;
  131. cbWaveSize = 0;
  132. DWORD * pdw = (DWORD *)pRes;
  133. DWORD dwRiff = *pdw++;
  134. DWORD dwLength = *pdw++;
  135. DWORD dwType = *pdw++;
  136. if( dwRiff != mmioFOURCC('R', 'I', 'F', 'F') )
  137. return FALSE; // not even RIFF
  138. if( dwType != mmioFOURCC('W', 'A', 'V', 'E') )
  139. return FALSE; // not a WAV
  140. DWORD * pdwEnd = (DWORD *)((BYTE *)pdw + dwLength-4);
  141. while( pdw < pdwEnd ) {
  142. dwType = *pdw++;
  143. dwLength = *pdw++;
  144. switch( dwType ) {
  145. case mmioFOURCC('f', 'm', 't', ' '):
  146. if( !pWaveHeader ) {
  147. if( dwLength < sizeof(WAVEFORMAT) )
  148. return FALSE; // not a WAV
  149. pWaveHeader = (WAVEFORMATEX *)pdw;
  150. if( pbWaveData && cbWaveSize )
  151. return TRUE;
  152. }
  153. break;
  154. case mmioFOURCC('d', 'a', 't', 'a'):
  155. pbWaveData = LPVOID(pdw);
  156. cbWaveSize = dwLength;
  157. if( pWaveHeader )
  158. return TRUE;
  159. break;
  160. }
  161. pdw = (DWORD *)((BYTE *)pdw + ((dwLength+1)&~1));
  162. }
  163. return FALSE;
  164. }
  165. BOOL CDirectSound::CreateSoundBuffer(WAVEFORMATEX * pcmwf)
  166. {
  167. DSBUFFERDESC dsbdesc;
  168. // Set up DSBUFFERDESC structure.
  169. memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); // Zero it out.
  170. dsbdesc.dwSize = sizeof(DSBUFFERDESC);
  171. // Need no controls (pan, volume, frequency).
  172. dsbdesc.dwFlags = DSBCAPS_STATIC; // assumes that the sound is played often
  173. dsbdesc.dwBufferBytes = m_dwTheSound;
  174. dsbdesc.lpwfxFormat = pcmwf; // Create buffer.
  175. HRESULT hRes;
  176. if( DS_OK != (hRes = m_lpDirectSound->CreateSoundBuffer(&dsbdesc, &m_pDsb, 0)) ) {
  177. // Failed.
  178. DSError(hRes);
  179. m_pDsb = 0;
  180. return FALSE;
  181. }
  182. return TRUE;
  183. }
  184. BOOL CDirectSound::SetSoundData(void * pSoundData, DWORD dwSoundSize) {
  185. LPVOID lpvPtr1;
  186. DWORD dwBytes1;
  187. // Obtain write pointer.
  188. HRESULT hr = m_pDsb->Lock(0, 0, &lpvPtr1, &dwBytes1, 0, 0, DSBLOCK_ENTIREBUFFER);
  189. // If DSERR_BUFFERLOST is returned, restore and retry lock.
  190. if(DSERR_BUFFERLOST == hr) {
  191. m_pDsb->Restore();
  192. hr = m_pDsb->Lock(0, 0, &lpvPtr1, &dwBytes1, 0, 0, DSBLOCK_ENTIREBUFFER);
  193. }
  194. if(DS_OK == hr) {
  195. // Write to pointers.
  196. ::CopyMemory(lpvPtr1, pSoundData, dwBytes1);
  197. // Release the data back to DirectSound.
  198. hr = m_pDsb->Unlock(lpvPtr1, dwBytes1, 0, 0);
  199. if(DS_OK == hr)
  200. return TRUE;
  201. }
  202. // Lock, Unlock, or Restore failed.
  203. return FALSE;
  204. }
  205. void CDirectSound::Play(DWORD dwStartPosition, BOOL bLoop)
  206. {
  207. if( ! IsValid() || ! IsEnabled() )
  208. return; // no chance to play the sound ...
  209. if( dwStartPosition > m_dwTheSound )
  210. dwStartPosition = m_dwTheSound;
  211. m_pDsb->SetCurrentPosition(dwStartPosition);
  212. if( DSERR_BUFFERLOST == m_pDsb->Play(0, 0, bLoop ? DSBPLAY_LOOPING : 0) ) {
  213. // another application had stolen our buffer
  214. // Note that a "Restore()" is not enough, because
  215. // the sound data is invalid after Restore().
  216. SetSoundData(m_pTheSound, m_dwTheSound);
  217. // Try playing again
  218. m_pDsb->Play(0, 0, bLoop ? DSBPLAY_LOOPING : 0);
  219. }
  220. }
  221. void CDirectSound::Stop()
  222. {
  223. if( IsValid() )
  224. m_pDsb->Stop();
  225. }
  226. void CDirectSound::Pause()
  227. {
  228. Stop();
  229. }
  230. void CDirectSound::Continue()
  231. {
  232. if( IsValid() ) {
  233. DWORD dwPlayCursor, dwWriteCursor;
  234. m_pDsb->GetCurrentPosition(&dwPlayCursor, &dwWriteCursor);
  235. Play(dwPlayCursor);
  236. }
  237. }
  238. BOOL CDirectSound::IsValid() const
  239. {
  240. return (m_lpDirectSound && m_pDsb && m_pTheSound && m_dwTheSound) ? TRUE : FALSE;
  241. }