80.5.5 Sending Buffered Messages

MIDI system-exclusive messages are the only MIDI messages that will not fit into a single DWORD. System exclusive messages can be any length. Windows provides the midiOutLongMsg function for sending one or more messages, including system exclusive messages, to MIDI output devices.

Use the MIDIHDR data structure to specify MIDI system-exclusive data blocks. This structure contains a pointer to a locked data block, the data-block length, and some assorted flags. The MMSYSTEM.H file defines the MIDIHDR data structure as follows:

typedef struct midihdr_tag {

LPSTR lpData; /* pointer to data block */

DWORD dwBufferLength; /* length of data block */

DWORD dwBytesRecorded; /* number of bytes recorded */

DWORD dwUser; /* user instance data */

DWORD dwFlags; /* assorted flags */

struct wavehdr_tag far *lpNext; /* private to the driver */

DWORD reserved; /* private to the driver */

} MIDIHDR;

Memory for the MIDIHDR data structure and the data block pointed to by lpData must be allocated and prepared, as shown in “Allocating and Preparing Audio Data Blocks,” earlier in this chapter.

After you send a system-exclusive data block using midiOutLongMsg, you must wait until the device driver is finished with the data block before freeing it. If you are sending multiple data blocks, you must monitor the completion of each data block so you know when to send additional blocks. For information on different techniques for monitoring data-block completion, see “Managing Audio Data Blocks,” earlier in this chapter.

Note:

Any MIDI status byte other than a system-real-time message will terminate a system exclusive message. If you are using multiple data blocks to send a single system-exclusive message, do not send any MIDI messages other than system-real-time messages between data blocks.

80.5.5.1 Using Window Messages to Manage Buffered Playback

The following messages can be sent to a window-procedure function for managing MIDI system-exclusive playback:

Message Description

MM_MOM_CLOSE Sent when the device is closed using midiOutClose.
MM_MOM_DONE Sent when the device driver is finished with a data block sent using midiOutLongMsg.
MM_MOM_OPEN Sent when the device is opened using midiOutOpen.

A wParam and lParam parameter is associated with each of these messages. The wParam parameter always specifies a handle to the open MIDI device. For the MM_MOM_DONE message, lParam specifies a far pointer to a MIDIHDR structure identifying the completed data block. The lParam parameter is unused for the MM_MOM_CLOSE and MM_MOM_OPEN messages.

The most useful message is the MM_MOM_DONE message. Unless you need to allocate memory or initialize variables, you probably don't need to process the MM_MOM_OPEN and MM_MOM_CLOSE messages. When playback of a data block is completed, you can clean up and free the data block as de- scribed in “Allocating and Preparing Audio Data Blocks,” earlier in this chapter.

80.5.5.2 Using a Callback to Manage Buffered Playback

This syntax of the low-level callback function for MIDI output devices is as follows:

void FAR PASCAL midiOutCallback(hMidiOut, wMsg, dwInstance, dwParam1, dwParam2)

The following messages can be sent to the wMsg parameter of MIDI output callback functions:

Message Description

MOM_CLOSE Sent when the device is closed using midiOutClose.
MOM_OPEN Sent when the device is opened using midiOutOpen.
MOM_DONE Sent when the device driver is finished with a data block sent using midiOutLongMsg.

These messages are similar to those sent to window-procedure functions, but the parameters are different. A handle to the open MIDI device is passed as a parameter to the callback, along with the DWORD of instance data passed using midiOutOpen.

The callback has two message-dependent parameters: dwParam1 and dwParam2. For the MOM_OPEN and MOM_CLOSE messages, these parameters are not used. For the MOM_DONE message, dwParam1 specifies a far pointer to a MIDIHDR structure identifying the completed data block and dwParam2 is not used.

After the driver is finished with a data block, you can clean up and free the data block. Because of the restrictions of low-level audio callbacks, you can't do this within the callback. See “Using a Callback Function to Process Driver Messages,” earlier in this chapter, for details on the restrictions when using callback functions.