1327 lines
31 KiB
C++
1327 lines
31 KiB
C++
/******************************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
|