/**************************************************************************** wave.c Level 1 kitchen sink DLL wave support module Copyright (c) Microsoft Corporation 1990. All rights reserved ****************************************************************************/ #include #include "mmsystem.h" #include "mmddk.h" #include "mmsysi.h" #include "thunks.h" /* ------------------------------------------------------------------------- ** Local functions ** ------------------------------------------------------------------------- */ static UINT NEAR PASCAL waveGetErrorText( UINT wError, LPSTR lpText, UINT wSize ); /* ------------------------------------------------------------------------- ** Local structures ** ------------------------------------------------------------------------- */ typedef struct wavedev_tag { PWAVEDRV wavedrv; UINT wDevice; DWORD dwDrvUser; UINT wDeviceID; } WAVEDEV, *PWAVEDEV; /* ------------------------------------------------------------------------- ** @doc INTERNAL WAVE validation code for WAVEHDRs ** ------------------------------------------------------------------------- */ #define IsWaveHeaderPrepared(hWave, lpwh) \ ((lpwh)->dwFlags & WHDR_PREPARED) #define MarkWaveHeaderPrepared(hWave, lpwh) \ ((lpwh)->dwFlags |= WHDR_PREPARED) #define MarkWaveHeaderUnprepared(hWave, lpwh) \ ((lpwh)->dwFlags &=~WHDR_PREPARED) /***************************************************************************** * @doc INTERNAL WAVE * * @api UINT | wavePrepareHeader | This function prepares the header and data * if the driver returns MMSYSERR_NOTSUPPORTED. * * @rdesc Returns zero if the function was successful. Otherwise, it * specifies an error number. ****************************************************************************/ static UINT NEAR PASCAL wavePrepareHeader( LPWAVEHDR lpWaveHdr, UINT wSize ) { if (!HugePageLock(lpWaveHdr, (DWORD)sizeof(WAVEHDR))) { return MMSYSERR_NOMEM; } if (!HugePageLock(lpWaveHdr->lpData, lpWaveHdr->dwBufferLength)) { HugePageUnlock(lpWaveHdr, (DWORD)sizeof(WAVEHDR)); return MMSYSERR_NOMEM; } // lpWaveHdr->dwFlags |= WHDR_PREPARED; return MMSYSERR_NOERROR; } /***************************************************************************** * @doc INTERNAL WAVE * * @api UINT | waveUnprepareHeader | This function unprepares the header and * data if the driver returns MMSYSERR_NOTSUPPORTED. * * @rdesc Currently always returns MMSYSERR_NOERROR. ****************************************************************************/ static UINT NEAR PASCAL waveUnprepareHeader( LPWAVEHDR lpWaveHdr, UINT wSize ) { HugePageUnlock(lpWaveHdr->lpData, lpWaveHdr->dwBufferLength); HugePageUnlock(lpWaveHdr, (DWORD)sizeof(WAVEHDR)); // lpWaveHdr->dwFlags &= ~WHDR_PREPARED; return MMSYSERR_NOERROR; } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// /***************************************************************************** * @doc EXTERNAL WAVE * * @api UINT | waveOutGetNumDevs | This function retrieves the number of * waveform output devices present in the system. * * @rdesc Returns the number of waveform output devices present in the system. * * @xref waveOutGetDevCaps ****************************************************************************/ UINT WINAPI waveOutGetNumDevs( void ) { return waveOIDMessage( 0, WODM_GETNUMDEVS, 0L, 0L, 0L ); } /***************************************************************************** * @doc EXTERNAL WAVE * * @api DWORD | waveOutMessage | This function sends messages to the waveform * output device drivers. * * @parm HWAVEOUT | hWaveOut | The handle to the audio device. * * @parm UINT | msg | The message to send. * * @parm DWORD | dw1 | Parameter 1. * * @parm DWORD | dw2 | Parameter 2. * * @rdesc Returns the value returned from the driver. ****************************************************************************/ DWORD WINAPI waveOutMessage( HWAVEOUT hWaveOut, UINT msg, DWORD dw1, DWORD dw2 ) { V_HANDLE(hWaveOut, TYPE_WAVEOUT, 0L); return waveOMessage( (HWAVE)hWaveOut, msg, dw1, dw2); } /***************************************************************************** * @doc EXTERNAL WAVE * * @api UINT | waveOutGetDevCaps | This function queries a specified waveform * device to determine its capabilities. * * @parm UINT | wDeviceID | Identifies the waveform output device. * * @parm LPWAVEOUTCAPS | lpCaps | Specifies a far pointer to a * structure. This structure is filled with information about the * capabilities of the device. * * @parm UINT | wSize | Specifies the size of the structure. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. Possible error returns are: * @flag MMSYSERR_BADDEVICEID | Specified device ID is out of range. * @flag MMSYSERR_NODRIVER | The driver was not installed. * * @comm Use to determine the number of waveform output * devices present in the system. The device ID specified by

* varies from zero to one less than the number of devices present. * The WAVE_MAPPER constant may also be used as a device id. Only *

bytes (or less) of information is copied to the location * pointed to by

. If

