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.

1891 lines
68 KiB

  1. /****************************************************************************
  2. wave.c
  3. Level 1 kitchen sink DLL wave support module
  4. Copyright (c) Microsoft Corporation 1990. All rights reserved
  5. ****************************************************************************/
  6. #include <windows.h>
  7. #include "mmsystem.h"
  8. #include "mmddk.h"
  9. #include "mmsysi.h"
  10. #include "thunks.h"
  11. /* -------------------------------------------------------------------------
  12. ** Local functions
  13. ** -------------------------------------------------------------------------
  14. */
  15. static UINT NEAR PASCAL
  16. waveGetErrorText(
  17. UINT wError,
  18. LPSTR lpText,
  19. UINT wSize
  20. );
  21. /* -------------------------------------------------------------------------
  22. ** Local structures
  23. ** -------------------------------------------------------------------------
  24. */
  25. typedef struct wavedev_tag {
  26. PWAVEDRV wavedrv;
  27. UINT wDevice;
  28. DWORD dwDrvUser;
  29. UINT wDeviceID;
  30. } WAVEDEV, *PWAVEDEV;
  31. /* -------------------------------------------------------------------------
  32. ** @doc INTERNAL WAVE validation code for WAVEHDRs
  33. ** -------------------------------------------------------------------------
  34. */
  35. #define IsWaveHeaderPrepared(hWave, lpwh) \
  36. ((lpwh)->dwFlags & WHDR_PREPARED)
  37. #define MarkWaveHeaderPrepared(hWave, lpwh) \
  38. ((lpwh)->dwFlags |= WHDR_PREPARED)
  39. #define MarkWaveHeaderUnprepared(hWave, lpwh) \
  40. ((lpwh)->dwFlags &=~WHDR_PREPARED)
  41. /*****************************************************************************
  42. * @doc INTERNAL WAVE
  43. *
  44. * @api UINT | wavePrepareHeader | This function prepares the header and data
  45. * if the driver returns MMSYSERR_NOTSUPPORTED.
  46. *
  47. * @rdesc Returns zero if the function was successful. Otherwise, it
  48. * specifies an error number.
  49. ****************************************************************************/
  50. static UINT NEAR PASCAL
  51. wavePrepareHeader(
  52. LPWAVEHDR lpWaveHdr,
  53. UINT wSize
  54. )
  55. {
  56. if (!HugePageLock(lpWaveHdr, (DWORD)sizeof(WAVEHDR))) {
  57. return MMSYSERR_NOMEM;
  58. }
  59. if (!HugePageLock(lpWaveHdr->lpData, lpWaveHdr->dwBufferLength)) {
  60. HugePageUnlock(lpWaveHdr, (DWORD)sizeof(WAVEHDR));
  61. return MMSYSERR_NOMEM;
  62. }
  63. // lpWaveHdr->dwFlags |= WHDR_PREPARED;
  64. return MMSYSERR_NOERROR;
  65. }
  66. /*****************************************************************************
  67. * @doc INTERNAL WAVE
  68. *
  69. * @api UINT | waveUnprepareHeader | This function unprepares the header and
  70. * data if the driver returns MMSYSERR_NOTSUPPORTED.
  71. *
  72. * @rdesc Currently always returns MMSYSERR_NOERROR.
  73. ****************************************************************************/
  74. static UINT NEAR PASCAL
  75. waveUnprepareHeader(
  76. LPWAVEHDR lpWaveHdr,
  77. UINT wSize
  78. )
  79. {
  80. HugePageUnlock(lpWaveHdr->lpData, lpWaveHdr->dwBufferLength);
  81. HugePageUnlock(lpWaveHdr, (DWORD)sizeof(WAVEHDR));
  82. // lpWaveHdr->dwFlags &= ~WHDR_PREPARED;
  83. return MMSYSERR_NOERROR;
  84. }
  85. //////////////////////////////////////////////////////////////////////////
  86. //////////////////////////////////////////////////////////////////////////
  87. /*****************************************************************************
  88. * @doc EXTERNAL WAVE
  89. *
  90. * @api UINT | waveOutGetNumDevs | This function retrieves the number of
  91. * waveform output devices present in the system.
  92. *
  93. * @rdesc Returns the number of waveform output devices present in the system.
  94. *
  95. * @xref waveOutGetDevCaps
  96. ****************************************************************************/
  97. UINT WINAPI
  98. waveOutGetNumDevs(
  99. void
  100. )
  101. {
  102. return waveOIDMessage( 0, WODM_GETNUMDEVS, 0L, 0L, 0L );
  103. }
  104. /*****************************************************************************
  105. * @doc EXTERNAL WAVE
  106. *
  107. * @api DWORD | waveOutMessage | This function sends messages to the waveform
  108. * output device drivers.
  109. *
  110. * @parm HWAVEOUT | hWaveOut | The handle to the audio device.
  111. *
  112. * @parm UINT | msg | The message to send.
  113. *
  114. * @parm DWORD | dw1 | Parameter 1.
  115. *
  116. * @parm DWORD | dw2 | Parameter 2.
  117. *
  118. * @rdesc Returns the value returned from the driver.
  119. ****************************************************************************/
  120. DWORD WINAPI
  121. waveOutMessage(
  122. HWAVEOUT hWaveOut,
  123. UINT msg,
  124. DWORD dw1,
  125. DWORD dw2
  126. )
  127. {
  128. V_HANDLE(hWaveOut, TYPE_WAVEOUT, 0L);
  129. return waveOMessage( (HWAVE)hWaveOut, msg, dw1, dw2);
  130. }
  131. /*****************************************************************************
  132. * @doc EXTERNAL WAVE
  133. *
  134. * @api UINT | waveOutGetDevCaps | This function queries a specified waveform
  135. * device to determine its capabilities.
  136. *
  137. * @parm UINT | wDeviceID | Identifies the waveform output device.
  138. *
  139. * @parm LPWAVEOUTCAPS | lpCaps | Specifies a far pointer to a <t WAVEOUTCAPS>
  140. * structure. This structure is filled with information about the
  141. * capabilities of the device.
  142. *
  143. * @parm UINT | wSize | Specifies the size of the <t WAVEOUTCAPS> structure.
  144. *
  145. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  146. * an error number. Possible error returns are:
  147. * @flag MMSYSERR_BADDEVICEID | Specified device ID is out of range.
  148. * @flag MMSYSERR_NODRIVER | The driver was not installed.
  149. *
  150. * @comm Use <f waveOutGetNumDevs> to determine the number of waveform output
  151. * devices present in the system. The device ID specified by <p wDeviceID>
  152. * varies from zero to one less than the number of devices present.
  153. * The WAVE_MAPPER constant may also be used as a device id. Only
  154. * <p wSize> bytes (or less) of information is copied to the location
  155. * pointed to by <p lpCaps>. If <p wSize> is zero, nothing is copied, and
  156. * the function returns zero.
  157. *
  158. * @xref waveOutGetNumDevs
  159. ****************************************************************************/
  160. UINT WINAPI
  161. waveOutGetDevCaps(
  162. UINT wDeviceID,
  163. LPWAVEOUTCAPS lpCaps,
  164. UINT wSize
  165. )
  166. {
  167. if (wSize == 0)
  168. return MMSYSERR_NOERROR;
  169. V_WPOINTER(lpCaps, wSize, MMSYSERR_INVALPARAM);
  170. if (ValidateHandle((HWAVEOUT)wDeviceID, TYPE_WAVEOUT)) {
  171. return((UINT)waveOMessage((HWAVE)wDeviceID,
  172. WODM_GETDEVCAPS,
  173. (DWORD)lpCaps,
  174. (DWORD)wSize));
  175. }
  176. return waveOIDMessage( wDeviceID, WODM_GETDEVCAPS, 0L,
  177. (DWORD)lpCaps, (DWORD)wSize);
  178. }
  179. /*****************************************************************************
  180. * @doc EXTERNAL WAVE
  181. *
  182. * @api UINT | waveOutGetVolume | This function queries the current volume
  183. * setting of a waveform output device.
  184. *
  185. * @parm UINT | wDeviceID | Identifies the waveform output device.
  186. *
  187. * @parm LPDWORD | lpdwVolume | Specifies a far pointer to a location to
  188. * be filled with the current volume setting. The low-order word of
  189. * this location contains the left channel volume setting, and the high-order
  190. * WORD contains the right channel setting. A value of 0xFFFF represents
  191. * full volume, and a value of 0x0000 is silence.
  192. *
  193. * If a device does not support both left and right volume
  194. * control, the low-order word of the specified location contains
  195. * the mono volume level.
  196. *
  197. * The full 16-bit setting(s)
  198. * set with <f waveOutSetVolume> is returned, regardless of whether
  199. * the device supports the full 16 bits of volume-level control.
  200. *
  201. *
  202. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  203. * an error number. Possible error returns are:
  204. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  205. * @flag MMSYSERR_NOTSUPPORTED | Function isn't supported.
  206. * @flag MMSYSERR_NODRIVER | The driver was not installed.
  207. *
  208. * @comm Not all devices support volume changes. To determine whether the
  209. * device supports volume control, use the WAVECAPS_VOLUME
  210. * flag to test the <e WAVEOUTCAPS.dwSupport> field of the <t WAVEOUTCAPS>
  211. * structure (filled by <f waveOutGetDevCaps>).
  212. *
  213. * To determine whether the device supports volume control on both
  214. * the left and right channels, use the WAVECAPS_VOLUME
  215. * flag to test the <e WAVEOUTCAPS.dwSupport> field of the <t WAVEOUTCAPS>
  216. * structure (filled by <f waveOutGetDevCaps>).
  217. *
  218. * @xref waveOutSetVolume
  219. ****************************************************************************/
  220. UINT WINAPI
  221. waveOutGetVolume(
  222. UINT wDeviceID,
  223. LPDWORD lpdwVolume
  224. )
  225. {
  226. V_WPOINTER(lpdwVolume, sizeof(DWORD), MMSYSERR_INVALPARAM);
  227. if (ValidateHandle((HWAVEOUT)wDeviceID, TYPE_WAVEOUT)) {
  228. return ( (UINT)waveOMessage( (HWAVE)wDeviceID,
  229. WODM_GETVOLUME,
  230. (DWORD)lpdwVolume,
  231. 0
  232. ));
  233. }
  234. return waveOIDMessage( wDeviceID,
  235. WODM_GETVOLUME, 0L, (DWORD)lpdwVolume, 0);
  236. }
  237. /*****************************************************************************
  238. * @doc EXTERNAL WAVE
  239. *
  240. * @api UINT | waveOutSetVolume | This function sets the volume of a
  241. * waveform output device.
  242. *
  243. * @parm UINT | wDeviceID | Identifies the waveform output device.
  244. *
  245. * @parm DWORD | dwVolume | Specifies the new volume setting. The
  246. * low-order word contains the left channel volume setting, and the
  247. * high-order word contains the right channel setting. A value of
  248. * 0xFFFF represents full volume, and a value of 0x0000 is silence.
  249. *
  250. * If a device does
  251. * not support both left and right volume control, the low-order word of
  252. * <p dwVolume> specifies the volume level, and the high-order word is
  253. * ignored.
  254. *
  255. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  256. * an error number. Possible error returns are:
  257. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  258. * @flag MMSYSERR_NOTSUPPORTED | Function isn't supported.
  259. * @flag MMSYSERR_NODRIVER | The driver was not installed.
  260. *
  261. * @comm Not all devices support volume changes. To determine whether the
  262. * device supports volume control, use the WAVECAPS_VOLUME
  263. * flag to test the <e WAVEOUTCAPS.dwSupport> field of the <t WAVEOUTCAPS>
  264. * structure (filled by <f waveOutGetDevCaps>).
  265. *
  266. * To determine whether the device supports volume control on both the
  267. * left and right channels, use the WAVECAPS_LRVOLUME flag
  268. * flag to test the <e WAVEOUTCAPS.dwSupport> field of the <t WAVEOUTCAPS>
  269. * structure (filled by <f waveOutGetDevCaps>).
  270. *
  271. * Most devices don't support the full 16 bits of volume level control
  272. * and will not use the high-order bits of the requested volume setting.
  273. * For example, for a device that supports 4 bits of volume control,
  274. * requested volume level values of 0x4000, 0x4fff, and 0x43be
  275. * all produce the same physical volume setting, 0x4000. The
  276. * <f waveOutGetVolume> function returns the full 16-bit setting set
  277. * with <f waveOutSetVolume>.
  278. *
  279. * Volume settings are interpreted logarithmically. This means the
  280. * perceived increase in volume is the same when increasing the
  281. * volume level from 0x5000 to 0x6000 as it is from 0x4000 to 0x5000.
  282. *
  283. * @xref waveOutGetVolume
  284. ****************************************************************************/
  285. UINT WINAPI
  286. waveOutSetVolume(
  287. UINT wDeviceID,
  288. DWORD dwVolume
  289. )
  290. {
  291. if (ValidateHandle((HWAVEOUT)wDeviceID, TYPE_WAVEOUT)) {
  292. return((UINT)waveOMessage((HWAVE)wDeviceID, WODM_SETVOLUME, dwVolume, 0));
  293. }
  294. return waveOIDMessage( wDeviceID, WODM_SETVOLUME, 0L, dwVolume, 0);
  295. }
  296. /*****************************************************************************
  297. * @doc INTERNAL WAVE
  298. *
  299. * @func UINT | waveGetErrorText | This function retrieves a textual
  300. * description of the error identified by the specified error number.
  301. *
  302. * @parm UINT | wError | Specifies the error number.
  303. *
  304. * @parm LPSTR | lpText | Specifies a far pointer to a buffer which
  305. * is filled with the textual error description.
  306. *
  307. * @parm UINT | wSize | Specifies the length of the buffer pointed to by
  308. * <p lpText>.
  309. *
  310. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  311. * an error number. Possible error returns are:
  312. * @flag MMSYSERR_BADERRNUM | Specified error number is out of range.
  313. *
  314. * @comm If the textual error description is longer than the specified buffer,
  315. * the description is truncated. The returned error string is always
  316. * null-terminated. If <p wSize> is zero, nothing is copied and MMSYSERR_NOERROR
  317. * is returned.
  318. ****************************************************************************/
  319. static UINT NEAR PASCAL
  320. waveGetErrorText(
  321. UINT wError,
  322. LPSTR lpText,
  323. UINT wSize
  324. )
  325. {
  326. lpText[0] = 0;
  327. #if MMSYSERR_BASE
  328. if ( ((wError < MMSYSERR_BASE) || (wError > MMSYSERR_LASTERROR))
  329. && ((wError < WAVERR_BASE) || (wError > WAVERR_LASTERROR))) {
  330. return MMSYSERR_BADERRNUM;
  331. }
  332. #else
  333. if ( (wError > MMSYSERR_LASTERROR)
  334. && ((wError < WAVERR_BASE) || (wError > WAVERR_LASTERROR))) {
  335. return MMSYSERR_BADERRNUM;
  336. }
  337. #endif
  338. if (wSize > 1) {
  339. if (!LoadString(ghInst, wError, lpText, wSize)) {
  340. return MMSYSERR_BADERRNUM;
  341. }
  342. }
  343. return MMSYSERR_NOERROR;
  344. }
  345. /*****************************************************************************
  346. * @doc EXTERNAL WAVE
  347. *
  348. * @api UINT | waveOutGetErrorText | This function retrieves a
  349. * textual description of the error identified by the specified
  350. * error number.
  351. *
  352. * @parm UINT | wError | Specifies the error number.
  353. *
  354. * @parm LPSTR | lpText | Specifies a far pointer to a buffer to be
  355. * filled with the textual error description.
  356. *
  357. * @parm UINT | wSize | Specifies the length of the buffer pointed
  358. * to by <p lpText>.
  359. *
  360. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  361. * an error number. Possible error returns are:
  362. * @flag MMSYSERR_BADERRNUM | Specified error number is out of range.
  363. *
  364. * @comm If the textual error description is longer than the specified buffer,
  365. * the description is truncated. The returned error string is always
  366. * null-terminated. If <p wSize> is zero, nothing is copied, and the function
  367. * returns zero. All error descriptions are less than MAXERRORLENGTH characters long.
  368. ****************************************************************************/
  369. UINT WINAPI
  370. waveOutGetErrorText(
  371. UINT wError,
  372. LPSTR lpText,
  373. UINT wSize
  374. )
  375. {
  376. if (wSize == 0) {
  377. return MMSYSERR_NOERROR;
  378. }
  379. V_WPOINTER(lpText, wSize, MMSYSERR_INVALPARAM);
  380. return waveGetErrorText(wError, lpText, wSize);
  381. }
  382. /*****************************************************************************
  383. * @doc EXTERNAL WAVE
  384. *
  385. * @api UINT | waveOutOpen | This function opens a specified waveform output
  386. * device for playback.
  387. *
  388. * @parm LPHWAVEOUT | lphWaveOut | Specifies a far pointer to an HWAVEOUT
  389. * handle. This location is filled with a handle identifying the opened
  390. * waveform output device. Use the handle to identify the device when
  391. * calling other waveform output functions. This parameter may be
  392. * NULL if the WAVE_FORMAT_QUERY flag is specified for <p dwFlags>.
  393. *
  394. * @parm UINT | wDeviceID | Identifies the waveform output device to open.
  395. * Use a valid device ID or the following flag:
  396. *
  397. * @flag WAVE_MAPPER | If this flag is specified, the function
  398. * selects a waveform output device
  399. * capable of playing the given format.
  400. *
  401. * @parm LPWAVEFORMAT | lpFormat | Specifies a pointer to a <t WAVEFORMAT>
  402. * structure that identifies the format of the waveform data
  403. * to be sent to the waveform output device.
  404. *
  405. * @parm DWORD | dwCallback | Specifies the address of a callback
  406. * function or a handle to a window called during waveform
  407. * playback to process messages related to the progress of the playback.
  408. * Specify NULL for this parameter if no callback is desired.
  409. *
  410. * @parm DWORD | dwCallbackInstance | Specifies user instance data
  411. * passed to the callback. This parameter is not used with
  412. * window callbacks.
  413. *
  414. * @parm DWORD | dwFlags | Specifies flags for opening the device.
  415. * @flag WAVE_FORMAT_QUERY | If this flag is specified, the device is
  416. * queried to determine if it supports the given format but is not
  417. * actually opened.
  418. * @flag WAVE_ALLOWSYNC | If this flag is not specified, then the
  419. * device will fail to open if it is a synchronous device.
  420. * @flag CALLBACK_WINDOW | If this flag is specified, <p dwCallback> is
  421. * assumed to be a window handle.
  422. * @flag CALLBACK_FUNCTION | If this flag is specified, <p dwCallback> is
  423. * assumed to be a callback procedure address.
  424. *
  425. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  426. * an error number. Possible error returns are:
  427. * @flag MMSYSERR_BADDEVICEID | Specified device ID is out of range.
  428. * @flag MMSYSERR_ALLOCATED | Specified resource is already allocated.
  429. * @flag MMSYSERR_NOMEM | Unable to allocate or lock memory.
  430. * @flag WAVERR_BADFORMAT | Attempted to open with an unsupported wave format.
  431. *
  432. * @comm Use <f waveOutGetNumDevs> to determine the number of waveform output
  433. * devices present in the system. The device ID specified by <p wDeviceID>
  434. * varies from zero to one less than the number of devices present.
  435. * The WAVE_MAPPER constant may also be used as a device id.
  436. *
  437. * The <t WAVEFORMAT> structure pointed to by <p lpFormat> may be extended
  438. * to include type-specific information for certain data formats.
  439. * For example, for PCM data, an extra UINT is added to specify the number
  440. * of bits per sample. Use the <t PCMWAVEFORMAT> structure in this case.
  441. *
  442. * If a window is chosen to receive callback information, the following
  443. * messages are sent to the window procedure function to indicate the
  444. * progress of waveform output: <m MM_WOM_OPEN>, <m MM_WOM_CLOSE>,
  445. * <m MM_WOM_DONE>
  446. *
  447. * If a function is chosen to receive callback information, the following
  448. * messages are sent to the function to indicate the progress of waveform
  449. * output: <m WOM_OPEN>, <m WOM_CLOSE>, <m WOM_DONE>. The callback function
  450. * must reside in a DLL. You do not have to use <f MakeProcInstance> to get
  451. * a procedure-instance address for the callback function.
  452. *
  453. * @cb void CALLBACK | WaveOutFunc | <f WaveOutFunc> is a placeholder for the
  454. * application-supplied function name. The actual name must be exported by
  455. * including it in an EXPORTS statement in the DLL's module-definition file.
  456. *
  457. * @parm HWAVEOUT | hWaveOut | Specifies a handle to the waveform device
  458. * associated with the callback.
  459. *
  460. * @parm UINT | wMsg | Specifies a waveform output message.
  461. *
  462. * @parm DWORD | dwInstance | Specifies the user instance data
  463. * specified with <f waveOutOpen>.
  464. *
  465. * @parm DWORD | dwParam1 | Specifies a parameter for the message.
  466. *
  467. * @parm DWORD | dwParam2 | Specifies a parameter for the message.
  468. *
  469. * @comm Because the callback is accessed at interrupt time, it must reside
  470. * in a DLL and its code segment must be specified as FIXED in the
  471. * module-definition file for the DLL. Any data that the callback accesses
  472. * must be in a FIXED data segment as well. The callback may not make any
  473. * system calls except for <f PostMessage>, <f timeGetSystemTime>,
  474. * <f timeGetTime>, <f timeSetEvent>, <f timeKillEvent>,
  475. * <f midiOutShortMsg>, <f midiOutLongMsg>, and <f OutputDebugStr>.
  476. *
  477. * @xref waveOutClose
  478. ****************************************************************************/
  479. UINT WINAPI
  480. waveOutOpen(
  481. LPHWAVEOUT lphWaveOut,
  482. UINT wDeviceID,
  483. const WAVEFORMAT FAR* lpFormat,
  484. DWORD dwCallback,
  485. DWORD dwInstance,
  486. DWORD dwFlags
  487. )
  488. {
  489. WAVEOPENDESC wo;
  490. PWAVEDEV pdev;
  491. UINT wRet;
  492. DWORD dwDrvUser;
  493. V_RPOINTER(lpFormat, sizeof(WAVEFORMAT), MMSYSERR_INVALPARAM);
  494. V_DCALLBACK(dwCallback, HIWORD(dwFlags), MMSYSERR_INVALPARAM);
  495. V_FLAGS(LOWORD(dwFlags), WAVE_VALID, waveOutOpen, MMSYSERR_INVALFLAG);
  496. if (!(dwFlags & WAVE_FORMAT_QUERY)) {
  497. V_WPOINTER(lphWaveOut, sizeof(HWAVEOUT), MMSYSERR_INVALPARAM);
  498. *lphWaveOut = NULL;
  499. }
  500. /*
  501. ** Check for no devices
  502. */
  503. // if (wTotalWaveOutDevs == 0 ) {
  504. // return MMSYSERR_BADDEVICEID;
  505. // }
  506. //
  507. // /*
  508. // ** check for device ID being to large
  509. // */
  510. // if ( wDeviceID != WAVE_MAPPER ) {
  511. // if ( wDeviceID >= wTotalWaveOutDevs ) {
  512. // return MMSYSERR_BADDEVICEID;
  513. // }
  514. // }
  515. if (dwFlags & WAVE_FORMAT_QUERY) {
  516. pdev = NULL;
  517. }
  518. else {
  519. if (!(pdev = (PWAVEDEV)NewHandle(TYPE_WAVEOUT, sizeof(WAVEDEV)))) {
  520. return MMSYSERR_NOMEM;
  521. }
  522. pdev->wDevice = wDeviceID;
  523. pdev->wDeviceID = wDeviceID;
  524. }
  525. wo.hWave = (HWAVE)pdev;
  526. wo.dwCallback = dwCallback;
  527. wo.dwInstance = dwInstance;
  528. wo.lpFormat = lpFormat;
  529. if ( (wDeviceID == WAVE_MAPPER) && (wodMapper != NULL) ) {
  530. wRet = (UINT)((*(wodMapper))(0, WODM_OPEN,
  531. (DWORD)(LPDWORD)&dwDrvUser,
  532. (DWORD)(LPWAVEOPENDESC)&wo,
  533. dwFlags));
  534. }
  535. else {
  536. wRet = waveOIDMessage( wDeviceID, WODM_OPEN, (DWORD)(LPDWORD)&dwDrvUser,
  537. (DWORD)(LPWAVEOPENDESC)&wo, dwFlags );
  538. }
  539. if (pdev) {
  540. if (wRet) {
  541. FreeHandle((HWAVEOUT)pdev);
  542. }
  543. else {
  544. *lphWaveOut = (HWAVEOUT)pdev;
  545. pdev->dwDrvUser = dwDrvUser;
  546. }
  547. }
  548. return wRet;
  549. }
  550. /*****************************************************************************
  551. * @doc EXTERNAL WAVE
  552. *
  553. * @api UINT | waveOutClose | This function closes the specified waveform
  554. * output device.
  555. *
  556. * @parm HWAVEOUT | hWaveOut | Specifies a handle to the waveform output
  557. * device. If the function is successful, the handle is no
  558. * longer valid after this call.
  559. *
  560. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  561. * an error number. Possible error returns are:
  562. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  563. * @flag WAVERR_STILLPLAYING | There are still buffers in the queue.
  564. *
  565. * @comm If the device is still playing a waveform, the close
  566. * operation will fail. Use <f waveOutReset> to terminate waveform
  567. * playback before calling <f waveOutClose>.
  568. *
  569. * @xref waveOutOpen waveOutReset
  570. ****************************************************************************/
  571. UINT WINAPI waveOutClose(HWAVEOUT hWaveOut)
  572. {
  573. UINT wRet;
  574. V_HANDLE(hWaveOut, TYPE_WAVEOUT, MMSYSERR_INVALHANDLE);
  575. wRet = (UINT)waveOMessage( (HWAVE)hWaveOut, WODM_CLOSE, 0L,0L);
  576. if (!wRet) {
  577. FreeHandle(hWaveOut);
  578. }
  579. return wRet;
  580. }
  581. /*****************************************************************************
  582. * @doc EXTERNAL WAVE
  583. *
  584. * @api UINT | waveOutPrepareHeader | This function prepares a
  585. * waveform data block for playback.
  586. *
  587. * @parm HWAVEOUT | hWaveOut | Specifies a handle to the waveform output
  588. * device.
  589. *
  590. * @parm LPWAVEHDR | lpWaveOutHdr | Specifies a pointer to a
  591. * <t WAVEHDR> structure that identifies the data block to be prepared.
  592. *
  593. * @parm UINT | wSize | Specifies the size of the <t WAVEHDR> structure.
  594. *
  595. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  596. * an error number. Possible error returns are:
  597. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  598. * @flag MMSYSERR_NOMEM | Unable to allocate or lock memory.
  599. *
  600. * @comm The <t WAVEHDR> data structure and the data block pointed to by its
  601. * <e WAVEHDR.lpData> field must be allocated with <f GlobalAlloc> using the
  602. * GMEM_MOVEABLE and GMEM_SHARE flags, and locked with <f GlobalLock>.
  603. * Preparing a header that has already been prepared has no effect, and
  604. * the function returns zero.
  605. *
  606. * @xref waveOutUnprepareHeader
  607. ****************************************************************************/
  608. UINT WINAPI
  609. waveOutPrepareHeader(
  610. HWAVEOUT hWaveOut,
  611. LPWAVEHDR lpWaveOutHdr,
  612. UINT wSize
  613. )
  614. {
  615. UINT wRet;
  616. V_HANDLE(hWaveOut, TYPE_WAVEOUT, MMSYSERR_INVALHANDLE);
  617. V_HEADER(lpWaveOutHdr, wSize, TYPE_WAVEOUT, MMSYSERR_INVALPARAM);
  618. if (IsWaveHeaderPrepared(hWaveOut, lpWaveOutHdr)) {
  619. DebugErr(DBF_WARNING,"waveOutPrepareHeader: header is already prepared.");
  620. return MMSYSERR_NOERROR;
  621. }
  622. lpWaveOutHdr->dwFlags &= (WHDR_BEGINLOOP | WHDR_ENDLOOP);
  623. wRet = wavePrepareHeader(lpWaveOutHdr, wSize);
  624. if (wRet == MMSYSERR_NOERROR) {
  625. wRet = (UINT)waveOMessage( (HWAVE)hWaveOut, WODM_PREPARE,
  626. (DWORD)lpWaveOutHdr, (DWORD)wSize);
  627. }
  628. return wRet;
  629. }
  630. /*****************************************************************************
  631. * @doc EXTERNAL WAVE
  632. *
  633. * @api UINT | waveOutUnprepareHeader | This function cleans up the
  634. * preparation performed by <f waveOutPrepareHeader>. The function
  635. * must be called after
  636. * the device driver is finished with a data block. You must call this
  637. * function before freeing the data buffer.
  638. *
  639. * @parm HWAVEOUT | hWaveOut | Specifies a handle to the waveform output
  640. * device.
  641. *
  642. * @parm LPWAVEHDR | lpWaveOutHdr | Specifies a pointer to a <t WAVEHDR>
  643. * structure identifying the data block to be cleaned up.
  644. *
  645. * @parm UINT | wSize | Specifies the size of the <t WAVEHDR> structure.
  646. *
  647. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  648. * an error number. Possible error returns are:
  649. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  650. * @flag WAVERR_STILLPLAYING | <p lpWaveOutHdr> is still in the queue.
  651. *
  652. * @comm This function is the complementary function to
  653. * <f waveOutPrepareHeader>. You must call this function before freeing the
  654. * data buffer with <f GlobalFree>.
  655. * After passing a buffer to the device driver with <f waveOutWrite>, you
  656. * must wait until the driver is finished with the buffer before calling
  657. * <f waveOutUnprepareHeader>.
  658. *
  659. * Unpreparing a buffer that has not been
  660. * prepared has no effect, and the function returns zero.
  661. *
  662. * @xref waveOutPrepareHeader
  663. ****************************************************************************/
  664. UINT WINAPI
  665. waveOutUnprepareHeader(
  666. HWAVEOUT hWaveOut,
  667. LPWAVEHDR lpWaveOutHdr,
  668. UINT wSize
  669. )
  670. {
  671. UINT wRet;
  672. V_HANDLE(hWaveOut, TYPE_WAVEOUT, MMSYSERR_INVALHANDLE);
  673. V_HEADER(lpWaveOutHdr, wSize, TYPE_WAVEOUT, MMSYSERR_INVALPARAM);
  674. if(lpWaveOutHdr->dwFlags & WHDR_INQUEUE) {
  675. DebugErr(DBF_WARNING,"waveOutUnprepareHeader: header still in queue.");
  676. return WAVERR_STILLPLAYING;
  677. }
  678. if (!IsWaveHeaderPrepared(hWaveOut, lpWaveOutHdr)) {
  679. DebugErr(DBF_WARNING,"waveOutUnprepareHeader: header is not prepared.");
  680. return MMSYSERR_NOERROR;
  681. }
  682. wRet = waveUnprepareHeader(lpWaveOutHdr, wSize);
  683. if (wRet == MMSYSERR_NOERROR) {
  684. wRet = (UINT)waveOMessage( (HWAVE)hWaveOut, WODM_UNPREPARE,
  685. (DWORD)lpWaveOutHdr, (DWORD)wSize);
  686. }
  687. return wRet;
  688. }
  689. /*****************************************************************************
  690. * @doc EXTERNAL WAVE
  691. *
  692. * @api UINT | waveOutWrite | This function sends a data block to the
  693. * specified waveform output device.
  694. *
  695. * @parm HWAVEOUT | hWaveOut | Specifies a handle to the waveform output
  696. * device.
  697. *
  698. * @parm LPWAVEHDR | lpWaveOutHdr | Specifies a far pointer to a <t WAVEHDR>
  699. * structure containing information about the data block.
  700. *
  701. * @parm UINT | wSize | Specifies the size of the <t WAVEHDR> structure.
  702. *
  703. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  704. * an error number. Possible error returns are:
  705. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  706. * @flag WAVERR_UNPREPARED | <p lpWaveOutHdr> hasn't been prepared.
  707. *
  708. * @comm The data buffer must be prepared with <f waveOutPrepareHeader> before
  709. * it is passed to <f waveOutWrite>. The <t WAVEHDR> data structure
  710. * and the data buffer pointed to by its <e WAVEHDR.lpData> field must be allocated
  711. * with <f GlobalAlloc> using the GMEM_MOVEABLE and GMEM_SHARE flags, and
  712. * locked with <f GlobalLock>. Unless the device is paused by calling
  713. * <f waveOutPause>, playback begins when the first data block is sent to
  714. * the device.
  715. *
  716. * @xref waveOutPrepareHeader waveOutPause waveOutReset waveOutRestart
  717. ****************************************************************************/
  718. UINT WINAPI
  719. waveOutWrite(
  720. HWAVEOUT hWaveOut,
  721. LPWAVEHDR lpWaveOutHdr,
  722. UINT wSize
  723. )
  724. {
  725. V_HANDLE(hWaveOut, TYPE_WAVEOUT, MMSYSERR_INVALHANDLE);
  726. V_HEADER(lpWaveOutHdr, wSize, TYPE_WAVEOUT, MMSYSERR_INVALPARAM);
  727. if (!IsWaveHeaderPrepared(hWaveOut, lpWaveOutHdr)) {
  728. DebugErr(DBF_WARNING,"waveOutWrite: header not prepared");
  729. return WAVERR_UNPREPARED;
  730. }
  731. if (lpWaveOutHdr->dwFlags & WHDR_INQUEUE) {
  732. DebugErr(DBF_WARNING,"waveOutWrite: header is still in queue");
  733. return WAVERR_STILLPLAYING;
  734. }
  735. lpWaveOutHdr->dwFlags &= ~WHDR_DONE;
  736. return (UINT)waveOMessage( (HWAVE)hWaveOut, WODM_WRITE,
  737. (DWORD)lpWaveOutHdr, (DWORD)wSize );
  738. }
  739. /*****************************************************************************
  740. * @doc EXTERNAL WAVE
  741. *
  742. * @api UINT | waveOutPause | This function pauses playback on a specified
  743. * waveform output device. The current playback position is saved. Use
  744. * <f waveOutRestart> to resume playback from the current playback position.
  745. *
  746. * @parm HWAVEOUT | hWaveOut | Specifies a handle to the waveform output
  747. * device.
  748. *
  749. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  750. * an error number. Possible error returns are:
  751. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  752. *
  753. * @comm Calling this function when the output is already paused has no
  754. * effect, and the function returns zero.
  755. *
  756. * @xref waveOutRestart waveOutBreakLoop
  757. ****************************************************************************/
  758. UINT WINAPI
  759. waveOutPause(
  760. HWAVEOUT hWaveOut
  761. )
  762. {
  763. V_HANDLE(hWaveOut, TYPE_WAVEOUT, MMSYSERR_INVALHANDLE);
  764. return (UINT)waveOMessage( (HWAVE)hWaveOut, WODM_PAUSE, 0L, 0L);
  765. }
  766. /*****************************************************************************
  767. * @doc EXTERNAL WAVE
  768. *
  769. * @api UINT | waveOutRestart | This function restarts a paused waveform
  770. * output device.
  771. *
  772. * @parm HWAVEOUT | hWaveOut | Specifies a handle to the waveform output
  773. * device.
  774. *
  775. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  776. * an error number. Possible error returns are:
  777. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  778. *
  779. * @comm Calling this function when the output is not paused has no
  780. * effect, and the function returns zero.
  781. *
  782. * @xref waveOutPause waveOutBreakLoop
  783. ****************************************************************************/
  784. UINT WINAPI
  785. waveOutRestart(
  786. HWAVEOUT hWaveOut
  787. )
  788. {
  789. V_HANDLE(hWaveOut, TYPE_WAVEOUT, MMSYSERR_INVALHANDLE);
  790. return (UINT)waveOMessage( (HWAVE)hWaveOut, WODM_RESTART, 0L, 0L);
  791. }
  792. /*****************************************************************************
  793. * @doc EXTERNAL WAVE
  794. *
  795. * @api UINT | waveOutReset | This function stops playback on a given waveform
  796. * output device and resets the current position to 0. All pending
  797. * playback buffers are marked as done and returned to the application.
  798. *
  799. * @parm HWAVEOUT | hWaveOut | Specifies a handle to the waveform output
  800. * device.
  801. *
  802. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  803. * an error number. Possible error returns are:
  804. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  805. *
  806. * @xref waveOutWrite waveOutClose
  807. /****************************************************************************/
  808. UINT WINAPI
  809. waveOutReset(
  810. HWAVEOUT hWaveOut
  811. )
  812. {
  813. V_HANDLE(hWaveOut, TYPE_WAVEOUT, MMSYSERR_INVALHANDLE);
  814. return (UINT)waveOMessage( (HWAVE)hWaveOut, WODM_RESET, 0L, 0L);
  815. }
  816. /*****************************************************************************
  817. * @doc EXTERNAL WAVE
  818. *
  819. * @api UINT | waveOutBreakLoop | This function breaks a loop on a
  820. * given waveform output device and allows playback to continue with the
  821. * next block in the driver list.
  822. *
  823. * @parm HWAVEOUT | hWaveOut | Specifies a handle to the waveform output
  824. * device.
  825. *
  826. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  827. * an error number. Possible error returns are:
  828. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  829. *
  830. * @comm Waveform looping is controlled by the <e WAVEHDR.dwLoops> and
  831. * <e WAVEHDR.dwFlags> fields in the <t WAVEHDR> structures passed to the device
  832. * with <f waveOutWrite>. Use the WHDR_BEGINLOOP and WHDR_ENDLOOP flags
  833. * in the <e WAVEHDR.dwFlags> field to specify the beginning and ending data
  834. * blocks for looping.
  835. *
  836. * To loop on a single block, specify both flags for the same block.
  837. * To specify the number of loops, use the <e WAVEHDR.dwLoops> field in
  838. * the <t WAVEHDR> structure for the first block in the loop.
  839. *
  840. * The blocks making up the loop are played to the end before the loop
  841. * is terminated.
  842. *
  843. * Calling this function when the nothing is playing or looping has no
  844. * effect, and the function returns zero.
  845. *
  846. * @xref waveOutWrite waveOutPause waveOutRestart
  847. /****************************************************************************/
  848. UINT WINAPI
  849. waveOutBreakLoop(
  850. HWAVEOUT hWaveOut
  851. )
  852. {
  853. V_HANDLE(hWaveOut, TYPE_WAVEOUT, MMSYSERR_INVALHANDLE);
  854. return (UINT)waveOMessage( (HWAVE)hWaveOut, WODM_BREAKLOOP, 0L, 0L );
  855. }
  856. /*****************************************************************************
  857. * @doc EXTERNAL WAVE
  858. *
  859. * @api UINT | waveOutGetPosition | This function retrieves the current
  860. * playback position of the specified waveform output device.
  861. *
  862. * @parm HWAVEOUT | hWaveOut | Specifies a handle to the waveform output
  863. * device.
  864. *
  865. * @parm LPMMTIME | lpInfo | Specifies a far pointer to an <t MMTIME>
  866. * structure.
  867. *
  868. * @parm UINT | wSize | Specifies the size of the <t MMTIME> structure.
  869. *
  870. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  871. * an error number. Possible error returns are:
  872. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  873. *
  874. * @comm Before calling <f waveOutGetPosition>, set the <e MMTIME.wType> field of the
  875. * MMTIME structure to indicate the time format that you desire. After
  876. * calling <f waveOutGetPosition>, check the <e MMTIME.wType> field
  877. * to determine if the desired time format is supported. If the desired
  878. * format is not supported, <e MMTIME.wType> will specify an alternative format.
  879. *
  880. * The position is set to zero when the device is opened or reset.
  881. ****************************************************************************/
  882. UINT WINAPI
  883. waveOutGetPosition(
  884. HWAVEOUT hWaveOut,
  885. LPMMTIME lpInfo,
  886. UINT wSize
  887. )
  888. {
  889. V_HANDLE(hWaveOut, TYPE_WAVEOUT, MMSYSERR_INVALHANDLE);
  890. V_WPOINTER(lpInfo, wSize, MMSYSERR_INVALPARAM);
  891. return (UINT)waveOMessage( (HWAVE)hWaveOut, WODM_GETPOS,
  892. (DWORD)lpInfo, (DWORD)wSize );
  893. }
  894. /*****************************************************************************
  895. * @doc EXTERNAL WAVE
  896. *
  897. * @api UINT | waveOutGetPitch | This function queries the the current pitch
  898. * setting of a waveform output device.
  899. *
  900. * @parm HWAVEOUT | hWaveOut | Specifies a handle to the waveform output
  901. * device.
  902. *
  903. * @parm LPDWORD | lpdwPitch | Specifies a far pointer to a location
  904. * to be filled with the current pitch multiplier setting. The pitch
  905. * multiplier indicates the current change in pitch from the original
  906. * authored setting. The pitch multiplier must be a positive value.
  907. *
  908. * The pitch multiplier is specified as a fixed-point value. The high-order word
  909. * of the DWORD location contains the signed integer part of the number,
  910. * and the low-order word contains the fractional part. The fraction is
  911. * expressed as a WORD in which a value of 0x8000 represents one half,
  912. * and 0x4000 represents one quarter. For example, the value 0x00010000
  913. * specifies a multiplier of 1.0 (no pitch change), and a value of
  914. * 0x000F8000 specifies a multiplier of 15.5.
  915. *
  916. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  917. * an error number. Possible error returns are:
  918. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  919. * @flag MMSYSERR_NOTSUPPORTED | Function isn't supported.
  920. *
  921. * @comm Changing the pitch does not change the playback rate, sample
  922. * rate, or playback time. Not all devices support
  923. * pitch changes. To determine whether the device supports pitch control,
  924. * use the WAVECAPS_PITCH flag to test the <e WAVEOUTCAPS.dwSupport>
  925. * field of the <t WAVEOUTCAPS> structure (filled by <f waveOutGetDevCaps>).
  926. *
  927. * @xref waveOutSetPitch waveOutGetPlaybackRate waveOutSetPlaybackRate
  928. ****************************************************************************/
  929. UINT WINAPI
  930. waveOutGetPitch(
  931. HWAVEOUT hWaveOut,
  932. LPDWORD lpdwPitch
  933. )
  934. {
  935. V_HANDLE(hWaveOut, TYPE_WAVEOUT, MMSYSERR_INVALHANDLE);
  936. V_WPOINTER(lpdwPitch, sizeof(DWORD), MMSYSERR_INVALPARAM);
  937. return (UINT)waveOMessage( (HWAVE)hWaveOut, WODM_GETPITCH,
  938. (DWORD)lpdwPitch, 0L);
  939. }
  940. /*****************************************************************************
  941. * @doc EXTERNAL WAVE
  942. *
  943. * @api UINT | waveOutSetPitch | This function sets the pitch of a waveform
  944. * output device.
  945. *
  946. * @parm HWAVEOUT | hWaveOut | Specifies a handle to the waveform
  947. * output device.
  948. *
  949. * @parm DWORD | dwPitch | Specifies the new pitch multiplier setting.
  950. * The pitch multiplier setting indicates the current change in pitch
  951. * from the original authored setting. The pitch multiplier must be a
  952. * positive value.
  953. *
  954. * The pitch multiplier is specified as a fixed-point value. The high-order word
  955. * location contains the signed integer part of the number,
  956. * and the low-order word contains the fractional part. The fraction is
  957. * expressed as a WORD in which a value of 0x8000 represents one half,
  958. * and 0x4000 represents one quarter.
  959. * For example, the value 0x00010000 specifies a multiplier
  960. * of 1.0 (no pitch change), and a value of 0x000F8000 specifies a
  961. * multiplier of 15.5.
  962. *
  963. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  964. * an error number. Possible error returns are:
  965. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  966. * @flag MMSYSERR_NOTSUPPORTED | Function isn't supported.
  967. *
  968. * @comm Changing the pitch does not change the playback rate or the sample
  969. * rate. The playback time is also unchanged. Not all devices support
  970. * pitch changes. To determine whether the device supports pitch control,
  971. * use the WAVECAPS_PITCH flag to test the <e WAVEOUTCAPS.dwSupport>
  972. * field of the <t WAVEOUTCAPS> structure (filled by <f waveOutGetDevCaps>).
  973. *
  974. * @xref waveOutGetPitch waveOutSetPlaybackRate waveOutGetPlaybackRate
  975. ****************************************************************************/
  976. UINT WINAPI
  977. waveOutSetPitch(
  978. HWAVEOUT hWaveOut,
  979. DWORD dwPitch
  980. )
  981. {
  982. V_HANDLE(hWaveOut, TYPE_WAVEOUT, MMSYSERR_INVALHANDLE);
  983. return (UINT)waveOMessage( (HWAVE)hWaveOut, WODM_SETPITCH, dwPitch, 0L );
  984. }
  985. /*****************************************************************************
  986. * @doc EXTERNAL WAVE
  987. *
  988. * @api UINT | waveOutGetPlaybackRate | This function queries the
  989. * current playback rate setting of a waveform output device.
  990. *
  991. * @parm HWAVEOUT | hWaveOut | Specifies a handle to the waveform output
  992. * device.
  993. *
  994. * @parm LPDWORD | lpdwRate | Specifies a far pointer to a location
  995. * to be filled with the current playback rate. The playback rate setting
  996. * is a multiplier indicating the current change in playback rate from
  997. * the original authored setting. The playback rate multiplier must be
  998. * a positive value.
  999. *
  1000. * The rate is specified as a fixed-point value. The high-order word
  1001. * of the DWORD location contains the signed integer part of the number,
  1002. * and the low-order word contains the fractional part. The fraction is
  1003. * expressed as a WORD in which a value of 0x8000 represents one half,
  1004. * and 0x4000 represents one quarter. For example, the value 0x00010000
  1005. * specifies a multiplier of 1.0 (no playback rate change), and a value
  1006. * of 0x000F8000 specifies a multiplier of 15.5.
  1007. *
  1008. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  1009. * an error number. Possible error returns are:
  1010. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  1011. * @flag MMSYSERR_NOTSUPPORTED | Function isn't supported.
  1012. *
  1013. * @comm Changing the playback rate does not change the sample rate but does
  1014. * change the playback time.
  1015. *
  1016. * Not all devices support playback rate changes. To determine whether a
  1017. * device supports playback rate changes, use
  1018. * the WAVECAPS_PLAYBACKRATE flag to test the <e WAVEOUTCAPS.dwSupport> field of the
  1019. * <t WAVEOUTCAPS> structure (filled by <f waveOutGetDevCaps>).
  1020. *
  1021. * @xref waveOutSetPlaybackRate waveOutSetPitch waveOutGetPitch
  1022. ****************************************************************************/
  1023. UINT WINAPI
  1024. waveOutGetPlaybackRate(
  1025. HWAVEOUT hWaveOut,
  1026. LPDWORD lpdwRate
  1027. )
  1028. {
  1029. V_HANDLE(hWaveOut, TYPE_WAVEOUT, MMSYSERR_INVALHANDLE);
  1030. V_WPOINTER(lpdwRate, sizeof(DWORD), MMSYSERR_INVALPARAM);
  1031. return (UINT)waveOMessage( (HWAVE)hWaveOut,
  1032. WODM_GETPLAYBACKRATE, (DWORD)lpdwRate, 0L );
  1033. }
  1034. /*****************************************************************************
  1035. * @doc EXTERNAL WAVE
  1036. *
  1037. * @api UINT | waveOutSetPlaybackRate | This function sets the
  1038. * playback rate of a waveform output device.
  1039. *
  1040. * @parm HWAVEOUT | hWaveOut | Specifies a handle to the waveform
  1041. * output device.
  1042. *
  1043. * @parm DWORD | dwRate | Specifies the new playback rate setting.
  1044. * The playback rate setting is a multiplier indicating the current
  1045. * change in playback rate from the original authored setting. The playback
  1046. * rate multiplier must be a positive value.
  1047. *
  1048. * The rate is specified as a fixed-point value. The high-order word
  1049. * contains the signed integer part of the number,
  1050. * and the low-order word contains the fractional part. The fraction is
  1051. * expressed as a WORD in which a value of 0x8000 represents one half,
  1052. * and 0x4000 represents one quarter.
  1053. * For example, the value 0x00010000 specifies a multiplier of 1.0 (no
  1054. * playback rate change), and a value of 0x000F8000 specifies a
  1055. * multiplier of 15.5.
  1056. *
  1057. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  1058. * an error number. Possible error returns are:
  1059. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  1060. * @flag MMSYSERR_NOTSUPPORTED | Function isn't supported.
  1061. *
  1062. * @comm Changing the playback rate does not change the sample rate but does
  1063. * change the playback time.
  1064. *
  1065. * Not all devices support playback rate changes. To determine whether a
  1066. * device supports playback rate changes,
  1067. * use the WAVECAPS_PLAYBACKRATE flag to test the <e WAVEOUTCAPS.dwSupport> field of the
  1068. * <t WAVEOUTCAPS> structure (filled by <f waveOutGetDevCaps>).
  1069. *
  1070. * @xref waveOutGetPlaybackRate waveOutSetPitch waveOutGetPitch
  1071. ****************************************************************************/
  1072. UINT WINAPI
  1073. waveOutSetPlaybackRate(
  1074. HWAVEOUT hWaveOut,
  1075. DWORD dwRate
  1076. )
  1077. {
  1078. V_HANDLE(hWaveOut, TYPE_WAVEOUT, MMSYSERR_INVALHANDLE);
  1079. return (UINT)waveOMessage( (HWAVE)hWaveOut, WODM_SETPLAYBACKRATE, dwRate, 0L );
  1080. }
  1081. /////////////////////////////////////////////////////////////////////////////
  1082. /////////////////////////////////////////////////////////////////////////////
  1083. /*****************************************************************************
  1084. * @doc EXTERNAL WAVE
  1085. *
  1086. * @api UINT | waveInGetNumDevs | This function returns the number of waveform
  1087. * input devices.
  1088. *
  1089. * @rdesc Returns the number of waveform input devices present in the system.
  1090. *
  1091. * @xref waveInGetDevCaps
  1092. ****************************************************************************/
  1093. UINT WINAPI
  1094. waveInGetNumDevs(
  1095. void
  1096. )
  1097. {
  1098. return waveIIDMessage( 0, WIDM_GETNUMDEVS, 0L, 0L, 0L );
  1099. }
  1100. /*****************************************************************************
  1101. * @doc EXTERNAL WAVE
  1102. *
  1103. * @api DWORD | waveInMessage | This function sends messages to the waveform
  1104. * output device drivers.
  1105. *
  1106. * @parm HWAVEIN | hWave | The handle to the audio device.
  1107. *
  1108. * @parm UINT | wMsg | The message to send.
  1109. *
  1110. * @parm DWORD | dw1 | Parameter 1.
  1111. *
  1112. * @parm DWORD | dw2 | Parameter 2.
  1113. *
  1114. * @rdesc Returns the value returned from the driver.
  1115. ****************************************************************************/
  1116. DWORD WINAPI
  1117. waveInMessage(
  1118. HWAVEIN hWaveIn,
  1119. UINT msg,
  1120. DWORD dw1,
  1121. DWORD dw2
  1122. )
  1123. {
  1124. V_HANDLE(hWaveIn, TYPE_WAVEIN, 0L);
  1125. return waveIMessage((HWAVE)hWaveIn, msg, dw1, dw2);
  1126. }
  1127. /*****************************************************************************
  1128. * @doc EXTERNAL WAVE
  1129. *
  1130. * @api UINT | waveInGetDevCaps | This function queries a specified waveform
  1131. * input device to determine its capabilities.
  1132. *
  1133. * @parm UINT | wDeviceID | Identifies the waveform input device.
  1134. *
  1135. * @parm LPWAVEINCAPS | lpCaps | Specifies a far pointer to a <t WAVEINCAPS>
  1136. * structure. This structure is filled with information about the
  1137. * capabilities of the device.
  1138. *
  1139. * @parm UINT | wSize | Specifies the size of the <t WAVEINCAPS> structure.
  1140. *
  1141. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  1142. * an error number. Possible error returns are:
  1143. * @flag MMSYSERR_BADDEVICEID | Specified device ID is out of range.
  1144. * @flag MMSYSERR_NODRIVER | The driver was not installed.
  1145. *
  1146. * @comm Use <f waveInGetNumDevs> to determine the number of waveform input
  1147. * devices present in the system. The device ID specified by <p wDeviceID>
  1148. * varies from zero to one less than the number of devices present.
  1149. * The WAVE_MAPPER constant may also be used as a device id. Only
  1150. * <p wSize> bytes (or less) of information is copied to the location
  1151. * pointed to by <p lpCaps>. If <p wSize> is zero, nothing is copied, and
  1152. * the function returns zero.
  1153. *
  1154. * @xref waveInGetNumDevs
  1155. ****************************************************************************/
  1156. UINT WINAPI
  1157. waveInGetDevCaps(
  1158. UINT wDeviceID,
  1159. LPWAVEINCAPS lpCaps,
  1160. UINT wSize
  1161. )
  1162. {
  1163. if (wSize == 0) {
  1164. return MMSYSERR_NOERROR;
  1165. }
  1166. V_WPOINTER(lpCaps, wSize, MMSYSERR_INVALPARAM);
  1167. if (ValidateHandle((HWAVEIN)wDeviceID, TYPE_WAVEIN)) {
  1168. return((UINT)waveIMessage((HWAVE)wDeviceID,
  1169. WIDM_GETDEVCAPS,
  1170. (DWORD)lpCaps,
  1171. (DWORD)wSize));
  1172. }
  1173. return waveIIDMessage( wDeviceID, WIDM_GETDEVCAPS,
  1174. 0L, (DWORD)lpCaps, (DWORD)wSize);
  1175. }
  1176. /*****************************************************************************
  1177. * @doc EXTERNAL WAVE
  1178. *
  1179. * @api UINT | waveInGetErrorText | This function retrieves a textual
  1180. * description of the error identified by the specified error number.
  1181. *
  1182. * @parm UINT | wError | Specifies the error number.
  1183. *
  1184. * @parm LPSTR | lpText | Specifies a far pointer to the buffer to be
  1185. * filled with the textual error description.
  1186. *
  1187. * @parm UINT | wSize | Specifies the size of the buffer pointed
  1188. * to by <p lpText>.
  1189. *
  1190. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  1191. * an error number. Possible error returns are:
  1192. * @flag MMSYSERR_BADERRNUM | Specified error number is out of range.
  1193. *
  1194. * @comm If the textual error description is longer than the specified buffer,
  1195. * the description is truncated. The returned error string is always
  1196. * null-terminated. If <p wSize> is zero, nothing is copied, and the function
  1197. * returns zero. All error descriptions are less than MAXERRORLENGTH characters long.
  1198. ****************************************************************************/
  1199. UINT WINAPI
  1200. waveInGetErrorText(
  1201. UINT wError,
  1202. LPSTR lpText,
  1203. UINT wSize
  1204. )
  1205. {
  1206. if (wSize == 0) {
  1207. return MMSYSERR_NOERROR;
  1208. }
  1209. V_WPOINTER(lpText, wSize, MMSYSERR_INVALPARAM);
  1210. return waveGetErrorText(wError, lpText, wSize);
  1211. }
  1212. /*****************************************************************************
  1213. * @doc EXTERNAL WAVE
  1214. *
  1215. * @api UINT | waveInOpen | This function opens a specified waveform
  1216. * input device for recording.
  1217. *
  1218. * @parm LPHWAVEIN | lphWaveIn | Specifies a far pointer to a HWAVEIN
  1219. * handle. This location is filled with a handle identifying the opened
  1220. * waveform input device. Use this handle to identify the device when
  1221. * calling other waveform input functions. This parameter may be NULL
  1222. * if the WAVE_FORMAT_QUERY flag is specified for <p dwFlags>.
  1223. *
  1224. * @parm UINT | wDeviceID | Identifies the waveform input device to open. Use
  1225. * a valid device ID or the following flag:
  1226. *
  1227. * @flag WAVE_MAPPER | If this flag is specified, the function
  1228. * selects a waveform input device capable of recording in the
  1229. * given format.
  1230. *
  1231. * @parm LPWAVEFORMAT | lpFormat | Specifies a pointer to a <t WAVEFORMAT>
  1232. * data structure that identifies the desired format for recording
  1233. * waveform data.
  1234. *
  1235. * @parm DWORD | dwCallback | Specifies the address of a callback
  1236. * function or a handle to a window called during waveform
  1237. * recording to process messages related to the progress of recording.
  1238. *
  1239. * @parm DWORD | dwCallbackInstance | Specifies user
  1240. * instance data passed to the callback. This parameter is not
  1241. * used with window callbacks.
  1242. *
  1243. * @parm DWORD | dwFlags | Specifies flags for opening the device.
  1244. * @flag WAVE_FORMAT_QUERY | If this flag is specified, the device will
  1245. * be queried to determine if it supports the given format but will not
  1246. * actually be opened.
  1247. * @flag WAVE_ALLOWSYNC | If this flag is not specified, then the
  1248. * device will fail to open if it is a synchronous device.
  1249. * @flag CALLBACK_WINDOW | If this flag is specified, <p dwCallback> is
  1250. * assumed to be a window handle.
  1251. * @flag CALLBACK_FUNCTION | If this flag is specified, <p dwCallback> is
  1252. * assumed to be a callback procedure address.
  1253. *
  1254. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  1255. * an error number. Possible error returns are:
  1256. * @flag MMSYSERR_BADDEVICEID | Specified device ID is out of range.
  1257. * @flag MMSYSERR_ALLOCATED | Specified resource is already allocated.
  1258. * @flag MMSYSERR_NOMEM | Unable to allocate or lock memory.
  1259. * @flag WAVERR_BADFORMAT | Attempted to open with an unsupported wave format.
  1260. *
  1261. * @comm Use <f waveInGetNumDevs> to determine the number of waveform input
  1262. * devices present in the system. The device ID specified by <p wDeviceID>
  1263. * varies from zero to one less than the number of devices present.
  1264. * The WAVE_MAPPER constant may also be used as a device id.
  1265. *
  1266. * If a window is chosen to receive callback information, the following
  1267. * messages are sent to the window procedure function to indicate the
  1268. * progress of waveform input: <m MM_WIM_OPEN>, <m MM_WIM_CLOSE>,
  1269. * <m MM_WIM_DATA>
  1270. *
  1271. * If a function is chosen to receive callback information, the following
  1272. * messages are sent to the function to indicate the progress of waveform
  1273. * input: <m WIM_OPEN>, <m WIM_CLOSE>, <m WIM_DATA>. The callback function
  1274. * must reside in a DLL. You do not have to use <f MakeProcInstance> to get
  1275. * a procedure-instance address for the callback function.
  1276. *
  1277. * @cb void CALLBACK | WaveInFunc | <f WaveInFunc> is a placeholder for the
  1278. * application-supplied function name. The actual name must be exported by
  1279. * including it in an EXPORTS statement in the DLL's module-definition file.
  1280. *
  1281. * @parm HWAVEIN | hWaveIn | Specifies a handle to the waveform device
  1282. * associated with the callback.
  1283. *
  1284. * @parm UINT | wMsg | Specifies a waveform input device.
  1285. *
  1286. * @parm DWORD | dwInstance | Specifies the user instance
  1287. * data specified with <f waveInOpen>.
  1288. *
  1289. * @parm DWORD | dwParam1 | Specifies a parameter for the message.
  1290. *
  1291. * @parm DWORD | dwParam2 | Specifies a parameter for the message.
  1292. *
  1293. * @comm Because the callback is accessed at interrupt time, it must reside
  1294. * in a DLL and its code segment must be specified as FIXED in the
  1295. * module-definition file for the DLL. Any data that the callback accesses
  1296. * must be in a FIXED data segment as well. The callback may not make any
  1297. * system calls except for <f PostMessage>, <f timeGetSystemTime>,
  1298. * <f timeGetTime>, <f timeSetEvent>, <f timeKillEvent>,
  1299. * <f midiOutShortMsg>, <f midiOutLongMsg>, and <f OutputDebugStr>.
  1300. *
  1301. * @xref waveInClose
  1302. ****************************************************************************/
  1303. UINT WINAPI
  1304. waveInOpen(
  1305. LPHWAVEIN lphWaveIn,
  1306. UINT wDeviceID,
  1307. const WAVEFORMAT FAR* lpFormat,
  1308. DWORD dwCallback,
  1309. DWORD dwInstance,
  1310. DWORD dwFlags
  1311. )
  1312. {
  1313. WAVEOPENDESC wo;
  1314. PWAVEDEV pdev;
  1315. UINT wRet;
  1316. DWORD dwDrvUser;
  1317. V_RPOINTER(lpFormat, sizeof(WAVEFORMAT), MMSYSERR_INVALPARAM);
  1318. V_DCALLBACK(dwCallback, HIWORD(dwFlags), MMSYSERR_INVALPARAM);
  1319. V_FLAGS(LOWORD(dwFlags), WAVE_VALID, waveInOpen, MMSYSERR_INVALFLAG);
  1320. if (!(dwFlags & WAVE_FORMAT_QUERY)) {
  1321. V_WPOINTER(lphWaveIn, sizeof(HWAVEIN), MMSYSERR_INVALPARAM);
  1322. *lphWaveIn = NULL;
  1323. }
  1324. /*
  1325. ** Check for no devices
  1326. */
  1327. // if (wTotalWaveInDevs == 0 ) {
  1328. // return MMSYSERR_BADDEVICEID;
  1329. // }
  1330. //
  1331. // /*
  1332. // ** check for device ID being to large
  1333. // */
  1334. // if ( wDeviceID != WAVE_MAPPER ) {
  1335. // if ( wDeviceID >= wTotalWaveInDevs ) {
  1336. // return MMSYSERR_BADDEVICEID;
  1337. // }
  1338. // }
  1339. if (dwFlags & WAVE_FORMAT_QUERY) {
  1340. pdev = NULL;
  1341. }
  1342. else {
  1343. if (!(pdev = (PWAVEDEV)NewHandle(TYPE_WAVEIN, sizeof(WAVEDEV))))
  1344. return MMSYSERR_NOMEM;
  1345. pdev->wDevice = wDeviceID;
  1346. pdev->wDeviceID = wDeviceID;
  1347. }
  1348. wo.hWave = (HWAVE)pdev;
  1349. wo.dwCallback = dwCallback;
  1350. wo.dwInstance = dwInstance;
  1351. wo.lpFormat = lpFormat;
  1352. if ( (wDeviceID == WAVE_MAPPER) && (wodMapper != NULL) ) {
  1353. wRet = (UINT)((*(widMapper))(0, WIDM_OPEN,
  1354. (DWORD)(LPDWORD)&dwDrvUser,
  1355. (DWORD)(LPWAVEOPENDESC)&wo,
  1356. dwFlags));
  1357. }
  1358. else {
  1359. wRet = waveIIDMessage( wDeviceID, WIDM_OPEN,
  1360. (DWORD)(LPDWORD)&dwDrvUser,
  1361. (DWORD)(LPWAVEOPENDESC)&wo, dwFlags );
  1362. }
  1363. if (pdev) {
  1364. if (wRet)
  1365. FreeHandle((HWAVEIN)pdev);
  1366. else {
  1367. *lphWaveIn = (HWAVEIN)pdev;
  1368. pdev->dwDrvUser = dwDrvUser;
  1369. }
  1370. }
  1371. return wRet;
  1372. }
  1373. /*****************************************************************************
  1374. * @doc EXTERNAL WAVE
  1375. *
  1376. * @api UINT | waveInClose | This function closes the specified waveform
  1377. * input device.
  1378. *
  1379. * @parm HWAVEIN | hWaveIn | Specifies a handle to the waveform input device.
  1380. * If the function is successful, the handle is no longer
  1381. * valid after this call.
  1382. *
  1383. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  1384. * an error number. Possible error returns are:
  1385. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  1386. * @flag WAVERR_STILLPLAYING | There are still buffers in the queue.
  1387. *
  1388. * @comm If there are input buffers that have been sent with
  1389. * <f waveInAddBuffer>, and haven't been returned to the application,
  1390. * the close operation will fail. Call <f waveInReset> to mark all
  1391. * pending buffers as done.
  1392. *
  1393. * @xref waveInOpen waveInReset
  1394. ****************************************************************************/
  1395. UINT WINAPI
  1396. waveInClose(
  1397. HWAVEIN hWaveIn
  1398. )
  1399. {
  1400. UINT wRet;
  1401. V_HANDLE(hWaveIn, TYPE_WAVEIN, MMSYSERR_INVALHANDLE);
  1402. wRet = (UINT)waveIMessage( (HWAVE)hWaveIn, WIDM_CLOSE, 0L, 0L);
  1403. if (!wRet) {
  1404. FreeHandle(hWaveIn);
  1405. }
  1406. return wRet;
  1407. }
  1408. /*****************************************************************************
  1409. * @doc EXTERNAL WAVE
  1410. *
  1411. * @api UINT | waveInPrepareHeader | This function prepares a buffer
  1412. * for waveform input.
  1413. *
  1414. * @parm HWAVEIN | hWaveIn | Specifies a handle to the waveform input
  1415. * device.
  1416. *
  1417. * @parm LPWAVEHDR | lpWaveInHdr | Specifies a pointer to a
  1418. * <t WAVEHDR> structure that identifies the buffer to be prepared.
  1419. *
  1420. * @parm UINT | wSize | Specifies the size of the <t WAVEHDR> structure.
  1421. *
  1422. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  1423. * an error number. Possible error returns are:
  1424. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  1425. * @flag MMSYSERR_NOMEM | Unable to allocate or lock memory.
  1426. *
  1427. * @comm The <t WAVEHDR> data structure and the data block pointed to by its
  1428. * <e WAVEHDR.lpData> field must be allocated with <f GlobalAlloc> using the
  1429. * GMEM_MOVEABLE and GMEM_SHARE flags, and locked with <f GlobalLock>.
  1430. * Preparing a header that has already been prepared will have no effect,
  1431. * and the function will return zero.
  1432. *
  1433. * @xref waveInUnprepareHeader
  1434. ****************************************************************************/
  1435. UINT WINAPI
  1436. waveInPrepareHeader(
  1437. HWAVEIN hWaveIn,
  1438. LPWAVEHDR lpWaveInHdr,
  1439. UINT wSize
  1440. )
  1441. {
  1442. UINT wRet;
  1443. V_HANDLE(hWaveIn, TYPE_WAVEIN, MMSYSERR_INVALHANDLE);
  1444. V_HEADER(lpWaveInHdr, wSize, TYPE_WAVEIN, MMSYSERR_INVALPARAM);
  1445. if (IsWaveHeaderPrepared(hWaveIn, lpWaveInHdr)) {
  1446. DebugErr(DBF_WARNING,"waveInPrepareHeader: header is already prepared.");
  1447. return MMSYSERR_NOERROR;
  1448. }
  1449. lpWaveInHdr->dwFlags = 0;
  1450. wRet = wavePrepareHeader(lpWaveInHdr, wSize);
  1451. if (wRet == MMSYSERR_NOERROR) {
  1452. wRet = (UINT)waveIMessage( (HWAVE)hWaveIn, WIDM_PREPARE,
  1453. (DWORD)lpWaveInHdr, (DWORD)wSize);
  1454. }
  1455. return wRet;
  1456. }
  1457. /*****************************************************************************
  1458. * @doc EXTERNAL WAVE
  1459. *
  1460. * @api UINT | waveInUnprepareHeader | This function cleans up the
  1461. * preparation performed by <f waveInPrepareHeader>. The function must
  1462. * be called after the device
  1463. * driver fills a data buffer and returns it to the application. You
  1464. * must call this function before freeing the data buffer.
  1465. *
  1466. * @parm HWAVEIN | hWaveIn | Specifies a handle to the waveform input
  1467. * device.
  1468. *
  1469. * @parm LPWAVEHDR | lpWaveInHdr | Specifies a pointer to a <t WAVEHDR>
  1470. * structure identifying the data buffer to be cleaned up.
  1471. *
  1472. * @parm UINT | wSize | Specifies the size of the <t WAVEHDR> structure.
  1473. *
  1474. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  1475. * an error number. Possible error returns are:
  1476. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  1477. * @flag WAVERR_STILLPLAYING | <p lpWaveInHdr> is still in the queue.
  1478. *
  1479. * @comm This function is the complementary function to <f waveInPrepareHeader>.
  1480. * You must call this function before freeing the data buffer with <f GlobalFree>.
  1481. * After passing a buffer to the device driver with <f waveInAddBuffer>, you
  1482. * must wait until the driver is finished with the buffer before calling
  1483. * <f waveInUnprepareHeader>. Unpreparing a buffer that has not been
  1484. * prepared has no effect, and the function returns zero.
  1485. *
  1486. * @xref waveInPrepareHeader
  1487. ****************************************************************************/
  1488. UINT WINAPI
  1489. waveInUnprepareHeader(
  1490. HWAVEIN hWaveIn,
  1491. LPWAVEHDR lpWaveInHdr,
  1492. UINT wSize
  1493. )
  1494. {
  1495. UINT wRet;
  1496. V_HANDLE(hWaveIn, TYPE_WAVEIN, MMSYSERR_INVALHANDLE);
  1497. V_HEADER(lpWaveInHdr, wSize, TYPE_WAVEIN, MMSYSERR_INVALPARAM);
  1498. if (lpWaveInHdr->dwFlags & WHDR_INQUEUE) {
  1499. DebugErr(DBF_WARNING, "waveInUnprepareHeader: buffer still in queue.");
  1500. return WAVERR_STILLPLAYING;
  1501. }
  1502. if (!IsWaveHeaderPrepared(hWaveIn, lpWaveInHdr)) {
  1503. DebugErr(DBF_WARNING,"waveInUnprepareHeader: header is not prepared.");
  1504. return MMSYSERR_NOERROR;
  1505. }
  1506. wRet = waveUnprepareHeader(lpWaveInHdr, wSize);
  1507. if (wRet == MMSYSERR_NOERROR) {
  1508. wRet = (UINT)waveIMessage( (HWAVE)hWaveIn, WIDM_UNPREPARE,
  1509. (DWORD)lpWaveInHdr, (DWORD)wSize);
  1510. }
  1511. return wRet;
  1512. }
  1513. /*****************************************************************************
  1514. * @doc EXTERNAL WAVE
  1515. *
  1516. * @api UINT | waveInAddBuffer | This function sends an input buffer to a
  1517. * waveform input device. When the buffer is filled, it is sent back
  1518. * to the application.
  1519. *
  1520. * @parm HWAVEIN | hWaveIn | Specifies a handle to the waveform input device.
  1521. *
  1522. * @parm LPWAVEHDR | lpWaveInHdr | Specifies a far pointer to a <t WAVEHDR>
  1523. * structure that identifies the buffer.
  1524. *
  1525. * @parm UINT | wSize | Specifies the size of the <t WAVEHDR> structure.
  1526. *
  1527. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  1528. * an error number. Possible error returns are:
  1529. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  1530. * @flag WAVERR_UNPREPARED | <p lpWaveInHdr> hasn't been prepared.
  1531. *
  1532. * @comm The data buffer must be prepared with <f waveInPrepareHeader> before
  1533. * it is passed to <f waveInAddBuffer>. The <t WAVEHDR> data structure
  1534. * and the data buffer pointed to by its <e WAVEHDR.lpData> field must be allocated
  1535. * with <f GlobalAlloc> using the GMEM_MOVEABLE and GMEM_SHARE flags, and
  1536. * locked with <f GlobalLock>.
  1537. *
  1538. * @xref waveInPrepareHeader
  1539. ****************************************************************************/
  1540. UINT WINAPI
  1541. waveInAddBuffer(
  1542. HWAVEIN hWaveIn,
  1543. LPWAVEHDR lpWaveInHdr,
  1544. UINT wSize
  1545. )
  1546. {
  1547. V_HANDLE(hWaveIn, TYPE_WAVEIN, MMSYSERR_INVALHANDLE);
  1548. V_HEADER(lpWaveInHdr, wSize, TYPE_WAVEIN, MMSYSERR_INVALPARAM);
  1549. if (!IsWaveHeaderPrepared(hWaveIn, lpWaveInHdr)) {
  1550. DebugErr(DBF_WARNING, "waveInAddBuffer: buffer not prepared.");
  1551. return WAVERR_UNPREPARED;
  1552. }
  1553. if (lpWaveInHdr->dwFlags & WHDR_INQUEUE) {
  1554. DebugErr(DBF_WARNING, "waveInAddBuffer: buffer already in queue.");
  1555. return WAVERR_STILLPLAYING;
  1556. }
  1557. return (UINT)waveIMessage( (HWAVE)hWaveIn, WIDM_ADDBUFFER,
  1558. (DWORD)lpWaveInHdr, (DWORD)wSize);
  1559. }
  1560. /*****************************************************************************
  1561. * @doc EXTERNAL WAVE
  1562. *
  1563. * @api UINT | waveInStart | This function starts input on the specified
  1564. * waveform input device.
  1565. *
  1566. * @parm HWAVEIN | hWaveIn | Specifies a handle to the waveform input device.
  1567. *
  1568. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  1569. * an error number. Possible error returns are:
  1570. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  1571. *
  1572. * @comm Buffers are returned to the client when full or when <f waveInReset>
  1573. * is called (the <e WAVEHDR.dwBytesRecorded> field in the header will contain the
  1574. * actual length of data). If there are no buffers in the queue, the data is
  1575. * thrown away without notification to the client, and input continues.
  1576. *
  1577. * Calling this function when input is already started has no effect, and
  1578. * the function returns zero.
  1579. *
  1580. * @xref waveInStop waveInReset
  1581. ****************************************************************************/
  1582. UINT WINAPI
  1583. waveInStart(
  1584. HWAVEIN hWaveIn
  1585. )
  1586. {
  1587. V_HANDLE(hWaveIn, TYPE_WAVEIN, MMSYSERR_INVALHANDLE);
  1588. return (UINT)waveIMessage( (HWAVE)hWaveIn, WIDM_START, 0L, 0L);
  1589. }
  1590. /*****************************************************************************
  1591. * @doc EXTERNAL WAVE
  1592. *
  1593. * @api UINT | waveInStop | This function stops waveform input.
  1594. *
  1595. * @parm HWAVEIN | hWaveIn | Specifies a handle to the waveform input
  1596. * device.
  1597. *
  1598. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  1599. * an error number. Possible error returns are:
  1600. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  1601. *
  1602. * @comm If there are any buffers in the queue, the current buffer will be
  1603. * marked as done (the <e WAVEHDR.dwBytesRecorded> field in the header will contain
  1604. * the actual length of data), but any empty buffers in the queue will remain
  1605. * there. Calling this function when input is not started has no effect,
  1606. * and the function returns zero.
  1607. *
  1608. * @xref waveInStart waveInReset
  1609. ****************************************************************************/
  1610. UINT WINAPI
  1611. waveInStop(
  1612. HWAVEIN hWaveIn
  1613. )
  1614. {
  1615. V_HANDLE(hWaveIn, TYPE_WAVEIN, MMSYSERR_INVALHANDLE);
  1616. return (UINT)waveIMessage( (HWAVE)hWaveIn, WIDM_STOP, 0L, 0L );
  1617. }
  1618. /*****************************************************************************
  1619. * @doc EXTERNAL WAVE
  1620. *
  1621. * @api UINT | waveInReset | This function stops input on a given waveform
  1622. * input device and resets the current position to 0. All pending
  1623. * buffers are marked as done and returned to the application.
  1624. *
  1625. * @parm HWAVEIN | hWaveIn | Specifies a handle to the waveform input device.
  1626. *
  1627. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  1628. * an error number. Possible error returns are:
  1629. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  1630. *
  1631. * @xref waveInStart waveInStop waveInAddBuffer waveInClose
  1632. /****************************************************************************/
  1633. UINT WINAPI
  1634. waveInReset(
  1635. HWAVEIN hWaveIn
  1636. )
  1637. {
  1638. V_HANDLE(hWaveIn, TYPE_WAVEIN, MMSYSERR_INVALHANDLE);
  1639. return (UINT)waveIMessage( (HWAVE)hWaveIn, WIDM_RESET, 0L, 0L );
  1640. }
  1641. /*****************************************************************************
  1642. * @doc EXTERNAL WAVE
  1643. *
  1644. * @api UINT | waveInGetPosition | This function retrieves the current input
  1645. * position of the specified waveform input device.
  1646. *
  1647. * @parm HWAVEIN | hWaveIn | Specifies a handle to the waveform input device.
  1648. *
  1649. * @parm LPMMTIME | lpInfo | Specifies a far pointer to an <t MMTIME>
  1650. * structure.
  1651. *
  1652. * @parm UINT | wSize | Specifies the size of the <t MMTIME> structure.
  1653. *
  1654. * @rdesc Returns zero if the function was successful. Otherwise, it returns
  1655. * an error number. Possible error returns are:
  1656. * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid.
  1657. *
  1658. * @comm Before calling <f waveInGetPosition>, set the <e MMTIME.wType> field of the
  1659. * <t MMTIME> structure to indicate the time format that you desire. After
  1660. * calling <f waveInGetPosition>, be sure to check the <e MMTIME.wType> field to
  1661. * determine if the desired time format is supported. If the desired
  1662. * format is not supported, <e MMTIME.wType> will specify an alternative format.
  1663. *
  1664. * The position is set to zero when the device is opened or reset.
  1665. ****************************************************************************/
  1666. UINT WINAPI
  1667. waveInGetPosition(
  1668. HWAVEIN hWaveIn,
  1669. LPMMTIME lpInfo,
  1670. UINT wSize
  1671. )
  1672. {
  1673. V_HANDLE(hWaveIn, TYPE_WAVEIN, MMSYSERR_INVALHANDLE);
  1674. V_WPOINTER(lpInfo, wSize, MMSYSERR_INVALPARAM);
  1675. return (UINT)waveIMessage( (HWAVE)hWaveIn,
  1676. WIDM_GETPOS, (DWORD)lpInfo, (DWORD)wSize );
  1677. }
  1678. /*****************************************************************************
  1679. * @doc EXTERNAL WAVE
  1680. *
  1681. * @api UINT | waveInGetID | This function gets the device ID for a
  1682. * waveform input device.
  1683. *
  1684. * @parm HWAVEIN | hWaveIn | Specifies the handle to the waveform
  1685. * input device.
  1686. * @parm UINT FAR* | lpwDeviceID | Specifies a pointer to the UINT-sized memory
  1687. * location to be filled with the device ID.
  1688. *
  1689. * @rdesc Returns zero if successful. Otherwise, it returns
  1690. * an error number. Possible error returns are:
  1691. * @flag MMSYSERR_INVALHANDLE | The <p hWaveIn> parameter specifies an
  1692. * invalid handle.
  1693. *
  1694. ****************************************************************************/
  1695. UINT WINAPI
  1696. waveInGetID(
  1697. HWAVEIN hWaveIn,
  1698. UINT FAR* lpwDeviceID
  1699. )
  1700. {
  1701. V_HANDLE(hWaveIn, TYPE_WAVEIN, MMSYSERR_INVALHANDLE);
  1702. V_WPOINTER(lpwDeviceID, sizeof(UINT), MMSYSERR_INVALPARAM);
  1703. *lpwDeviceID = ((PWAVEDEV)hWaveIn)->wDeviceID;
  1704. return MMSYSERR_NOERROR;
  1705. }
  1706. /*****************************************************************************
  1707. * @doc EXTERNAL WAVE
  1708. *
  1709. * @api UINT | waveOutGetID | This function gets the device ID for a
  1710. * waveform output device.
  1711. *
  1712. * @parm HWAVEOUT | hWaveOut | Specifies the handle to the waveform
  1713. * output device.
  1714. * @parm UINT FAR* | lpwDeviceID | Specifies a pointer to the UINT-sized memory
  1715. * location to be filled with the device ID.
  1716. *
  1717. * @rdesc Returns zero if successful. Otherwise, it returns
  1718. * an error number. Possible error returns are:
  1719. * @flag MMSYSERR_INVALHANDLE | The <p hWaveOut> parameter specifies an
  1720. * invalid handle.
  1721. ****************************************************************************/
  1722. UINT WINAPI
  1723. waveOutGetID(
  1724. HWAVEOUT hWaveOut,
  1725. UINT FAR* lpwDeviceID
  1726. )
  1727. {
  1728. V_HANDLE(hWaveOut, TYPE_WAVEOUT, MMSYSERR_INVALHANDLE);
  1729. V_WPOINTER(lpwDeviceID, sizeof(UINT), MMSYSERR_INVALPARAM);
  1730. *lpwDeviceID = ((PWAVEDEV)hWaveOut)->wDeviceID;
  1731. return MMSYSERR_NOERROR;
  1732. }
  1733.