Opening MCI Audio Devices

Unlike MCI_SOUND, many MCI commands require that an audio device be opened before it can be accessed. Use the MCI_OPEN command along with the MCI_OPEN_PARMS parameter block to open an audio device and obtain an MCI device ID. Subsequent commands use this device ID to identify the device to receive the command. MMSYSTEM.H defines the MCI_OPEN_PARMS param-eter block as follows:

typedef struct {
        DWORD        dwCallback;                        /* callback for MCI_NOTIFY flag */
        WORD        wDeviceID;                        /* device ID returned to user */
        WORD        wReserved0;                        /* reserved */
        LPSTR        lpstrDeviceType;        /* device type */
        LPSTR        lpstrElementName;        /* device element */
        LPSTR        lpstrAlias;                        /* optional device alias (reserved) */
} MCI_OPEN_PARMS;

The MCI device ID is returned in the wDeviceID field. You should always check the return value of mciSendCommand after sending an MCI_OPEN command before using this device ID. A non-zero return value indicates that there was an error in opening the device and the returned device ID will not be valid.

Summary: Extended Parameter Block for Waveform Devices

For waveform audio devices, you can use an extended parameter block, MCI_WAVE_OPEN_PARMS. This structure has a dwBufferSeconds field to specify the number of seconds of buffering used by the MCI waveform device driver. If you use this field, you must specify the MCI_WAVE_OPEN_BUFFER flag for the dwParam1 parameter of mciSendCommand to validate the field. MMSYSTEM.H defines the MCI_WAVE_OPEN_PARMS parameter block as follows:

typedef struct {
        DWORD        dwCallback;                        /* callback for MCI_NOTIFY flag */
        WORD        wDeviceID;                        /* device ID returned to user */
        WORD        wReserved0;                        /* reserved */
        LPSTR        lpstrDeviceType;        /* device type */
        LPSTR        lpstrElementName;        /* device element */
        LPSTR        lpstrAlias;                        /* optional device alias (reserved) */
        DWORD        dwBufferSeconds;        /* buffer size in seconds */
} MCI_WAVE_OPEN_PARMS;

Unless you want to specify the number of seconds of buffering for the driver to use, you can use the MCI_WAVE_OPEN_PARMS parameter block when you open waveform audio devices.

Summary: Specifying Device Types

When you open a simple device, such as a compact disc audio device, you must specify the device type in the lpstrDeviceType field. When you open a compound device, such as a waveform or MIDI sequencer device, the device type is optional.

Use the lpstrDeviceType field of the MCI_OPEN_PARMS structure to specify the device type. MCI lets you use a string or a constant for this field. The following table shows the strings and constants for MCI audio device types:

Device Type String Constant

Compact disc “cdaudio” MCI_DEVTYPE_CD_AUDIO
Waveform “waveaudio” MCI_DEVTYPE_WAVEFORM_AUDIO
MIDI sequencer “sequencer” MCI_DEVTYPE_SEQUENCER

Using a string is the default convention for specifying device types. If you use a constant to specify the device type, you must specify the MCI_OPEN_TYPE_ID flag in addition to the MCI_OPEN_TYPE flag.

Opening Waveform and MIDI Sequencer Devices

Waveform and MIDI sequencer devices are compound devices. Compound devices require an associated device element—a WAVE or MIDI file. There are three ways to open compound devices:

Specify only the device type.

Specify only the device element and let MCI select the device type from the file extension of the device element.

Specify both the device type and the device element.

Use the first approach, specifying only the device type, when opening a device to query its capabilities with the MCI_GETDEVCAPS command and when you plan to use the device to play more than one device element.

Summary: Example of Opening a MIDI Sequencer Audio Device

If you don't specify a device type when you open a compound device, MCI will choose an appropriate device type by looking at the file extension of the device element and at entries in the [mci extensions] section of WIN.INI. The following code fragment uses this technique to open a MIDI sequencer device to play a MIDI file named CHOPIN.RMI:

WORD wDeviceID;
MCI_OPEN_PARMS mciOpenParms;
.
.
.
/* Open the device by specifying only the device element
 */
mciOpenParms.lpstrElementName = "CHOPIN.RMI";
if (mciSendCommand(0,                                   // device ID
                   MCI_OPEN,                            // command
                   MCI_OPEN_ELEMENT,                    // flags
                   (DWORD)(LPVOID) &mciOpenParms))      // parameter block
    /* Error, unable to open device
     */
    ...
