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.

260 lines
5.9 KiB

  1. /*************************************************
  2. * waveodev.cpp *
  3. * *
  4. * Copyright (C) 1995-1999 Microsoft Inc. *
  5. * *
  6. *************************************************/
  7. // waveodev.cpp : implementation file
  8. //
  9. #include "stdafx.h"
  10. #include "wave.h"
  11. #ifdef _DEBUG
  12. #undef THIS_FILE
  13. static char BASED_CODE THIS_FILE[] = __FILE__;
  14. #endif
  15. // global items
  16. CWaveOutDevice theDefaultWaveOutDevice;
  17. /////////////////////////////////////////////////////////////////////////////
  18. // CWaveOutDevice
  19. CWaveOutDevice::CWaveOutDevice()
  20. {
  21. m_hOutDev = NULL;
  22. m_iBlockCount = 0;
  23. }
  24. CWaveOutDevice::~CWaveOutDevice()
  25. {
  26. }
  27. BEGIN_MESSAGE_MAP(CWaveOutDevice, CWnd)
  28. //{{AFX_MSG_MAP(CWaveOutDevice)
  29. ON_MESSAGE(MM_WOM_DONE, OnWomDone)
  30. //}}AFX_MSG_MAP
  31. END_MESSAGE_MAP()
  32. BOOL CWaveOutDevice::Create()
  33. {
  34. if (!CreateEx(0,
  35. AfxRegisterWndClass(0),
  36. "Wave Wnd",
  37. WS_POPUP,
  38. 0,
  39. 0,
  40. 0,
  41. 0,
  42. NULL,
  43. NULL)) {
  44. TRACE("Failed to create wave notification window");
  45. return FALSE;
  46. }
  47. return TRUE;
  48. }
  49. #ifndef _DEBUG
  50. #define MMERR(n) 0
  51. #else
  52. void MMERR(MMRESULT mmr)
  53. {
  54. switch (mmr) {
  55. case WAVERR_BADFORMAT:
  56. TRACE("No wave device supports format");
  57. break;
  58. case MMSYSERR_NOMEM:
  59. TRACE("Out of memory");
  60. break;
  61. case MMSYSERR_ALLOCATED:
  62. TRACE("Resource is already allocated");
  63. break;
  64. case MMSYSERR_BADDEVICEID:
  65. TRACE("Bad device id");
  66. break;
  67. case MMSYSERR_INVALHANDLE:
  68. TRACE("Invalid device handle");
  69. break;
  70. case MMSYSERR_HANDLEBUSY:
  71. TRACE("Device in use by another thread");
  72. break;
  73. case WAVERR_UNPREPARED:
  74. TRACE("Header not prepared");
  75. break;
  76. default:
  77. TRACE("Unknown error");
  78. break;
  79. }
  80. }
  81. #endif // _DEBUG
  82. /////////////////////////////////////////////////////////////////////////////
  83. // CWaveOutDevice message handlers
  84. LRESULT CWaveOutDevice::OnWomDone(WPARAM w, LPARAM l)
  85. {
  86. ASSERT(l);
  87. WAVEHDR* phdr = (WAVEHDR*) l;
  88. CWave* pWave = (CWave*)(phdr->dwUser);
  89. ASSERT(pWave->IsKindOf(RUNTIME_CLASS(CWave)));
  90. CWaveOutDevice* pOutDev = pWave->GetOutDevice();
  91. ASSERT(pOutDev);
  92. pOutDev->WaveOutDone(pWave, phdr);
  93. UNREFERENCED_PARAMETER(w);
  94. return 0;
  95. }
  96. BOOL CWaveOutDevice::IsOpen()
  97. {
  98. return m_hOutDev ? TRUE : FALSE;
  99. }
  100. BOOL CWaveOutDevice::Open(WAVEFORMATEX *pFormat)
  101. {
  102. MMRESULT mmr;
  103. // Make sure we have a callback window.
  104. if (!m_hWnd) {
  105. Create(); // Create the window.
  106. ASSERT(m_hWnd);
  107. }
  108. // See whether it's already open for this format.
  109. if (IsOpen()) {
  110. // See whether it can handle this format.
  111. if (CanDoFormat(pFormat)) {
  112. return TRUE;
  113. } else {
  114. TRACE("Open for different format");
  115. return FALSE;
  116. }
  117. }
  118. // See whether we can open for this format.
  119. mmr = waveOutOpen(&m_hOutDev,
  120. WAVE_MAPPER,
  121. pFormat,
  122. (DWORD_PTR)(GetSafeHwnd()),
  123. 0,
  124. CALLBACK_WINDOW);
  125. if (mmr != 0) {
  126. MMERR(mmr);
  127. return FALSE;
  128. }
  129. return TRUE;
  130. }
  131. BOOL CWaveOutDevice::CanDoFormat(WAVEFORMATEX* pFormat)
  132. {
  133. MMRESULT mmr;
  134. if (!IsOpen()) {
  135. TRACE("Not open");
  136. return FALSE;
  137. }
  138. HWAVEOUT hDev = NULL;
  139. mmr = waveOutOpen(&hDev,
  140. WAVE_MAPPER,
  141. pFormat,
  142. NULL,
  143. 0,
  144. WAVE_FORMAT_QUERY);
  145. if (mmr != 0) {
  146. MMERR(mmr);
  147. return FALSE;
  148. }
  149. return TRUE;
  150. }
  151. BOOL CWaveOutDevice::Close()
  152. {
  153. if (m_hOutDev) {
  154. // Close the device.
  155. waveOutReset(m_hOutDev);
  156. MMRESULT mmr = waveOutClose(m_hOutDev);
  157. if (mmr != 0) {
  158. MMERR(mmr);
  159. }
  160. m_hOutDev = NULL;
  161. }
  162. // Destroy the window.
  163. DestroyWindow();
  164. ASSERT(m_hWnd == NULL);
  165. return TRUE;
  166. }
  167. BOOL CWaveOutDevice::Play(CWave* pWave)
  168. {
  169. if (!Open(pWave->GetFormat())) {
  170. return FALSE;
  171. }
  172. // Allocate a header.
  173. WAVEHDR* phdr = (WAVEHDR*)malloc(sizeof(WAVEHDR));
  174. ASSERT(phdr);
  175. // Fill out the wave header.
  176. memset(phdr, 0, sizeof(WAVEHDR));
  177. //#if 1 // BUGFIX for VC++ 2.0
  178. // phdr->lpData = (BYTE*) pWave->GetSamples();
  179. //#else
  180. phdr->lpData = (char*) pWave->GetSamples();
  181. //#endif
  182. phdr->dwBufferLength = pWave->GetSize();
  183. phdr->dwUser = (DWORD_PTR)(void*)pWave; // So we can find the object
  184. // Prepare the header
  185. MMRESULT mmr = waveOutPrepareHeader(m_hOutDev,
  186. phdr,
  187. sizeof(WAVEHDR));
  188. if (mmr) {
  189. MMERR(mmr);
  190. return FALSE;
  191. }
  192. // Mark the wave as busy.
  193. pWave->SetBusy(TRUE);
  194. // Start it playing.
  195. mmr = waveOutWrite(m_hOutDev,
  196. phdr,
  197. sizeof(WAVEHDR));
  198. if (mmr) {
  199. MMERR(mmr);
  200. return FALSE;
  201. }
  202. // Add one to the block count.
  203. m_iBlockCount++;
  204. return TRUE;
  205. }
  206. void CWaveOutDevice::WaveOutDone(CWave *pWave, WAVEHDR *pHdr)
  207. {
  208. // Unprepare the header.
  209. MMRESULT mmr = waveOutUnprepareHeader(m_hOutDev,
  210. pHdr,
  211. sizeof(WAVEHDR));
  212. if (mmr) {
  213. MMERR(mmr);
  214. }
  215. // Free the header.
  216. free(pHdr);
  217. // Decrement the block count.
  218. ASSERT(m_iBlockCount > 0);
  219. m_iBlockCount--;
  220. if (m_iBlockCount == 0) {
  221. // Close the device.
  222. Close();
  223. }
  224. // Notify the object that it is done.
  225. pWave->SetBusy(FALSE);
  226. pWave->OnWaveOutDone();
  227. }