Once you successfully open an MCI audio device, you can use the MCI_PLAY command along with the MCI_PLAY_PARMS parameter block to begin playback. MMSYSTEM.H defines the MCI_PLAY_PARMS parameter block as follows:
typedef struct {
DWORD dwCallback; /* callback for MCI_NOTIFY flag */
DWORD dwFrom; /* playback begin position */
DWORD dwTo; /* playback end position */
} MCI_PLAY_PARMS;
Playback begins at the current position in the device element. When a device element is opened, the current position is set to the beginning of the media. After a device element is played, the current position is at the end of the media. You can use the MCI_SEEK command to change the current position, as explained in “Changing the Current Position,” later in this chapter.
You can also set beginning and ending positions for playback by specifying the MCI_FROM and MCI_TO flags with the MCI_PLAY command. If you specify one of these flags, you must fill in the corresponding dwFrom or dwTo field in the MCI_PLAY_PARMS structure with the desired beginning or ending time. If you are using a time format other than the default time format (milliseconds), you must set the time format before specifying a beginning or ending time with MCI_PLAY.
The following function opens a waveform device and plays the WAVE file specified by the lpszWAVEFileName parameter:
/* Plays a given WAVE file using MCI_OPEN, MCI_PLAY. Returns when playback
* begins. Returns 0L on success, otherwise returns an MCI error code.
*/
DWORD playWAVEFile(HWND hWndNotify, LPSTR lpszWAVEFileName)
{
UINT wDeviceID;
DWORD dwReturn;
MCI_OPEN_PARMS mciOpenParms;
MCI_PLAY_PARMS mciPlayParms;
/* Open the device by specifying the device name and device element.
* MCI will choose a device capable of playing the given file.
*/
mciOpenParms.lpstrDeviceType = "waveaudio";
mciOpenParms.lpstrElementName = lpszWAVEFileName;
if (dwReturn = mciSendCommand(0, MCI_OPEN,
MCI_OPEN_TYPE | MCI_OPEN_ELEMENT,
(DWORD)(LPVOID) &mciOpenParms))
{
/* Failed to open device; don't close it, just return error
*/
return (dwReturn);
}
/* Device opened successfully, get the device ID
*/
wDeviceID = mciOpenParms.wDeviceID;
/* Begin playback. The window procedure function for the parent window
* will be notified with an MM_MCINOTIFY message when playback is
* complete. At this time, the window procedure closes the device.
*/
mciPlayParms.dwCallback = (DWORD) hWndNotify;
if (dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY,
(DWORD)(LPVOID) &mciPlayParms))
{
mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
return (dwReturn);
}
return (0L);
}
The following function opens a MIDI sequencer device, verifies that the MIDI Mapper was selected as the output port, plays the MIDI file specified by the lpszMIDIFileName parameter, and closes the device after playback is complete:
/* Plays a given MIDI file using MCI_OPEN, MCI_PLAY. Returns as soon as
* playback begins. The window procedure function for the given window
* will be notified when playback is complete. Returns 0L on success;
* otherwise, it returns an MCI error code.
*/
DWORD playMIDIFile(HWND hWndNotify, LPSTR lpszMIDIFileName)
{
UINT wDeviceID;
DWORD dwReturn;
MCI_OPEN_PARMS mciOpenParms;
MCI_PLAY_PARMS mciPlayParms;
MCI_STATUS_PARMS mciStatusParms;
MCI_SEQ_SET_PARMS mciSeqSetParms;
/* Open the device by specifying the device name and device element.
* MCI will attempt to choose the MIDI Mapper as the output port.
*/
mciOpenParms.lpstrDeviceType = "sequencer";
mciOpenParms.lpstrElementName = lpszMIDIFileName;
if (dwReturn = mciSendCommand(NULL, MCI_OPEN,
MCI_OPEN_TYPE | MCI_OPEN_ELEMENT,
(DWORD)(LPVOID) &mciOpenParms))
{
/* Failed to open device; don't close it, just return error.
*/
return (dwReturn);
}
/* Device opened successfully, get the device ID.
*/
wDeviceID = mciOpenParms.wDeviceID;
/* See if the output port is the MIDI Mapper.
*/
mciStatusParms.dwItem = MCI_SEQ_STATUS_PORT;
if (dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM,
(DWORD)(LPVOID) &mciStatusParms))
{
mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
return (dwReturn);
}
/* The output port is not the MIDI Mapper,
* ask if user wants to continue.
*/
if (LOWORD(mciStatusParms.dwReturn) != MIDI_MAPPER)
{
if (MessageBox(hMainWnd,
"The MIDI Mapper is not available. Continue?",
"", MB_YESNO) == IDNO)
{
/* User does not want to continue. Not an error,
* just close the device and return.
*/
mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
return (0L);
}
}
/* Begin playback. The window procedure function for the parent window
* will be notified with an MM_MCINOTIFY message when playback is
* complete. At this time, the window procedure closes the device.
*/
mciPlayParms.dwCallback = (DWORD) hWndNotify;
if (dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY,
(DWORD)(LPVOID) &mciPlayParms))
{
mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
return (dwReturn);
}
return (0L);
}
The following function opens a compact disc device, plays the track specified by the wTrack parameter, and closes the device after playback is complete:
/* Plays a given compact disc track using MCI_OPEN, MCI_PLAY. Returns as
* soon as playback begins. The window procedure function for the given
* window will be notified when playback is complete. Returns 0L on success;
* otherwise, it returns an MCI error code.
*/
DWORD playCDTrack(HWND hWndNotify, BYTE bTrack)
{
UINT wDeviceID;
DWORD dwReturn;
MCI_OPEN_PARMS mciOpenParms;
MCI_SET_PARMS mciSetParms;
MCI_PLAY_PARMS mciPlayParms;
/* Open the compact disc device by specifying the device name.
*/
mciOpenParms.lpstrDeviceType = "cdaudio";
if (dwReturn = mciSendCommand(NULL, MCI_OPEN,
MCI_OPEN_TYPE,
(DWORD)(LPVOID) &mciOpenParms))
{
/* Failed to open device; don't close it, just return error.
*/
return (dwReturn);
}
/* Device opened successfully, get the device ID.
*/
wDeviceID = mciOpenParms.wDeviceID;
/* Set the time format to track/minute/second/frame.
*/
mciSetParms.dwTimeFormat = MCI_FORMAT_TMSF;
if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_TIME_FORMAT,
(DWORD)(LPVOID) &mciSetParms))
{
mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
return (dwReturn);
}
/* Begin playback from the given track and play until the beginning of
* the next track. The window procedure function for the parent window
* will be notified with an MM_MCINOTIFY message when playback is
* complete. Unless the play command fails, the window procedure
* closes the device.
*/
mciPlayParms.dwFrom = 0L;
mciPlayParms.dwTo = 0L;
mciPlayParms.dwFrom = MCI_MAKE_TMSF(bTrack, 0, 0, 0);
mciPlayParms.dwTo = MCI_MAKE_TMSF(bTrack + 1, 0, 0, 0);
mciPlayParms.dwCallback = (DWORD) hWndNotify;
if (dwReturn = mciSendCommand(wDeviceID, MCI_PLAY,
MCI_FROM | MCI_TO | MCI_NOTIFY,
(DWORD)(LPVOID) &mciPlayParms))
{
mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
return (dwReturn);
}
return (0L);
}
To specify a track-relative position with a compact disc device, you must use the track/minute/second/frame time format. See “Setting the Time Format,” later in this chapter, for details on setting time formats.