/***************************************************************************** midi.c Level 1 kitchen sink DLL midi 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 midiGetErrorText( UINT wError, LPSTR lpText, UINT wSize ); /* ------------------------------------------------------------------------- ** Local structures ** ------------------------------------------------------------------------- */ typedef struct mididev_tag { PMIDIDRV mididrv; UINT wDevice; DWORD dwDrvUser; UINT wDeviceID; } MIDIDEV; typedef MIDIDEV *PMIDIDEV; /* ------------------------------------------------------------------------- ** Segmentation ** ** Define the fixed code for this file. ** ------------------------------------------------------------------------- */ #pragma alloc_text( FIX, midiIMessage) #pragma alloc_text( FIX, midiOMessage) #pragma alloc_text( FIX, midiOutMessage) #pragma alloc_text( FIX, midiOutShortMsg) #pragma alloc_text( FIX, midiOutLongMsg) #pragma alloc_text( FIX, midiOutReset) /* ------------------------------------------------------------------------- ** Global data ** ------------------------------------------------------------------------- */ static int iMidiLockCount = 0; /***************************************************************************** * @doc INTERNAL MIDI * * @api void | midiLockData | * * This function is called every time a new MIDI handle is created, it * makes sure MMSYSTEM's data segment is page-locked. MIDI handles * are useable at interupt time so we must page-lock the data seg. * * in the future we should re-do the MIDI system. * ****************************************************************************/ BOOL NEAR PASCAL midiLockData( void ) { if (iMidiLockCount == 0) { DOUT("MMSYSTEM: Locking data segment\r\n"); if ( !GlobalPageLock((HGLOBAL)HIWORD((DWORD)(LPVOID)&iMidiLockCount)) && (WinFlags & WF_ENHANCED)) { return 0; } } return ++iMidiLockCount; } /***************************************************************************** * @doc INTERNAL MIDI * * @api void | midiUnlockData | * * This function is called every time a MIDI handle is closed, it * makes sure MMSYSTEM's data segment is un-page-locked. MIDI handles * are useable at interupt time so we must page-lock the data seg. * * in the future we should re-do the MIDI system. * ****************************************************************************/ void NEAR PASCAL midiUnlockData( void ) { #ifdef DEBUG if (iMidiLockCount == 0) DOUT("MMSYSTEM: midiUnlockData() underflow!!!!\r\n"); #endif if (--iMidiLockCount == 0) { DOUT("MMSYSTEM: Unlocking data segment\r\n"); GlobalPageUnlock((HGLOBAL)HIWORD((DWORD)(LPVOID)&iMidiLockCount)); } } /***************************************************************************** * @doc INTERNAL MIDI * * @api UINT | midiPrepareHeader | This function prepares the header and data * if the driver returns MMSYSERR_NOTSUPPORTED. * * @rdesc Currently always returns MMSYSERR_NOERROR. ****************************************************************************/ static UINT NEAR PASCAL midiPrepareHeader( LPMIDIHDR lpMidiHdr, UINT wSize ) { if (!HugePageLock(lpMidiHdr, (DWORD)sizeof(MIDIHDR))) return MMSYSERR_NOMEM; if (!HugePageLock(lpMidiHdr->lpData, lpMidiHdr->dwBufferLength)) { HugePageUnlock(lpMidiHdr, (DWORD)sizeof(MIDIHDR)); return MMSYSERR_NOMEM; } // lpMidiHdr->dwFlags |= MHDR_PREPARED; return MMSYSERR_NOERROR; } /***************************************************************************** * @doc INTERNAL MIDI * * @api UINT | midiUnprepareHeader | This function unprepares the header and * data if the driver returns MMSYSERR_NOTSUPPORTED. * * @rdesc Currently always returns MMSYSERR_NOERROR. ****************************************************************************/ static UINT NEAR PASCAL midiUnprepareHeader( LPMIDIHDR lpMidiHdr, UINT wSize ) { HugePageUnlock(lpMidiHdr->lpData, lpMidiHdr->dwBufferLength); HugePageUnlock(lpMidiHdr, (DWORD)sizeof(MIDIHDR)); // lpMidiHdr->dwFlags &= ~MHDR_PREPARED; return MMSYSERR_NOERROR; } /***************************************************************************** * @doc EXTERNAL MIDI * * @api UINT | midiOutGetNumDevs | This function retrieves the number of MIDI * output devices present in the system. * * @rdesc Returns the number of MIDI output devices present in the system. * * @xref midiOutGetDevCaps ****************************************************************************/ UINT WINAPI midiOutGetNumDevs(void) { return midiOIDMessage( 0, MODM_GETNUMDEVS, 0L, 0L, 0L ); } /**************************************************************************** * @doc EXTERNAL MIDI * * @api DWORD | midiOutMessage | This function sends messages to the MIDI device * drivers. * * @parm HMIDIOUT | hMidiOut | The handle to the MIDI device. * * @parm UINT | msg | The message to send. * * @parm DWORD | dw1 | Parameter 1. * * @parm DWORD | dw2 | Parameter 2. * * @rdesc Returns the value of the message sent. ***************************************************************************/ DWORD WINAPI midiOutMessage(HMIDIOUT hMidiOut, UINT msg, DWORD dw1, DWORD dw2) { V_HANDLE(hMidiOut, TYPE_MIDIOUT, 0L); return midiOMessage( (HMIDI)hMidiOut, msg, dw1, dw2); } /***************************************************************************** * @doc EXTERNAL MIDI * * @api UINT | midiOutGetDevCaps | This function queries a specified * MIDI output device to determine its capabilities. * * @parm UINT | wDeviceID | Identifies the MIDI output device. * * @parm LPMIDIOUTCAPS | 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. * @flag MMSYSERR_NOMEM | Unable load mapper string description. * * @comm Use to determine the number of MIDI output * devices present in the system. The device ID specified by

