home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
viscobv6.zip
/
vac22os2
/
ibmcobol
/
samples
/
toolkit
/
mm
/
cdmcidrv
/
cdaudio.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-11-19
|
46KB
|
958 lines
/****************************************************************************/
/* */
/* SOURCE FILE NAME: CDAUDIO.C */
/* */
/* DESCRIPTIVE NAME: CD AUDIO MCI DRIVER */
/* */
/* COPYRIGHT: (c) IBM Corp. 1991 - 1993 */
/* */
/* FUNCTION: This file contains the hardware independent code that the */
/* CD Audio MCI Driver uses. This includes the entry point for */
/* the MDM/MCI calls to the DLL and the global structures, */
/* utilities and parameter checking. The Process Command */
/* functions are in CDAUDPRO.C */
/* */
/* */
/* NOTES: The hardware dependent code is found in file IBMCDROM.C. */
/* This MCD (MCI Driver) is an example of a non-streaming MCD */
/* with simple support. */
/* */
/* ENTRY POINTS: */
/* mciDriverEntry - performs component specific messages of this MCI */
/* Driver. */
/* */
/* OTHER FUNCTIONS: */
/* pre_process_msg - Pre-Process the requested command message. */
/* process_msg - Process the requested command message. */
/* verify_entry - Verify that entry parameters are valid. */
/* QMAudio - Query master audio's current settings. */
/* Register - Register drive. */
/* ReRegister - Register disc and tracks. */
/* VSDReturn - Process return information from VSD. */
/* SetTrackInst - Set Track info in Instance, seek to start. */
/* ValPointer - Validate address to record structures. */
/* */
/* */
/****************************************************************************/
#define INCL_DOSERRORS
#define INCL_DOSPROCESS
#define INCL_DOSMEMMGR
#define INCL_DOSMODULEMGR
#define INCL_DOSSEMAPHORES
#include <os2.h>
#include <string.h>
#define INCL_MCIOS2
#include <os2me.h>
#include <cdaudos2.h>
#include "cdaudibm.h"
#include "hhpheap.h"
extern PVOID CDMC_hHeap;
/****************************************************************************/
/* */
/* SUBROUTINE NAME: mciDriverEntry */
/* */
/* DESCRIPTIVE NAME: MCI Driver Entry */
/* */
/* FUNCTION: Processes the CD Audio component commands. */
/* */
/* PARAMETERS: */
/* PVOID lpInstance -- Pointer to device handle. */
/* USHORT usMessage -- Command message. */
/* ULONG ulParam1 -- Flag for this message. */
/* PVOID pParam2 -- Pointer to data record structure. */
/* USHORT usUserParm -- User Parameter for mciDriverNotify. */
/* */
/* EXIT CODES: */
/* MCIERR_SUCCESS -- Action completed without error. */
/* MCIERR_INI_FILE -- Corrupted file, invalid open or connection. */
/* MCIERR_DEVICE_NOT_READY -- Device was not ready, no disc. */
/* MCIERR_DEVICE_OPEN -- Error on open. */
/* MCIERR_INVALID_MEDIA_TYPE -- No audio tracks were found. */
/* MCIERR_INVALID_BUFFER -- Buffer size was too small. */
/* MCIERR_OUTOFRANGE -- Invalid value or stream error. */
/* MCIERR_NO_CONNECTION -- No way to play, no stream/DAC */
/* MCIERR_OUT_OF_MEMORY -- Out of memory. */
/* MCIERR_INSTANCE_INACTIVE -- Instance is suspended. */
/* MCIERR_PARAM_OVERFLOW -- Invalid pointer in Parms. */
/* MCIERR_MISSING_PARAMETER -- Invalid PARMS pointer. */
/* MCIERR_INVALID_DEVICE_NAME -- Illegal drive name. */
/* MCIERR_UNSUPPORTED_FUNCTION -- Invalid command message. */
/* MCIERR_FLAGS_NOT_COMPATIBLE -- Invalid flag combinations. */
/* MCIERR_INVALID_FLAG -- Unknown or unsupported flag. */
/* MCIERR_CANNOT_LOAD_DRIVER -- Unable to load VSD. */
/* MCIERR_INVALID_CUEPOINT -- Unable to locate event. */
/* MCIERR_CUEPOINT_LIMIT_REACHED -- No more room to add events. */
/* MCIERR_DUPLICATE_CUEPOINT -- Duplicate cuepoint. */
/* MCIERR_INVALID_ITEM_FLAG -- Invalid item specified. */
/* MCIERR_INVALID_SPEED_FORMAT_FLAG -- Unknown speed type specified. */
/* MCIERR_INVALID_TIME_FORMAT_FLAG -- Unknown time type specified. */
/* MCIERR_INVALID_CONNECTOR_INDEX -- Invalid connector specified. */
/* MCIERR_INVALID_CONNECTOR_TYPE -- Invalid connector specified. */
/* MCIERR_UNSUPPORTED_CONN_TYPE -- Unsupported connector specified. */
/* MCIERR_INVALID_CALLBACK_HANDLE -- Invalid call back handle. */
/* MCIERR_INVALID_AUDIO_FLAG -- Unknown audio flag specified. */
/* MCIERR_DEVICE_LOCKED -- CD-ROM drive, previously opened exclusively.*/
/* */
/* NOTES: Assumes that if NOT MCI_WAIT then it is MCI_NOTIFY, no check */
/* if no flag is passed. */
/* */
/****************************************************************************/
ULONG APIENTRY mciDriverEntry(PVOID lpInstance, USHORT usMessage,
ULONG ulParam1, PVOID pParam2, USHORT usUserParm)
{
ULONG rc;
/* verify inputs */
rc = verify_entry((PINST)lpInstance, usMessage, ulParam1, &pParam2);
if (!rc)
rc = process_msg((PINST)lpInstance, usMessage, &ulParam1,
pParam2, usUserParm);
/* if successful and notify is requested then send notification */
if (!(ULONG_LOWD(rc)) && ulParam1 & MCI_NOTIFY)
{
mdmDriverNotify(((struct instance_state *)lpInstance)->usDeviceID,
((MCI_GENERIC_PARMS *)pParam2)->hwndCallback, MM_MCINOTIFY,
usUserParm, MAKEULONG(usMessage, MCI_NOTIFY_SUCCESSFUL));
} /* of if no error and NOTIFY is set */
return(rc);
} /* of mciDriverEntry() */
/****************************************************************************/
/* */
/* SUBROUTINE NAME: pre_process_msg */
/* */
/* DESCRIPTIVE NAME: Pre-process messages. */
/* */
/* FUNCTION: The code for this function was in process_msg but was */
/* placed here to make it neater. */
/* */
/* PARAMETERS: */
/* PINST pInst -- instance pointer. */
/* USHORT *pusMessage -- requested action to be performed. */
/* ULONG ulParam1 -- flag for this message. */
/* */
/* EXIT CODES: */
/* MCIERR_SUCCESS -- action completed without error. */
/* */
/* NOTES: */
/* */
/****************************************************************************/
ULONG pre_process_msg(PINST pInst, USHORT *pusMessage, ULONG ulParam1)
{
ULONG rc = MCIERR_SUCCESS;
if (*pusMessage == MCIDRV_RESTORE)
{
/* process shareable flag */
if (ulParam1 & MCI_OPEN_SHAREABLE)
pInst->ulMode |= CDMC_SHAREABLE;
else
pInst->ulMode &= ~CDMC_SHAREABLE;
if (pInst->usStatus < SUSPEND)
*pusMessage = 0; //ignore restores without a save
} /* of id message is RESTORE */
/* re-register if necessary */
if (pInst->usStatus <= NODISC) //try registering disc and tracks
ReRegister(pInst); //ignore RC, let message process state
/* re-restore if necessary */
if (pInst->usStatus >= SUSPEND && *pusMessage == MCIDRV_SAVE)
*pusMessage = 0; //ignore saves when saved
return(rc);
} /* of pre_process_msg() */
/****************************************************************************/
/* */
/* SUBROUTINE NAME: process_msg */
/* */
/* DESCRIPTIVE NAME: Process Control Message */
/* */
/* FUNCTION: Processes the CD Audio commands. */
/* */
/* PARAMETERS: */
/* PINST pInst -- instance pointer. */
/* USHORT usMessage -- requested action to be performed. */
/* ULONG *pulParam1 -- pointer to flag for this message. */
/* PVOID pParam2 -- pointer to structure (message dependent). */
/* USHORT usUserParm -- User Parameter for mciDriverNotify. */
/* */
/* EXIT CODES: */
/* MCIERR_SUCCESS -- action completed without error. */
/* MCIERR_INI_FILE -- corrupted file, invalid open or connection. */
/* MCIERR_DEVICE_NOT_READY -- device was not ready, no disc. */
/* MCIERR_INVALID_MEDIA_TYPE -- No audio tracks were found. */
/* MCIERR_OUTOFRANGE -- Invalid value. */
/* MCIERR_NO_CONNECTION -- No way to play, no stream/DAC. */
/* MCIERR_OUT_OF_MEMORY -- Out of memory. */
/* MCIERR_INSTANCE_INACTIVE -- Instance is suspended. */
/* MCIERR_PARAM_OVERFLOW -- Invalid PARMS pointer. */
/* MCIERR_INVALID_DEVICE_ID -- invalid instance handle. */
/* MCIERR_INVALID_BUFFER -- Buffer size was too small. */
/* MCIERR_UNSUPPORTED_FUNCTION -- Invalid command message. */
/* MCIERR_FLAGS_NOT_COMPATIBLE -- Invalid flag combinations. */
/* MCIERR_INVALID_FLAG -- Unknown or unsupported flag. */
/* MCIERR_INVALID_DEVICE_NAME -- Illegal drive name. */
/* MCIERR_INVALID_CUEPOINT -- unable to locate event. */
/* MCIERR_CUEPOINT_LIMIT_REACHED -- no more room to add events. */
/* MCIERR_DUPLICATE_CUEPOINT -- duplicate cuepoint. */
/* MCIERR_INVALID_ITEM_FLAG -- Invalid item specified. */
/* MCIERR_INVALID_SPEED_FORMAT_FLAG -- Unknown speed type specified. */
/* MCIERR_INVALID_TIME_FORMAT_FLAG -- Unknown time type specified. */
/* MCIERR_INVALID_CONNECTOR_INDEX -- Invalid connector specified. */
/* MCIERR_INVALID_CONNECTOR_TYPE -- Invalid connector specified. */
/* MCIERR_UNSUPPORTED_CONN_TYPE -- Unsupported connector specified. */
/* MCIERR_INVALID_CALLBACK_HANDLE -- invalid call back handle. */
/* MCIERR_INVALID_AUDIO_FLAG -- Unknown audio flag specified. */
/* MCIERR_CANNOT_LOAD_DRIVER -- Unable to load VSD. */
/* MCIERR_DEVICE_LOCKED -- CD-ROM drive, previously opened exclusively.*/
/* */
/* NOTES: */
/* */
/* */
/****************************************************************************/
ULONG process_msg(PINST pInst, USHORT usMessage, ULONG *pulParam1,
PVOID pParam2, USHORT usUserParm)
{
ULONG rc;
if (usMessage != MCI_OPEN)
DosRequestMutexSem(pInst->hInstSem, WAIT_FOREVER);
/* bypass restores if opening or closing */
if (usMessage == MCI_CLOSE || usMessage == MCI_OPEN)
rc = MCIERR_SUCCESS;
else
{
if (rc = pre_process_msg(pInst, &usMessage, *pulParam1))
{
DosReleaseMutexSem(pInst->hInstSem);
return(rc);
}
} /* of else not close */
switch(usMessage)
{
case 0 : /* save or restore when already in that state */
DosReleaseMutexSem(pInst->hInstSem);
break;
case MCI_CLOSE :
rc = ProcClose(pInst, pulParam1, pParam2, usUserParm);
break;
case MCI_CONNECTOR :
rc = ProcConnector(pInst, *pulParam1, (MCI_CONNECTOR_PARMS *)pParam2);
DosReleaseMutexSem(pInst->hInstSem);
break;
case MCI_CUE :
rc = ProcCue(pInst, *pulParam1);
DosReleaseMutexSem(pInst->hInstSem);
break;
case MCI_ESCAPE :
DosReleaseMutexSem(pInst->hInstSem); /* can't provide protection */
rc = ProcGeneral(pInst, usMessage, pulParam1, pParam2, usUserParm);
break;
case MCI_GETDEVCAPS :
DosReleaseMutexSem(pInst->hInstSem); /* doesn't need protection */
rc = ProcCaps(pInst, *pulParam1, (MCI_GETDEVCAPS_PARMS *) pParam2);
break;
case MCI_GETTOC :
DosReleaseMutexSem(pInst->hInstSem); /* doesn't need protection */
rc = ProcGeneral(pInst, usMessage, pulParam1, pParam2, usUserParm);
break;
case MCI_INFO :
DosReleaseMutexSem(pInst->hInstSem); /* doesn't need protection */
rc = ProcInfo(pInst, *pulParam1, (MCI_INFO_PARMS *)pParam2);
break;
case MCI_MASTERAUDIO :
rc = ProcMAudio(pInst, *pulParam1, (MCI_MASTERAUDIO_PARMS *)pParam2);
DosReleaseMutexSem(pInst->hInstSem);
break;
case MCI_OPEN :
rc = ProcOpen(pulParam1, (MMDRV_OPEN_PARMS *)pParam2, usUserParm);
break;
case MCI_PAUSE :
rc = ProcPause(pInst, *pulParam1);
DosReleaseMutexSem(pInst->hInstSem);
break;
case MCI_PLAY :
rc = ProcPlay(pInst, pulParam1, (MCI_PLAY_PARMS *)pParam2,
usUserParm);
break;
case MCIDRV_RESTORE :
ProcRestore(pInst); //from MDM, return success
DosReleaseMutexSem(pInst->hInstSem);
break;
case MCI_RESUME :
rc = ProcResume(pInst, *pulParam1);
DosReleaseMutexSem(pInst->hInstSem);
break;
case MCIDRV_SAVE :
ProcSave(pInst); //from MDM, return success
DosReleaseMutexSem(pInst->hInstSem);
break;
case MCI_SEEK :
rc = ProcSeek(pInst, *pulParam1, (MCI_SEEK_PARMS *) pParam2);
DosReleaseMutexSem(pInst->hInstSem);
break;
case MCI_SET :
rc = ProcSet(pInst, pulParam1, (MCI_SET_PARMS *) pParam2);
break;
case MCI_SET_CUEPOINT :
rc = ProcCuePoint(pInst, *pulParam1, (MCI_CUEPOINT_PARMS *) pParam2);
DosReleaseMutexSem(pInst->hInstSem);
break;
case MCI_SET_POSITION_ADVISE :
rc = ProcPosAdvise(pInst, *pulParam1, (MCI_POSITION_PARMS *) pParam2);
DosReleaseMutexSem(pInst->hInstSem);
break;
case MCI_SET_SYNC_OFFSET :
rc = ProcSetSync(pInst, *pulParam1, (MCI_SYNC_OFFSET_PARMS *) pParam2);
DosReleaseMutexSem(pInst->hInstSem);
break;
case MCI_STATUS :
rc = ProcStatus(pInst, *pulParam1, (MCI_STATUS_PARMS *) pParam2);
DosReleaseMutexSem(pInst->hInstSem);
break;
case MCI_STOP :
rc = ProcStop(pInst, *pulParam1);
DosReleaseMutexSem(pInst->hInstSem);
break;
case MCIDRV_SYNC :
rc = ProcSync(pInst, *pulParam1, (MCIDRV_SYNC_PARMS *) pParam2);
DosReleaseMutexSem(pInst->hInstSem);
break;
default :
DosReleaseMutexSem(pInst->hInstSem); /* can't provide protection */
rc = ProcGeneral(pInst, usMessage, pulParam1, pParam2, usUserParm);
} /* of switch */
return(rc);
} /* of process_msg() */
/****************************************************************************/
/* */
/* SUBROUTINE NAME: verify_entry */
/* */
/* DESCRIPTIVE NAME: Verify Entry. */
/* */
/* FUNCTION: Verifies the input parameters from the mciDriverEntry */
/* point of entry. The handle or instance pointer is verified */
/* to be a valid open instance. Also the PARMS record pointer */
/* is validated to be in a writable data segment. */
/* */
/* PARAMETERS: */
/* PINST pInst -- instance pointer. */
/* USHORT usMessage -- requested action to be performed. */
/* ULONG ulParam1 -- flag for this message. */
/* PVOID pParam2 -- pointer to structure (message dependent). */
/* */
/* EXIT CODES: */
/* MCIERR_SUCCESS -- action completed without error. */
/* MCIERR_INI_FILE -- open device type is not CD Audio. */
/* MCIERR_INVALID_DEVICE_ID -- invalid instance handle. */
/* MCIERR_INVALID_BUFFER -- invalid pointer in o/p buffer. */
/* MCIERR_MISSING_PARAMETER -- invalid PARMS pointer, or i/p buffer. */
/* MCIERR_OUT_OF_MEMORY -- out of memory. */
/* MCIERR_UNSUPPORTED_FUNCTION -- Invalid command message. */
/* */
/* NOTES: */
/* */
/****************************************************************************/
ULONG verify_entry(PINST pInst, USHORT usMessage,
ULONG ulParam1, PVOID *pParam2)
{
ULONG rc = MCIERR_SUCCESS;
USHORT usFlag;
if (usMessage == MCI_OPEN) /* make sure correct device type is used */
{
if (((MMDRV_OPEN_PARMS *)*pParam2)->usDeviceType != MCI_DEVTYPE_CD_AUDIO)
rc = MCIERR_INI_FILE;
}
else /* verify that component handle exists and is valid */
{
if (!usMessage)
rc = MCIERR_UNSUPPORTED_FUNCTION;
if (ValPointer(pInst, VALLEN)) // is it a real pointer?
rc = MCIERR_INVALID_DEVICE_ID;
else
if (strncmp(pInst->valid, VALIDID, VALLEN)) // does it point to
rc = MCIERR_INVALID_DEVICE_ID; // an instance?
if (rc && (usMessage == MCI_DEVICESETTINGS)) // DevSets don't need an
rc = MCIERR_UNSUPPORTED_FUNCTION; // instance ptr
} /* of if not open */
/* test *pParam2 is a valid pointer */
if (!rc)
{
switch (usMessage) /* does message require pParam2 ? */
{
case MCI_DEVICESETTINGS :
case MCI_ESCAPE : case MCI_GETDEVCAPS :
case MCI_GETTOC : case MCI_INFO : case MCI_LOAD :
case MCI_MASTERAUDIO : case MCI_OPEN : case MCI_RECORD :
case MCI_SAVE: case MCI_SET_CUEPOINT :
case MCI_SET_POSITION_ADVISE : case MCI_SET_SYNC_OFFSET :
case MCI_STATUS : case MCI_STEP : case MCI_SYSINFO :
usFlag = TRUE;
break;
case MCI_CONNECTOR :
if (ulParam1 & (MCI_QUERY_CONNECTOR_STATUS |
MCI_CONNECTOR_TYPE | MCI_CONNECTOR_INDEX))
usFlag = TRUE;
else
usFlag = FALSE;
break;
case MCI_PLAY :
if (ulParam1 & MCI_FROM || ulParam1 & MCI_TO)
usFlag = TRUE;
else
usFlag = FALSE;
break;
case MCI_SEEK :
if (ulParam1 & MCI_TO)
usFlag = TRUE;
else
usFlag = FALSE;
break;
case MCI_SET :
if (ulParam1 & MCI_SET_AUDIO || ulParam1 & MCI_SET_SPEED_FORMAT ||
ulParam1 & MCI_SET_TIME_FORMAT || ulParam1 & MCI_SET_VOLUME ||
ulParam1 & MCI_OVER)
usFlag = TRUE;
else
usFlag = FALSE;
break;
default : /* other commands are on their own */
usFlag = FALSE;
} /* of switch */
/* Verify that pParam2 is a valid pointer if necessary */
rc = ValPointer(*pParam2, sizeof(ULONG));
if (rc && (!(ulParam1 & MCI_NOTIFY) && !usFlag))
{
rc = MCIERR_SUCCESS; //pParam2 not required
*pParam2 = NULL;
}
} /* of if no error */
return(rc);
} /* of verify_entry() */
/****************************************************************************/
/* */
/* SUBROUTINE NAME: QMAudio */
/* */
/* DESCRIPTIVE NAME: Query Master Audio */
/* */
/* FUNCTION: Query current volume and headphone/speaker settings from */
/* Master Audio. */
/* */
/* PARAMETERS: */
/* PINST pInst -- pointer to instance. */
/* */
/* EXIT CODES: None */
/* */
/* NOTES: */
/* */
/****************************************************************************/
VOID QMAudio(PINST pInst)
{
ULONG rc;
USHORT ulChanType = 0L;
MCI_MASTERAUDIO_PARMS recMasterAudio;
/* get current master volume */
rc = mciSendCommand(pInst->usDeviceID, MCI_MASTERAUDIO,
MCI_WAIT | MCI_QUERYCURRENTSETTING | MCI_MASTERVOL,
&recMasterAudio, 0);
if (ULONG_LOWD(rc))
{
if (pInst->ulMasterVolume == (ULONG) -1L)
pInst->ulMasterVolume = 75L; //if first time error set to default
}
else
pInst->ulMasterVolume = recMasterAudio.ulReturn;
/* get current speaker status */
rc = mciSendCommand(pInst->usDeviceID, MCI_MASTERAUDIO,
MCI_WAIT | MCI_QUERYCURRENTSETTING | MCI_SPEAKERS,
&recMasterAudio, 0);
if (ULONG_LOWD(rc))
ulChanType = CDMC_SPEAKER; //if error set to default
else
if (recMasterAudio.ulReturn)
ulChanType = CDMC_SPEAKER; //SPEAKERS are turned on
/* get current headphone status */
rc = mciSendCommand(pInst->usDeviceID, MCI_MASTERAUDIO,
MCI_WAIT | MCI_QUERYCURRENTSETTING | MCI_HEADPHONES,
&recMasterAudio, 0);
if (ULONG_LOWD(rc))
ulChanType |= CDMC_HEADPHONE; //if error set to default
else
if (recMasterAudio.ulReturn)
ulChanType |= CDMC_HEADPHONE; //HEADPHONES are turned on
pInst->ulMode = (pInst->ulMode & CHAN_TYPE_SET) | ulChanType;
} /* of QMAudio() */
/****************************************************************************/
/* */
/* SUBROUTINE NAME: Register */
/* */
/* DESCRIPTIVE NAME: Register. */
/* */
/* FUNCTION: Register the CD-ROM Drive for the MCI Driver. */
/* */
/* PARAMETERS: */
/* PINST pInst -- pointer to instance. */
/* */
/* EXIT CODES: */
/* MCIERR_SUCCESS -- action completed without error. */
/* MCIERR_OUT_OF_MEMORY -- couldn't allocate memory for semaphore. */
/* */
/* NOTES: */
/* */
/****************************************************************************/
ULONG Register(PINST pInst)
{
ULONG rc;
MCI_CD_REGDRIVE_PARMS recDrive;
/* register drive */
recDrive.ulCDMCDID = (ULONG) pInst;
recDrive.pCDMCDReturn = VSDReturn;
rc = pInst->pMCIDriver(pInst->hHWMCID, MCIDRV_REGISTER_DRIVE, 0L,
&recDrive, 0);
if (!rc)
{
pInst->usStatus = REGDRIVE;
pInst->usCaps = recDrive.usCaps;
pInst->ulPrerollType = recDrive.ulPrerollType;
pInst->ulPrerollTime = recDrive.ulPrerollTime;
pInst->ulMinStartTime = recDrive.ulMinStartTime;
/* STREAM_CAP field in ulMode was cleared in ProcOpen() */
if (recDrive.usCaps & CDVSD_CAP_HAS_DAC)
{
pInst->ulMode |= CDMC_CAN_DAC;
pInst->ulMode |= CDMC_INTDAC;
}
if (recDrive.usCaps & CDVSD_CAP_CAN_STREAM)
pInst->ulMode |= CDMC_CAN_STREAM;
/* just set potential to stream, don't go into stream mode until */
/* the MCI_CONNECTOR command message is sent. */
if (rc) /* if error, clear stream mode */
pInst->ulMode &= STREAM_MODE_SET;
} /* of if no error registering drive */
return(rc);
} /* of Register() */
/****************************************************************************/
/* */
/* SUBROUTINE NAME: ReRegister */
/* */
/* DESCRIPTIVE NAME: Re-Register. */
/* */
/* FUNCTION: Register the discs and tracks for the MCI Driver. */
/* */
/* PARAMETERS: */
/* PINST pInst -- pointer to instance. */
/* */
/* EXIT CODES: */
/* MCIERR_SUCCESS -- action completed without error. */
/* MCIERR_DEVICE_NOT_READY -- device was not ready, no disc. */
/* MCIERR_INVALID_MEDIA_TYPE -- No audio tracks were found. */
/* */
/* NOTES: */
/* */
/****************************************************************************/
ULONG ReRegister(PINST pInst)
{
ULONG rc = MCIERR_SUCCESS; // assume the best
ULONG ulSetParam1;
ULONG ulInfoSize;
USHORT usTemp, usChange = TRUE;
MCI_SET_PARMS recSet;
MCI_CD_ID DiscID;
memcpy(&DiscID, &pInst->recDisc.DiscID, IDSIZE);
/* Get new disk information */
rc = pInst->pMCIDriver(pInst->hHWMCID, MCIDRV_REGISTER_DISC, 0L,
&pInst->recDisc, 0);
if (rc == MCIERR_MEDIA_CHANGED) // Get it again to make sure
pInst->pMCIDriver(pInst->hHWMCID, MCIDRV_REGISTER_DISC, 0L,
&pInst->recDisc, 0);
/* if no error and previous disc check to see if it's the same */
if (!rc && DiscID.Mode != (BYTE) -1)
if (memcmp(&pInst->recDisc.DiscID, &DiscID, IDSIZE))
rc = MCIERR_MEDIA_CHANGED;
else
usChange = FALSE; //same disc perhaps
if (rc && rc != MCIERR_MEDIA_CHANGED)
pInst->usStatus = REGDRIVE; //Reg Disc, failed
else
{ /* Disc was registered */
/* set initial volume */
if (pInst->ulMasterVolume == (ULONG) -1L)
{
/* if mastervolume is not set then set it */
/* get current master volume */
QMAudio(pInst);
/* set local volume */
usTemp = pInst->usStatus;
pInst->usStatus = STOPPED;
recSet.ulAudio = MCI_SET_AUDIO_LEFT;
recSet.ulLevel = (ULONG) VOL_LEFT(pInst->ulLevel);
recSet.ulOver = 0L;
ulSetParam1 = MCI_SET_AUDIO | MCI_SET_VOLUME | MCI_WAIT;
ProcSet(pInst, &ulSetParam1, &recSet);
pInst->usStatus = usTemp;
} /* of setting the device with initial volume setting */
ulInfoSize = (pInst->recDisc.HighestTrackNum -
pInst->recDisc.LowestTrackNum + 1) *
sizeof(MCI_CD_REGTRACK_REC);
/* make sure we have enough memory to hold new disc */
if (ulInfoSize > pInst->ulTrackInfoSize)
{
/* free old pointer if one existed */
if (pInst->ulTrackInfoSize)
HhpFreeMem(CDMC_hHeap, pInst->pTrackInfo);
pInst->pTrackInfo = HhpAllocMem(CDMC_hHeap, (size_t)ulInfoSize);
if (pInst->pTrackInfo == NULL)
{
pInst->ulTrackInfoSize = 0;
pInst->usStatus = REGDISC; //No memory to reg tracks
}
else
pInst->ulTrackInfoSize = ulInfoSize;
} /* of if need more memory */
/* Get ready to get track info */
pInst->recTrack.ulBufSize = pInst->ulTrackInfoSize;
pInst->recTrack.TrackRecArr = (MCI_CD_REGTRACK_REC *)pInst->pTrackInfo;
rc = pInst->pMCIDriver(pInst->hHWMCID, MCIDRV_REGISTER_TRACKS, 0L,
&pInst->recTrack, 0);
if (rc)
pInst->usStatus = REGDRIVE; //Reg Tracks failed
else
{
/* Set Track Info into instance & Seek to start of first audio track */
pInst->usStatus = REGTRACK;
rc = SetTrackInst(pInst, usChange);
/* report change only if there was a previous disc */
if (!rc && usChange && DiscID.Mode != (BYTE) -1)
rc = MCIERR_MEDIA_CHANGED;
} /* of else no error registering tracks */
} /* of else no error registering disc */
if (rc == MCIERR_MEDIA_CHANGED || rc == MCIERR_INVALID_MEDIA_TYPE)
DisableEvents(pInst);
if (rc == MCIERR_MEDIA_CHANGED)
rc = MCIERR_SUCCESS;
return(rc);
} /* of ReRegister() */
/****************************************************************************/
/* */
/* SUBROUTINE NAME: VSDReturn */
/* */
/* DESCRIPTIVE NAME: VSD Return */
/* */
/* FUNCTION: Process return information from VSDs. This function is */
/* called by the VSD to inform the MCD of changes in the */
/* component mode or state. This is needed when the VSD */
/* creates a thread to process a command (ie MCI_PLAY with */
/* MCI_NOTIFY) and needs to inform the MCD of the results */
/* (ie PLAY terminated because of an error or PLAY completed */
/* and the MCD must now be in a STOPPED state). This function */
/* is called also by the VSD when a non-standard message or */
/* MCI_ESCAPE alters the mode of the device (ie it stops is). */
/* */
/* PARAMETERS: */
/* ULONG pInst -- MCD Instance ID / pointer to instance. */
/* ULONG ulMsgParm -- Message Parm, same format as in mdmDriverNotify()*/
/* ULONG ulMode -- Mode the component is in. */
/* */
/* EXIT CODES: None */
/* */
/* NOTES: */
/* */
/****************************************************************************/
VOID VSDReturn(ULONG pInst, ULONG ulMsgParm, ULONG ulMode)
{
USHORT usMessage, usErrorCode, usChange = FALSE;
/* extract error and message codes */
usMessage = LOUSHORT(ulMsgParm);
usErrorCode = HIUSHORT(ulMsgParm);
switch(usMessage)
{
case MCI_PLAY :
if (usErrorCode != MCI_NOTIFY_SUPERSEDED &&
usErrorCode != MCI_NOTIFY_ABORTED)
{
usChange = TRUE; //PLAY completed or had error
ulMode = MCI_MODE_STOP;
}
break;
case MCI_CONNECTOR : case MCI_GETDEVCAPS : case MCI_GETTOC :
case MCI_INFO : case MCI_MASTERAUDIO : case MCI_OPEN :
case MCI_RECORD : case MCI_SAVE: case MCI_SEEK :
case MCI_SET_CUEPOINT :
case MCI_SET_POSITION_ADVISE : case MCI_SET_SYNC_OFFSET :
case MCI_STATUS : case MCI_STEP : case MCI_SYSINFO :
break; // messages processed by MCD
case MCI_LOAD : case MCI_SET :
usChange = TRUE; // possible change, listen to VSD
break;
default : // unknown message, listen to VSD
usChange = TRUE;
} /* of switch */
if (usChange)
{
switch (ulMode)
{
case MCI_MODE_NOT_READY :
((PINST) pInst)->usStatus = NODISC;
break;
case MCI_MODE_PAUSE :
((PINST) pInst)->usStatus = PAUSED;
break;
case MCI_MODE_PLAY :
((PINST) pInst)->usStatus = PLAYING;
break;
case MCI_MODE_STOP :
((PINST) pInst)->usStatus = STOPPED;
break;
} /* of switch */
} /* of if change was needed */
} /* of VSDReturn() */
/****************************************************************************/
/* */
/* SUBROUTINE NAME: SetTrackInst */
/* */
/* DESCRIPTIVE NAME: Set Track Information of Instance. */
/* */
/* FUNCTION: Sets the Track related information in the instance structure. */
/* It also seeks to the start of the first audio track. */
/* If any error occurs, it will update the usStatus field */
/* as an extension of the registration portion. */
/* */
/* PARAMETERS: */
/* PINST pInst -- pointer to instance. */
/* USHORT usChange -- Change Disc flag. */
/* */
/* EXIT CODES: */
/* MCIERR_SUCCESS -- action completed without error. */
/* MCIERR_DEVICE_NOT_READY -- device was not ready, no disc. */
/* MCIERR_INVALID_MEDIA_TYPE -- No audio tracks were found. */
/* MCIERR_MEDIA_CHANGED -- different disc was inserted. */
/* */
/* NOTES: MCIERR_MEDIA_CHANGED is returned when usChange is FALSE and */
/* a difference was found, otherwise it expects that the */
/* calling function is aware of the change and will return */
/* MCIERR_MEDIA_CHANGED if needed. */
/* */
/****************************************************************************/
ULONG SetTrackInst(PINST pInst, USHORT usChange)
{
ULONG rc = MCIERR_SUCCESS; // assume the best
int i, cnt;
MCI_SEEK_PARMS recSeek;
MCI_STATUS_PARMS recStatus;
ULONG ulParam1, ulDirt = FALSE, ulFlags;
cnt = (BYTE) (pInst->recDisc.HighestTrackNum -
pInst->recDisc.LowestTrackNum + 1);
/* find the start of the audio section */
for (i = 0; i < cnt; i++)
{
if (!((pInst->recTrack.TrackRecArr + i)->TrackControl & IS_DATA_TRK))
{
pInst->ulStart_disk = (pInst->recTrack.TrackRecArr + i)->ulStartAddr;
break;
}
} /* of for loop, finding first audio track */
/* Did we get it ? */
if (i == cnt)
{
pInst->ulStart_disk = 0L;
pInst->ulEnd_disk = 0L;
pInst->ulCur_pos = 0L;
rc = MCIERR_INVALID_MEDIA_TYPE;
}
else
{
/* find last audio track */
for (i = cnt-1; ; i--)
{
if (!((pInst->recTrack.TrackRecArr + i)->TrackControl & IS_DATA_TRK))
{
pInst->ulEnd_disk = (pInst->recTrack.TrackRecArr + i)->ulEndAddr;
break;
}
} /* of for loop, finding last audio track */
if (usChange)
/* now seek to start of playable disc */
recSeek.ulTo = pInst->ulStart_disk;
else // we think its the same disc, reseek to current position
{
recStatus.ulItem = MCI_STATUS_POSITION;
ulFlags = MCI_STATUS_ITEM | MCI_WAIT;
rc = pInst->pMCIDriver(pInst->hHWMCID, MCI_STATUS,
&ulFlags, &recStatus, 0);
if (ULONG_LOWD(rc))
rc = vsdResponse(pInst, rc);
else
recSeek.ulTo = recStatus.ulReturn;
if (rc) //error getting current position, try last known position
{
rc = MCIERR_SUCCESS;
recSeek.ulTo = pInst->ulCur_pos;
ulDirt = TRUE;
}
if (ValAddress(pInst, NULL, &recSeek.ulTo, FALSE))
{
recSeek.ulTo = pInst->ulStart_disk;
ulDirt = TRUE;
}
} /* of else assuming same disc */
/* check hardware start limitations */
if (recSeek.ulTo < pInst->ulMinStartTime)
recSeek.ulTo = pInst->ulMinStartTime;
ulParam1 = MCI_TO | MCI_WAIT;
rc = pInst->pMCIDriver(pInst->hHWMCID, MCI_SEEK, &ulParam1, &recSeek, 0);
/* just incase they changed the disc again, check it */
if (rc)
rc = vsdResponse(pInst, rc);
else
{
pInst->usStatus = STOPPED;
pInst->ulCur_pos = recSeek.ulTo;
if (ulDirt)
rc = MCIERR_MEDIA_CHANGED;
} /* of else no error seeking */
} /* of else disc contains playable tracks */
return(rc);
} /* of SetTrackInst() */
/****************************************************************************/
/* */
/* SUBROUTINE NAME: ValPointer */
/* */
/* DESCRIPTIVE NAME: Validate Pointer */
/* */
/* FUNCTION: Validate Pointers as writable addresses. */
/* */
/* PARAMETERS: */
/* PVOID ptr -- pointer, address to be checked. */
/* ULONG usLen -- length to be checked. */
/* */
/* EXIT CODES: */
/* MCIERR_SUCCESS -- action completed without error. */
/* MCIERR_MISSING_PARAMETER -- invalid pointer. */
/* */
/* NOTES: If interrupted, pretend that it was successful. */
/* */
/* */
/****************************************************************************/
ULONG ValPointer(PVOID ptr, ULONG ulLen)
{
ULONG rc = MCIERR_SUCCESS; // assume the best
ULONG ulFlags;
if (ptr == 0L)
rc = MCIERR_MISSING_PARAMETER;
else
{
rc = DosQueryMem(ptr, &ulLen, &ulFlags);
if (rc != ERROR_INTERRUPT) // ignore interruptions
if (rc)
rc = MCIERR_MISSING_PARAMETER;
else
if (!(ulFlags & PAG_WRITE))
rc = MCIERR_MISSING_PARAMETER;
}
return(rc);
} /* of ValPointer() */