Getting Information About Devices and Media

Use the MCI_STATUS command along with the MCI_STATUS_PARMS parameter block to get information about the status of an open device and its associated device element. MMSYSTEM.H defines the MCI_STATUS_PARMS parameter block as:

typedef struct {
    DWORD   dwCallback;                /* callback for MCI_NOTIFY flag */
    DWORD   dwReturn;                /* status information is returned here */
    DWORD   dwItem;                        /* identifies status item */
    DWORD   dwTrack;                /* track number */
} MCI_STATUS_PARMS;

Before using the MCI_STATUS command, you must identify the status item
to query for by putting a constant in the dwItem field of the parameter block.
The following list shows different status items you can query for and the corresponding constant for each item for different types of audio devices:

Status Item   Constant  

All Audio Devices   ^  
  Length of the media   MCI_STATUS_LENGTH
  Current position   MCI_STATUS_POSITION
  Current mode   MCI_STATUS_MODE
  Time format   MCI_STATUS_TIME_FORMAT
  Ready state   MCI_STATUS_READY
Waveform Devices   ^  
  Block alignment   MCI_WAVE_STATUS_BLOCKALIGN
  Format tag   MCI_WAVE_STATUS_FORMATTAG
  Number of channels   MCI_WAVE_STATUS_CHANNELS
  Sample rate   MCI_WAVE_STATUS_SAMPLESPERSEC
  Average bytes per second   MCI_WAVE_STATUS_AVGBYTESPERSEC
  Bits per sample   MCI_WAVE_STATUS_BITSPERSAMPLE
  Record level   MCI_WAVE_STATUS_LEVEL
  ,    
  ,    
Compact Disc Devices ,    
  Number of tracks   MCI_STATUS_NUMBER_OF_TRACKS
  Media present   MCI_STATUS_MEDIA_PRESENT
  Current track   MCI_STATUS_CURRENT_TRACK
MIDI Sequencer Devices   ^  
  Tempo   MCI_SEQ_STATUS_TEMPO
  Port   MCI_SEQ_STATUS_PORT
  SMPTE offset   MCI_SEQ_STATUS_OFFSET
  division type of file   MCI_SEQ_STATUS_DIVTYPE

Getting Track-Relative Information for Compact Disc Devices

For compact disc devices, you can get the starting position and length of a track by specifying the MCI_TRACK flag and setting the dwTrack field of MCI_STATUS_PARMS to the desired track number. To get the starting position of a track, set the dwItem field to MCI_STATUS_POSITION. To get the length of a track, set dwItem to MCI_STATUS_LENGTH. For example, the following function gets the total number of tracks on the disc and the starting position of each track. It then uses the MessageBox function to report the starting positions of the tracks.

/* Uses the MCI_STATUS command to get and display the starting times
 * for the tracks on a compact disc. Returns 0L on success; otherwise,
 * it returns an MCI error code.
 */
DWORD getCDTrackStartTimes(void)
{
    WORD wDeviceID;
    int i, iNumTracks;
    DWORD dwReturn;
    DWORD dwPosition;
    DWORD *pMem;
    char szTempString[64];
    char szTimeString[512] = "\0";      // big enough for 20 tracks
    MCI_OPEN_PARMS mciOpenParms;
    MCI_SET_PARMS mciSetParms;
    MCI_STATUS_PARMS mciStatusParms;

    /* Open the compact disc device by specifying the device type.
     */
    mciOpenParms.lpstrDeviceType = "cdaudio";
    if (dwReturn = mciSendCommand(NULL, MCI_OPEN,
                                  MCI_OPEN_TYPE,
                                  (DWORD)(LPVOID) &mciOpenParms))
    {
        /* Failed to open device; don't have to close it, just return error.
         */
        return (dwReturn);
    }

    /* Device opened successfully, get the device ID.
     */
    wDeviceID = mciOpenParms.wDeviceID;

    /* Set the time format to minute/second/frame format.
     */
    mciSetParms.dwTimeFormat = MCI_FORMAT_MSF;
    if (dwReturn = mciSendCommand(wDeviceID, MCI_SET, MCI_SET_TIME_FORMAT, 
                                  (DWORD)(LPVOID) &mciSetParms))
    {
        mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
        return (dwReturn);
    }

    /* Get the number of tracks; limit to number we can display (20).
     */
    mciStatusParms.dwItem = MCI_STATUS_NUMBER_OF_TRACKS;
    if (dwReturn = mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM, 
                                  (DWORD)(LPVOID) &mciStatusParms))
    {
        mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
        return (dwReturn);
    }
    iNumTracks = mciStatusParms.dwReturn;
    iNumTracks = min(iNumTracks, 20);

    /* Allocate memory to hold starting positions.
     */
    pMem = (DWORD *)LocalAlloc(LPTR, iNumTracks * sizeof(DWORD));
    if (pMem == NULL)
    {
        mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
        return (-1);
    }


    /* For each track, get and save the starting position and
     * build a string containing starting positions.
     */
    for(i=1; i<=iNumTracks; i++)
    {
        mciStatusParms.dwItem = MCI_STATUS_POSITION;
        mciStatusParms.dwTrack = i;
        if (dwReturn = mciSendCommand(wDeviceID, MCI_STATUS,
                                      MCI_STATUS_ITEM | MCI_TRACK, 
                                      (DWORD)(LPVOID) &mciStatusParms))
        {
            mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL);
            return (dwReturn);
        }

        pMem[i-1] = mciStatusParms.dwReturn;

        wsprintf(szTempString, "Track %2d - %02d:%02d:%02d\n",
                 i,
                 MCI_MSF_MINUTE(pMem[i-1]),
                 MCI_MSF_SECOND(pMem[i-1]),
                 MCI_MSF_FRAME(pMem[i-1]));

        lstrcat(szTimeString, szTempString);
    }

    /* Use MessageBox to display starting times.
     */
    MessageBox(hMainWnd, szTimeString, "Track Starting Position",
               MB_ICONINFORMATION);

    /* Free memory and close the device.
     */
    LocalFree((HANDLE) pMem);
    if (dwReturn = mciSendCommand(wDeviceID, MCI_CLOSE, 0, NULL))
    {
        return (dwReturn);
    }

    return (0L);
}