is zero, nothing is copied, and * the function returns zero. * * @xref waveOutGetNumDevs ****************************************************************************/ UINT WINAPI waveOutGetDevCaps( UINT wDeviceID, LPWAVEOUTCAPS lpCaps, UINT wSize ) { if (wSize == 0) return MMSYSERR_NOERROR; V_WPOINTER(lpCaps, wSize, MMSYSERR_INVALPARAM); if (ValidateHandle((HWAVEOUT)wDeviceID, TYPE_WAVEOUT)) { return((UINT)waveOMessage((HWAVE)wDeviceID, WODM_GETDEVCAPS, (DWORD)lpCaps, (DWORD)wSize)); } return waveOIDMessage( wDeviceID, WODM_GETDEVCAPS, 0L, (DWORD)lpCaps, (DWORD)wSize); } /***************************************************************************** * @doc EXTERNAL WAVE * * @api UINT | waveOutGetVolume | This function queries the current volume * setting of a waveform output device. * * @parm UINT | wDeviceID | Identifies the waveform output device. * * @parm LPDWORD | lpdwVolume | Specifies a far pointer to a location to * be filled with the current volume setting. The low-order word of * this location contains the left channel volume setting, and the high-order * WORD contains the right channel setting. A value of 0xFFFF represents * full volume, and a value of 0x0000 is silence. * * If a device does not support both left and right volume * control, the low-order word of the specified location contains * the mono volume level. * * The full 16-bit setting(s) * set with is returned, regardless of whether * the device supports the full 16 bits of volume-level control. * * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. Possible error returns are: * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid. * @flag MMSYSERR_NOTSUPPORTED | Function isn't supported. * @flag MMSYSERR_NODRIVER | The driver was not installed. * * @comm Not all devices support volume changes. To determine whether the * device supports volume control, use the WAVECAPS_VOLUME * flag to test the field of the * structure (filled by ). * * To determine whether the device supports volume control on both * the left and right channels, use the WAVECAPS_VOLUME * flag to test the field of the * structure (filled by ). * * @xref waveOutSetVolume ****************************************************************************/ UINT WINAPI waveOutGetVolume( UINT wDeviceID, LPDWORD lpdwVolume ) { V_WPOINTER(lpdwVolume, sizeof(DWORD), MMSYSERR_INVALPARAM); if (ValidateHandle((HWAVEOUT)wDeviceID, TYPE_WAVEOUT)) { return ( (UINT)waveOMessage( (HWAVE)wDeviceID, WODM_GETVOLUME, (DWORD)lpdwVolume, 0 )); } return waveOIDMessage( wDeviceID, WODM_GETVOLUME, 0L, (DWORD)lpdwVolume, 0); } /***************************************************************************** * @doc EXTERNAL WAVE * * @api UINT | waveOutSetVolume | This function sets the volume of a * waveform output device. * * @parm UINT | wDeviceID | Identifies the waveform output device. * * @parm DWORD | dwVolume | Specifies the new volume setting. The * low-order word contains the left channel volume setting, and the * high-order word contains the right channel setting. A value of * 0xFFFF represents full volume, and a value of 0x0000 is silence. * * If a device does * not support both left and right volume control, the low-order word of *

specifies the volume level, and the high-order word is * ignored. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. Possible error returns are: * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid. * @flag MMSYSERR_NOTSUPPORTED | Function isn't supported. * @flag MMSYSERR_NODRIVER | The driver was not installed. * * @comm Not all devices support volume changes. To determine whether the * device supports volume control, use the WAVECAPS_VOLUME * flag to test the field of the * structure (filled by ). * * To determine whether the device supports volume control on both the * left and right channels, use the WAVECAPS_LRVOLUME flag * flag to test the field of the * structure (filled by ). * * Most devices don't support the full 16 bits of volume level control * and will not use the high-order bits of the requested volume setting. * For example, for a device that supports 4 bits of volume control, * requested volume level values of 0x4000, 0x4fff, and 0x43be * all produce the same physical volume setting, 0x4000. The * function returns the full 16-bit setting set * with . * * Volume settings are interpreted logarithmically. This means the * perceived increase in volume is the same when increasing the * volume level from 0x5000 to 0x6000 as it is from 0x4000 to 0x5000. * * @xref waveOutGetVolume ****************************************************************************/ UINT WINAPI waveOutSetVolume( UINT wDeviceID, DWORD dwVolume ) { if (ValidateHandle((HWAVEOUT)wDeviceID, TYPE_WAVEOUT)) { return((UINT)waveOMessage((HWAVE)wDeviceID, WODM_SETVOLUME, dwVolume, 0)); } return waveOIDMessage( wDeviceID, WODM_SETVOLUME, 0L, dwVolume, 0); } /***************************************************************************** * @doc INTERNAL WAVE * * @func UINT | waveGetErrorText | This function retrieves a textual * description of the error identified by the specified error number. * * @parm UINT | wError | Specifies the error number. * * @parm LPSTR | lpText | Specifies a far pointer to a buffer which * is filled with the textual error description. * * @parm UINT | wSize | Specifies the length of the buffer pointed to by *

. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. Possible error returns are: * @flag MMSYSERR_BADERRNUM | Specified error number is out of range. * * @comm If the textual error description is longer than the specified buffer, * the description is truncated. The returned error string is always * null-terminated. If

is zero, nothing is copied and MMSYSERR_NOERROR * is returned. ****************************************************************************/ static UINT NEAR PASCAL waveGetErrorText( UINT wError, LPSTR lpText, UINT wSize ) { lpText[0] = 0; #if MMSYSERR_BASE if ( ((wError < MMSYSERR_BASE) || (wError > MMSYSERR_LASTERROR)) && ((wError < WAVERR_BASE) || (wError > WAVERR_LASTERROR))) { return MMSYSERR_BADERRNUM; } #else if ( (wError > MMSYSERR_LASTERROR) && ((wError < WAVERR_BASE) || (wError > WAVERR_LASTERROR))) { return MMSYSERR_BADERRNUM; } #endif if (wSize > 1) { if (!LoadString(ghInst, wError, lpText, wSize)) { return MMSYSERR_BADERRNUM; } } return MMSYSERR_NOERROR; } /***************************************************************************** * @doc EXTERNAL WAVE * * @api UINT | waveOutGetErrorText | This function retrieves a * textual description of the error identified by the specified * error number. * * @parm UINT | wError | Specifies the error number. * * @parm LPSTR | lpText | Specifies a far pointer to a buffer to be * filled with the textual error description. * * @parm UINT | wSize | Specifies the length of the buffer pointed * to by

. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. Possible error returns are: * @flag MMSYSERR_BADERRNUM | Specified error number is out of range. * * @comm If the textual error description is longer than the specified buffer, * the description is truncated. The returned error string is always * null-terminated. If

is zero, nothing is copied, and the function * returns zero. All error descriptions are less than MAXERRORLENGTH characters long. ****************************************************************************/ UINT WINAPI waveOutGetErrorText( UINT wError, LPSTR lpText, UINT wSize ) { if (wSize == 0) { return MMSYSERR_NOERROR; } V_WPOINTER(lpText, wSize, MMSYSERR_INVALPARAM); return waveGetErrorText(wError, lpText, wSize); } /***************************************************************************** * @doc EXTERNAL WAVE * * @api UINT | waveOutOpen | This function opens a specified waveform output * device for playback. * * @parm LPHWAVEOUT | lphWaveOut | Specifies a far pointer to an HWAVEOUT * handle. This location is filled with a handle identifying the opened * waveform output device. Use the handle to identify the device when * calling other waveform output functions. This parameter may be * NULL if the WAVE_FORMAT_QUERY flag is specified for

. * * @parm UINT | wDeviceID | Identifies the waveform output device to open. * Use a valid device ID or the following flag: * * @flag WAVE_MAPPER | If this flag is specified, the function * selects a waveform output device * capable of playing the given format. * * @parm LPWAVEFORMAT | lpFormat | Specifies a pointer to a * structure that identifies the format of the waveform data * to be sent to the waveform output device. * * @parm DWORD | dwCallback | Specifies the address of a callback * function or a handle to a window called during waveform * playback to process messages related to the progress of the playback. * Specify NULL for this parameter if no callback is desired. * * @parm DWORD | dwCallbackInstance | Specifies user instance data * passed to the callback. This parameter is not used with * window callbacks. * * @parm DWORD | dwFlags | Specifies flags for opening the device. * @flag WAVE_FORMAT_QUERY | If this flag is specified, the device is * queried to determine if it supports the given format but is not * actually opened. * @flag WAVE_ALLOWSYNC | If this flag is not specified, then the * device will fail to open if it is a synchronous device. * @flag CALLBACK_WINDOW | If this flag is specified,

is * assumed to be a window handle. * @flag CALLBACK_FUNCTION | If this flag is specified,

is * assumed to be a callback procedure address. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. Possible error returns are: * @flag MMSYSERR_BADDEVICEID | Specified device ID is out of range. * @flag MMSYSERR_ALLOCATED | Specified resource is already allocated. * @flag MMSYSERR_NOMEM | Unable to allocate or lock memory. * @flag WAVERR_BADFORMAT | Attempted to open with an unsupported wave format. * * @comm Use to determine the number of waveform output * devices present in the system. The device ID specified by

* varies from zero to one less than the number of devices present. * The WAVE_MAPPER constant may also be used as a device id. * * The structure pointed to by

may be extended * to include type-specific information for certain data formats. * For example, for PCM data, an extra UINT is added to specify the number * of bits per sample. Use the structure in this case. * * If a window is chosen to receive callback information, the following * messages are sent to the window procedure function to indicate the * progress of waveform output: , , * * * If a function is chosen to receive callback information, the following * messages are sent to the function to indicate the progress of waveform * output: , , . The callback function * must reside in a DLL. You do not have to use to get * a procedure-instance address for the callback function. * * @cb void CALLBACK | WaveOutFunc | is a placeholder for the * application-supplied function name. The actual name must be exported by * including it in an EXPORTS statement in the DLL's module-definition file. * * @parm HWAVEOUT | hWaveOut | Specifies a handle to the waveform device * associated with the callback. * * @parm UINT | wMsg | Specifies a waveform output message. * * @parm DWORD | dwInstance | Specifies the user instance data * specified with . * * @parm DWORD | dwParam1 | Specifies a parameter for the message. * * @parm DWORD | dwParam2 | Specifies a parameter for the message. * * @comm Because the callback is accessed at interrupt time, it must reside * in a DLL and its code segment must be specified as FIXED in the * module-definition file for the DLL. Any data that the callback accesses * must be in a FIXED data segment as well. The callback may not make any * system calls except for , , * , , , * , , and . * * @xref waveOutClose ****************************************************************************/ UINT WINAPI waveOutOpen( LPHWAVEOUT lphWaveOut, UINT wDeviceID, const WAVEFORMAT FAR* lpFormat, DWORD dwCallback, DWORD dwInstance, DWORD dwFlags ) { WAVEOPENDESC wo; PWAVEDEV pdev; UINT wRet; DWORD dwDrvUser; V_RPOINTER(lpFormat, sizeof(WAVEFORMAT), MMSYSERR_INVALPARAM); V_DCALLBACK(dwCallback, HIWORD(dwFlags), MMSYSERR_INVALPARAM); V_FLAGS(LOWORD(dwFlags), WAVE_VALID, waveOutOpen, MMSYSERR_INVALFLAG); if (!(dwFlags & WAVE_FORMAT_QUERY)) { V_WPOINTER(lphWaveOut, sizeof(HWAVEOUT), MMSYSERR_INVALPARAM); *lphWaveOut = NULL; } /* ** Check for no devices */ // if (wTotalWaveOutDevs == 0 ) { // return MMSYSERR_BADDEVICEID; // } // // /* // ** check for device ID being to large // */ // if ( wDeviceID != WAVE_MAPPER ) { // if ( wDeviceID >= wTotalWaveOutDevs ) { // return MMSYSERR_BADDEVICEID; // } // } if (dwFlags & WAVE_FORMAT_QUERY) { pdev = NULL; } else { if (!(pdev = (PWAVEDEV)NewHandle(TYPE_WAVEOUT, sizeof(WAVEDEV)))) { return MMSYSERR_NOMEM; } pdev->wDevice = wDeviceID; pdev->wDeviceID = wDeviceID; } wo.hWave = (HWAVE)pdev; wo.dwCallback = dwCallback; wo.dwInstance = dwInstance; wo.lpFormat = lpFormat; if ( (wDeviceID == WAVE_MAPPER) && (wodMapper != NULL) ) { wRet = (UINT)((*(wodMapper))(0, WODM_OPEN, (DWORD)(LPDWORD)&dwDrvUser, (DWORD)(LPWAVEOPENDESC)&wo, dwFlags)); } else { wRet = waveOIDMessage( wDeviceID, WODM_OPEN, (DWORD)(LPDWORD)&dwDrvUser, (DWORD)(LPWAVEOPENDESC)&wo, dwFlags ); } if (pdev) { if (wRet) { FreeHandle((HWAVEOUT)pdev); } else { *lphWaveOut = (HWAVEOUT)pdev; pdev->dwDrvUser = dwDrvUser; } } return wRet; } /***************************************************************************** * @doc EXTERNAL WAVE * * @api UINT | waveOutClose | This function closes the specified waveform * output device. * * @parm HWAVEOUT | hWaveOut | Specifies a handle to the waveform output * device. If the function is successful, the handle is no * longer valid after this call. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. Possible error returns are: * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid. * @flag WAVERR_STILLPLAYING | There are still buffers in the queue. * * @comm If the device is still playing a waveform, the close * operation will fail. Use to terminate waveform * playback before calling . * * @xref waveOutOpen waveOutReset ****************************************************************************/ UINT WINAPI waveOutClose(HWAVEOUT hWaveOut) { UINT wRet; V_HANDLE(hWaveOut, TYPE_WAVEOUT, MMSYSERR_INVALHANDLE); wRet = (UINT)waveOMessage( (HWAVE)hWaveOut, WODM_CLOSE, 0L,0L); if (!wRet) { FreeHandle(hWaveOut); } return wRet; } /***************************************************************************** * @doc EXTERNAL WAVE * * @api UINT | waveOutPrepareHeader | This function prepares a * waveform data block for playback. * * @parm HWAVEOUT | hWaveOut | Specifies a handle to the waveform output * device. * * @parm LPWAVEHDR | lpWaveOutHdr | Specifies a pointer to a * structure that identifies the data block to be prepared. * * @parm UINT | wSize | Specifies the size of the structure. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. Possible error returns are: * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid. * @flag MMSYSERR_NOMEM | Unable to allocate or lock memory. * * @comm The data structure and the data block pointed to by its * field must be allocated with using the * GMEM_MOVEABLE and GMEM_SHARE flags, and locked with . * Preparing a header that has already been prepared has no effect, and * the function returns zero. * * @xref waveOutUnprepareHeader ****************************************************************************/ UINT WINAPI waveOutPrepareHeader( HWAVEOUT hWaveOut, LPWAVEHDR lpWaveOutHdr, UINT wSize ) { UINT wRet; V_HANDLE(hWaveOut, TYPE_WAVEOUT, MMSYSERR_INVALHANDLE); V_HEADER(lpWaveOutHdr, wSize, TYPE_WAVEOUT, MMSYSERR_INVALPARAM); if (IsWaveHeaderPrepared(hWaveOut, lpWaveOutHdr)) { DebugErr(DBF_WARNING,"waveOutPrepareHeader: header is already prepared."); return MMSYSERR_NOERROR; } lpWaveOutHdr->dwFlags &= (WHDR_BEGINLOOP | WHDR_ENDLOOP); wRet = wavePrepareHeader(lpWaveOutHdr, wSize); if (wRet == MMSYSERR_NOERROR) { wRet = (UINT)waveOMessage( (HWAVE)hWaveOut, WODM_PREPARE, (DWORD)lpWaveOutHdr, (DWORD)wSize); } return wRet; } /***************************************************************************** * @doc EXTERNAL WAVE * * @api UINT | waveOutUnprepareHeader | This function cleans up the * preparation performed by . The function * must be called after * the device driver is finished with a data block. You must call this * function before freeing the data buffer. * * @parm HWAVEOUT | hWaveOut | Specifies a handle to the waveform output * device. * * @parm LPWAVEHDR | lpWaveOutHdr | Specifies a pointer to a * structure identifying the data block to be cleaned up. * * @parm UINT | wSize | Specifies the size of the structure. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. Possible error returns are: * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid. * @flag WAVERR_STILLPLAYING |

is still in the queue. * * @comm This function is the complementary function to * . You must call this function before freeing the * data buffer with . * After passing a buffer to the device driver with , you * must wait until the driver is finished with the buffer before calling * . * * Unpreparing a buffer that has not been * prepared has no effect, and the function returns zero. * * @xref waveOutPrepareHeader ****************************************************************************/ UINT WINAPI waveOutUnprepareHeader( HWAVEOUT hWaveOut, LPWAVEHDR lpWaveOutHdr, UINT wSize ) { UINT wRet; V_HANDLE(hWaveOut, TYPE_WAVEOUT, MMSYSERR_INVALHANDLE); V_HEADER(lpWaveOutHdr, wSize, TYPE_WAVEOUT, MMSYSERR_INVALPARAM); if(lpWaveOutHdr->dwFlags & WHDR_INQUEUE) { DebugErr(DBF_WARNING,"waveOutUnprepareHeader: header still in queue."); return WAVERR_STILLPLAYING; } if (!IsWaveHeaderPrepared(hWaveOut, lpWaveOutHdr)) { DebugErr(DBF_WARNING,"waveOutUnprepareHeader: header is not prepared."); return MMSYSERR_NOERROR; } wRet = waveUnprepareHeader(lpWaveOutHdr, wSize); if (wRet == MMSYSERR_NOERROR) { wRet = (UINT)waveOMessage( (HWAVE)hWaveOut, WODM_UNPREPARE, (DWORD)lpWaveOutHdr, (DWORD)wSize); } return wRet; } /***************************************************************************** * @doc EXTERNAL WAVE * * @api UINT | waveOutWrite | This function sends a data block to the * specified waveform output device. * * @parm HWAVEOUT | hWaveOut | Specifies a handle to the waveform output * device. * * @parm LPWAVEHDR | lpWaveOutHdr | Specifies a far pointer to a * structure containing information about the data block. * * @parm UINT | wSize | Specifies the size of the structure. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. Possible error returns are: * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid. * @flag WAVERR_UNPREPARED |

hasn't been prepared. * * @comm The data buffer must be prepared with before * it is passed to . The data structure * and the data buffer pointed to by its field must be allocated * with using the GMEM_MOVEABLE and GMEM_SHARE flags, and * locked with . Unless the device is paused by calling * , playback begins when the first data block is sent to * the device. * * @xref waveOutPrepareHeader waveOutPause waveOutReset waveOutRestart ****************************************************************************/ UINT WINAPI waveOutWrite( HWAVEOUT hWaveOut, LPWAVEHDR lpWaveOutHdr, UINT wSize ) { V_HANDLE(hWaveOut, TYPE_WAVEOUT, MMSYSERR_INVALHANDLE); V_HEADER(lpWaveOutHdr, wSize, TYPE_WAVEOUT, MMSYSERR_INVALPARAM); if (!IsWaveHeaderPrepared(hWaveOut, lpWaveOutHdr)) { DebugErr(DBF_WARNING,"waveOutWrite: header not prepared"); return WAVERR_UNPREPARED; } if (lpWaveOutHdr->dwFlags & WHDR_INQUEUE) { DebugErr(DBF_WARNING,"waveOutWrite: header is still in queue"); return WAVERR_STILLPLAYING; } lpWaveOutHdr->dwFlags &= ~WHDR_DONE; return (UINT)waveOMessage( (HWAVE)hWaveOut, WODM_WRITE, (DWORD)lpWaveOutHdr, (DWORD)wSize ); } /***************************************************************************** * @doc EXTERNAL WAVE * * @api UINT | waveOutPause | This function pauses playback on a specified * waveform output device. The current playback position is saved. Use * to resume playback from the current playback position. * * @parm HWAVEOUT | hWaveOut | Specifies a handle to the waveform output * device. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. Possible error returns are: * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid. * * @comm Calling this function when the output is already paused has no * effect, and the function returns zero. * * @xref waveOutRestart waveOutBreakLoop ****************************************************************************/ UINT WINAPI waveOutPause( HWAVEOUT hWaveOut ) { V_HANDLE(hWaveOut, TYPE_WAVEOUT, MMSYSERR_INVALHANDLE); return (UINT)waveOMessage( (HWAVE)hWaveOut, WODM_PAUSE, 0L, 0L); } /***************************************************************************** * @doc EXTERNAL WAVE * * @api UINT | waveOutRestart | This function restarts a paused waveform * output device. * * @parm HWAVEOUT | hWaveOut | Specifies a handle to the waveform output * device. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. Possible error returns are: * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid. * * @comm Calling this function when the output is not paused has no * effect, and the function returns zero. * * @xref waveOutPause waveOutBreakLoop ****************************************************************************/ UINT WINAPI waveOutRestart( HWAVEOUT hWaveOut ) { V_HANDLE(hWaveOut, TYPE_WAVEOUT, MMSYSERR_INVALHANDLE); return (UINT)waveOMessage( (HWAVE)hWaveOut, WODM_RESTART, 0L, 0L); } /***************************************************************************** * @doc EXTERNAL WAVE * * @api UINT | waveOutReset | This function stops playback on a given waveform * output device and resets the current position to 0. All pending * playback buffers are marked as done and returned to the application. * * @parm HWAVEOUT | hWaveOut | Specifies a handle to the waveform output * device. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. Possible error returns are: * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid. * * @xref waveOutWrite waveOutClose /****************************************************************************/ UINT WINAPI waveOutReset( HWAVEOUT hWaveOut ) { V_HANDLE(hWaveOut, TYPE_WAVEOUT, MMSYSERR_INVALHANDLE); return (UINT)waveOMessage( (HWAVE)hWaveOut, WODM_RESET, 0L, 0L); } /***************************************************************************** * @doc EXTERNAL WAVE * * @api UINT | waveOutBreakLoop | This function breaks a loop on a * given waveform output device and allows playback to continue with the * next block in the driver list. * * @parm HWAVEOUT | hWaveOut | Specifies a handle to the waveform output * device. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. Possible error returns are: * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid. * * @comm Waveform looping is controlled by the and * fields in the structures passed to the device * with . Use the WHDR_BEGINLOOP and WHDR_ENDLOOP flags * in the field to specify the beginning and ending data * blocks for looping. * * To loop on a single block, specify both flags for the same block. * To specify the number of loops, use the field in * the structure for the first block in the loop. * * The blocks making up the loop are played to the end before the loop * is terminated. * * Calling this function when the nothing is playing or looping has no * effect, and the function returns zero. * * @xref waveOutWrite waveOutPause waveOutRestart /****************************************************************************/ UINT WINAPI waveOutBreakLoop( HWAVEOUT hWaveOut ) { V_HANDLE(hWaveOut, TYPE_WAVEOUT, MMSYSERR_INVALHANDLE); return (UINT)waveOMessage( (HWAVE)hWaveOut, WODM_BREAKLOOP, 0L, 0L ); } /***************************************************************************** * @doc EXTERNAL WAVE * * @api UINT | waveOutGetPosition | This function retrieves the current * playback position of the specified waveform output device. * * @parm HWAVEOUT | hWaveOut | Specifies a handle to the waveform output * device. * * @parm LPMMTIME | lpInfo | Specifies a far pointer to an * structure. * * @parm UINT | wSize | Specifies the size of the structure. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. Possible error returns are: * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid. * * @comm Before calling , set the field of the * MMTIME structure to indicate the time format that you desire. After * calling , check the field * to determine if the desired time format is supported. If the desired * format is not supported, will specify an alternative format. * * The position is set to zero when the device is opened or reset. ****************************************************************************/ UINT WINAPI waveOutGetPosition( HWAVEOUT hWaveOut, LPMMTIME lpInfo, UINT wSize ) { V_HANDLE(hWaveOut, TYPE_WAVEOUT, MMSYSERR_INVALHANDLE); V_WPOINTER(lpInfo, wSize, MMSYSERR_INVALPARAM); return (UINT)waveOMessage( (HWAVE)hWaveOut, WODM_GETPOS, (DWORD)lpInfo, (DWORD)wSize ); } /***************************************************************************** * @doc EXTERNAL WAVE * * @api UINT | waveOutGetPitch | This function queries the the current pitch * setting of a waveform output device. * * @parm HWAVEOUT | hWaveOut | Specifies a handle to the waveform output * device. * * @parm LPDWORD | lpdwPitch | Specifies a far pointer to a location * to be filled with the current pitch multiplier setting. The pitch * multiplier indicates the current change in pitch from the original * authored setting. The pitch multiplier must be a positive value. * * The pitch multiplier is specified as a fixed-point value. The high-order word * of the DWORD location contains the signed integer part of the number, * and the low-order word contains the fractional part. The fraction is * expressed as a WORD in which a value of 0x8000 represents one half, * and 0x4000 represents one quarter. For example, the value 0x00010000 * specifies a multiplier of 1.0 (no pitch change), and a value of * 0x000F8000 specifies a multiplier of 15.5. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. Possible error returns are: * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid. * @flag MMSYSERR_NOTSUPPORTED | Function isn't supported. * * @comm Changing the pitch does not change the playback rate, sample * rate, or playback time. Not all devices support * pitch changes. To determine whether the device supports pitch control, * use the WAVECAPS_PITCH flag to test the * field of the structure (filled by ). * * @xref waveOutSetPitch waveOutGetPlaybackRate waveOutSetPlaybackRate ****************************************************************************/ UINT WINAPI waveOutGetPitch( HWAVEOUT hWaveOut, LPDWORD lpdwPitch ) { V_HANDLE(hWaveOut, TYPE_WAVEOUT, MMSYSERR_INVALHANDLE); V_WPOINTER(lpdwPitch, sizeof(DWORD), MMSYSERR_INVALPARAM); return (UINT)waveOMessage( (HWAVE)hWaveOut, WODM_GETPITCH, (DWORD)lpdwPitch, 0L); } /***************************************************************************** * @doc EXTERNAL WAVE * * @api UINT | waveOutSetPitch | This function sets the pitch of a waveform * output device. * * @parm HWAVEOUT | hWaveOut | Specifies a handle to the waveform * output device. * * @parm DWORD | dwPitch | Specifies the new pitch multiplier setting. * The pitch multiplier setting indicates the current change in pitch * from the original authored setting. The pitch multiplier must be a * positive value. * * The pitch multiplier is specified as a fixed-point value. The high-order word * location contains the signed integer part of the number, * and the low-order word contains the fractional part. The fraction is * expressed as a WORD in which a value of 0x8000 represents one half, * and 0x4000 represents one quarter. * For example, the value 0x00010000 specifies a multiplier * of 1.0 (no pitch change), and a value of 0x000F8000 specifies a * multiplier of 15.5. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. Possible error returns are: * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid. * @flag MMSYSERR_NOTSUPPORTED | Function isn't supported. * * @comm Changing the pitch does not change the playback rate or the sample * rate. The playback time is also unchanged. Not all devices support * pitch changes. To determine whether the device supports pitch control, * use the WAVECAPS_PITCH flag to test the * field of the structure (filled by ). * * @xref waveOutGetPitch waveOutSetPlaybackRate waveOutGetPlaybackRate ****************************************************************************/ UINT WINAPI waveOutSetPitch( HWAVEOUT hWaveOut, DWORD dwPitch ) { V_HANDLE(hWaveOut, TYPE_WAVEOUT, MMSYSERR_INVALHANDLE); return (UINT)waveOMessage( (HWAVE)hWaveOut, WODM_SETPITCH, dwPitch, 0L ); } /***************************************************************************** * @doc EXTERNAL WAVE * * @api UINT | waveOutGetPlaybackRate | This function queries the * current playback rate setting of a waveform output device. * * @parm HWAVEOUT | hWaveOut | Specifies a handle to the waveform output * device. * * @parm LPDWORD | lpdwRate | Specifies a far pointer to a location * to be filled with the current playback rate. The playback rate setting * is a multiplier indicating the current change in playback rate from * the original authored setting. The playback rate multiplier must be * a positive value. * * The rate is specified as a fixed-point value. The high-order word * of the DWORD location contains the signed integer part of the number, * and the low-order word contains the fractional part. The fraction is * expressed as a WORD in which a value of 0x8000 represents one half, * and 0x4000 represents one quarter. For example, the value 0x00010000 * specifies a multiplier of 1.0 (no playback rate change), and a value * of 0x000F8000 specifies a multiplier of 15.5. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. Possible error returns are: * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid. * @flag MMSYSERR_NOTSUPPORTED | Function isn't supported. * * @comm Changing the playback rate does not change the sample rate but does * change the playback time. * * Not all devices support playback rate changes. To determine whether a * device supports playback rate changes, use * the WAVECAPS_PLAYBACKRATE flag to test the field of the * structure (filled by ). * * @xref waveOutSetPlaybackRate waveOutSetPitch waveOutGetPitch ****************************************************************************/ UINT WINAPI waveOutGetPlaybackRate( HWAVEOUT hWaveOut, LPDWORD lpdwRate ) { V_HANDLE(hWaveOut, TYPE_WAVEOUT, MMSYSERR_INVALHANDLE); V_WPOINTER(lpdwRate, sizeof(DWORD), MMSYSERR_INVALPARAM); return (UINT)waveOMessage( (HWAVE)hWaveOut, WODM_GETPLAYBACKRATE, (DWORD)lpdwRate, 0L ); } /***************************************************************************** * @doc EXTERNAL WAVE * * @api UINT | waveOutSetPlaybackRate | This function sets the * playback rate of a waveform output device. * * @parm HWAVEOUT | hWaveOut | Specifies a handle to the waveform * output device. * * @parm DWORD | dwRate | Specifies the new playback rate setting. * The playback rate setting is a multiplier indicating the current * change in playback rate from the original authored setting. The playback * rate multiplier must be a positive value. * * The rate is specified as a fixed-point value. The high-order word * contains the signed integer part of the number, * and the low-order word contains the fractional part. The fraction is * expressed as a WORD in which a value of 0x8000 represents one half, * and 0x4000 represents one quarter. * For example, the value 0x00010000 specifies a multiplier of 1.0 (no * playback rate change), and a value of 0x000F8000 specifies a * multiplier of 15.5. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. Possible error returns are: * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid. * @flag MMSYSERR_NOTSUPPORTED | Function isn't supported. * * @comm Changing the playback rate does not change the sample rate but does * change the playback time. * * Not all devices support playback rate changes. To determine whether a * device supports playback rate changes, * use the WAVECAPS_PLAYBACKRATE flag to test the field of the * structure (filled by ). * * @xref waveOutGetPlaybackRate waveOutSetPitch waveOutGetPitch ****************************************************************************/ UINT WINAPI waveOutSetPlaybackRate( HWAVEOUT hWaveOut, DWORD dwRate ) { V_HANDLE(hWaveOut, TYPE_WAVEOUT, MMSYSERR_INVALHANDLE); return (UINT)waveOMessage( (HWAVE)hWaveOut, WODM_SETPLAYBACKRATE, dwRate, 0L ); } ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// /***************************************************************************** * @doc EXTERNAL WAVE * * @api UINT | waveInGetNumDevs | This function returns the number of waveform * input devices. * * @rdesc Returns the number of waveform input devices present in the system. * * @xref waveInGetDevCaps ****************************************************************************/ UINT WINAPI waveInGetNumDevs( void ) { return waveIIDMessage( 0, WIDM_GETNUMDEVS, 0L, 0L, 0L ); } /***************************************************************************** * @doc EXTERNAL WAVE * * @api DWORD | waveInMessage | This function sends messages to the waveform * output device drivers. * * @parm HWAVEIN | hWave | The handle to the audio device. * * @parm UINT | wMsg | The message to send. * * @parm DWORD | dw1 | Parameter 1. * * @parm DWORD | dw2 | Parameter 2. * * @rdesc Returns the value returned from the driver. ****************************************************************************/ DWORD WINAPI waveInMessage( HWAVEIN hWaveIn, UINT msg, DWORD dw1, DWORD dw2 ) { V_HANDLE(hWaveIn, TYPE_WAVEIN, 0L); return waveIMessage((HWAVE)hWaveIn, msg, dw1, dw2); } /***************************************************************************** * @doc EXTERNAL WAVE * * @api UINT | waveInGetDevCaps | This function queries a specified waveform * input device to determine its capabilities. * * @parm UINT | wDeviceID | Identifies the waveform input device. * * @parm LPWAVEINCAPS | lpCaps | Specifies a far pointer to a * structure. This structure is filled with information about the * capabilities of the device. * * @parm UINT | wSize | Specifies the size of the structure. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. Possible error returns are: * @flag MMSYSERR_BADDEVICEID | Specified device ID is out of range. * @flag MMSYSERR_NODRIVER | The driver was not installed. * * @comm Use to determine the number of waveform input * devices present in the system. The device ID specified by

* varies from zero to one less than the number of devices present. * The WAVE_MAPPER constant may also be used as a device id. Only *

bytes (or less) of information is copied to the location * pointed to by

. If

is zero, nothing is copied, and * the function returns zero. * * @xref waveInGetNumDevs ****************************************************************************/ UINT WINAPI waveInGetDevCaps( UINT wDeviceID, LPWAVEINCAPS lpCaps, UINT wSize ) { if (wSize == 0) { return MMSYSERR_NOERROR; } V_WPOINTER(lpCaps, wSize, MMSYSERR_INVALPARAM); if (ValidateHandle((HWAVEIN)wDeviceID, TYPE_WAVEIN)) { return((UINT)waveIMessage((HWAVE)wDeviceID, WIDM_GETDEVCAPS, (DWORD)lpCaps, (DWORD)wSize)); } return waveIIDMessage( wDeviceID, WIDM_GETDEVCAPS, 0L, (DWORD)lpCaps, (DWORD)wSize); } /***************************************************************************** * @doc EXTERNAL WAVE * * @api UINT | waveInGetErrorText | This function retrieves a textual * description of the error identified by the specified error number. * * @parm UINT | wError | Specifies the error number. * * @parm LPSTR | lpText | Specifies a far pointer to the buffer to be * filled with the textual error description. * * @parm UINT | wSize | Specifies the size of the buffer pointed * to by

. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. Possible error returns are: * @flag MMSYSERR_BADERRNUM | Specified error number is out of range. * * @comm If the textual error description is longer than the specified buffer, * the description is truncated. The returned error string is always * null-terminated. If

is zero, nothing is copied, and the function * returns zero. All error descriptions are less than MAXERRORLENGTH characters long. ****************************************************************************/ UINT WINAPI waveInGetErrorText( UINT wError, LPSTR lpText, UINT wSize ) { if (wSize == 0) { return MMSYSERR_NOERROR; } V_WPOINTER(lpText, wSize, MMSYSERR_INVALPARAM); return waveGetErrorText(wError, lpText, wSize); } /***************************************************************************** * @doc EXTERNAL WAVE * * @api UINT | waveInOpen | This function opens a specified waveform * input device for recording. * * @parm LPHWAVEIN | lphWaveIn | Specifies a far pointer to a HWAVEIN * handle. This location is filled with a handle identifying the opened * waveform input device. Use this handle to identify the device when * calling other waveform input functions. This parameter may be NULL * if the WAVE_FORMAT_QUERY flag is specified for

. * * @parm UINT | wDeviceID | Identifies the waveform input device to open. Use * a valid device ID or the following flag: * * @flag WAVE_MAPPER | If this flag is specified, the function * selects a waveform input device capable of recording in the * given format. * * @parm LPWAVEFORMAT | lpFormat | Specifies a pointer to a * data structure that identifies the desired format for recording * waveform data. * * @parm DWORD | dwCallback | Specifies the address of a callback * function or a handle to a window called during waveform * recording to process messages related to the progress of recording. * * @parm DWORD | dwCallbackInstance | Specifies user * instance data passed to the callback. This parameter is not * used with window callbacks. * * @parm DWORD | dwFlags | Specifies flags for opening the device. * @flag WAVE_FORMAT_QUERY | If this flag is specified, the device will * be queried to determine if it supports the given format but will not * actually be opened. * @flag WAVE_ALLOWSYNC | If this flag is not specified, then the * device will fail to open if it is a synchronous device. * @flag CALLBACK_WINDOW | If this flag is specified,

is * assumed to be a window handle. * @flag CALLBACK_FUNCTION | If this flag is specified,

is * assumed to be a callback procedure address. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. Possible error returns are: * @flag MMSYSERR_BADDEVICEID | Specified device ID is out of range. * @flag MMSYSERR_ALLOCATED | Specified resource is already allocated. * @flag MMSYSERR_NOMEM | Unable to allocate or lock memory. * @flag WAVERR_BADFORMAT | Attempted to open with an unsupported wave format. * * @comm Use to determine the number of waveform input * devices present in the system. The device ID specified by

* varies from zero to one less than the number of devices present. * The WAVE_MAPPER constant may also be used as a device id. * * If a window is chosen to receive callback information, the following * messages are sent to the window procedure function to indicate the * progress of waveform input: , , * * * If a function is chosen to receive callback information, the following * messages are sent to the function to indicate the progress of waveform * input: , , . The callback function * must reside in a DLL. You do not have to use to get * a procedure-instance address for the callback function. * * @cb void CALLBACK | WaveInFunc | is a placeholder for the * application-supplied function name. The actual name must be exported by * including it in an EXPORTS statement in the DLL's module-definition file. * * @parm HWAVEIN | hWaveIn | Specifies a handle to the waveform device * associated with the callback. * * @parm UINT | wMsg | Specifies a waveform input device. * * @parm DWORD | dwInstance | Specifies the user instance * data specified with . * * @parm DWORD | dwParam1 | Specifies a parameter for the message. * * @parm DWORD | dwParam2 | Specifies a parameter for the message. * * @comm Because the callback is accessed at interrupt time, it must reside * in a DLL and its code segment must be specified as FIXED in the * module-definition file for the DLL. Any data that the callback accesses * must be in a FIXED data segment as well. The callback may not make any * system calls except for , , * , , , * , , and . * * @xref waveInClose ****************************************************************************/ UINT WINAPI waveInOpen( LPHWAVEIN lphWaveIn, UINT wDeviceID, const WAVEFORMAT FAR* lpFormat, DWORD dwCallback, DWORD dwInstance, DWORD dwFlags ) { WAVEOPENDESC wo; PWAVEDEV pdev; UINT wRet; DWORD dwDrvUser; V_RPOINTER(lpFormat, sizeof(WAVEFORMAT), MMSYSERR_INVALPARAM); V_DCALLBACK(dwCallback, HIWORD(dwFlags), MMSYSERR_INVALPARAM); V_FLAGS(LOWORD(dwFlags), WAVE_VALID, waveInOpen, MMSYSERR_INVALFLAG); if (!(dwFlags & WAVE_FORMAT_QUERY)) { V_WPOINTER(lphWaveIn, sizeof(HWAVEIN), MMSYSERR_INVALPARAM); *lphWaveIn = NULL; } /* ** Check for no devices */ // if (wTotalWaveInDevs == 0 ) { // return MMSYSERR_BADDEVICEID; // } // // /* // ** check for device ID being to large // */ // if ( wDeviceID != WAVE_MAPPER ) { // if ( wDeviceID >= wTotalWaveInDevs ) { // return MMSYSERR_BADDEVICEID; // } // } if (dwFlags & WAVE_FORMAT_QUERY) { pdev = NULL; } else { if (!(pdev = (PWAVEDEV)NewHandle(TYPE_WAVEIN, sizeof(WAVEDEV)))) return MMSYSERR_NOMEM; pdev->wDevice = wDeviceID; pdev->wDeviceID = wDeviceID; } wo.hWave = (HWAVE)pdev; wo.dwCallback = dwCallback; wo.dwInstance = dwInstance; wo.lpFormat = lpFormat; if ( (wDeviceID == WAVE_MAPPER) && (wodMapper != NULL) ) { wRet = (UINT)((*(widMapper))(0, WIDM_OPEN, (DWORD)(LPDWORD)&dwDrvUser, (DWORD)(LPWAVEOPENDESC)&wo, dwFlags)); } else { wRet = waveIIDMessage( wDeviceID, WIDM_OPEN, (DWORD)(LPDWORD)&dwDrvUser, (DWORD)(LPWAVEOPENDESC)&wo, dwFlags ); } if (pdev) { if (wRet) FreeHandle((HWAVEIN)pdev); else { *lphWaveIn = (HWAVEIN)pdev; pdev->dwDrvUser = dwDrvUser; } } return wRet; } /***************************************************************************** * @doc EXTERNAL WAVE * * @api UINT | waveInClose | This function closes the specified waveform * input device. * * @parm HWAVEIN | hWaveIn | Specifies a handle to the waveform input device. * If the function is successful, the handle is no longer * valid after this call. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. Possible error returns are: * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid. * @flag WAVERR_STILLPLAYING | There are still buffers in the queue. * * @comm If there are input buffers that have been sent with * , and haven't been returned to the application, * the close operation will fail. Call to mark all * pending buffers as done. * * @xref waveInOpen waveInReset ****************************************************************************/ UINT WINAPI waveInClose( HWAVEIN hWaveIn ) { UINT wRet; V_HANDLE(hWaveIn, TYPE_WAVEIN, MMSYSERR_INVALHANDLE); wRet = (UINT)waveIMessage( (HWAVE)hWaveIn, WIDM_CLOSE, 0L, 0L); if (!wRet) { FreeHandle(hWaveIn); } return wRet; } /***************************************************************************** * @doc EXTERNAL WAVE * * @api UINT | waveInPrepareHeader | This function prepares a buffer * for waveform input. * * @parm HWAVEIN | hWaveIn | Specifies a handle to the waveform input * device. * * @parm LPWAVEHDR | lpWaveInHdr | Specifies a pointer to a * structure that identifies the buffer to be prepared. * * @parm UINT | wSize | Specifies the size of the structure. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. Possible error returns are: * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid. * @flag MMSYSERR_NOMEM | Unable to allocate or lock memory. * * @comm The data structure and the data block pointed to by its * field must be allocated with using the * GMEM_MOVEABLE and GMEM_SHARE flags, and locked with . * Preparing a header that has already been prepared will have no effect, * and the function will return zero. * * @xref waveInUnprepareHeader ****************************************************************************/ UINT WINAPI waveInPrepareHeader( HWAVEIN hWaveIn, LPWAVEHDR lpWaveInHdr, UINT wSize ) { UINT wRet; V_HANDLE(hWaveIn, TYPE_WAVEIN, MMSYSERR_INVALHANDLE); V_HEADER(lpWaveInHdr, wSize, TYPE_WAVEIN, MMSYSERR_INVALPARAM); if (IsWaveHeaderPrepared(hWaveIn, lpWaveInHdr)) { DebugErr(DBF_WARNING,"waveInPrepareHeader: header is already prepared."); return MMSYSERR_NOERROR; } lpWaveInHdr->dwFlags = 0; wRet = wavePrepareHeader(lpWaveInHdr, wSize); if (wRet == MMSYSERR_NOERROR) { wRet = (UINT)waveIMessage( (HWAVE)hWaveIn, WIDM_PREPARE, (DWORD)lpWaveInHdr, (DWORD)wSize); } return wRet; } /***************************************************************************** * @doc EXTERNAL WAVE * * @api UINT | waveInUnprepareHeader | This function cleans up the * preparation performed by . The function must * be called after the device * driver fills a data buffer and returns it to the application. You * must call this function before freeing the data buffer. * * @parm HWAVEIN | hWaveIn | Specifies a handle to the waveform input * device. * * @parm LPWAVEHDR | lpWaveInHdr | Specifies a pointer to a * structure identifying the data buffer to be cleaned up. * * @parm UINT | wSize | Specifies the size of the structure. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. Possible error returns are: * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid. * @flag WAVERR_STILLPLAYING |

is still in the queue. * * @comm This function is the complementary function to . * You must call this function before freeing the data buffer with . * After passing a buffer to the device driver with , you * must wait until the driver is finished with the buffer before calling * . Unpreparing a buffer that has not been * prepared has no effect, and the function returns zero. * * @xref waveInPrepareHeader ****************************************************************************/ UINT WINAPI waveInUnprepareHeader( HWAVEIN hWaveIn, LPWAVEHDR lpWaveInHdr, UINT wSize ) { UINT wRet; V_HANDLE(hWaveIn, TYPE_WAVEIN, MMSYSERR_INVALHANDLE); V_HEADER(lpWaveInHdr, wSize, TYPE_WAVEIN, MMSYSERR_INVALPARAM); if (lpWaveInHdr->dwFlags & WHDR_INQUEUE) { DebugErr(DBF_WARNING, "waveInUnprepareHeader: buffer still in queue."); return WAVERR_STILLPLAYING; } if (!IsWaveHeaderPrepared(hWaveIn, lpWaveInHdr)) { DebugErr(DBF_WARNING,"waveInUnprepareHeader: header is not prepared."); return MMSYSERR_NOERROR; } wRet = waveUnprepareHeader(lpWaveInHdr, wSize); if (wRet == MMSYSERR_NOERROR) { wRet = (UINT)waveIMessage( (HWAVE)hWaveIn, WIDM_UNPREPARE, (DWORD)lpWaveInHdr, (DWORD)wSize); } return wRet; } /***************************************************************************** * @doc EXTERNAL WAVE * * @api UINT | waveInAddBuffer | This function sends an input buffer to a * waveform input device. When the buffer is filled, it is sent back * to the application. * * @parm HWAVEIN | hWaveIn | Specifies a handle to the waveform input device. * * @parm LPWAVEHDR | lpWaveInHdr | Specifies a far pointer to a * structure that identifies the buffer. * * @parm UINT | wSize | Specifies the size of the structure. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. Possible error returns are: * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid. * @flag WAVERR_UNPREPARED |

hasn't been prepared. * * @comm The data buffer must be prepared with before * it is passed to . The data structure * and the data buffer pointed to by its field must be allocated * with using the GMEM_MOVEABLE and GMEM_SHARE flags, and * locked with . * * @xref waveInPrepareHeader ****************************************************************************/ UINT WINAPI waveInAddBuffer( HWAVEIN hWaveIn, LPWAVEHDR lpWaveInHdr, UINT wSize ) { V_HANDLE(hWaveIn, TYPE_WAVEIN, MMSYSERR_INVALHANDLE); V_HEADER(lpWaveInHdr, wSize, TYPE_WAVEIN, MMSYSERR_INVALPARAM); if (!IsWaveHeaderPrepared(hWaveIn, lpWaveInHdr)) { DebugErr(DBF_WARNING, "waveInAddBuffer: buffer not prepared."); return WAVERR_UNPREPARED; } if (lpWaveInHdr->dwFlags & WHDR_INQUEUE) { DebugErr(DBF_WARNING, "waveInAddBuffer: buffer already in queue."); return WAVERR_STILLPLAYING; } return (UINT)waveIMessage( (HWAVE)hWaveIn, WIDM_ADDBUFFER, (DWORD)lpWaveInHdr, (DWORD)wSize); } /***************************************************************************** * @doc EXTERNAL WAVE * * @api UINT | waveInStart | This function starts input on the specified * waveform input device. * * @parm HWAVEIN | hWaveIn | Specifies a handle to the waveform input device. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. Possible error returns are: * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid. * * @comm Buffers are returned to the client when full or when * is called (the field in the header will contain the * actual length of data). If there are no buffers in the queue, the data is * thrown away without notification to the client, and input continues. * * Calling this function when input is already started has no effect, and * the function returns zero. * * @xref waveInStop waveInReset ****************************************************************************/ UINT WINAPI waveInStart( HWAVEIN hWaveIn ) { V_HANDLE(hWaveIn, TYPE_WAVEIN, MMSYSERR_INVALHANDLE); return (UINT)waveIMessage( (HWAVE)hWaveIn, WIDM_START, 0L, 0L); } /***************************************************************************** * @doc EXTERNAL WAVE * * @api UINT | waveInStop | This function stops waveform input. * * @parm HWAVEIN | hWaveIn | Specifies a handle to the waveform input * device. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. Possible error returns are: * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid. * * @comm If there are any buffers in the queue, the current buffer will be * marked as done (the field in the header will contain * the actual length of data), but any empty buffers in the queue will remain * there. Calling this function when input is not started has no effect, * and the function returns zero. * * @xref waveInStart waveInReset ****************************************************************************/ UINT WINAPI waveInStop( HWAVEIN hWaveIn ) { V_HANDLE(hWaveIn, TYPE_WAVEIN, MMSYSERR_INVALHANDLE); return (UINT)waveIMessage( (HWAVE)hWaveIn, WIDM_STOP, 0L, 0L ); } /***************************************************************************** * @doc EXTERNAL WAVE * * @api UINT | waveInReset | This function stops input on a given waveform * input device and resets the current position to 0. All pending * buffers are marked as done and returned to the application. * * @parm HWAVEIN | hWaveIn | Specifies a handle to the waveform input device. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. Possible error returns are: * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid. * * @xref waveInStart waveInStop waveInAddBuffer waveInClose /****************************************************************************/ UINT WINAPI waveInReset( HWAVEIN hWaveIn ) { V_HANDLE(hWaveIn, TYPE_WAVEIN, MMSYSERR_INVALHANDLE); return (UINT)waveIMessage( (HWAVE)hWaveIn, WIDM_RESET, 0L, 0L ); } /***************************************************************************** * @doc EXTERNAL WAVE * * @api UINT | waveInGetPosition | This function retrieves the current input * position of the specified waveform input device. * * @parm HWAVEIN | hWaveIn | Specifies a handle to the waveform input device. * * @parm LPMMTIME | lpInfo | Specifies a far pointer to an * structure. * * @parm UINT | wSize | Specifies the size of the structure. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * an error number. Possible error returns are: * @flag MMSYSERR_INVALHANDLE | Specified device handle is invalid. * * @comm Before calling , set the field of the * structure to indicate the time format that you desire. After * calling , be sure to check the field to * determine if the desired time format is supported. If the desired * format is not supported, will specify an alternative format. * * The position is set to zero when the device is opened or reset. ****************************************************************************/ UINT WINAPI waveInGetPosition( HWAVEIN hWaveIn, LPMMTIME lpInfo, UINT wSize ) { V_HANDLE(hWaveIn, TYPE_WAVEIN, MMSYSERR_INVALHANDLE); V_WPOINTER(lpInfo, wSize, MMSYSERR_INVALPARAM); return (UINT)waveIMessage( (HWAVE)hWaveIn, WIDM_GETPOS, (DWORD)lpInfo, (DWORD)wSize ); } /***************************************************************************** * @doc EXTERNAL WAVE * * @api UINT | waveInGetID | This function gets the device ID for a * waveform input device. * * @parm HWAVEIN | hWaveIn | Specifies the handle to the waveform * input device. * @parm UINT FAR* | lpwDeviceID | Specifies a pointer to the UINT-sized memory * location to be filled with the device ID. * * @rdesc Returns zero if successful. Otherwise, it returns * an error number. Possible error returns are: * @flag MMSYSERR_INVALHANDLE | The

parameter specifies an * invalid handle. * ****************************************************************************/ UINT WINAPI waveInGetID( HWAVEIN hWaveIn, UINT FAR* lpwDeviceID ) { V_HANDLE(hWaveIn, TYPE_WAVEIN, MMSYSERR_INVALHANDLE); V_WPOINTER(lpwDeviceID, sizeof(UINT), MMSYSERR_INVALPARAM); *lpwDeviceID = ((PWAVEDEV)hWaveIn)->wDeviceID; return MMSYSERR_NOERROR; } /***************************************************************************** * @doc EXTERNAL WAVE * * @api UINT | waveOutGetID | This function gets the device ID for a * waveform output device. * * @parm HWAVEOUT | hWaveOut | Specifies the handle to the waveform * output device. * @parm UINT FAR* | lpwDeviceID | Specifies a pointer to the UINT-sized memory * location to be filled with the device ID. * * @rdesc Returns zero if successful. Otherwise, it returns * an error number. Possible error returns are: * @flag MMSYSERR_INVALHANDLE | The

parameter specifies an * invalid handle. ****************************************************************************/ UINT WINAPI waveOutGetID( HWAVEOUT hWaveOut, UINT FAR* lpwDeviceID ) { V_HANDLE(hWaveOut, TYPE_WAVEOUT, MMSYSERR_INVALHANDLE); V_WPOINTER(lpwDeviceID, sizeof(UINT), MMSYSERR_INVALPARAM); *lpwDeviceID = ((PWAVEDEV)hWaveOut)->wDeviceID; return MMSYSERR_NOERROR; }