* varies from zero to one less than the number of devices present. * The MIDI_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 midiOutGetNumDevs ****************************************************************************/ UINT WINAPI midiOutGetDevCaps( UINT wDeviceID, LPMIDIOUTCAPS lpCaps, UINT wSize ) { if (wSize == 0) { return MMSYSERR_NOERROR; } V_WPOINTER(lpCaps, wSize, MMSYSERR_INVALPARAM); if (ValidateHandle((HMIDIOUT)wDeviceID, TYPE_MIDIOUT)) { return((UINT)midiOMessage((HMIDI)wDeviceID, MODM_GETDEVCAPS, (DWORD)lpCaps, (DWORD)wSize)); } return midiOIDMessage( wDeviceID, MODM_GETDEVCAPS, 0L, (DWORD)lpCaps, (DWORD)wSize); } /***************************************************************************** * @doc EXTERNAL MIDI * * @api UINT | midiOutGetVolume | This function returns the current volume * setting of a MIDI output device. * * @parm UINT | wDeviceID | Identifies the MIDI 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 control. To determine whether the * device supports volume control, use the MIDICAPS_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 MIDICAPS_LRVOLUME flag to test * the field of the * structure (filled by ). * * @xref midiOutSetVolume ****************************************************************************/ UINT WINAPI midiOutGetVolume( UINT wDeviceID, LPDWORD lpdwVolume ) { V_WPOINTER(lpdwVolume, sizeof(DWORD), MMSYSERR_INVALPARAM); if (ValidateHandle((HMIDIOUT)wDeviceID, TYPE_MIDIOUT)) { return((UINT)midiOMessage((HMIDI)wDeviceID, MODM_GETVOLUME, (DWORD)lpdwVolume, 0)); } return midiOIDMessage( wDeviceID, MODM_GETVOLUME, 0L, (DWORD)lpdwVolume, 0 ); } /***************************************************************************** * @doc EXTERNAL MIDI * * @api UINT | midiOutSetVolume | This function sets the volume of a * MIDI output device. * * @parm UINT | wDeviceID | Identifies the MIDI 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 MIDICAPS_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 MIDICAPS_LRVOLUME flag to test * the field of the * structure (filled by ). * * Most devices do not support the full 16 bits of volume level control * and will use only 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 will * all produce the same physical volume setting, 0x4000. The * function will return 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 midiOutGetVolume ****************************************************************************/ UINT WINAPI midiOutSetVolume( UINT wDeviceID, DWORD dwVolume ) { if (ValidateHandle((HMIDIOUT)wDeviceID, TYPE_MIDIOUT)) { return((UINT)midiOMessage((HMIDI)wDeviceID, MODM_SETVOLUME, dwVolume, 0)); } return midiOIDMessage( wDeviceID, MODM_SETVOLUME, 0L, dwVolume, 0); } /***************************************************************************** * @doc INTERNAL MIDI * * @func UINT | midiGetErrorText | 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 midiGetErrorText( UINT wError, LPSTR lpText, UINT wSize ) { lpText[0] = 0; #if MMSYSERR_BASE if ( ((wError < MMSYSERR_BASE) || (wError > MMSYSERR_LASTERROR)) && ((wError < MIDIERR_BASE) || (wError > MIDIERR_LASTERROR))) { return MMSYSERR_BADERRNUM; } #else if ((wError > MMSYSERR_LASTERROR) && ((wError < MIDIERR_BASE) || (wError > MIDIERR_LASTERROR))) { return MMSYSERR_BADERRNUM; } #endif if (wSize > 1) { if (!LoadString(ghInst, wError, lpText, wSize)) { return MMSYSERR_BADERRNUM; } } return MMSYSERR_NOERROR; } /***************************************************************************** * @doc EXTERNAL MIDI * * @api UINT | midiOutGetErrorText | 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 MMSYSERR_NOERROR. All error descriptions are * less than MAXERRORLENGTH characters long. ****************************************************************************/ UINT WINAPI midiOutGetErrorText( UINT wError, LPSTR lpText, UINT wSize ) { if(wSize == 0) { return MMSYSERR_NOERROR; } V_WPOINTER(lpText, wSize, MMSYSERR_INVALPARAM); return midiGetErrorText(wError, lpText, wSize); } /***************************************************************************** * @doc EXTERNAL MIDI * * @api UINT | midiOutOpen | This function opens a specified MIDI * output device for playback. * * @parm LPHMIDIOUT | lphMidiOut | Specifies a far pointer to an HMIDIOUT * handle. This location is filled with a handle identifying the opened * MIDI output device. Use the handle to identify the device when calling * other MIDI output functions. * * @parm UINT | wDeviceID | Identifies the MIDI output device that is * to be opened. * * @parm DWORD | dwCallback | Specifies the address of a fixed callback * function or * a handle to a window called during MIDI 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 a callback flag for opening the 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 as follows: * @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 MIDIERR_NOMAP | There is no current MIDI map. This occurs only * when opening the mapper. * @flag MIDIERR_NODEVICE | A port in the current MIDI map doesn't exist. * This occurs only when opening the mapper. * * @comm Use to determine the number of MIDI output * devices present in the system. The device ID specified by

* varies from zero to one less than the number of devices present. * You may also specify MIDI_MAPPER as the device ID to open the MIDI mapper. * * If a window is chosen to receive callback information, the following * messages are sent to the window procedure function to indicate the * progress of MIDI output: , , * . * * If a function is chosen to receive callback information, the following * messages are sent to the function to indicate the progress of MIDI * 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 | MidiOutFunc | 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 HMIDIOUT | hMidiOut | Specifies a handle to the MIDI device * associated with the callback. * * @parm UINT | wMsg | Specifies a MIDI output message. * * @parm DWORD | dwInstance | Specifies the instance data * supplied 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 midiOutClose ****************************************************************************/ UINT WINAPI midiOutOpen( LPHMIDIOUT lphMidiOut, UINT wDeviceID, DWORD dwCallback, DWORD dwInstance, DWORD dwFlags ) { MIDIOPENDESC mo; PMIDIDEV pdev; UINT wRet; V_WPOINTER(lphMidiOut, sizeof(HMIDIOUT), MMSYSERR_INVALPARAM); V_DCALLBACK(dwCallback, HIWORD(dwFlags), MMSYSERR_INVALPARAM); V_FLAGS(LOWORD(dwFlags), 0, midiOutOpen, MMSYSERR_INVALFLAG); /* ** Check for no devices */ // if (wTotalMidiOutDevs == 0 ) { // return MMSYSERR_BADDEVICEID; // } // // /* // ** check for device ID being to large // */ // if ( wDeviceID != MIDI_MAPPER ) { // if ( wDeviceID >= wTotalMidiOutDevs ) { // return MMSYSERR_BADDEVICEID; // } // } *lphMidiOut = NULL; if (!midiLockData()) { return MMSYSERR_NOMEM; } pdev = (PMIDIDEV)NewHandle(TYPE_MIDIOUT, sizeof(MIDIDEV)); if( pdev == NULL) { return MMSYSERR_NOMEM; } pdev->wDevice = wDeviceID; pdev->wDeviceID = wDeviceID; mo.hMidi = (HMIDI)pdev; mo.dwCallback = dwCallback; mo.dwInstance = dwInstance; wRet = midiOIDMessage( wDeviceID, MODM_OPEN, (DWORD)(LPDWORD)&pdev->dwDrvUser, (DWORD)(LPMIDIOPENDESC)&mo, dwFlags ); if (wRet) { FreeHandle((HMIDIOUT)pdev); midiUnlockData(); } else { *lphMidiOut = (HMIDIOUT)pdev; } return wRet; } /***************************************************************************** * @doc EXTERNAL MIDI * * @api UINT | midiOutClose | This function closes the specified MIDI * output device. * * @parm HMIDIOUT | hMidiOut | Specifies a handle to the MIDI 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 MIDIERR_STILLPLAYING | There are still buffers in the queue. * * @comm If there are output 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 being done. * * @xref midiOutOpen midiOutReset ****************************************************************************/ UINT WINAPI midiOutClose( HMIDIOUT hMidiOut ) { UINT wRet; V_HANDLE(hMidiOut, TYPE_MIDIOUT, MMSYSERR_INVALHANDLE); wRet = (UINT)midiOMessage( (HMIDI)hMidiOut, MODM_CLOSE, 0L,0L); if (!wRet) { FreeHandle(hMidiOut); midiUnlockData(); } return wRet; } /***************************************************************************** * @doc EXTERNAL MIDI * * @api UINT | midiOutPrepareHeader | This function prepares a MIDI * system-exclusive data block for output. * * @parm HMIDIOUT | hMidiOut | Specifies a handle to the MIDI output * device. * * @parm LPMIDIHDR | lpMidiOutHdr | Specifies a far 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 midiOutUnprepareHeader ****************************************************************************/ UINT WINAPI midiOutPrepareHeader( HMIDIOUT hMidiOut, LPMIDIHDR lpMidiOutHdr, UINT wSize ) { UINT wRet; V_HANDLE(hMidiOut, TYPE_MIDIOUT, MMSYSERR_INVALHANDLE); V_HEADER(lpMidiOutHdr, wSize, TYPE_MIDIOUT, MMSYSERR_INVALPARAM); if (lpMidiOutHdr->dwFlags & MHDR_PREPARED) { return MMSYSERR_NOERROR; } lpMidiOutHdr->dwFlags = 0; wRet = midiPrepareHeader(lpMidiOutHdr, wSize); if (wRet == MMSYSERR_NOERROR) { wRet = (UINT)midiOMessage( (HMIDI)hMidiOut, MODM_PREPARE, (DWORD)lpMidiOutHdr, (DWORD)wSize ); } return wRet; } /***************************************************************************** * @doc EXTERNAL MIDI * * @api UINT | midiOutUnprepareHeader | 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 HMIDIOUT | hMidiOut | Specifies a handle to the MIDI output * device. * * @parm LPMIDIHDR | lpMidiOutHdr | Specifies a pointer to a * structure identifying the 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 MIDIERR_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 midiOutPrepareHeader ****************************************************************************/ UINT WINAPI midiOutUnprepareHeader( HMIDIOUT hMidiOut, LPMIDIHDR lpMidiOutHdr, UINT wSize ) { UINT wRet; V_HANDLE(hMidiOut, TYPE_MIDIOUT, MMSYSERR_INVALHANDLE); V_HEADER(lpMidiOutHdr, wSize, TYPE_MIDIOUT, MMSYSERR_INVALPARAM); if (!(lpMidiOutHdr->dwFlags & MHDR_PREPARED)) { return MMSYSERR_NOERROR; } if(lpMidiOutHdr->dwFlags & MHDR_INQUEUE) { DebugErr( DBF_WARNING, "midiOutUnprepareHeader: header still in queue\r\n"); return MIDIERR_STILLPLAYING; } wRet = midiUnprepareHeader(lpMidiOutHdr, wSize); if (wRet == MMSYSERR_NOERROR) { wRet = (UINT)midiOMessage( (HMIDI)hMidiOut, MODM_UNPREPARE, (DWORD)lpMidiOutHdr, (DWORD)wSize ); } return wRet; } /***************************************************************************** * @doc EXTERNAL MIDI * * @api UINT | midiOutShortMsg | This function sends a short MIDI message to * the specified MIDI output device. Use this function to send any MIDI * message except for system-exclusive messages. * * @parm HMIDIOUT | hMidiOut | Specifies a handle to the MIDI output * device. * * @parm DWORD | dwMsg | Specifies the MIDI message. The message is packed * into a DWORD with the first byte of the message in the low-order byte. * * @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 MIDIERR_NOTREADY | The hardware is busy with other data. * * @comm This function may not return until the message has been sent to the * output device. * * @xref midiOutLongMsg ****************************************************************************/ UINT WINAPI midiOutShortMsg( HMIDIOUT hMidiOut, DWORD dwMsg ) { V_HANDLE(hMidiOut, TYPE_MIDIOUT, MMSYSERR_INVALHANDLE); return (UINT)midiOMessage( (HMIDI)hMidiOut, MODM_DATA, dwMsg, 0L ); } /***************************************************************************** * @doc EXTERNAL MIDI * * @api UINT | midiOutLongMsg | This function sends a system-exclusive * MIDI message to the specified MIDI output device. * * @parm HMIDIOUT | hMidiOut | Specifies a handle to the MIDI output * device. * * @parm LPMIDIHDR | lpMidiOutHdr | Specifies a far pointer to a * structure that identifies the MIDI data 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 MIDIERR_UNPREPARED |

hasn't been prepared. * @flag MIDIERR_NOTREADY | The hardware is busy with other data. * * @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 . The MIDI output * device driver determines whether the data is sent synchronously or * asynchronously. * * @xref midiOutShortMsg midiOutPrepareHeader ****************************************************************************/ UINT WINAPI midiOutLongMsg( HMIDIOUT hMidiOut, LPMIDIHDR lpMidiOutHdr, UINT wSize ) { V_HANDLE(hMidiOut, TYPE_MIDIOUT, MMSYSERR_INVALHANDLE); // // we can't call these at interupt time. // #pragma message("header not validated for midiOutLongMessage") ////V_HEADER(lpMidiOutHdr, wSize, TYPE_MIDIOUT, MMSYSERR_INVALPARAM); if ( HIWORD(lpMidiOutHdr) == 0 ) { return MMSYSERR_INVALPARAM; } if ( wSize != sizeof(MIDIHDR) ) { return MMSYSERR_INVALPARAM; } if (LOWORD(lpMidiOutHdr->dwFlags) & ~MHDR_VALID) { return MMSYSERR_INVALFLAG; } if (!(lpMidiOutHdr->dwFlags & MHDR_PREPARED)) { return MIDIERR_UNPREPARED; } if (lpMidiOutHdr->dwFlags & MHDR_INQUEUE) { return MIDIERR_STILLPLAYING; } return (UINT)midiOMessage( (HMIDI)hMidiOut, MODM_LONGDATA, (DWORD)lpMidiOutHdr, (DWORD)wSize); } /***************************************************************************** * @doc EXTERNAL MIDI * * @api UINT | midiOutReset | This function turns off all notes on all MIDI * channels for the specified MIDI output device. Any pending * system-exclusive output buffers are marked as done and * returned to the application. * * @parm HMIDIOUT | hMidiOut | Specifies a handle to the MIDI 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 To turn off all notes, a note-off message for each note for each * channel is sent. In addition, the sustain controller is turned off for * each channel. * * @xref midiOutLongMsg midiOutClose ****************************************************************************/ UINT WINAPI midiOutReset( HMIDIOUT hMidiOut ) { V_HANDLE(hMidiOut, TYPE_MIDIOUT, MMSYSERR_INVALHANDLE); return (UINT)midiOMessage( (HMIDI)hMidiOut, MODM_RESET, 0L, 0L ); } /***************************************************************************** * @doc EXTERNAL MIDI * * @api UINT | midiOutCachePatches | This function requests that an internal * MIDI synthesizer device preload a specified set of patches. Some * synthesizers are not capable of keeping all patches loaded simultaneously * and must load data from disk when they receive MIDI program change * messages. Caching patches ensures specified patches are immediately * available. * * @parm HMIDIOUT | hMidiOut | Specifies a handle to the opened MIDI output * device. This device must be an internal MIDI synthesizer. * * @parm UINT | wBank | Specifies which bank of patches should be used. * This parameter should be set to zero to cache the default patch bank. * * @parm WORD FAR* | lpPatchArray | Specifies a pointer to a * array indicating the patches to be cached or uncached. * * @parm UINT | wFlags | Specifies options for the cache operation. Only one * of the following flags can be specified: * @flag MIDI_CACHE_ALL | Cache all of the specified patches. If they * can't all be cached, cache none, clear the array, * and return MMSYSERR_NOMEM. * @flag MIDI_CACHE_BESTFIT | Cache all of the specified patches. * If all patches can't be cached, cache as many patches as * possible, change the array to reflect which * patches were cached, and return MMSYSERR_NOMEM. * @flag MIDI_CACHE_QUERY | Change the array to indicate * which patches are currently cached. * @flag MIDI_UNCACHE | Uncache the specified patches and clear the * array. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * one of the following error codes: * @flag MMSYSERR_INVALHANDLE | The specified device handle is invalid. * @flag MMSYSERR_NOTSUPPORTED | The specified device does not support * patch caching. * @flag MMSYSERR_NOMEM | The device does not have enough memory to cache * all of the requested patches. * * @comm The data type is defined as: * * typedef WORD PATCHARRAY[MIDIPATCHSIZE]; * * Each element of the array represents one of the 128 patches and * has bits set for * each of the 16 MIDI channels that use that particular patch. The * least-significant bit represents physical channel 0; the * most-significant bit represents physical channel 15 (0x0F). For * example, if patch 0 is used by physical channels 0 and 8, element 0 * would be set to 0x0101. * * This function only applies to internal MIDI synthesizer devices. * Not all internal synthesizers support patch caching. Use the * MIDICAPS_CACHE flag to test the field of the * structure filled by to see if the * device supports patch caching. * * @xref midiOutCacheDrumPatches ****************************************************************************/ UINT WINAPI midiOutCachePatches( HMIDIOUT hMidiOut, UINT wBank, WORD FAR* lpPatchArray, UINT wFlags ) { V_HANDLE(hMidiOut, TYPE_MIDIOUT, MMSYSERR_INVALHANDLE); V_WPOINTER(lpPatchArray, sizeof(PATCHARRAY), MMSYSERR_INVALPARAM); V_FLAGS(wFlags, MIDI_CACHE_VALID, midiOutCachePatches, MMSYSERR_INVALFLAG); return (UINT)midiOMessage( (HMIDI)hMidiOut, MODM_CACHEPATCHES, (DWORD)lpPatchArray, MAKELONG(wFlags, wBank) ); } /***************************************************************************** * @doc EXTERNAL MIDI * * @api UINT | midiOutCacheDrumPatches | This function requests that an * internal MIDI synthesizer device preload a specified set of key-based * percussion patches. Some synthesizers are not capable of keeping all * percussion patches loaded simultaneously. Caching patches ensures * specified patches are available. * * @parm HMIDIOUT | hMidiOut | Specifies a handle to the opened MIDI output * device. This device should be an internal MIDI synthesizer. * * @parm UINT | wPatch | Specifies which drum patch number should be used. * This parameter should be set to zero to cache the default drum patch. * * @parm WORD FAR* | lpKeyArray | Specifies a pointer to a * array indicating the key numbers of the specified percussion patches * to be cached or uncached. * * @parm UINT | wFlags | Specifies options for the cache operation. Only one * of the following flags can be specified: * @flag MIDI_CACHE_ALL | Cache all of the specified patches. If they * can't all be cached, cache none, clear the array, * and return MMSYSERR_NOMEM. * @flag MIDI_CACHE_BESTFIT | Cache all of the specified patches. * If all patches can't be cached, cache as many patches as * possible, change the array to reflect which * patches were cached, and return MMSYSERR_NOMEM. * @flag MIDI_CACHE_QUERY | Change the array to indicate * which patches are currently cached. * @flag MIDI_UNCACHE | Uncache the specified patches and clear the * array. * * @rdesc Returns zero if the function was successful. Otherwise, it returns * one of the following error codes: * @flag MMSYSERR_INVALHANDLE | The specified device handle is invalid. * @flag MMSYSERR_NOTSUPPORTED | The specified device does not support * patch caching. * @flag MMSYSERR_NOMEM | The device does not have enough memory to cache * all of the requested patches. * * @comm The data type is defined as: * * typedef WORD KEYARRAY[MIDIPATCHSIZE]; * * Each element of the array represents one of the 128 key-based percussion * patches and has bits set for * each of the 16 MIDI channels that use that particular patch. The * least-significant bit represents physical channel 0; the * most-significant bit represents physical channel 15. For * example, if the patch on key number 60 is used by physical channels 9 * and 15, element 60 would be set to 0x8200. * * This function applies only to internal MIDI synthesizer devices. * Not all internal synthesizers support patch caching. Use the * MIDICAPS_CACHE flag to test the field of the * structure filled by to see if the * device supports patch caching. * * @xref midiOutCachePatches ****************************************************************************/ UINT WINAPI midiOutCacheDrumPatches( HMIDIOUT hMidiOut, UINT wPatch, WORD FAR* lpKeyArray, UINT wFlags ) { V_HANDLE(hMidiOut, TYPE_MIDIOUT, MMSYSERR_INVALHANDLE); V_WPOINTER(lpKeyArray, sizeof(KEYARRAY), MMSYSERR_INVALPARAM); V_FLAGS(wFlags, MIDI_CACHE_VALID, midiOutCacheDrumPatches, MMSYSERR_INVALFLAG); return (UINT)midiOMessage( (HMIDI)hMidiOut, MODM_CACHEDRUMPATCHES, (DWORD)lpKeyArray, MAKELONG(wFlags, wPatch) ); } /***************************************************************************** * @doc EXTERNAL MIDI * * @api UINT | midiInGetNumDevs | This function retrieves the number of MIDI * input devices in the system. * * @rdesc Returns the number of MIDI input devices present in the system. * * @xref midiInGetDevCaps ****************************************************************************/ UINT WINAPI midiInGetNumDevs( void ) { return midiIIDMessage( 0, MIDM_GETNUMDEVS, 0L, 0L, 0L ); } /**************************************************************************** * @doc EXTERNAL MIDI * * @api DWORD | midiInMessage | This function sends messages to the MIDI device * drivers. * * @parm HMIDIIN | hMidiIn | The handle to the MIDI device. * * @parm UINT | msg | The message to send. * * @parm DWORD | dw1 | Parameter 1. * * @parm DWORD | dw2 | Parameter 2. * * @rdesc Returns the value of the message sent. ***************************************************************************/ DWORD WINAPI midiInMessage( HMIDIIN hMidiIn, UINT msg, DWORD dw1, DWORD dw2 ) { V_HANDLE(hMidiIn, TYPE_MIDIIN, 0L); return midiIMessage( (HMIDI)hMidiIn, msg, dw1, dw2); } /***************************************************************************** * @doc EXTERNAL MIDI * * @api UINT | midiInGetDevCaps | This function queries a specified MIDI input * device to determine its capabilities. * * @parm UINT | wDeviceID | Identifies the MIDI input device. * * @parm LPMIDIINCAPS | lpCaps | Specifies a far pointer to a * data 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 MIDI input * devices present in the system. The device ID specified by

* varies from zero to one less than the number of devices present. * The MIDI_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 midiInGetNumDevs ****************************************************************************/ UINT WINAPI midiInGetDevCaps( UINT wDeviceID, LPMIDIINCAPS lpCaps, UINT wSize ) { if (wSize == 0) { return MMSYSERR_NOERROR; } V_WPOINTER(lpCaps, wSize, MMSYSERR_INVALPARAM); if (ValidateHandle((HMIDIIN)wDeviceID, TYPE_MIDIIN)) { return((UINT)midiIMessage((HMIDIIN)wDeviceID, MIDM_GETDEVCAPS, (DWORD)lpCaps, (DWORD)wSize)); } return midiIIDMessage( wDeviceID, MIDM_GETDEVCAPS, 0L, (DWORD)lpCaps, (DWORD)wSize); } /***************************************************************************** * @doc EXTERNAL MIDI * * @api UINT | midiInGetErrorText | 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 length of 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 midiInGetErrorText( UINT wError, LPSTR lpText, UINT wSize ) { if(wSize == 0) { return MMSYSERR_NOERROR; } V_WPOINTER(lpText, wSize, MMSYSERR_INVALPARAM); return midiGetErrorText(wError, lpText, wSize); } /***************************************************************************** * @doc EXTERNAL MIDI * * @api UINT | midiInOpen | This function opens a specified MIDI input device. * * @parm LPHMIDIIN | lphMidiIn | Specifies a far pointer to an HMIDIIN handle. * This location is filled with a handle identifying the opened MIDI * input device. Use the handle to identify the device when calling * other MIDI input functions. * * @parm UINT | wDeviceID | Identifies the MIDI input device to be * opened. * * @parm DWORD | dwCallback | Specifies the address of a fixed callback * function or a handle to a window called with information * about incoming MIDI messages. * * @parm DWORD | dwCallbackInstance | Specifies user instance data * passed to the callback function. This parameter is not * used with window callbacks. * * @parm DWORD | dwFlags | Specifies a callback flag for opening the 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. * * @comm Use to determine the number of MIDI input * devices present in the system. The device ID specified by

* varies from zero to one less than the number of devices present. * The MIDI_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 MIDI input: , , * , , , * . * * If a function is chosen to receive callback information, the following * messages are sent to the function to indicate the progress of MIDI * 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 | MidiInFunc | 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 HMIDIIN | hMidiIn | Specifies a handle to the MIDI input device. * * @parm UINT | wMsg | Specifies a MIDI input message. * * @parm DWORD | dwInstance | Specifies the instance data supplied * 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 midiInClose ****************************************************************************/ UINT WINAPI midiInOpen( LPHMIDIIN lphMidiIn, UINT wDeviceID, DWORD dwCallback, DWORD dwInstance, DWORD dwFlags ) { MIDIOPENDESC mo; PMIDIDEV pdev; UINT wRet; V_WPOINTER(lphMidiIn, sizeof(HMIDIIN), MMSYSERR_INVALPARAM); V_DCALLBACK(dwCallback, HIWORD(dwFlags), MMSYSERR_INVALPARAM); V_FLAGS(LOWORD(dwFlags), 0, midiInOpen, MMSYSERR_INVALFLAG); /* ** Check for no devices */ // if (wTotalMidiInDevs == 0 ) { // return MMSYSERR_BADDEVICEID; // } // // /* // ** check for device ID being to large // */ // if ( wDeviceID != MIDI_MAPPER ) { // if ( wDeviceID >= wTotalMidiInDevs ) { // return MMSYSERR_BADDEVICEID; // } // } *lphMidiIn = NULL; if (!midiLockData()) { return MMSYSERR_NOMEM; } pdev = (PMIDIDEV)NewHandle(TYPE_MIDIIN, sizeof(MIDIDEV)); if( pdev == NULL) { return MMSYSERR_NOMEM; } pdev->wDevice = wDeviceID; pdev->wDeviceID = wDeviceID; mo.hMidi = (HMIDI)pdev; mo.dwCallback = dwCallback; mo.dwInstance = dwInstance; wRet = midiIIDMessage( wDeviceID, MIDM_OPEN, (DWORD)(LPDWORD)&pdev->dwDrvUser, (DWORD)(LPMIDIOPENDESC)&mo, dwFlags ); if (wRet) { FreeHandle((HMIDIIN)pdev); midiUnlockData(); } else { *lphMidiIn = (HMIDIIN)pdev; } return wRet; } /***************************************************************************** * @doc EXTERNAL MIDI * * @api UINT | midiInClose | This function closes the specified MIDI input * device. * * @parm HMIDIIN | hMidiIn | Specifies a handle to the MIDI 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 MIDIERR_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 being done. * * @xref midiInOpen midiInReset ****************************************************************************/ UINT WINAPI midiInClose( HMIDIIN hMidiIn ) { UINT wRet; V_HANDLE(hMidiIn, TYPE_MIDIIN, MMSYSERR_INVALHANDLE); wRet = (UINT)midiIMessage( (HMIDI)hMidiIn, MIDM_CLOSE, 0L, 0L); if (!wRet) { FreeHandle(hMidiIn); midiUnlockData(); } return wRet; } /***************************************************************************** * @doc EXTERNAL MIDI * * @api UINT | midiInPrepareHeader | This function prepares a buffer for * MIDI input. * * @parm HMIDIIN | hMidiIn | Specifies a handle to the MIDI input * device. * * @parm LPMIDIHDR | lpMidiInHdr | 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 has no effect, * and the function returns zero. * * @xref midiInUnprepareHeader ****************************************************************************/ UINT WINAPI midiInPrepareHeader( HMIDIIN hMidiIn, LPMIDIHDR lpMidiInHdr, UINT wSize ) { UINT wRet; V_HANDLE(hMidiIn, TYPE_MIDIIN, MMSYSERR_INVALHANDLE); V_HEADER(lpMidiInHdr, wSize, TYPE_MIDIIN, MMSYSERR_INVALPARAM); if (lpMidiInHdr->dwFlags & MHDR_PREPARED) { return MMSYSERR_NOERROR; } lpMidiInHdr->dwFlags = 0; wRet = midiPrepareHeader(lpMidiInHdr, wSize); if (wRet == MMSYSERR_NOERROR) { wRet = (UINT)midiIMessage( (HMIDI)hMidiIn, MIDM_PREPARE, (DWORD)lpMidiInHdr, (DWORD)wSize); } return wRet; } /***************************************************************************** * @doc EXTERNAL MIDI * * @api UINT | midiInUnprepareHeader | 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 HMIDIIN | hMidiIn | Specifies a handle to the MIDI input * device. * * @parm LPMIDIHDR | lpMidiInHdr | 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 MIDIERR_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 midiInPrepareHeader ****************************************************************************/ UINT WINAPI midiInUnprepareHeader( HMIDIIN hMidiIn, LPMIDIHDR lpMidiInHdr, UINT wSize ) { UINT wRet; V_HANDLE(hMidiIn, TYPE_MIDIIN, MMSYSERR_INVALHANDLE); V_HEADER(lpMidiInHdr, wSize, TYPE_MIDIIN, MMSYSERR_INVALPARAM); if (!(lpMidiInHdr->dwFlags & MHDR_PREPARED)) { return MMSYSERR_NOERROR; } if(lpMidiInHdr->dwFlags & MHDR_INQUEUE) { DebugErr( DBF_WARNING, "midiInUnprepareHeader: header still in queue\r\n"); return MIDIERR_STILLPLAYING; } wRet = midiUnprepareHeader(lpMidiInHdr, wSize); if (wRet == MMSYSERR_NOERROR) { wRet = (UINT)midiIMessage( (HMIDI)hMidiIn, MIDM_UNPREPARE, (DWORD)lpMidiInHdr, (DWORD)wSize); } return wRet; } /****************************************************************************** * @doc EXTERNAL MIDI * * @api UINT | midiInAddBuffer | This function sends an input buffer * to a specified opened MIDI input device. When the buffer is filled, * it is sent back to the application. Input buffers are * used only for system-exclusive messages. * * @parm HMIDIIN | hMidiIn | Specifies a handle to the MIDI input device. * * @parm LPMIDIHDR | lpMidiInHdr | 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 MIDIERR_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 midiInPrepareHeader *****************************************************************************/ UINT WINAPI midiInAddBuffer( HMIDIIN hMidiIn, LPMIDIHDR lpMidiInHdr, UINT wSize ) { V_HANDLE(hMidiIn, TYPE_MIDIIN, MMSYSERR_INVALHANDLE); V_HEADER(lpMidiInHdr, wSize, TYPE_MIDIIN, MMSYSERR_INVALPARAM); if (!(lpMidiInHdr->dwFlags & MHDR_PREPARED)) { DebugErr(DBF_WARNING, "midiInAddBuffer: buffer not prepared\r\n"); return MIDIERR_UNPREPARED; } if (lpMidiInHdr->dwFlags & MHDR_INQUEUE) { DebugErr(DBF_WARNING, "midiInAddBuffer: buffer already in queue\r\n"); return MIDIERR_STILLPLAYING; } return (UINT)midiIMessage( (HMIDI)hMidiIn, MIDM_ADDBUFFER, (DWORD)lpMidiInHdr, (DWORD)wSize ); } /***************************************************************************** * @doc EXTERNAL MIDI * * @api UINT | midiInStart | This function starts MIDI input on the * specified MIDI input device. * * @parm HMIDIIN | hMidiIn | Specifies a handle to the MIDI 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 This function resets the timestamps to zero; timestamp values for * subsequently received messages are relative to the time this * function was called. * * All messages other than system-exclusive messages are sent * directly to the client when received. System-exclusive * messages are placed in the buffers supplied by ; * if there are no buffers in the queue, * the data is thrown away without notification to the client, and input * continues. * * Buffers are returned to the client when full, when a * complete system-exclusive message has been received, * or when is * called. The field in the header will contain the * actual length of data received. * * Calling this function when input is already started has no effect, and * the function returns zero. * * @xref midiInStop midiInReset ****************************************************************************/ UINT WINAPI midiInStart( HMIDIIN hMidiIn ) { V_HANDLE(hMidiIn, TYPE_MIDIIN, MMSYSERR_INVALHANDLE); return (UINT)midiIMessage( (HMIDI)hMidiIn, MIDM_START, 0L, 0L); } /***************************************************************************** * @doc EXTERNAL MIDI * * @api UINT | midiInStop | This function terminates MIDI input on the * specified MIDI input device. * * @parm HMIDIIN | hMidiIn | Specifies a handle to the MIDI 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 Current status (running status, parsing state, etc.) is maintained * across calls to and . * If there are any system-exclusive message buffers in the queue, * the current buffer * is marked as done (the field in the header will * contain the actual length of data), but any empty buffers in the queue * remain there. Calling this function when input is not started has no * no effect, and the function returns zero. * * @xref midiInStart midiInReset ****************************************************************************/ UINT WINAPI midiInStop( HMIDIIN hMidiIn ) { V_HANDLE(hMidiIn, TYPE_MIDIIN, MMSYSERR_INVALHANDLE); return (UINT)midiIMessage( (HMIDI)hMidiIn, MIDM_STOP, 0L, 0L); } /***************************************************************************** * @doc EXTERNAL MIDI * * @api UINT | midiInReset | This function stops input on a given MIDI * input device and marks all pending input buffers as done. * * @parm HMIDIIN | hMidiIn | Specifies a handle to the MIDI 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 midiInStart midiInStop midiInAddBuffer midiInClose ****************************************************************************/ UINT WINAPI midiInReset( HMIDIIN hMidiIn ) { V_HANDLE(hMidiIn, TYPE_MIDIIN, MMSYSERR_INVALHANDLE); return (UINT)midiIMessage( (HMIDI)hMidiIn, MIDM_RESET, 0L, 0L ); } /***************************************************************************** * @doc EXTERNAL MIDI * * @api UINT | midiInGetID | This function gets the device ID for a * MIDI input device. * * @parm HMIDIIN | hMidiIn | Specifies the handle to the MIDI 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, returns * an error number. Possible error returns are: * * @flag MMSYSERR_INVALHANDLE | The

parameter specifies an * invalid handle. * ****************************************************************************/ UINT WINAPI midiInGetID( HMIDIIN hMidiIn, UINT FAR* lpwDeviceID ) { V_HANDLE(hMidiIn, TYPE_MIDIIN, MMSYSERR_INVALHANDLE); V_WPOINTER(lpwDeviceID, sizeof(UINT), MMSYSERR_INVALPARAM); *lpwDeviceID = ((PMIDIDEV)hMidiIn)->wDeviceID; return MMSYSERR_NOERROR; } /***************************************************************************** * @doc EXTERNAL MIDI * * @api UINT | midiOutGetID | This function gets the device ID for a * MIDI output device. * * @parm HMIDIOUT | hMidiOut | Specifies the handle to the MIDI output * device. * @parm UINT FAR* | lpwDeviceID | Specifies a pointer to the UINT-sized * memory location to be filled with the device ID. * * @rdesc Returns MMSYSERR_NOERROR if successful. Otherwise, returns * an error number. Possible error returns are: * * @flag MMSYSERR_INVALHANDLE | The

parameter specifies an * invalid handle. * ****************************************************************************/ UINT WINAPI midiOutGetID( HMIDIOUT hMidiOut, UINT FAR* lpwDeviceID ) { V_HANDLE(hMidiOut, TYPE_MIDIOUT, MMSYSERR_INVALHANDLE); V_WPOINTER(lpwDeviceID, sizeof(UINT), MMSYSERR_INVALPARAM); *lpwDeviceID = ((PMIDIDEV)hMidiOut)->wDeviceID; return MMSYSERR_NOERROR; } #if 0 /*****************************Private*Routine******************************\ * midiIDMessage * * * * History: * dd-mm-93 - StephenE - Created * \**************************************************************************/ UINT FAR PASCAL midiIDMessage( LPSOUNDDEVMSGPROC lpProc, UINT wDeviceID, UINT wMessage, DWORD dwUser, DWORD dwParam1, DWORD dwParam2 ) { return CallProc32W( (DWORD)wDeviceID, (DWORD)wMessage, dwUser, dwParam1, dwParam2, lpProc, 0L, 5L ); } #endif