Playing audio CDs, part 6 – MCI Command playback


Today, we play the actual audio track on the CD using the MCI commands.

HRESULT CMCICommandCDPlayer::PlayTrack(int TrackNumber)
{
    MCIERROR mciError;
    MCI_SET_PARMS setParms = {0};
    MCI_PLAY_PARMS playParms = {0};
    //
    // The track number from the host app is )ORIGIN 0, MCI is )ORIGIN 1, so adjust it.
    //
    TrackNumber += 1;
    if (TrackNumber > (int)_TrackCount)
    {
        printf("Track out of range\n");
        return E_FAIL;
    }

    // Set the MCI time format to track/minute/second/frame.
    setParms.dwTimeFormat = MCI_FORMAT_TMSF;
    mciError = mciSendCommand(_MciHandle, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD_PTR)&setParms);
    if (mciError != 0)
    {
        printf("MCI Error %x determining CD media status\n",mciError);
        return HRESULT_FROM_WIN32(mciError);
    }

    playParms.dwFrom = MCI_MAKE_TMSF(TrackNumber, 0, 0, 0);
    if (TrackNumber < _TrackCount)
    {
        playParms.dwTo = MCI_MAKE_TMSF(TrackNumber+1, 0, 0, 0);
    }
    mciError = mciSendCommand(_MciHandle, MCI_PLAY, MCI_FROM | (TrackNumber <_TrackCount ? MCI_TO : 0) | MCI_WAIT, (DWORD_PTR)&playParms);
    if (mciError != 0)
    {
        printf("MCI Error %x playing media\n",mciError);
        return HRESULT_FROM_WIN32(mciError);
    }

    return S_OK;
}

Not much different from the previous versions, in fact it’s a pretty straightforward transcription of the previous programs.  One minor change is that I’m using the MCI_WAIT flag to ask the MCI commands

That allows me to avoid the Sleep() at the end.  I could have done the same thing in the string based version by appending the ” wait” command to the play command string.

I’m going to skip a couple of days on this series, it’ll take a while to get the Digital Audio Extraction version of this problem ready for publication, DAE’s sufficiently compilicated that it’ll take several articles to fully describe what I’m doing.

Comments (2)

  1. Todd Spatafore says:

    Out of curiosity, why didn’t you use the " wait" command in the string based version? Is there a performance and/or security advantage to using a Sleep()?

  2. Todd,

    Official answer? I did it to show the sync/async versions. There’s no real difference between the two (but you really don’t want to use the sync version in a Windows app).

    Honest answer? I didn’t think of it – the WMP version needed a sleep, so I put a sleep into the MCI version 🙂