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.

264 lines
7.2 KiB

  1. /* - - - - - - - - */
  2. //
  3. // sound.c
  4. //
  5. // Copyright (C) 1994 Microsoft Corporation. All Rights Reserved.
  6. //
  7. /* - - - - - - - - */
  8. #define STRICT
  9. #include <windows.h>
  10. #include <windowsx.h>
  11. #include <mmsystem.h>
  12. #include <mmddk.h>
  13. #include "sound.h"
  14. #include <tchar.h>
  15. /* - - - - - - - - */
  16. typedef struct tagSOUND FAR *PSOUND;
  17. typedef struct tagSOUND
  18. {
  19. WAVEHDR header;
  20. LPBYTE pbData;
  21. DWORD cbLength;
  22. LPWAVEFORMATEX lpwfx;
  23. HGLOBAL hgData;
  24. HWAVEOUT hwave;
  25. HWND hwndNotify;
  26. } SOUND;
  27. typedef struct
  28. {
  29. FOURCC fccRiff;
  30. DWORD cbSize;
  31. FOURCC fccWave;
  32. } FILEHEADER, *LPFILEHEADER;
  33. typedef struct
  34. {
  35. DWORD dwCKID;
  36. DWORD dwSize;
  37. } CHUNKHEADER, *LPCHUNKHEADER;
  38. #define RIFF_FILE MAKEFOURCC('R','I','F','F')
  39. #define RIFF_WAVE MAKEFOURCC('W','A','V','E')
  40. #define RIFF_FORMAT MAKEFOURCC('f','m','t',' ')
  41. #define RIFF_DATA MAKEFOURCC('d','a','t','a')
  42. /* - - - - - - - - */
  43. #ifdef DEBUG
  44. #define STATIC
  45. #else
  46. #define STATIC static
  47. #endif
  48. typedef CHUNKHEADER UNALIGNED FAR *ULPCHUNKHEADER;
  49. typedef WAVEFORMATEX UNALIGNED FAR *ULPWAVEFORMATEX;
  50. /* - - - - - - - - */
  51. STATIC MMRESULT NEAR PASCAL soundInitWaveHeader(
  52. PSOUND ps)
  53. {
  54. size_t cbWFX;
  55. ULPWAVEFORMATEX pwfx;
  56. ULPCHUNKHEADER pckhdr;
  57. LPFILEHEADER pfhdr;
  58. LPBYTE pbData;
  59. DWORD dwFileSize;
  60. DWORD dwCurPos;
  61. if (ps->cbLength < sizeof(FILEHEADER))
  62. return MMSYSERR_INVALPARAM;
  63. pfhdr = (LPFILEHEADER)ps->pbData;
  64. if ((pfhdr->fccRiff != RIFF_FILE) || (pfhdr->fccWave != RIFF_WAVE))
  65. return MMSYSERR_NOTSUPPORTED;
  66. dwFileSize = pfhdr->cbSize;
  67. dwCurPos = sizeof(FILEHEADER);
  68. pbData = (LPBYTE)ps->pbData + sizeof(FILEHEADER);
  69. if (ps->cbLength < dwFileSize)
  70. return MMSYSERR_INVALPARAM;
  71. for (;;)
  72. {
  73. pckhdr = (ULPCHUNKHEADER)pbData;
  74. if (pckhdr->dwCKID == RIFF_FORMAT)
  75. break;
  76. dwCurPos += pckhdr->dwSize + sizeof(CHUNKHEADER);
  77. if (dwCurPos >= dwFileSize)
  78. return MMSYSERR_INVALPARAM;
  79. pbData += pckhdr->dwSize + sizeof(CHUNKHEADER);
  80. }
  81. pwfx = (ULPWAVEFORMATEX)(pbData + sizeof(CHUNKHEADER));
  82. cbWFX = sizeof(WAVEFORMATEX);
  83. if (pwfx->wFormatTag!=WAVE_FORMAT_PCM)
  84. {
  85. cbWFX += pwfx->cbSize;
  86. }
  87. if ((ps->lpwfx = (LPWAVEFORMATEX)GlobalAlloc (GMEM_FIXED, cbWFX)) == 0)
  88. return MMSYSERR_NOMEM;
  89. memcpy ((char *)ps->lpwfx, pwfx, cbWFX);
  90. pbData = pbData + ((ULPCHUNKHEADER)pbData)->dwSize + sizeof(CHUNKHEADER);
  91. for (;;)
  92. {
  93. pckhdr = (ULPCHUNKHEADER)pbData;
  94. if (pckhdr->dwCKID == RIFF_DATA)
  95. break;
  96. dwCurPos += pckhdr->dwSize + sizeof(CHUNKHEADER);
  97. if (dwCurPos >= dwFileSize)
  98. {
  99. GlobalFree ((HGLOBAL)ps->lpwfx);
  100. ps->lpwfx = NULL;
  101. return MMSYSERR_INVALPARAM;
  102. }
  103. pbData += pckhdr->dwSize + sizeof(CHUNKHEADER);
  104. }
  105. ps->header.lpData = pbData + sizeof(CHUNKHEADER);
  106. ps->header.dwBufferLength = pckhdr->dwSize;
  107. ps->header.dwBytesRecorded = 0;
  108. ps->header.dwUser = (DWORD_PTR)ps;
  109. ps->header.dwFlags = 0;
  110. ps->header.dwLoops = 0;
  111. ps->header.lpNext = NULL;
  112. ps->header.reserved = 0;
  113. return MMSYSERR_NOERROR;
  114. }
  115. /* - - - - - - - - */
  116. STATIC MMRESULT NEAR PASCAL soundLoadFile(
  117. LPCTSTR pszSound,
  118. HWND hwndNotify,
  119. PSOUND ps)
  120. {
  121. HFILE hf;
  122. MMRESULT mmr;
  123. if ((hf = HandleToUlong(CreateFile(pszSound,GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL))) != HFILE_ERROR)
  124. {
  125. ps->cbLength = _llseek(hf, 0L, SEEK_END);
  126. _llseek(hf, 0L, SEEK_SET);
  127. if (ps->hgData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, ps->cbLength))
  128. {
  129. if (ps->pbData = GlobalLock(ps->hgData))
  130. {
  131. if (_hread(hf, ps->pbData, ps->cbLength) == (LONG)ps->cbLength)
  132. {
  133. if (!(mmr = soundInitWaveHeader(ps)))
  134. {
  135. _lclose(hf);
  136. ps->hwndNotify = hwndNotify;
  137. return MMSYSERR_NOERROR;
  138. }
  139. }
  140. else
  141. mmr = MMSYSERR_ERROR;
  142. GlobalUnlock(ps->hgData);
  143. }
  144. else
  145. mmr = MMSYSERR_ERROR;
  146. GlobalFree(ps->hgData);
  147. }
  148. else
  149. mmr = MMSYSERR_NOMEM;
  150. _lclose(hf);
  151. }
  152. else
  153. mmr = MMSYSERR_ERROR;
  154. return mmr;
  155. }
  156. /* - - - - - - - - */
  157. void FAR PASCAL soundOnDone(
  158. HSOUND hs)
  159. {
  160. PSOUND ps;
  161. ps = (PSOUND)hs;
  162. waveOutUnprepareHeader(ps->hwave, &ps->header, sizeof(WAVEHDR));
  163. waveOutClose(ps->hwave);
  164. ps->hwave = NULL;
  165. }
  166. /* - - - - - - - - */
  167. MMRESULT FAR PASCAL soundOpen(
  168. LPCTSTR pszSound,
  169. HWND hwndNotify,
  170. PHSOUND phs)
  171. {
  172. MMRESULT mmr;
  173. if (!(*phs = (HSOUND)LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, sizeof(SOUND))))
  174. return MMSYSERR_NOMEM;
  175. if (mmr = soundLoadFile(pszSound, hwndNotify, (PSOUND)*phs))
  176. LocalFree((HLOCAL)*phs);
  177. return mmr;
  178. }
  179. /* - - - - - - - - */
  180. MMRESULT FAR PASCAL soundClose(
  181. HSOUND hs)
  182. {
  183. PSOUND ps;
  184. MMRESULT mmr;
  185. if (mmr = soundStop(hs))
  186. return mmr;
  187. ps = (PSOUND)hs;
  188. if (ps->lpwfx != NULL) {
  189. GlobalFree ((HGLOBAL)ps->lpwfx);
  190. ps->lpwfx = NULL;
  191. }
  192. GlobalUnlock(ps->hgData);
  193. GlobalFree(ps->hgData);
  194. LocalFree((HLOCAL)hs);
  195. return MMSYSERR_NOERROR;
  196. }
  197. /* - - - - - - - - */
  198. MMRESULT FAR PASCAL soundPlay(
  199. HSOUND hs)
  200. {
  201. PSOUND ps;
  202. MMRESULT mmr;
  203. if (mmr = soundStop(hs))
  204. return mmr;
  205. ps = (PSOUND)hs;
  206. if (!(mmr = waveOutOpen(&ps->hwave, WAVE_MAPPER, ps->lpwfx, (DWORD_PTR)ps->hwndNotify, (DWORD_PTR)ps, CALLBACK_WINDOW | WAVE_ALLOWSYNC)))
  207. {
  208. ps->header.dwFlags &= ~WHDR_DONE;
  209. if (!(mmr = waveOutPrepareHeader(ps->hwave, &ps->header, sizeof(WAVEHDR))))
  210. {
  211. if (!(mmr = waveOutWrite(ps->hwave, &ps->header, sizeof(WAVEHDR))))
  212. return MMSYSERR_NOERROR;
  213. waveOutUnprepareHeader(ps->hwave, &ps->header, sizeof(WAVEHDR));
  214. }
  215. waveOutClose(ps->hwave);
  216. ps->hwave = NULL;
  217. }
  218. return mmr;
  219. }
  220. /* - - - - - - - - */
  221. MMRESULT FAR PASCAL soundStop(
  222. HSOUND hs)
  223. {
  224. PSOUND ps;
  225. MSG msg;
  226. ps = (PSOUND)hs;
  227. if (ps->hwave)
  228. waveOutReset(ps->hwave);
  229. if (IsWindow(ps->hwndNotify))
  230. while (PeekMessage(&msg, ps->hwndNotify, MM_WOM_OPEN, MM_WOM_DONE, PM_REMOVE))
  231. {
  232. DispatchMessage(&msg);
  233. }
  234. return MMSYSERR_NOERROR;
  235. }
  236. /* - - - - - - - - */