Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1326 lines
31 KiB

/******************************Module*Header*******************************\
* Module Name: cdapimci.c
*
* This module encapsulates the CD-ROM device into a set of callable apis.
* The api's are implemented using the cdaudio mci interface.
*
* Created: 26-04-93
* Author: Stephen Estrop [StephenE]
*
* Copyright (c) 1993 - 1995 Microsoft Corporation. All rights reserved.
\**************************************************************************/
#pragma warning( once : 4201 4214 )
#define NOOLE
#include <windows.h> /* required for all Windows applications */
#include <windowsx.h>
#include <string.h>
#include "playres.h"
#include "cdplayer.h"
#include "cdapi.h"
#include "scan.h"
#include "trklst.h"
#include "..\cdopt\cdopt.h"
#ifdef __cplusplus
extern "C" {
#endif
/* -------------------------------------------------------------------------
**
** High level routines
**
** -------------------------------------------------------------------------
*/
BOOL g_fCDOpen = TRUE;
/******************************Public*Routine******************************\
* OpenCdRom
*
*
*
* History:
* dd-mm-94 - StephenE - Created
*
\**************************************************************************/
MCIDEVICEID
OpenCdRom(
TCHAR chDrive,
LPDWORD lpdwErrCode
)
{
MCI_OPEN_PARMS mciOpen;
TCHAR szElementName[4];
TCHAR szAliasName[32];
DWORD dwFlags;
DWORD dwAliasCount = GetCurrentTime();
DWORD dwRet;
ZeroMemory( &mciOpen, sizeof(mciOpen) );
mciOpen.lpstrDeviceType = (LPTSTR)MCI_DEVTYPE_CD_AUDIO;
wsprintf( szElementName, TEXT("%c:"), chDrive );
wsprintf( szAliasName, TEXT("SJE%lu:"), dwAliasCount );
mciOpen.lpstrElementName = szElementName;
mciOpen.lpstrAlias = szAliasName;
OSVERSIONINFO os;
os.dwOSVersionInfoSize = sizeof(os);
GetVersionEx(&os);
if (os.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
dwFlags = MCI_OPEN_ELEMENT | MCI_OPEN_SHAREABLE | MCI_OPEN_ALIAS |
MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID | MCI_WAIT;
}
else
{
dwFlags = MCI_OPEN_ELEMENT | MCI_OPEN_ALIAS |
MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID | MCI_WAIT;
}
dwRet = mciSendCommand(0, MCI_OPEN, dwFlags, (DWORD_PTR)(LPVOID)&mciOpen);
if ( dwRet == MMSYSERR_NOERROR ) {
MCI_SET_PARMS mciSet;
ZeroMemory( &mciSet, sizeof(mciSet) );
mciSet.dwTimeFormat = MCI_FORMAT_MSF;
mciSendCommand( mciOpen.wDeviceID, MCI_SET,
MCI_SET_TIME_FORMAT, (DWORD_PTR)(LPVOID)&mciSet );
}
else {
/*
** Only return the error code if we have been given a valid pointer
*/
if (lpdwErrCode != NULL) {
*lpdwErrCode = dwRet;
}
mciOpen.wDeviceID = 0;
}
return mciOpen.wDeviceID;
}
/******************************Public*Routine******************************\
* CloseCdRom
*
*
*
* History:
* dd-mm-94 - StephenE - Created
*
\**************************************************************************/
void
CloseCdRom(
MCIDEVICEID DevHandle
)
{
mciSendCommand( DevHandle, MCI_CLOSE, 0L, 0L );
}
/******************************Public*Routine******************************\
* CheckStatus
*
* Check return code for known bad codes and inform
* user how to correct (if possible) the problem.
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
void
CheckStatus(
LPSTR szCaller,
DWORD status,
int cdrom
)
{
#if DBG
TCHAR s[200];
TCHAR err[100];
#endif
if (status==ERROR_SUCCESS)
return;
/*
switch (status)
{
case MCIERR_HARDWARE:
NoMediaUpdate( cdrom );
break;
}
*/
#if DBG
mciGetErrorString( status, err, sizeof(err) / sizeof(TCHAR) );
wsprintf( s, IdStr( STR_ERR_GEN ), g_Devices[cdrom]->drive, err );
OutputDebugString (s);
OutputDebugString (TEXT("\r\n"));
#endif
}
/******************************Public*Routine******************************\
* CheckUnitCdrom
*
* Queries the device state, checking to see if a disc has been ejected or
* inserted.
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
void
CheckUnitCdrom(
int cdrom,
BOOL fForceRescan
)
{
DWORD status;
if ((cdrom < 0) || (cdrom >= MAX_CD_DEVICES))
{
return;
}
if (fForceRescan)
{
// Close Device to force read of correct TOC
if (g_Devices[cdrom]->hCd != 0L)
{
CloseCdRom (g_Devices[cdrom]->hCd);
g_Devices[cdrom]->hCd = 0L;
}
}
if ( g_Devices[cdrom]->hCd == 0L ) {
g_Devices[cdrom]->hCd = OpenCdRom( g_Devices[cdrom]->drive, NULL );
if ( g_Devices[cdrom]->hCd == 0 ) {
return;
}
else {
/*
** Force a rescan of this disc.
*/
g_Devices[cdrom]->State = CD_NO_CD;
}
}
status = TestUnitReadyCdrom( g_Devices[cdrom]->hCd );
if (g_Devices[cdrom]->State & CD_NO_CD)
{
if (status == ERROR_SUCCESS) {
/*
** A new disc has been inserted, scan it now.
*/
RescanDevice( g_hwndApp, cdrom );
}
}
else {
if (status != ERROR_SUCCESS) {
/*
** Disc has been ejected.
*/
NoMediaUpdate( cdrom );
}
}
}
/******************************Public*Routine******************************\
* NoMediaUpdate
*
* Update the user display when it is found that no media is in the device.
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
void
NoMediaUpdate(
int cdrom
)
{
BOOL fChangePlayButtons;
if ( cdrom == g_CurrCdrom )
{
fChangePlayButtons = TRUE;
}
else {
fChangePlayButtons = FALSE;
}
g_Devices[cdrom]->State = (CD_NO_CD | CD_STOPPED);
if (fChangePlayButtons)
{
g_pSink->OnEvent(MMEVENT_ONMEDIAUNLOADED,NULL);
//tell the UI to gray out the button
HWND hwndTrackButton = GetDlgItem(GetParent(g_hwndApp),IDB_TRACK);
if (hwndTrackButton)
{
EnableWindow(hwndTrackButton,FALSE);
}
SetPlayButtonsEnableState();
}
//tell the playlist
// Drive has been ejected
if (g_pSink)
{
LPCDOPT pOpt = (LPCDOPT)g_pSink->GetOptions();
LPCDOPTIONS pCDOpts = NULL;
LPCDUNIT pUnit = NULL;
if (pOpt)
{
pCDOpts = pOpt->GetCDOpts();
}
if (pCDOpts)
{
pUnit = pCDOpts->pCDUnitList;
}
//scan the list to find the one we want
for (int index = 0; index < cdrom; index++)
{
if (pUnit)
{
pUnit = pUnit->pNext;
}
}
if (pUnit)
{
pUnit->dwTitleID = CDTITLE_NODISC;
pUnit->dwNumTracks = 0;
pUnit->szNetQuery[0] = '\0';
pOpt->DiscChanged(pUnit);
}
} //end if sink
TimeAdjustInitialize( cdrom );
}
/******************************Public*Routine******************************\
* EjectTheCdromDisc
*
* Eject the disc from the specified cdrom device.
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
BOOL
EjectTheCdromDisc(
int cdrom
)
{
DWORD status;
/*
** Stop the drive first
*/
status = StopCdrom( g_Devices[cdrom]->hCd );
/*
** Eject the disc
*/
status = EjectCdrom( g_Devices[cdrom]->hCd );
CheckStatus( "EjectCdrom", status, cdrom );
return status == ERROR_SUCCESS;
}
/******************************Public*Routine******************************\
* PlayCurrTrack
*
* Set cdrom device playing from start MSF to end MSF of current
* track.
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
BOOL
PlayCurrTrack(
int cdrom
)
{
DWORD status;
MCI_PLAY_PARMS pam;
int min,sec,endindex;
PTRACK_PLAY tr;
tr = CURRTRACK( cdrom );
if (tr==NULL) {
return( FALSE );
}
sec = TRACK_S(cdrom,tr->TocIndex) + CDTIME(cdrom).TrackCurSec;
min = TRACK_M(cdrom,tr->TocIndex) + CDTIME(cdrom).TrackCurMin;
min+= (sec / 60);
sec = (sec % 60);
pam.dwFrom = MCI_MAKE_MSF( min, sec, TRACK_F(cdrom,tr->TocIndex) );
endindex = FindContiguousEnd( cdrom, tr );
pam.dwTo = MCI_MAKE_MSF( TRACK_M(cdrom,endindex),
TRACK_S(cdrom,endindex),
TRACK_F(cdrom,endindex) );
#if DBG
{
long lAddress, lEndPos, lStartPos;
dprintf( TEXT("Playing from : %2.2d:%2.2d:%2.2d"),
MCI_MSF_MINUTE(pam.dwFrom),
MCI_MSF_SECOND(pam.dwFrom),
MCI_MSF_FRAME( pam.dwFrom) );
dprintf( TEXT("Playing to : %2.2d:%2.2d:%2.2d"),
MCI_MSF_MINUTE(pam.dwTo),
MCI_MSF_SECOND(pam.dwTo),
MCI_MSF_FRAME( pam.dwTo) );
lAddress = pam.dwFrom;
lStartPos = (MCI_MSF_MINUTE(lAddress) * FRAMES_PER_MINUTE) +
(MCI_MSF_SECOND(lAddress) * FRAMES_PER_SECOND) +
(MCI_MSF_FRAME(lAddress));
lAddress = pam.dwTo;
lEndPos = (MCI_MSF_MINUTE(lAddress) * FRAMES_PER_MINUTE) +
(MCI_MSF_SECOND(lAddress) * FRAMES_PER_SECOND) +
(MCI_MSF_FRAME(lAddress));
lAddress = lEndPos - lStartPos;
lStartPos =
MCI_MAKE_MSF((lAddress / FRAMES_PER_MINUTE),
(lAddress % FRAMES_PER_MINUTE) / FRAMES_PER_SECOND,
(lAddress % FRAMES_PER_MINUTE) % FRAMES_PER_SECOND);
lAddress = lStartPos;
dprintf( TEXT("Play length : %2.2d:%2.2d:%2.2d"),
MCI_MSF_MINUTE(lAddress),
MCI_MSF_SECOND(lAddress),
MCI_MSF_FRAME( lAddress) );
}
#endif
status = PlayCdrom( g_Devices[cdrom]->hCd, &pam );
CheckStatus( "PlayCurrTrack", status, cdrom );
return status == ERROR_SUCCESS;
}
/******************************Public*Routine******************************\
* StopTheCdromDrive
*
* Tell the cdrom device to stop playing
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
BOOL
StopTheCdromDrive(
int cdrom
)
{
DWORD status;
status = StopCdrom( g_Devices[cdrom]->hCd );
CheckStatus( "StopCdrom", status, cdrom );
return status == ERROR_SUCCESS;
}
/******************************Public*Routine******************************\
* PauseTheCdromDrive
*
* Tell the cdrom device to pause playing
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
BOOL
PauseTheCdromDrive(
int cdrom
)
{
DWORD status;
status = PauseCdrom( g_Devices[cdrom]->hCd );
CheckStatus( "PauseCdrom", status, cdrom );
return status == ERROR_SUCCESS;
}
/******************************Public*Routine******************************\
* ResumeTheCdromDrive
*
* Tell the cdrom device to resume playing
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
BOOL
ResumeTheCdromDrive(
int cdrom
)
{
DWORD status;
status = ResumeCdrom( g_Devices[cdrom]->hCd, cdrom );
CheckStatus( "ResumeCdrom", status, cdrom );
if ( status == ERROR_NOT_READY ) {
NoMediaUpdate( cdrom );
}
return status == ERROR_SUCCESS;
}
/******************************Public*Routine******************************\
* SeekToCurrSecond
*
* Seek to the position on the disc represented by the
* current time (position) information in gDevices, and
* continue playing to the end of the current track.
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
BOOL
SeekToCurrSecond(
int cdrom
)
{
DWORD status;
int endindex;
PTRACK_PLAY tr;
UCHAR StartingF, StartingS, StartingM;
/*
** Build starting and ending positions for play
*/
tr = CDTIME(cdrom).CurrTrack;
if (tr == NULL) {
return FALSE;
}
StartingM = (TRACK_M(cdrom,tr->TocIndex) + CDTIME(cdrom).TrackCurMin);
StartingS = (TRACK_S(cdrom,tr->TocIndex) + CDTIME(cdrom).TrackCurSec);
StartingF = (TRACK_F(cdrom,tr->TocIndex));
if (StartingS > 59) {
StartingM++;
StartingS -= (UCHAR)60;
}
if (g_Devices[ cdrom ]->State & CD_PLAYING) {
MCI_PLAY_PARMS mciPlay;
endindex = FindContiguousEnd( cdrom, tr );
mciPlay.dwFrom = MCI_MAKE_MSF( StartingM, StartingS, StartingF );
mciPlay.dwTo = MCI_MAKE_MSF( TRACK_M(cdrom,endindex),
TRACK_S(cdrom,endindex),
TRACK_F(cdrom,endindex) );
status = PlayCdrom( g_Devices[ cdrom ]->hCd, &mciPlay );
}
else {
MCI_SEEK_PARMS mciSeek;
mciSeek.dwTo = MCI_MAKE_MSF( StartingM, StartingS, StartingF );
status = SeekCdrom( g_Devices[ cdrom ]->hCd, &mciSeek );
}
CheckStatus( "SeekToCurrSec", status, cdrom );
return status == ERROR_SUCCESS;
}
/******************************Public*Routine******************************\
* GetCurrPos
*
* Query cdrom device for its current position and status
* and return information in callers buffer.
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
BOOL
GetCurrPos(
int cdrom,
PCURRPOS CpPtr
)
{
DWORD status;
DWORD dwStatus;
DWORD dwTrack;
DWORD dwAbsPos;
BOOL fNT;
OSVERSIONINFO os;
os.dwOSVersionInfoSize = sizeof(os);
GetVersionEx(&os);
if (os.dwPlatformId == VER_PLATFORM_WIN32_NT)
{
fNT = TRUE;
}
else
{
fNT = FALSE;
}
/*
** Tell lower layer what we want it to do...in this case,
** we need to specify which SubQData format we want returned.
** This is exported from scsicdrom.sys to the user layer
** so that it could be implemented in one call, instead of
** four separate calls (there are four SubQData formats)
*/
/*
** Set up for current position SubQData format.
*/
if (CDTIME(cdrom).CurrTrack != NULL) {
if (fNT)
{
status = StatusTrackPosCdrom ( g_Devices[ cdrom ]->hCd, &dwStatus, &dwTrack, &dwAbsPos);
}
else
{
status = GetCdromCurrentPosition( g_Devices[ cdrom ]->hCd, &dwAbsPos );
}
}
else {
status = MCIERR_INTERNAL;
}
if (status == ERROR_SUCCESS) {
int iTrack;
LONG lAbsPosF;
LONG lStartPos;
LONG lTrackPos;
if (!fNT)
{
iTrack = (int)GetCdromCurrentTrack( g_Devices[ cdrom ]->hCd );
}
else
{
iTrack = (int)dwTrack;
}
if (!fNT)
{
CpPtr->AudioStatus = GetCdromMode( g_Devices[ cdrom ]->hCd );
}
else
{
CpPtr->AudioStatus = dwStatus;
}
CpPtr->Track = iTrack;
CpPtr->Index = 1;
iTrack--;
lStartPos = (TRACK_M(cdrom, iTrack ) * FRAMES_PER_MINUTE) +
(TRACK_S(cdrom, iTrack ) * FRAMES_PER_SECOND) +
(TRACK_F(cdrom, iTrack ));
lAbsPosF = (MCI_MSF_MINUTE(dwAbsPos) * FRAMES_PER_MINUTE) +
(MCI_MSF_SECOND(dwAbsPos) * FRAMES_PER_SECOND) +
(MCI_MSF_FRAME(dwAbsPos));
lTrackPos = lAbsPosF - lStartPos;
/*
** Are we in the track lead in zone ?
*/
if ( lTrackPos < 0 ) {
/*
** Have we just entered the lead in zone
*/
if (!g_Devices[cdrom]->fProcessingLeadIn) {
g_Devices[cdrom]->fProcessingLeadIn = TRUE;
/*
** Is the track that we are currently in the next track
** that we actually want to play. If it is then everything is
** OK. If it isn't then we need to hack the current position
** information so that it looks like we sre still playing the
** previous track.
*/
if ( CURRTRACK(cdrom)->nextplay
&& CURRTRACK(cdrom)->nextplay->TocIndex == iTrack) {
g_Devices[cdrom]->fShowLeadIn = TRUE;
}
else {
g_Devices[cdrom]->fShowLeadIn = FALSE;
}
}
g_Devices[cdrom]->fShowLeadIn = FALSE;
if (g_Devices[cdrom]->fShowLeadIn) {
CpPtr->Index = 0;
lTrackPos = -lTrackPos;
}
else {
CpPtr->Track = iTrack;
iTrack--;
lTrackPos = lAbsPosF
- g_Devices[cdrom]->toc.TrackData[iTrack].AddressF;
}
}
else {
g_Devices[cdrom]->fShowLeadIn = FALSE;
g_Devices[cdrom]->fProcessingLeadIn = FALSE;
}
CpPtr->m = (int)(lTrackPos / FRAMES_PER_MINUTE);
CpPtr->s = (int)(lTrackPos % FRAMES_PER_MINUTE) / FRAMES_PER_SECOND;
CpPtr->f = (int)(lTrackPos % FRAMES_PER_MINUTE) % FRAMES_PER_SECOND;
CpPtr->ab_m = (int)MCI_MSF_MINUTE(dwAbsPos);
CpPtr->ab_s = (int)MCI_MSF_SECOND(dwAbsPos);
CpPtr->ab_f = (int)MCI_MSF_FRAME(dwAbsPos);
/*
** Round up to the nearest second.
*/
if (CpPtr->f > (FRAMES_PER_SECOND / 2) ) {
if ( ++CpPtr->s > 59 ) {
CpPtr->s = 0;
CpPtr->m++;
}
}
else {
CpPtr->f = 0;
}
if (CpPtr->ab_f > (FRAMES_PER_SECOND / 2) ) {
if ( ++CpPtr->ab_s > 59 ) {
CpPtr->ab_s = 0;
CpPtr->ab_m++;
}
}
else {
CpPtr->ab_f = 0;
}
}
else {
ZeroMemory( CpPtr, sizeof(*CpPtr) );
}
CheckStatus( "GetCurrPos", status, cdrom );
return status==ERROR_SUCCESS;
}
/******************************Public*Routine******************************\
* SeekToTrackAndHold
*
* Seek to specified track and enter hold state.
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
BOOL
SeekToTrackAndHold(
int cdrom,
int tindex
)
{
DWORD status;
MCI_SEEK_PARMS sam;
sam.dwTo = MCI_MAKE_MSF( TRACK_M(cdrom,tindex),
TRACK_S(cdrom,tindex),
TRACK_F(cdrom,tindex) );
status = SeekCdrom( g_Devices[ cdrom ]->hCd, &sam );
CheckStatus( "SeekToTrackAndHold", status, cdrom );
return status == ERROR_SUCCESS;
}
/* -------------------------------------------------------------------------
**
** Low level routines
**
** -------------------------------------------------------------------------
*/
/******************************Public*Routine******************************\
* GetCdromTOC
*
* This routine will get the table of contents from
* a CDRom device.
*
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
DWORD
GetCdromTOC(
MCIDEVICEID DevHandle,
PCDROM_TOC TocPtr
)
{
MCI_STATUS_PARMS mciStatus;
long lAddress, lStartPos, lDiskLen;
int i;
DWORD dwRet;
#if DBG
dprintf( TEXT("Reading TOC for drive %d"), DevHandle );
#endif
ZeroMemory( &mciStatus, sizeof(mciStatus) );
mciStatus.dwItem = MCI_STATUS_NUMBER_OF_TRACKS;
//
// NOTE: none of the mciSendCommand calls below bother to check the
// return code. This is asking for trouble... but if the
// commands fail we cannot do much about it.
//
dwRet = mciSendCommand( DevHandle, MCI_STATUS,
MCI_STATUS_ITEM, (DWORD_PTR)(LPVOID)&mciStatus);
TocPtr->FirstTrack = 1;
TocPtr->LastTrack = (UCHAR)mciStatus.dwReturn;
mciStatus.dwItem = MCI_STATUS_POSITION;
for ( i = 0; i < TocPtr->LastTrack; i++ ) {
mciStatus.dwTrack = i + 1;
dwRet = mciSendCommand( DevHandle, MCI_STATUS,
MCI_STATUS_ITEM | MCI_TRACK,
(DWORD_PTR)(LPVOID)&mciStatus);
TocPtr->TrackData[i].TrackNumber = (UCHAR)(i + 1);
lAddress = TocPtr->TrackData[i].Address = (long)mciStatus.dwReturn;
lStartPos = (MCI_MSF_MINUTE(lAddress) * FRAMES_PER_MINUTE) +
(MCI_MSF_SECOND(lAddress) * FRAMES_PER_SECOND) +
(MCI_MSF_FRAME( lAddress));
TocPtr->TrackData[i].AddressF = lStartPos;
}
mciStatus.dwItem = MCI_STATUS_LENGTH;
dwRet = mciSendCommand( DevHandle, MCI_STATUS,
MCI_STATUS_ITEM, (DWORD_PTR)(LPVOID)&mciStatus);
/*
** Convert the absolute start address of the first track
** into Frames
*/
lAddress = TocPtr->TrackData[0].Address;
lStartPos = TocPtr->TrackData[0].AddressF;
/*
** Convert the total disk length into Frames
*/
lAddress = (long)mciStatus.dwReturn;
lDiskLen = (MCI_MSF_MINUTE(lAddress) * FRAMES_PER_MINUTE) +
(MCI_MSF_SECOND(lAddress) * FRAMES_PER_SECOND) +
(MCI_MSF_FRAME(lAddress));
/*
** Now, determine the absolute start position of the sentinel
** track. That is, the special track that marks the end of the
** disk.
*/
lAddress = lStartPos + lDiskLen;
TocPtr->TrackData[i].TrackNumber = 0;
TocPtr->TrackData[i].Address =
MCI_MAKE_MSF((lAddress / FRAMES_PER_MINUTE),
(lAddress % FRAMES_PER_MINUTE) / FRAMES_PER_SECOND,
(lAddress % FRAMES_PER_MINUTE) % FRAMES_PER_SECOND);
return (TocPtr->LastTrack != 0) ? ERROR_SUCCESS : MCIERR_INTERNAL;
}
/******************************Public*Routine******************************\
* StopCdrom
*
* This routine will stop a CDRom device that is playing.
*
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
DWORD
StopCdrom(
MCIDEVICEID DevHandle
)
{
MCI_GENERIC_PARMS mciGen;
ZeroMemory( &mciGen, sizeof(mciGen) );
return mciSendCommand( DevHandle, MCI_STOP, 0L, (DWORD_PTR)(LPVOID)&mciGen );
}
/******************************Public*Routine******************************\
* PauseCdrom
*
* This routine will pause a CDRom device.
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
DWORD
PauseCdrom(
MCIDEVICEID DevHandle
)
{
MCI_GENERIC_PARMS mciGen;
ZeroMemory( &mciGen, sizeof(mciGen) );
return mciSendCommand( DevHandle, MCI_PAUSE, 0L, (DWORD_PTR)(LPVOID)&mciGen );
}
/******************************Public*Routine******************************\
* ResumeCdrom
*
* This routine will resume a paused CDRom device.
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
DWORD
ResumeCdrom(
MCIDEVICEID DevHandle,
int cdrom
)
{
MCI_GENERIC_PARMS mciGen;
DWORD dwRet;
static int fCanResume = -1;
ZeroMemory( &mciGen, sizeof(mciGen) );
switch (fCanResume) {
case -1:
dwRet = mciSendCommand( DevHandle, MCI_RESUME, MCI_TO, (DWORD_PTR)(LPVOID)&mciGen );
fCanResume = (dwRet == MMSYSERR_NOERROR ? 1 : 0);
if (0 == fCanResume) {
dwRet = (PlayCurrTrack( cdrom ) ? MMSYSERR_NOERROR : MCIERR_HARDWARE);
}
break;
case 0:
dwRet = (PlayCurrTrack( cdrom ) ? MMSYSERR_NOERROR : MCIERR_HARDWARE);
break;
case 1:
dwRet = mciSendCommand( DevHandle, MCI_RESUME, MCI_TO, (DWORD_PTR)(LPVOID)&mciGen );
break;
}
return dwRet;
}
/******************************Public*Routine******************************\
* PlayCdrom
*
* This routine plays a CDRom device starting and ending at the MSF
* positions specified in the structure passed in.
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
DWORD
PlayCdrom(
MCIDEVICEID DevHandle,
MCI_PLAY_PARMS *mciPlay
)
{
return mciSendCommand( DevHandle, MCI_PLAY,
MCI_FROM | MCI_TO, (DWORD_PTR)(LPVOID)mciPlay );
}
/******************************Public*Routine******************************\
* IsCdromTrackAudio
*
*
*
* History:
* dd-mm-94 - StephenE - Created
*
\**************************************************************************/
BOOL
IsCdromTrackAudio(
CDHANDLE DevHandle,
int iTrackNumber
)
{
MCI_STATUS_PARMS mciStatus;
ZeroMemory( &mciStatus, sizeof(mciStatus) );
mciStatus.dwItem = MCI_CDA_STATUS_TYPE_TRACK;
mciStatus.dwTrack = iTrackNumber + 1;
mciSendCommand( DevHandle, MCI_STATUS, MCI_STATUS_ITEM | MCI_TRACK,
(DWORD_PTR)(LPVOID)&mciStatus);
return mciStatus.dwReturn == (DWORD)MCI_CDA_TRACK_AUDIO;
}
/******************************Public*Routine******************************\
* GetCdromCurrentPosition
*
* Gets the current ABSOLUTE position of the specified cdrom device.
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
DWORD
GetCdromCurrentPosition(
CDHANDLE DevHandle,
DWORD *lpdwPosition
)
{
MCI_STATUS_PARMS mciStatus;
DWORD dwErr;
ZeroMemory( &mciStatus, sizeof(mciStatus) );
mciStatus.dwItem = MCI_STATUS_POSITION;
dwErr = mciSendCommand( DevHandle, MCI_STATUS,
MCI_STATUS_ITEM, (DWORD_PTR)(LPVOID)&mciStatus );
*lpdwPosition = (long)mciStatus.dwReturn;
return dwErr;
}
/******************************Public*Routine******************************\
* GetCdromMode
*
* Gets the current mode of the cdrom.
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
DWORD
GetCdromMode(
MCIDEVICEID DevHandle
)
{
MCI_STATUS_PARMS mciStatus;
ZeroMemory( &mciStatus, sizeof(mciStatus) );
mciStatus.dwItem = MCI_STATUS_MODE;
mciSendCommand( DevHandle, MCI_STATUS,
MCI_STATUS_ITEM, (DWORD_PTR)(LPVOID)&mciStatus );
return (DWORD)mciStatus.dwReturn;
}
/******************************Public*Routine******************************\
* GetCdromCurrentTrack
*
* Gets the current track of the cdrom.
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
DWORD
GetCdromCurrentTrack(
MCIDEVICEID DevHandle
)
{
MCI_STATUS_PARMS mciStatus;
ZeroMemory( &mciStatus, sizeof(mciStatus) );
mciStatus.dwItem = MCI_STATUS_CURRENT_TRACK;
mciSendCommand( DevHandle, MCI_STATUS,
MCI_STATUS_ITEM, (DWORD_PTR)(LPVOID)&mciStatus );
return (DWORD)mciStatus.dwReturn;
}
/******************************Public*Routine******************************\
* SeekCdrom
*
* This routine seek to an MSF address on the audio CD and enters
* a hold (paused) state.
*
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
DWORD
SeekCdrom(
MCIDEVICEID DevHandle,
MCI_SEEK_PARMS *mciSeek
)
{
return mciSendCommand( DevHandle, MCI_SEEK,
MCI_TO, (DWORD_PTR)(LPVOID)mciSeek );
}
/******************************Public*Routine******************************\
* EjectCdrom
*
* This routine will eject a disc from a CDRom device or close the tray if
* it is open.
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
DWORD
EjectCdrom(
MCIDEVICEID DevHandle
)
{
MCI_SET_PARMS mciSet;
DWORD mmr = ERROR_SUCCESS;
ZeroMemory( &mciSet, sizeof(mciSet) );
if ((GetCdromMode(DevHandle) == (DWORD)MCI_MODE_OPEN) && g_fCDOpen)
{
mmr = mciSendCommand( DevHandle, MCI_SET,
MCI_SET_DOOR_CLOSED, (DWORD_PTR)(LPVOID)&mciSet );
if (mmr == ERROR_SUCCESS)
{
g_fCDOpen = FALSE;
}
}
else
{
mmr = mciSendCommand( DevHandle, MCI_SET,
MCI_SET_DOOR_OPEN, (DWORD_PTR)(LPVOID)&mciSet );
if (mmr == ERROR_SUCCESS)
{
g_fCDOpen = TRUE;
}
}
return (mmr);
}
/******************************Public*Routine******************************\
* TestUnitReadyCdrom
*
* This routine will retrieve the status of the CDRom device.
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
DWORD
TestUnitReadyCdrom(
MCIDEVICEID DevHandle
)
{
MCI_STATUS_PARMS mciStatus;
ZeroMemory( &mciStatus, sizeof(mciStatus) );
mciStatus.dwItem = MCI_STATUS_MEDIA_PRESENT;
if ( mciSendCommand( DevHandle, MCI_STATUS, MCI_STATUS_ITEM,
(DWORD_PTR)(LPVOID)&mciStatus ) == MMSYSERR_NOERROR ) {
return mciStatus.dwReturn ? ERROR_SUCCESS : ERROR_NOT_READY;
}
return ERROR_NOT_READY;
}
/******************************Public*Routine******************************\
* StatusTrackPosCdrom
*
* This routine will retrieve the
* status, current track, and current position of the CDRom device.
*
* History:
* 18-11-93 - StephenE - Created
*
\**************************************************************************/
DWORD
StatusTrackPosCdrom(
MCIDEVICEID DevHandle,
DWORD * pStatus,
DWORD * pTrack,
DWORD * pPos
)
{
DWORD dwErr;
MCI_STATUS_PARMS mciStatus;
PSTATUSTRACKPOS pSTP = NULL;
STATUSTRACKPOS stp;
ZeroMemory( &mciStatus, sizeof(mciStatus) );
// Note: This is a non-standard MCI call (I.E. HACK!)
// the only reason for this behavior is it reduces
// the number of IOCTL's per 1/2 second on the HeartBeat
// thread for updating the timer display from ~15 to only
// ~1 on average. Resulting in a major reduction in
// system traffic on the SCSI or IDE bus.
// Note: we are passing down a structre to MCICDA containing
// the position, track, and status values which it will
// fill in for us and return.
mciStatus.dwItem = MCI_STATUS_TRACK_POS;
mciStatus.dwReturn = (DWORD_PTR)&stp;
dwErr = mciSendCommand( DevHandle, MCI_STATUS, MCI_STATUS_ITEM,
(DWORD_PTR)(LPVOID)&mciStatus );
if (dwErr == MMSYSERR_NOERROR)
{
pSTP = (PSTATUSTRACKPOS)mciStatus.dwReturn;
if (pSTP)
{
if (pStatus)
*pStatus = pSTP->dwStatus;
if (pTrack)
*pTrack = pSTP->dwTrack;
if (pPos)
*pPos = pSTP->dwDiscTime;
pSTP = NULL;
}
}
return dwErr;
} // End StatusTrackPosCdrom
#ifdef __cplusplus
};
#endif