/* -*- tab-width: 8; c-basic-offset: 4 -*- */ /* * MCI CDAUDIO Driver for OS/2. Interface to OS/2 DosIOCtrl() * * Copyright 2000 Chris Wohlgemuth * 2001 Przemyslaw Dobrowolski * Project Odin Software License can be found in LICENSE.TXT * */ #define INCL_DOSDEVICES #define INCL_DOSDEVIOCTL #define INCL_DOS #include #include //#include #pragma pack(1) typedef struct{ UCHAR ucFirstTrack; UCHAR ucLastTrack; ULONG ulLeadOut; }CDINFO; typedef struct { int ADR_data_for_track:4; // ADR data for track int preemphasis:1; // 0 = Audio without preemphasis // 1 = Audio with preemphasis int cdda_permitted:1; // 0 = Digital copy prohibited // 1 = Digital copy permitted int type_of_track:1; // 0 = Audio track // 1 = Data track int channels:1; // 0 = Two-channel audio // 1 = Four-channel audio }TRACKTYPE; typedef struct { ULONG ulTrackAddress; TRACKTYPE track_type; }CDTRACKINFO; typedef struct { UCHAR signature[4]; UCHAR ucTrackNum; }TINFOPARAM; typedef struct { UCHAR ucFrames; UCHAR ucSeconds; UCHAR ucMinutes; UCHAR ucNotUsed; }MSF; typedef struct { USHORT usStatusBits; ULONG ulStarting; ULONG ulEnding; }AUDIOSTATUS; typedef struct { UCHAR signature[4]; UCHAR ucAddressMode; ULONG ulStartSector; ULONG ulEndSector; }PLAYPARAM2; typedef struct { UCHAR signature[4]; UCHAR ucAddressMode; ULONG ulTo; }SEEKPARAM; typedef struct { UCHAR ucCtrlAdr; UCHAR ucTrack; UCHAR ucIndex; UCHAR ucTrackMins; UCHAR ucTrackSecs; UCHAR UCTrackFrames; UCHAR ucNull; UCHAR ucDiskMins; UCHAR ucDiskSecs; UCHAR ucDiskFrames; }SUBCHANNELQ; #pragma pack() LONG static _CDCalculateSector(MSF* msf1) { return ((msf1->ucMinutes*60+msf1->ucSeconds)*75+msf1->ucFrames); } HANDLE os2CDOpen(char *drive) { HANDLE hfDrive = 0; ULONG ulAction; ULONG rc; rc = DosOpen(drive, &hfDrive, &ulAction, 0, FILE_NORMAL, OPEN_ACTION_OPEN_IF_EXISTS, OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY | OPEN_FLAGS_DASD|OPEN_FLAGS_FAIL_ON_ERROR, NULL); if(rc) return 0;//Error return hfDrive; } ULONG os2CDClose(ULONG hfOS2Handle) { return DosClose(hfOS2Handle); } /******************************************/ /* Result: 0: Error -1: CD is Data Disk other: # Audio tracks */ /******************************************/ int os2GetNumTracks(HANDLE hfOS2Handle, ULONG *ulLeadOut) { ULONG ulParamLen; ULONG ulDataLen; ULONG rc; CDINFO cdInfo; TINFOPARAM tip; CDTRACKINFO trackInfo; ulDataLen=sizeof(cdInfo); ulParamLen=4; if(!hfOS2Handle) return 0; rc = DosDevIOCtl(hfOS2Handle, IOCTL_CDROMAUDIO, CDROMAUDIO_GETAUDIODISK, (void*)"CD01", 4, &ulParamLen, &cdInfo, sizeof(cdInfo), &ulDataLen); if(rc) { return 0;//Error } ulDataLen=sizeof(trackInfo); ulParamLen=sizeof(TINFOPARAM); tip.signature[0]='C'; tip.signature[1]='D'; tip.signature[2]='0'; tip.signature[3]='1'; tip.ucTrackNum=1; /* We have a disc. Check if it's audio */ rc = DosDevIOCtl(hfOS2Handle, IOCTL_CDROMAUDIO, CDROMAUDIO_GETAUDIOTRACK, &tip, sizeof(tip), &ulParamLen, &trackInfo, sizeof(trackInfo), &ulDataLen); if(rc) { return 0;//Error } // PD: Don't return error when data track is found. // if(trackInfo.ucTCInfo & 0x40) { // return -1;//It's a data track // } *ulLeadOut=cdInfo.ulLeadOut; return cdInfo.ucLastTrack-cdInfo.ucFirstTrack+1; } BOOL os2GetCDStatus(HANDLE hfOS2Handle, ULONG *ulStatus) { ULONG ulParamLen; ULONG ulDeviceStatus; ULONG ulDataLen; ULONG rc; ulDeviceStatus=0; /* Get status */ ulDataLen=sizeof(ulDeviceStatus); ulParamLen=4; rc = DosDevIOCtl(hfOS2Handle, IOCTL_CDROMDISK, CDROMDISK_DEVICESTATUS, (void*)"CD01", 4, &ulParamLen, &ulDeviceStatus, sizeof(ulDeviceStatus), &ulDataLen); if(rc) { return FALSE;//Error } *ulStatus=ulDeviceStatus; return TRUE; } BOOL os2GetCDAudioStatus(HANDLE hfOS2Handle, USHORT *usStatus) { AUDIOSTATUS asStatus; ULONG ulParamLen; ULONG ulDataLen; ULONG rc; /* Get status */ ulDataLen=sizeof(asStatus); ulParamLen=4; /* Get information */ rc = DosDevIOCtl(hfOS2Handle, IOCTL_CDROMAUDIO, CDROMAUDIO_GETAUDIOSTATUS, (void*)"CD01", 4, &ulParamLen, &asStatus, sizeof(asStatus), &ulDataLen); if(rc) { *usStatus=rc; return FALSE;//Error } *usStatus=asStatus.usStatusBits; return TRUE; } /* Returns sector info of track #numTrack */ /* Starting with track 0 */ ULONG os2CDQueryTrackStartSector( HANDLE hfDrive, ULONG numTrack, BOOL *pflAudio) { ULONG ulParamLen; ULONG ulDataLen; ULONG rc; CDINFO cdInfo; TINFOPARAM tip; CDTRACKINFO trackInfo[2]; do { if(!hfDrive) break; /* Get cd info */ ulDataLen=sizeof(cdInfo); ulParamLen=4; rc = DosDevIOCtl(hfDrive, IOCTL_CDROMAUDIO, CDROMAUDIO_GETAUDIODISK, (void*)"CD01", 4, &ulParamLen, &cdInfo, sizeof(cdInfo), &ulDataLen); if(rc) break;//Error ulDataLen=sizeof(trackInfo); ulParamLen=sizeof(TINFOPARAM); tip.signature[0]='C'; tip.signature[1]='D'; tip.signature[2]='0'; tip.signature[3]='1'; /* Get information about our track */ tip.ucTrackNum=numTrack+1; if(tip.ucTrackNum<=cdInfo.ucLastTrack) { rc = DosDevIOCtl(hfDrive, IOCTL_CDROMAUDIO, CDROMAUDIO_GETAUDIOTRACK, &tip, sizeof(tip), &ulParamLen, &trackInfo[0], sizeof(trackInfo[0]), &ulDataLen); if(rc) break;//Error *pflAudio=!trackInfo[0].track_type.type_of_track; }else return _CDCalculateSector((MSF*)&cdInfo.ulLeadOut); return _CDCalculateSector((MSF*)&trackInfo[0].ulTrackAddress); }while(TRUE); /* error */ return 0; } BOOL os2CDEject(HANDLE hfDrive) { ULONG ulParamLen; ULONG rc; if(!hfDrive) return FALSE; ulParamLen=4; rc = DosDevIOCtl(hfDrive, IOCTL_CDROMDISK, CDROMDISK_EJECTDISK, (void*)"CD01", 4, &ulParamLen,0, 0, 0); if(rc) return FALSE;//Error return TRUE; } #ifndef CDROMDISK_CLOSETRAY #define CDROMDISK_CLOSETRAY 0x0045 #endif BOOL os2CDCloseTray(HANDLE hfDrive) { ULONG ulParamLen; ULONG rc; if(!hfDrive) return FALSE; ulParamLen=4; rc = DosDevIOCtl(hfDrive, IOCTL_CDROMDISK, CDROMDISK_CLOSETRAY, (void*)"CD01", 4, &ulParamLen,0, 0, 0); if(rc) return FALSE;//Error return TRUE; } BOOL os2CDStop(HANDLE hfDrive) { ULONG ulParamLen; ULONG rc; if(!hfDrive) return FALSE; /* Stop CD */ ulParamLen=4; rc = DosDevIOCtl(hfDrive, IOCTL_CDROMAUDIO, CDROMAUDIO_STOPAUDIO, (void*)"CD01", 4, &ulParamLen,0, 0, 0); if(rc) return FALSE;//Error return TRUE; } /*****************************************/ /* */ /* Plays frame range */ /* */ /* Returns TRUE if successful */ /* */ /*****************************************/ BOOL os2CDPlayRange(HANDLE hfDrive ,ULONG ulFrom, ULONG ulTo) { ULONG ulParamLen; ULONG ulDataLen; ULONG rc; CDINFO cdInfo; TINFOPARAM tip; CDTRACKINFO trackInfo[2]; PLAYPARAM2 playParam={0}; if(!hfDrive) return FALSE; //memcpy(&playParam,PlayParam, sizeof(playParam)); /* Play the Track... */ ulParamLen=sizeof(PLAYPARAM2); playParam.signature[0]='C'; playParam.signature[1]='D'; playParam.signature[2]='0'; playParam.signature[3]='1'; //playParam.ucAddressMode=01; playParam.ulStartSector=ulFrom; playParam.ulEndSector=ulTo; rc = DosDevIOCtl(hfDrive, IOCTL_CDROMAUDIO, CDROMAUDIO_PLAYAUDIO, &playParam, sizeof(playParam), &ulParamLen,0, 0, 0); return rc; if(rc) return FALSE; return TRUE; } BOOL os2CDResume(HANDLE hfDrive) { ULONG ulParamLen; ULONG rc; if(!hfDrive) return FALSE; /* Stop CD */ ulParamLen=4; rc = DosDevIOCtl(hfDrive, IOCTL_CDROMAUDIO, CDROMAUDIO_RESUMEAUDIO, (void*)"CD01", 4, &ulParamLen,0, 0, 0); if(rc) return FALSE;//Error return TRUE; } BOOL os2CDGetHeadLocation(HANDLE hfOS2Handle, ULONG *ulHeadLocation) { UCHAR ucParam[5]={0}; ULONG ulParamLen; ULONG ulDeviceStatus; ULONG ulDataLen; ULONG rc; ulDeviceStatus=0; if(!hfOS2Handle) return FALSE; /* Get Location */ ulDataLen=sizeof(ulDeviceStatus); ulParamLen=5; ucParam[0]='C'; ucParam[1]='D'; ucParam[2]='0'; ucParam[3]='1'; ucParam[4]=0; rc = DosDevIOCtl(hfOS2Handle, IOCTL_CDROMDISK, CDROMDISK_GETHEADLOC, &ucParam, 5, &ulParamLen, &ulDeviceStatus, sizeof(ulDeviceStatus), &ulDataLen); if(rc) { return FALSE;//Error } *ulHeadLocation=ulDeviceStatus; return TRUE; } BOOL os2CDSeek(HANDLE hfOS2Handle, ULONG ulTo) { SEEKPARAM sp={0}; ULONG ulParamLen; ULONG rc; if(!hfOS2Handle) return FALSE; sp.signature[0]='C'; sp.signature[1]='D'; sp.signature[2]='0'; sp.signature[3]='1'; sp.ulTo=ulTo; ulParamLen=sizeof(sp); /* We have a disc. Check if it's audio */ rc = DosDevIOCtl(hfOS2Handle, IOCTL_CDROMDISK, CDROMDISK_SEEK, &sp, sizeof(sp), &ulParamLen, 0, 0, 0); if(rc) { return FALSE;//Error } return TRUE; } BOOL os2CDQueryCurTrack(HANDLE hfOS2Handle, UINT * uiCurTrack) { ULONG ulParamLen; ULONG ulDeviceStatus; ULONG ulDataLen; ULONG rc; SUBCHANNELQ scq; if(!hfOS2Handle) return FALSE; /* Get status */ ulDataLen=sizeof(scq); ulParamLen=4; rc = DosDevIOCtl(hfOS2Handle, IOCTL_CDROMAUDIO, CDROMAUDIO_GETSUBCHANNELQ, (void*)"CD01", 4, &ulParamLen, &scq, sizeof(scq), &ulDataLen); if(rc) { return FALSE;//Error } *uiCurTrack=(scq.ucTrack & 0xF)+(scq.ucTrack & 0xF0)*10; return TRUE; } /**************************************************************/ /* */ /* This funktion returns the CD-Drives in the system */ /* */ /* iNumCD (output): # of CD-Drives */ /* cFirstDrive (output): first cd-Drive letter */ /* returns TRUE: We have cd-drives */ /* */ /**************************************************************/ BOOL os2CDQueryCDDrives(int *iNumCD, char * cFirstDrive) { HANDLE hfDevice; ULONG ulAction; ULONG ulLen; static char cFirst=0; static int iNumCDLocal=0; static BOOL haveCD=FALSE; static BOOL done=FALSE; struct { USHORT usCountCD; USHORT usFirstCD; } CDInfo; if(!done){ ulLen = sizeof(CDInfo); if(!DosOpen("\\DEV\\CD-ROM2$", &hfDevice, &ulAction, 0, FILE_NORMAL, OPEN_ACTION_OPEN_IF_EXISTS, OPEN_SHARE_DENYNONE | OPEN_ACCESS_READONLY, NULL)) { if(!DosDevIOCtl(hfDevice, 0x82, 0x60, NULL, 0, NULL, &CDInfo, ulLen, &ulLen)) { if(CDInfo.usCountCD) { haveCD=TRUE; iNumCDLocal=CDInfo.usCountCD; cFirst='A'+ CDInfo.usFirstCD; } } DosClose(hfDevice); } done=TRUE; } *iNumCD=iNumCDLocal; *cFirstDrive=cFirst; return haveCD; }