else
    /* Device opened successfully, get the device ID
     */
    wDeviceID = mciOpenParms.wDeviceID;

Summary: Example of Opening a Waveform Audio Device

Instead of letting MCI choose the device type, you can specify the type when you open the device. The following code fragment uses this technique to open a waveform audio device to play the C:\SOUNDS\BELLS.WAV file. This example uses a string to specify the device type. For an example using a constant to specify the device type, see “Opening Compact Disc Devices,” later in this chapter.

WORD wDeviceID;
MCI_OPEN_PARMS mciOpenParms;
.
.
.
/* Open the device by specifying both the device element and the device type
 */
mciOpenParms.lpstrDeviceType = "waveaudio";
mciOpenParms.lpstrElementName = "C:\\SOUNDS\\BELLS.WAV";
if (mciSendCommand(0,                                     // device ID
                   MCI_OPEN,                              // command
                   MCI_OPEN_ELEMENT | MCI_OPEN_TYPE,      // flags
                   (DWORD)(LPVOID) &mciOpenParms))        // parameter block
    /* Error, unable to open device
     */
    ...
else
    /* Device opened successfully, get the device ID
     */
    wDeviceID = mciOpenParms.wDeviceID;

Using the MIDI Mapper with the MCI Sequencer

The MIDI Mapper is the default output device for the MCI MIDI sequencer. It provides standard patch services for device-independent playback of MIDI files. Applications that use the MCI sequencer to play MIDI files should use the MIDI Mapper. For details on the MIDI Mapper, see “The MIDI Mapper,” later in this chapter. For information on authoring device-independent MIDI files, see “Authoring MIDI Files,” also later in this chapter.

When you open the MCI MIDI sequencer, MCI attempts to select the MIDI Mapper as the output device. If the Mapper is unavailable because it's already in use, MCI selects another MIDI output device.

Note:

The MIDI Mapper currently supports only one client at a time. This might change in future versions of the Multimedia extensions.

Summary: Example of Verifying the Output Device

After opening the sequencer, you should check to see if the MIDI Mapper was available and selected as the output device. The following code fragment uses the MCI_STATUS command to verify that the MIDI Mapper is the output device for the MCI sequencer:

WORD wDeviceID;
DWORD dwReturn;
MCI_STATUS_PARMS mciStatusParms;
.
.
.
/* Make sure the opened device is the MIDI Mapper
 */
mciStatusParms.dwItem = MCI_SEQ_STATUS_PORT;
if (dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM,
                              (DWORD)(LPVOID) &mciStatusParms))
{
    /* Error sending MCI_STATUS command */
    ...
    return;
}
if (LOWORD(mciStatusParms.dwReturn) == MIDIMAPPER)
    /* The MIDI Mapper is the output device */
    ...

else
    /* The MIDI Mapper is not the output device */
    ...

Summary: Example Selecting MIDI Mapper as the Output Device

MCI also provides a command to explicitly select the MIDI Mapper as the output device for the sequencer. The following code fragment uses the MCI_SET command to select the MIDI Mapper as the output device for the MCI sequencer:

WORD wDeviceID;
DWORD dwReturn;
MCI_SEQ_SET_PARMS mciSeqSetParms;
.
.
.
/* Set the MIDI Mapper as the output port for the open device
 */
mciSeqSetParms.dwPort = MIDIMAPPER;
if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SEQ_SET_PORT,
                              (DWORD)(LPVOID) &mciSeqSetParms))
{
    /* Error, unable to set Mapper as output port */
    ...
}

Before querying the sequencer or setting an output port, you must successfully open the sequencer. Both of the previous examples assume that the wDeviceID parameter contains a valid device ID for the sequencer.

Opening Compact Disc Devices

Because a compact disc audio device is a simple device, you need only specify the device type when opening it by using either a string or a constant ID. The following code fragment opens a compact disc device using a constant ID to specify the device type:

WORD wDeviceID;
MCI_OPEN_PARMS mciOpenParms;
.
.
.
/* Open the device by specifying a device ID constant
 */
mciOpenParms.lpstrDeviceType = (LPSTR) MCI_DEVTYPE_CD_AUDIO;
if (mciSendCommand(0,                                   // device ID
                   MCI_OPEN,                            // command
                   MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID,    // flags
                   (DWORD)(LPVOID) &mciOpenParms))      // parameter block
    /* Error, unable to open device
     */
    ...
else
    /* Device opened successfully, get the device ID
     */
    wDeviceID = mciOpenParms.wDeviceID;