DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
src/dos/cdrom_ioctl_win32.cpp
00001 /*
00002  *  Copyright (C) 2002-2015  The DOSBox Team
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with this program; if not, write to the Free Software
00016  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017  */
00018 
00019 
00020 #if defined (WIN32) && 0
00021 
00022 // *****************************************************************
00023 // Windows IOCTL functions (not suitable for 95/98/Me)
00024 // *****************************************************************
00025 
00026 #include <windows.h>
00027 #include <io.h>
00028 
00029 #if defined (_MSC_VER)
00030 //#include <ntddcdrm.h>                 // Ioctl stuff
00031 #include <winioctl.h>                   // Ioctl stuff
00032 #else 
00033 #include "ddk/ntddcdrm.h"               // Ioctl stuff
00034 #endif
00035 
00036 #include <mmsystem.h>
00037 
00038 #include "cdrom.h"
00039 
00040 // for a more sophisticated implementation of the mci cdda functionality
00041 // see the SDL sources, which the mci_ functions are based on
00042 
00043 /* General ioctl() CD-ROM command function */
00044 bool CDROM_Interface_Ioctl::mci_CDioctl(UINT msg, DWORD flags, void *arg) {
00045         MCIERROR mci_error = mciSendCommand(mci_devid, msg, flags, (DWORD_PTR)arg);
00046         if (mci_error!=MMSYSERR_NOERROR) {
00047                 char error[256];
00048                 mciGetErrorString(mci_error, error, 256);
00049                 LOG_MSG("mciSendCommand() error: %s", error);
00050                 return true;
00051         }
00052         return false;
00053 }
00054 
00055 bool CDROM_Interface_Ioctl::mci_CDOpen(char drive) {
00056         MCI_OPEN_PARMS mci_open;
00057         MCI_SET_PARMS mci_set;
00058         char device[3];
00059         DWORD flags;
00060 
00061         /* Open the requested device */
00062         mci_open.lpstrDeviceType = (LPCSTR) MCI_DEVTYPE_CD_AUDIO;
00063         device[0] = drive;
00064         device[1] = ':';
00065         device[2] = '\0';
00066         mci_open.lpstrElementName = device;
00067         flags = (MCI_OPEN_TYPE|MCI_OPEN_TYPE_ID|MCI_OPEN_SHAREABLE|MCI_OPEN_ELEMENT);
00068         if (mci_CDioctl(MCI_OPEN, flags, &mci_open)) {
00069                 flags &= ~MCI_OPEN_SHAREABLE;
00070                 if (mci_CDioctl(MCI_OPEN, flags, &mci_open)) {
00071                         return true;
00072                 }
00073         }
00074         mci_devid = mci_open.wDeviceID;
00075 
00076         /* Set the minute-second-frame time format */
00077         mci_set.dwTimeFormat = MCI_FORMAT_MSF;
00078         mci_CDioctl(MCI_SET, MCI_SET_TIME_FORMAT, &mci_set);
00079 
00080         return false;
00081 }
00082 
00083 bool CDROM_Interface_Ioctl::mci_CDClose(void) {
00084         return mci_CDioctl(MCI_CLOSE, MCI_WAIT, NULL);
00085 }
00086 
00087 bool CDROM_Interface_Ioctl::mci_CDPlay(int start, int length) {
00088         DWORD flags = MCI_FROM | MCI_TO | MCI_NOTIFY;
00089         MCI_PLAY_PARMS mci_play;
00090         mci_play.dwCallback = 0;
00091 
00092         int m, s, f;
00093         FRAMES_TO_MSF(start, &m, &s, &f);
00094         mci_play.dwFrom = MCI_MAKE_MSF(m, s, f);
00095 
00096         FRAMES_TO_MSF(start+length, &m, &s, &f);
00097         mci_play.dwTo = MCI_MAKE_MSF(m, s, f);
00098 
00099         return mci_CDioctl(MCI_PLAY, flags, &mci_play);
00100 }
00101 
00102 bool CDROM_Interface_Ioctl::mci_CDPause(void) {
00103         return mci_CDioctl(MCI_PAUSE, MCI_WAIT, NULL);
00104 }
00105 
00106 bool CDROM_Interface_Ioctl::mci_CDResume(void) {
00107         return mci_CDioctl(MCI_RESUME, MCI_WAIT, NULL);
00108 }
00109 
00110 bool CDROM_Interface_Ioctl::mci_CDStop(void) {
00111         return mci_CDioctl(MCI_STOP, MCI_WAIT, NULL);
00112 }
00113 
00114 int CDROM_Interface_Ioctl::mci_CDStatus(void) {
00115         int status;
00116         MCI_STATUS_PARMS mci_status;
00117 
00118         DWORD flags = MCI_STATUS_ITEM | MCI_WAIT;
00119         mci_status.dwItem = MCI_STATUS_MODE;
00120         if (mci_CDioctl(MCI_STATUS, flags, &mci_status)) {
00121                 status = -1;
00122         } else {
00123                 switch (mci_status.dwReturn) {
00124                         case MCI_MODE_NOT_READY:
00125                         case MCI_MODE_OPEN:
00126                                 status = 0;
00127                                 break;
00128                         case MCI_MODE_STOP:
00129                                 status = 1;
00130                                 break;
00131                         case MCI_MODE_PLAY:
00132                                 status = 2;
00133                                 break;
00134                         case MCI_MODE_PAUSE:
00135                                 status = 3;
00136                                 break;
00137                         default:
00138                                 status = -1;
00139                                 break;
00140                 }
00141         }
00142 
00143         return status;
00144 }
00145 
00146 bool CDROM_Interface_Ioctl::mci_CDPosition(int *position) {
00147         *position = 0;
00148 
00149         DWORD flags = MCI_STATUS_ITEM | MCI_WAIT;
00150 
00151         MCI_STATUS_PARMS mci_status;
00152         mci_status.dwItem = MCI_STATUS_MODE;
00153         if (mci_CDioctl(MCI_STATUS, flags, &mci_status)) return true;
00154         switch (mci_status.dwReturn) {
00155                 case MCI_MODE_NOT_READY:
00156                 case MCI_MODE_OPEN:
00157                 case MCI_MODE_STOP:
00158                         return true;    // not ready/undefined status
00159                 case MCI_MODE_PLAY:
00160                 case MCI_MODE_PAUSE:
00161                         mci_status.dwItem = MCI_STATUS_POSITION;
00162                         if (!mci_CDioctl(MCI_STATUS, flags, &mci_status)) {
00163                                 *position = MSF_TO_FRAMES(
00164                                         MCI_MSF_MINUTE(mci_status.dwReturn),
00165                                         MCI_MSF_SECOND(mci_status.dwReturn),
00166                                         MCI_MSF_FRAME(mci_status.dwReturn));
00167                         }
00168                         return false;   // no error, position read
00169                 default:
00170                         break;
00171         }
00172         return false;
00173 }
00174 
00175 
00176 CDROM_Interface_Ioctl::dxPlayer CDROM_Interface_Ioctl::player = {
00177         NULL, NULL, NULL, {0}, 0, 0, 0, false, false, false, {0} };
00178 
00179 CDROM_Interface_Ioctl::CDROM_Interface_Ioctl(cdioctl_cdatype ioctl_cda) {
00180         pathname[0] = 0;
00181         hIOCTL = INVALID_HANDLE_VALUE;
00182         memset(&oldLeadOut,0,sizeof(oldLeadOut));
00183         cdioctl_cda_selected = ioctl_cda;
00184 }
00185 
00186 CDROM_Interface_Ioctl::~CDROM_Interface_Ioctl() {
00187         StopAudio();
00188         if (use_mciplay) mci_CDStop();
00189         Close();
00190         if (use_mciplay) mci_CDClose();
00191 }
00192 
00193 bool CDROM_Interface_Ioctl::GetUPC(unsigned char& attr, char* upc) {
00194         // FIXME : To Do
00195         return true;
00196 }
00197 
00198 bool CDROM_Interface_Ioctl::GetAudioTracks(int& stTrack, int& endTrack, TMSF& leadOut) {
00199         CDROM_TOC toc;
00200         DWORD   byteCount;
00201         BOOL    bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC, NULL, 0, 
00202                                                                         &toc, sizeof(toc), &byteCount,NULL);
00203         if (!bStat) return false;
00204 
00205         stTrack         = toc.FirstTrack;
00206         endTrack        = toc.LastTrack;
00207         leadOut.min = toc.TrackData[endTrack].Address[1];
00208         leadOut.sec     = toc.TrackData[endTrack].Address[2];
00209         leadOut.fr      = toc.TrackData[endTrack].Address[3];
00210 
00211         if ((use_mciplay || use_dxplay) && (!track_start_valid)) {
00212                 Bits track_num = 0;
00213                 // get track start address of all tracks
00214                 for (Bits i=toc.FirstTrack; i<=toc.LastTrack+1; i++) {
00215                         if (((toc.TrackData[i].Control&1)==0) || (i==toc.LastTrack+1)) {
00216                                 track_start[track_num] = MSF_TO_FRAMES(toc.TrackData[track_num].Address[1],toc.TrackData[track_num].Address[2],toc.TrackData[track_num].Address[3])-150;
00217                                 track_start[track_num] += 150;
00218                                 track_num++;
00219                         }
00220                 }
00221                 track_start_first = 0;
00222                 track_start_last = track_num-1;
00223                 track_start_valid = true;
00224         }
00225 
00226         return true;
00227 }
00228 
00229 bool CDROM_Interface_Ioctl::GetAudioTrackInfo(int track, TMSF& start, unsigned char& attr) {
00230         CDROM_TOC toc;
00231         DWORD   byteCount;
00232         BOOL    bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC, NULL, 0, 
00233                                                                         &toc, sizeof(toc), &byteCount,NULL);
00234         if (!bStat) return false;
00235         
00236         attr            = (toc.TrackData[track-1].Control << 4) & 0xEF;
00237         start.min       = toc.TrackData[track-1].Address[1];
00238         start.sec       = toc.TrackData[track-1].Address[2];
00239         start.fr        = toc.TrackData[track-1].Address[3];
00240         return true;
00241 }       
00242 
00243 bool CDROM_Interface_Ioctl::GetAudioTracksAll(void) {
00244         if (track_start_valid) return true;
00245 
00246         CDROM_TOC toc;
00247         DWORD   byteCount;
00248         BOOL    bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_TOC, NULL, 0, 
00249                                                                         &toc, sizeof(toc), &byteCount,NULL);
00250         if (!bStat) return false;
00251 
00252         Bits track_num = 0;
00253         // get track start address of all tracks
00254         for (Bits i=toc.FirstTrack; i<=toc.LastTrack+1; i++) {
00255                 if (((toc.TrackData[i].Control&1)==0) || (i==toc.LastTrack+1)) {
00256                         track_start[track_num] = MSF_TO_FRAMES(toc.TrackData[track_num].Address[1],toc.TrackData[track_num].Address[2],toc.TrackData[track_num].Address[3])-150;
00257                         track_start[track_num] += 150;
00258                         track_num++;
00259                 }
00260         }
00261         track_start_first = 0;
00262         track_start_last = track_num-1;
00263         track_start_valid = true;
00264         return true;
00265 }
00266 
00267 bool CDROM_Interface_Ioctl::GetAudioSub(unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos) {
00268         if (use_dxplay) {
00269                 track = 1;
00270                 FRAMES_TO_MSF(player.currFrame + 150, &absPos.min, &absPos.sec, &absPos.fr);
00271                 FRAMES_TO_MSF(player.currFrame + 150, &relPos.min, &relPos.sec, &relPos.fr);
00272 
00273                 if (GetAudioTracksAll()) {
00274                         // get track number from current frame
00275                         for (int i=track_start_first; i<=track_start_last; i++) {
00276                                 if ((player.currFrame + 150<track_start[i+1]) && (player.currFrame + 150>=track_start[i])) {
00277                                         // track found, calculate relative position
00278                                         track = i;
00279                                         FRAMES_TO_MSF(player.currFrame + 150-track_start[i],&relPos.min,&relPos.sec,&relPos.fr);
00280                                         break;
00281                                 }
00282                         }
00283                 }
00284 
00285                 return true;
00286         }
00287 
00288         CDROM_SUB_Q_DATA_FORMAT insub;
00289         SUB_Q_CHANNEL_DATA sub;
00290         DWORD   byteCount;
00291 
00292         insub.Format = IOCTL_CDROM_CURRENT_POSITION;
00293 
00294         BOOL    bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_Q_CHANNEL, &insub, sizeof(insub), 
00295                                                                         &sub, sizeof(sub), &byteCount,NULL);
00296         if (!bStat) return false;
00297 
00298         attr            = (sub.CurrentPosition.Control << 4) & 0xEF;
00299         track           = sub.CurrentPosition.TrackNumber;
00300         index           = sub.CurrentPosition.IndexNumber;
00301         relPos.min      = sub.CurrentPosition.TrackRelativeAddress[1];
00302         relPos.sec      = sub.CurrentPosition.TrackRelativeAddress[2];
00303         relPos.fr       = sub.CurrentPosition.TrackRelativeAddress[3];
00304         absPos.min      = sub.CurrentPosition.AbsoluteAddress[1];
00305         absPos.sec      = sub.CurrentPosition.AbsoluteAddress[2];
00306         absPos.fr       = sub.CurrentPosition.AbsoluteAddress[3];
00307 
00308         if (use_mciplay) {
00309                 int cur_pos;
00310                 if (!mci_CDPosition(&cur_pos)) {
00311                         // absolute position read, try to calculate the track-relative position
00312                         if (GetAudioTracksAll()) {
00313                                 for (int i=track_start_first; i<=track_start_last; i++) {
00314                                         if ((cur_pos<track_start[i+1]) && (cur_pos>=track_start[i])) {
00315                                                 // track found, calculate relative position
00316                                                 FRAMES_TO_MSF(cur_pos-track_start[i],&relPos.min,&relPos.sec,&relPos.fr);
00317                                                 break;
00318                                         }
00319                                 }
00320                         }
00321                         FRAMES_TO_MSF(cur_pos,&absPos.min,&absPos.sec,&absPos.fr);
00322                 }
00323         }
00324 
00325         return true;
00326 }
00327 
00328 bool CDROM_Interface_Ioctl::GetAudioStatus(bool& playing, bool& pause) {
00329         if (use_mciplay) {
00330                 int status = mci_CDStatus();
00331                 if (status<0) return false;
00332                 playing = (status==2);
00333                 pause   = (status==3);
00334                 return true;
00335         }
00336         if (use_dxplay) {
00337                 playing = player.isPlaying;
00338                 pause = player.isPaused;
00339                 return true;
00340         }
00341 
00342         CDROM_SUB_Q_DATA_FORMAT insub;
00343         SUB_Q_CHANNEL_DATA sub;
00344         DWORD byteCount;
00345 
00346         insub.Format = IOCTL_CDROM_CURRENT_POSITION;
00347 
00348         BOOL    bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_READ_Q_CHANNEL, &insub, sizeof(insub), 
00349                                                                         &sub, sizeof(sub), &byteCount,NULL);
00350         if (!bStat) return false;
00351 
00352         playing = (sub.CurrentPosition.Header.AudioStatus == AUDIO_STATUS_IN_PROGRESS);
00353         pause   = (sub.CurrentPosition.Header.AudioStatus == AUDIO_STATUS_PAUSED);
00354 
00355         return true;
00356 }
00357 
00358 bool CDROM_Interface_Ioctl::GetMediaTrayStatus(bool& mediaPresent, bool& mediaChanged, bool& trayOpen) {
00359         // Seems not possible to get this values using ioctl...
00360         int             track1,track2;
00361         TMSF    leadOut;
00362         // If we can read, there's a media
00363         mediaPresent = GetAudioTracks(track1, track2, leadOut),
00364         trayOpen         = !mediaPresent;
00365         mediaChanged = (oldLeadOut.min!=leadOut.min) || (oldLeadOut.sec!=leadOut.sec) || (oldLeadOut.fr!=leadOut.fr);
00366         if (mediaChanged) {
00367                 Close();
00368                 if (use_mciplay) mci_CDClose();
00369                 // Open new medium
00370                 Open();
00371 
00372                 if (cdioctl_cda_selected == CDIOCTL_CDA_MCI) {
00373                         // check this (what to do if cd is ejected):
00374                         use_mciplay = false;
00375                         if (!mci_CDOpen(pathname[4])) use_mciplay = true;
00376                 }
00377                 track_start_valid = false;
00378         }
00379         // Save old values
00380         oldLeadOut.min = leadOut.min;
00381         oldLeadOut.sec = leadOut.sec;
00382         oldLeadOut.fr  = leadOut.fr;
00383         // always success
00384         return true;
00385 }
00386 
00387 bool CDROM_Interface_Ioctl::PlayAudioSector     (unsigned long start,unsigned long len) {
00388         if (use_mciplay) {
00389                 if (!mci_CDPlay(start+150, len))        return true;
00390                 if (!mci_CDPlay(start+150, len-1))      return true;
00391                 return false;
00392         }
00393         if (use_dxplay) {
00394                 SDL_mutexP(player.mutex);
00395                 player.cd = this;
00396                 player.currFrame = start;
00397                 player.targetFrame = start + len;
00398                 player.isPlaying = true;
00399                 player.isPaused = false;
00400                 SDL_mutexV(player.mutex);
00401                 return true;
00402         }
00403 
00404         CDROM_PLAY_AUDIO_MSF audio;
00405         DWORD   byteCount;
00406         // Start
00407         unsigned long addr      = start + 150;
00408         audio.StartingF = (UCHAR)(addr%75); addr/=75;
00409         audio.StartingS = (UCHAR)(addr%60); 
00410         audio.StartingM = (UCHAR)(addr/60);
00411         // End
00412         addr                    = start + len + 150;
00413         audio.EndingF   = (UCHAR)(addr%75); addr/=75;
00414         audio.EndingS   = (UCHAR)(addr%60); 
00415         audio.EndingM   = (UCHAR)(addr/60);
00416 
00417         BOOL    bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_PLAY_AUDIO_MSF, &audio, sizeof(audio), 
00418                                                                         NULL, 0, &byteCount,NULL);
00419         return bStat>0;
00420 }
00421 
00422 bool CDROM_Interface_Ioctl::PauseAudio(bool resume) {
00423         if (use_mciplay) {
00424                 if (resume) {
00425                         if (!mci_CDResume()) return true;
00426                 } else {
00427                         if (!mci_CDPause()) return true;
00428                 }
00429                 return false;
00430         }
00431         if (use_dxplay) {
00432                 player.isPaused = !resume;
00433                 return true;
00434         }
00435 
00436         BOOL bStat; 
00437         DWORD byteCount;
00438         if (resume) bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_RESUME_AUDIO, NULL, 0, 
00439                                                                                 NULL, 0, &byteCount,NULL);      
00440         else            bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_PAUSE_AUDIO, NULL, 0, 
00441                                                                                 NULL, 0, &byteCount,NULL);
00442         return bStat>0;
00443 }
00444 
00445 bool CDROM_Interface_Ioctl::StopAudio(void) {
00446         if (use_mciplay) {
00447                 if (!mci_CDStop()) return true;
00448                 return false;
00449         }
00450         if (use_dxplay) {
00451                 player.isPlaying = false;
00452                 player.isPaused = false;
00453                 return true;
00454         }
00455 
00456         BOOL bStat; 
00457         DWORD byteCount;
00458         bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_STOP_AUDIO, NULL, 0, 
00459                                                         NULL, 0, &byteCount,NULL);      
00460         return bStat>0;
00461 }
00462 
00463 void CDROM_Interface_Ioctl::ChannelControl(TCtrl ctrl)
00464 {
00465         player.ctrlUsed = (ctrl.out[0]!=0 || ctrl.out[1]!=1 || ctrl.vol[0]<0xfe || ctrl.vol[1]<0xfe);
00466         player.ctrlData = ctrl;
00467 }
00468 
00469 bool CDROM_Interface_Ioctl::LoadUnloadMedia(bool unload) {
00470         BOOL bStat; 
00471         DWORD byteCount;
00472         if (unload) bStat = DeviceIoControl(hIOCTL,IOCTL_STORAGE_EJECT_MEDIA, NULL, 0, 
00473                                                                                 NULL, 0, &byteCount,NULL);      
00474         else            bStat = DeviceIoControl(hIOCTL,IOCTL_STORAGE_LOAD_MEDIA, NULL, 0, 
00475                                                                                 NULL, 0, &byteCount,NULL);      
00476         track_start_valid = false;
00477         return bStat>0;
00478 }
00479 
00480 bool CDROM_Interface_Ioctl::ReadSector(Bit8u *buffer, bool raw, unsigned long sector) {
00481         BOOL  bStat;
00482         DWORD byteCount = 0;
00483 
00484         Bitu    buflen  = raw ? RAW_SECTOR_SIZE : COOKED_SECTOR_SIZE;
00485 
00486         if (!raw) {
00487                 // Cooked
00488                 int       success = 0;
00489                 DWORD newPos  = SetFilePointer(hIOCTL, sector*COOKED_SECTOR_SIZE, 0, FILE_BEGIN);
00490                 if (newPos != 0xFFFFFFFF) success = ReadFile(hIOCTL, buffer, buflen, &byteCount, NULL);
00491                 bStat = (success!=0);
00492         } else {
00493                 // Raw
00494                 RAW_READ_INFO in;
00495                 in.DiskOffset.LowPart   = sector*COOKED_SECTOR_SIZE;
00496                 in.DiskOffset.HighPart  = 0;
00497                 in.SectorCount                  = 1;
00498                 in.TrackMode                    = CDDA;         
00499                 bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_RAW_READ, &in, sizeof(in), 
00500                                                                 buffer, buflen, &byteCount,NULL);
00501         }
00502 
00503         return (byteCount==buflen) && (bStat>0);
00504 }
00505 
00506 bool CDROM_Interface_Ioctl::ReadSectors(PhysPt buffer, bool raw, unsigned long sector, unsigned long num) {
00507         BOOL  bStat;
00508         DWORD byteCount = 0;
00509 
00510         Bitu    buflen  = raw ? num*RAW_SECTOR_SIZE : num*COOKED_SECTOR_SIZE;
00511         Bit8u*  bufdata = new Bit8u[buflen];
00512 
00513         if (!raw) {
00514                 // Cooked
00515                 int       success = 0;
00516                 DWORD newPos  = SetFilePointer(hIOCTL, sector*COOKED_SECTOR_SIZE, 0, FILE_BEGIN);
00517                 if (newPos != 0xFFFFFFFF) success = ReadFile(hIOCTL, bufdata, buflen, &byteCount, NULL);
00518                 bStat = (success!=0);
00519         } else {
00520                 // Raw
00521                 RAW_READ_INFO in;
00522                 in.DiskOffset.LowPart   = sector*COOKED_SECTOR_SIZE;
00523                 in.DiskOffset.HighPart  = 0;
00524                 in.SectorCount                  = num;
00525                 in.TrackMode                    = CDDA;         
00526                 bStat = DeviceIoControl(hIOCTL,IOCTL_CDROM_RAW_READ, &in, sizeof(in), 
00527                                                                 bufdata, buflen, &byteCount,NULL);
00528         }
00529 
00530         MEM_BlockWrite(buffer,bufdata,buflen);
00531         delete[] bufdata;
00532 
00533         return (byteCount==buflen) && (bStat>0);
00534 }
00535 
00536 void CDROM_Interface_Ioctl::dx_CDAudioCallBack(Bitu len) {
00537         len *= 4;       // 16 bit, stereo
00538         if (!len) return;
00539         if (!player.isPlaying || player.isPaused) {
00540                 player.channel->AddSilence();
00541                 return;
00542         }
00543         SDL_mutexP(player.mutex);
00544         while (player.bufLen < (Bits)len) {
00545                 bool success;
00546                 if (player.targetFrame > player.currFrame)
00547                         success = player.cd->ReadSector(&player.buffer[player.bufLen], true, player.currFrame);
00548                 else success = false;
00549                 
00550                 if (success) {
00551                         player.currFrame++;
00552                         player.bufLen += RAW_SECTOR_SIZE;
00553                 } else {
00554                         memset(&player.buffer[player.bufLen], 0, len - player.bufLen);
00555                         player.bufLen = len;
00556                         player.isPlaying = false;
00557                 }
00558         }
00559         SDL_mutexV(player.mutex);
00560         if (player.ctrlUsed) {
00561                 Bit16s sample0,sample1;
00562                 Bit16s * samples=(Bit16s *)&player.buffer;
00563                 for (Bitu pos=0;pos<len/4;pos++) {
00564                         sample0=samples[pos*2+player.ctrlData.out[0]];
00565                         sample1=samples[pos*2+player.ctrlData.out[1]];
00566                         samples[pos*2+0]=(Bit16s)(sample0*player.ctrlData.vol[0]/255.0);
00567                         samples[pos*2+1]=(Bit16s)(sample1*player.ctrlData.vol[1]/255.0);
00568                 }
00569         }
00570         player.channel->AddSamples_s16(len/4,(Bit16s *)player.buffer);
00571         memmove(player.buffer, &player.buffer[len], player.bufLen - len);
00572         player.bufLen -= len;
00573 }
00574 
00575 bool CDROM_Interface_Ioctl::SetDevice(char* path, int forceCD) {
00576         mci_devid = 0;
00577         use_mciplay = false;
00578         use_dxplay = false;
00579         track_start_valid = false;
00580         if (GetDriveType(path)==DRIVE_CDROM) {
00581                 char letter [3] = { 0, ':', 0 };
00582                 letter[0] = path[0];
00583                 strcpy(pathname,"\\\\.\\");
00584                 strcat(pathname,letter);
00585                 if (Open()) {
00586                         if (cdioctl_cda_selected == CDIOCTL_CDA_MCI) {
00587                                 // check if MCI-interface can be used for cd audio
00588                                 if (!mci_CDOpen(path[0])) use_mciplay = true;
00589                         }
00590                         if (!use_mciplay) {
00591                                 if (cdioctl_cda_selected == CDIOCTL_CDA_DX) {
00592                                         // use direct sector access for cd audio routines
00593                                         player.mutex = SDL_CreateMutex();
00594                                         if (!player.channel) {
00595                                                 player.channel = MIXER_AddChannel(&dx_CDAudioCallBack, 44100, "CDAUDIO");
00596                                         }
00597                                         player.channel->Enable(true);
00598                                         use_dxplay = true;
00599                                 }
00600                         }
00601                         return true;
00602                 };
00603         }
00604         return false;
00605 }
00606 
00607 bool CDROM_Interface_Ioctl::Open(void) {
00608         hIOCTL  = CreateFile(pathname,                  // drive to open
00609                                                 GENERIC_READ,           // read access
00610                                                 FILE_SHARE_READ |       // share mode
00611                                                 FILE_SHARE_WRITE, 
00612                                                 NULL,                           // default security attributes
00613                                                 OPEN_EXISTING,          // disposition
00614                                                 0,                                      // file attributes
00615                                                 NULL);                          // do not copy file attributes
00616         return (hIOCTL!=INVALID_HANDLE_VALUE);
00617 }
00618 
00619 void CDROM_Interface_Ioctl::Close(void) {
00620         CloseHandle(hIOCTL);
00621 }
00622 
00623 bool CDROM_Interface_Ioctl::ReadSectorsHost(void *buffer, bool raw, unsigned long sector, unsigned long num)
00624 {
00625         return false;/*TODO*/
00626 };
00627 
00628 #endif