src/cdrom/macos/SDL_syscdrom.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. LMGetUnitTableEntryCount
  2. SDL_SYS_ShortToBCD
  3. SDL_SYS_BCDToShort
  4. SDL_SYS_CDInit
  5. SDL_SYS_CDName
  6. get_drivenum
  7. SDL_SYS_CDOpen
  8. SDL_SYS_CDGetTOC
  9. SDL_SYS_CDStatus
  10. SDL_SYS_CDPlay
  11. SDL_SYS_CDPause
  12. SDL_SYS_CDResume
  13. SDL_SYS_CDStop
  14. SDL_SYS_CDEject
  15. SDL_SYS_CDClose
  16. SDL_SYS_CDQuit

   1 /*
   2     SDL - Simple DirectMedia Layer
   3     Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
   4 
   5     This library is free software; you can redistribute it and/or
   6     modify it under the terms of the GNU Library General Public
   7     License as published by the Free Software Foundation; either
   8     version 2 of the License, or (at your option) any later version.
   9 
  10     This library is distributed in the hope that it will be useful,
  11     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13     Library General Public License for more details.
  14 
  15     You should have received a copy of the GNU Library General Public
  16     License along with this library; if not, write to the Free
  17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18 
  19     Sam Lantinga
  20     slouken@devolution.com
  21 */
  22 
  23 #ifdef SAVE_RCSID
  24 static char rcsid =
  25  "@(#) $Id: SDL_syscdrom.c,v 1.3.2.6 2001/02/28 12:17:11 hercules Exp $";
  26 #endif
  27 
  28 /* MacOS functions for system-level CD-ROM audio control */
  29 
  30 #include <Devices.h>
  31 #include <Files.h>
  32 #include <LowMem.h> /* Use entry table macros, not functions in InterfaceLib  */
  33 
  34 #include "SDL_cdrom.h"
  35 #include "SDL_syscdrom.h"
  36 #include "SDL_syscdrom_c.h"
  37 
  38 /* Added by Matt Slot */
  39 #if !defined(LMGetUnitTableEntryCount)
  40   #define LMGetUnitTableEntryCount()   *(short *)0x01D2
     /* [<][>][^][v][top][bottom][index][help] */
  41 #endif
  42 
  43 /* The maximum number of CD-ROM drives we'll detect */
  44 #define MAX_DRIVES      26      
  45 
  46 /* A list of available CD-ROM drives */
  47 static long SDL_cdversion = 0;
  48 static struct {
  49         short           dRefNum;
  50         short           driveNum;
  51         long            frames;
  52         char            name[256];
  53         Boolean         hasAudio;
  54         } SDL_cdlist[MAX_DRIVES];
  55 static StringPtr gDriverName = "\p.AppleCD";
  56 
  57 /* The system-dependent CD control functions */
  58 static const char *SDL_SYS_CDName(int drive);
  59 static int SDL_SYS_CDOpen(int drive);
  60 static int SDL_SYS_CDGetTOC(SDL_CD *cdrom);
  61 static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position);
  62 static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length);
  63 static int SDL_SYS_CDPause(SDL_CD *cdrom);
  64 static int SDL_SYS_CDResume(SDL_CD *cdrom);
  65 static int SDL_SYS_CDStop(SDL_CD *cdrom);
  66 static int SDL_SYS_CDEject(SDL_CD *cdrom);
  67 static void SDL_SYS_CDClose(SDL_CD *cdrom);
  68 
  69 static short SDL_SYS_ShortToBCD(short value)
     /* [<][>][^][v][top][bottom][index][help] */
  70 {
  71         return((value % 10) + (value / 10) * 0x10); /* Convert value to BCD */
  72 }
  73 
  74 static short SDL_SYS_BCDToShort(short value)
     /* [<][>][^][v][top][bottom][index][help] */
  75 {
  76         return((value % 0x10) + (value / 0x10) * 10); /* Convert value from BCD */
  77 }
  78 
  79 int  SDL_SYS_CDInit(void)
     /* [<][>][^][v][top][bottom][index][help] */
  80 {
  81         SInt16                  dRefNum = 0;
  82         SInt16                  first, last;
  83 
  84         SDL_numcds = 0;
  85 
  86         /* Check that the software is available */
  87         if (Gestalt(kGestaltAudioCDSelector, &SDL_cdversion) || 
  88                         !SDL_cdversion) return(0);
  89 
  90         /* Fill in our driver capabilities */
  91         SDL_CDcaps.Name = SDL_SYS_CDName;
  92         SDL_CDcaps.Open = SDL_SYS_CDOpen;
  93         SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
  94         SDL_CDcaps.Status = SDL_SYS_CDStatus;
  95         SDL_CDcaps.Play = SDL_SYS_CDPlay;
  96         SDL_CDcaps.Pause = SDL_SYS_CDPause;
  97         SDL_CDcaps.Resume = SDL_SYS_CDResume;
  98         SDL_CDcaps.Stop = SDL_SYS_CDStop;
  99         SDL_CDcaps.Eject = SDL_SYS_CDEject;
 100         SDL_CDcaps.Close = SDL_SYS_CDClose;
 101 
 102         /* Walk the list, count each AudioCD driver, and save the refnums */
 103         first = -1;
 104         last = 0 - LMGetUnitTableEntryCount();
 105         for(dRefNum = first; dRefNum >= last; dRefNum--) {
 106                 Str255          driverName;
 107                 StringPtr       namePtr;
 108                 DCtlHandle      deviceEntry;
 109 
 110                 deviceEntry = GetDCtlEntry(dRefNum);
 111                 if (! deviceEntry) continue;
 112                 
 113                 /* Is this an .AppleCD ? */
 114                 namePtr = (*deviceEntry)->dCtlFlags & (1L << dRAMBased) ?
 115                                 ((StringPtr) ((DCtlPtr) deviceEntry)->dCtlDriver + 18) :
 116                                 ((StringPtr) (*deviceEntry)->dCtlDriver + 18);
 117                 BlockMoveData(namePtr, driverName, namePtr[0]+1);
 118                 if (driverName[0] > gDriverName[0]) driverName[0] = gDriverName[0];
 119                 if (! EqualString(driverName, gDriverName, false, false)) continue;
 120 
 121                 /* Record the basic info for each drive */
 122                 SDL_cdlist[SDL_numcds].dRefNum = dRefNum;
 123                 BlockMoveData(namePtr + 1, SDL_cdlist[SDL_numcds].name, namePtr[0]);
 124                 SDL_cdlist[SDL_numcds].name[namePtr[0]] = 0;
 125                 SDL_cdlist[SDL_numcds].hasAudio = false;
 126                 SDL_numcds++;
 127         }
 128         return(0);
 129 }
 130 
 131 static const char *SDL_SYS_CDName(int drive)
     /* [<][>][^][v][top][bottom][index][help] */
 132 {
 133         return(SDL_cdlist[drive].name);
 134 }
 135 
 136 static int get_drivenum(int drive)
     /* [<][>][^][v][top][bottom][index][help] */
 137 {
 138         QHdr *driveQ = GetDrvQHdr();
 139         DrvQEl *driveElem;
 140 
 141         /* Update the drive number */
 142         SDL_cdlist[drive].driveNum = 0;
 143         if ( driveQ->qTail ) {
 144                 driveQ->qTail->qLink = 0;
 145         }
 146         for ( driveElem=(DrvQEl *)driveQ->qHead; driveElem;
 147               driveElem = (DrvQEl *)driveElem->qLink ) {
 148                 if ( driveElem->dQRefNum == SDL_cdlist[drive].dRefNum ) {
 149                         SDL_cdlist[drive].driveNum = driveElem->dQDrive;
 150                         break;
 151                 }
 152         }
 153         return(SDL_cdlist[drive].driveNum);
 154 }
 155 
 156 static int SDL_SYS_CDOpen(int drive)
     /* [<][>][^][v][top][bottom][index][help] */
 157 {
 158         return(drive);
 159 }
 160 
 161 static int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
     /* [<][>][^][v][top][bottom][index][help] */
 162 {
 163         CDCntrlParam            cdpb;
 164         CDTrackData                     tracks[SDL_MAX_TRACKS];
 165         long                            i, leadout;
 166 
 167         /* Get the number of tracks on the CD by examining the TOC */
 168         memset(&cdpb, 0, sizeof(cdpb));
 169         cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum;
 170         cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
 171         cdpb.csCode = kReadTOC;
 172         cdpb.csParam.words[0] = kGetTrackRange;
 173         if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) {
 174                 SDL_SetError("PBControlSync() failed");
 175                 return(-1);
 176         }
 177 
 178         cdrom->numtracks = 
 179                         SDL_SYS_BCDToShort(cdpb.csParam.bytes[1]) - 
 180                         SDL_SYS_BCDToShort(cdpb.csParam.bytes[0]) + 1;
 181         if ( cdrom->numtracks > SDL_MAX_TRACKS )
 182                 cdrom->numtracks = SDL_MAX_TRACKS;
 183         cdrom->status = CD_STOPPED;
 184         cdrom->cur_track = 0; /* Apparently these are set elsewhere */
 185         cdrom->cur_frame = 0; /* Apparently these are set elsewhere */
 186 
 187 
 188         /* Get the lead out area of the CD by examining the TOC */
 189         memset(&cdpb, 0, sizeof(cdpb));
 190         cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum;
 191         cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
 192         cdpb.csCode = kReadTOC;
 193         cdpb.csParam.words[0] = kGetLeadOutArea;
 194         if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) {
 195                 SDL_SetError("PBControlSync() failed");
 196                 return(-1);
 197         }
 198 
 199         leadout = MSF_TO_FRAMES(
 200                         SDL_SYS_BCDToShort(cdpb.csParam.bytes[0]),
 201                         SDL_SYS_BCDToShort(cdpb.csParam.bytes[1]),
 202                         SDL_SYS_BCDToShort(cdpb.csParam.bytes[2]));
 203 
 204         /* Get an array of track locations by examining the TOC */
 205         memset(tracks, 0, sizeof(tracks));
 206         memset(&cdpb, 0, sizeof(cdpb));
 207         cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum;
 208         cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
 209         cdpb.csCode = kReadTOC;
 210         cdpb.csParam.words[0] = kGetTrackEntries;       /* Type of Query */
 211         * ((long *) (cdpb.csParam.words+1)) = (long) tracks;                            
 212         cdpb.csParam.words[3] = cdrom->numtracks * sizeof(tracks[0]);           
 213         * ((char *) (cdpb.csParam.words+4)) = 1;        /* First track */
 214         if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) {
 215                 SDL_SetError("PBControlSync() failed");
 216                 return(-1);
 217         }
 218 
 219         /* Read all the track TOC entries */
 220         SDL_cdlist[cdrom->id].hasAudio = false;
 221         for ( i=0; i<cdrom->numtracks; ++i ) 
 222                 {
 223                 cdrom->track[i].id = i+1;
 224                 if (tracks[i].entry.control & kDataTrackMask)
 225                         cdrom->track[i].type = SDL_DATA_TRACK;
 226                 else
 227                         {
 228                         cdrom->track[i].type = SDL_AUDIO_TRACK;
 229                         SDL_cdlist[SDL_numcds].hasAudio = true;
 230                         }
 231                 
 232                 cdrom->track[i].offset = MSF_TO_FRAMES(
 233                                 SDL_SYS_BCDToShort(tracks[i].entry.min),
 234                                 SDL_SYS_BCDToShort(tracks[i].entry.min),
 235                                 SDL_SYS_BCDToShort(tracks[i].entry.frame));
 236                 cdrom->track[i].length = MSF_TO_FRAMES(
 237                                 SDL_SYS_BCDToShort(tracks[i+1].entry.min),
 238                                 SDL_SYS_BCDToShort(tracks[i+1].entry.min),
 239                                 SDL_SYS_BCDToShort(tracks[i+1].entry.frame)) -
 240                                 cdrom->track[i].offset;
 241                 }
 242         
 243         /* Apparently SDL wants a fake last entry */
 244         cdrom->track[i].offset = leadout;
 245         cdrom->track[i].length = 0;
 246 
 247         return(0);
 248 }
 249 
 250 /* Get CD-ROM status */
 251 static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position)
     /* [<][>][^][v][top][bottom][index][help] */
 252 {
 253         CDCntrlParam cdpb;
 254         CDstatus status = CD_ERROR;
 255         Boolean spinning = false;
 256 
 257         if (position) *position = 0;
 258 
 259         /* Get the number of tracks on the CD by examining the TOC */
 260         if ( ! get_drivenum(cdrom->id) ) {
 261                 return(CD_TRAYEMPTY);
 262         }
 263         memset(&cdpb, 0, sizeof(cdpb));
 264         cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum;
 265         cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
 266         cdpb.csCode = kReadTOC;
 267         cdpb.csParam.words[0] = kGetTrackRange;
 268         if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) {
 269                 SDL_SetError("PBControlSync() failed");
 270                 return(CD_ERROR);
 271         }
 272 
 273         cdrom->numtracks = 
 274                         SDL_SYS_BCDToShort(cdpb.csParam.bytes[1]) - 
 275                         SDL_SYS_BCDToShort(cdpb.csParam.bytes[0]) + 1;
 276         if ( cdrom->numtracks > SDL_MAX_TRACKS )
 277                 cdrom->numtracks = SDL_MAX_TRACKS;
 278         cdrom->cur_track = 0; /* Apparently these are set elsewhere */
 279         cdrom->cur_frame = 0; /* Apparently these are set elsewhere */
 280 
 281 
 282         if (1 || SDL_cdlist[cdrom->id].hasAudio) {
 283                 /* Get the current playback status */
 284                 memset(&cdpb, 0, sizeof(cdpb));
 285                 cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum;
 286                 cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
 287                 cdpb.csCode = kAudioStatus;
 288                 if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) {
 289                         SDL_SetError("PBControlSync() failed");
 290                         return(-1);
 291                 }
 292         
 293                 switch(cdpb.csParam.cd.status) {
 294                         case kStatusPlaying:
 295                                 status = CD_PLAYING;
 296                                 spinning = true;
 297                                 break;
 298                         case kStatusPaused:
 299                                 status = CD_PAUSED;
 300                                 spinning = true;
 301                                 break;
 302                         case kStatusMuted:
 303                                 status = CD_PLAYING; /* What should I do here? */
 304                                 spinning = true;
 305                                 break;
 306                         case kStatusDone:
 307                                 status = CD_STOPPED;
 308                                 spinning = true;
 309                                 break;
 310                         case kStatusStopped:
 311                                 status = CD_STOPPED;
 312                                 spinning = false;
 313                                 break;
 314                         case kStatusError:
 315                         default:
 316                                 status = CD_ERROR;
 317                                 spinning = false;
 318                                 break;
 319                         }
 320 
 321                 if (spinning && position) *position = MSF_TO_FRAMES(
 322                                 SDL_SYS_BCDToShort(cdpb.csParam.cd.minute),
 323                                 SDL_SYS_BCDToShort(cdpb.csParam.cd.second),
 324                                 SDL_SYS_BCDToShort(cdpb.csParam.cd.frame));
 325                 }
 326         else
 327                 status = CD_ERROR; /* What should I do here? */
 328 
 329         return(status);
 330 }
 331 
 332 /* Start play */
 333 static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
     /* [<][>][^][v][top][bottom][index][help] */
 334 {
 335         CDCntrlParam cdpb;
 336 
 337         /* Pause the current audio playback to avoid audible artifacts */
 338         if ( SDL_SYS_CDPause(cdrom) < 0 ) {
 339                 return(-1);
 340         }
 341 
 342         /* Specify the AudioCD playback mode */
 343         memset(&cdpb, 0, sizeof(cdpb));
 344         cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum;
 345         cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
 346         cdpb.csCode = kSetPlayMode;
 347         cdpb.csParam.bytes[0] = false;                  /* Repeat? */
 348         cdpb.csParam.bytes[1] = kPlayModeSequential;    /* Play mode */
 349         /* ¥¥¥ÊTreat as soft error, NEC Drive doesnt support this call ¥¥¥ */
 350         PBControlSync((ParmBlkPtr) &cdpb);
 351 
 352 #if 1
 353         /* Specify the end of audio playback */
 354         memset(&cdpb, 0, sizeof(cdpb));
 355         cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum;
 356         cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
 357         cdpb.csCode = kAudioStop;
 358         cdpb.csParam.words[0] = kBlockPosition;         /* Position Mode */
 359         *(long *) (cdpb.csParam.words + 1) = start+length-1; /* Search Address */
 360         if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) {
 361                 SDL_SetError("PBControlSync() failed");
 362                 return(-1);
 363         }
 364 
 365         /* Specify the start of audio playback, and start it */
 366         memset(&cdpb, 0, sizeof(cdpb));
 367         cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum;
 368         cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
 369         cdpb.csCode = kAudioPlay;
 370         cdpb.csParam.words[0] = kBlockPosition;                 /* Position Mode */
 371         *(long *) (cdpb.csParam.words + 1) = start+1;   /* Search Address */
 372         cdpb.csParam.words[3] = false;                                  /* Stop address? */
 373         cdpb.csParam.words[4] = kStereoPlayMode;                /* Audio Play Mode */
 374         if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) {
 375                 SDL_SetError("PBControlSync() failed");
 376                 return(-1);
 377         }
 378 #else
 379         /* Specify the end of audio playback */
 380         FRAMES_TO_MSF(start+length, &m, &s, &f);
 381         memset(&cdpb, 0, sizeof(cdpb));
 382         cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum;
 383         cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
 384         cdpb.csCode = kAudioStop;
 385         cdpb.csParam.words[0] = kTrackPosition;                 /* Position Mode */
 386         cdpb.csParam.words[1] = 0;                                              /* Search Address (hiword)*/
 387         cdpb.csParam.words[2] =                                                 /* Search Address (loword)*/
 388                         SDL_SYS_ShortToBCD(cdrom->numtracks);   
 389         if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) {
 390                 SDL_SetError("PBControlSync() failed");
 391                 return(-1);
 392         }
 393 
 394         /* Specify the start of audio playback, and start it */
 395         FRAMES_TO_MSF(start, &m, &s, &f);
 396         memset(&cdpb, 0, sizeof(cdpb));
 397         cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum;
 398         cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
 399         cdpb.csCode = kAudioPlay;
 400         cdpb.csParam.words[0] = kTrackPosition;                 /* Position Mode */
 401         cdpb.csParam.words[1] = 0;                                              /* Search Address (hiword)*/
 402         cdpb.csParam.words[2] = SDL_SYS_ShortToBCD(1);  /* Search Address (loword)*/
 403         cdpb.csParam.words[3] = false;                                  /* Stop address? */
 404         cdpb.csParam.words[4] = kStereoPlayMode;                /* Audio Play Mode */
 405         if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) {
 406                 SDL_SetError("PBControlSync() failed");
 407                 return(-1);
 408         }
 409 #endif
 410 
 411         return(0);
 412 }
 413 
 414 /* Pause play */
 415 static int SDL_SYS_CDPause(SDL_CD *cdrom)
     /* [<][>][^][v][top][bottom][index][help] */
 416 {
 417         CDCntrlParam cdpb;
 418 
 419         memset(&cdpb, 0, sizeof(cdpb));
 420         cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum;
 421         cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
 422         cdpb.csCode = kAudioPause;
 423         cdpb.csParam.words[0] = 0;      /* Pause/Continue Flag (hiword) */
 424         cdpb.csParam.words[1] = 1;      /* Pause/Continue Flag (loword) */
 425         if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) {
 426                 SDL_SetError("PBControlSync() failed");
 427                 return(-1);
 428         }
 429         return(0);
 430 }
 431 
 432 /* Resume play */
 433 static int SDL_SYS_CDResume(SDL_CD *cdrom)
     /* [<][>][^][v][top][bottom][index][help] */
 434 {
 435         CDCntrlParam cdpb;
 436 
 437         memset(&cdpb, 0, sizeof(cdpb));
 438         cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum;
 439         cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
 440         cdpb.csCode = kAudioPause;
 441         cdpb.csParam.words[0] = 0;      /* Pause/Continue Flag (hiword) */
 442         cdpb.csParam.words[1] = 0;      /* Pause/Continue Flag (loword) */
 443         if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) {
 444                 SDL_SetError("PBControlSync() failed");
 445                 return(-1);
 446         }
 447         return(0);
 448 }
 449 
 450 /* Stop play */
 451 static int SDL_SYS_CDStop(SDL_CD *cdrom)
     /* [<][>][^][v][top][bottom][index][help] */
 452 {
 453         CDCntrlParam cdpb;
 454 
 455         memset(&cdpb, 0, sizeof(cdpb));
 456         cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum;
 457         cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
 458         cdpb.csCode = kAudioStop;
 459         cdpb.csParam.words[0] = 0;              /* Position Mode */
 460         cdpb.csParam.words[1] = 0;              /* Search Address (hiword) */
 461         cdpb.csParam.words[2] = 0;              /* Search Address (loword) */
 462         if ( PBControlSync((ParmBlkPtr)&cdpb) != noErr ) {
 463                 SDL_SetError("PBControlSync() failed");
 464                 return(-1);
 465         }
 466         return(0);
 467 }
 468 
 469 /* Eject the CD-ROM */
 470 static int SDL_SYS_CDEject(SDL_CD *cdrom)
     /* [<][>][^][v][top][bottom][index][help] */
 471 {
 472         Boolean disk = false;
 473         QHdr *driveQ = GetDrvQHdr();
 474         DrvQEl *driveElem;
 475         HParamBlockRec hpb;
 476         ParamBlockRec cpb;
 477 
 478         for ( driveElem = (DrvQEl *) driveQ->qHead; driveElem; driveElem = 
 479                           (driveElem) ? ((DrvQEl *) driveElem->qLink) : 
 480                           ((DrvQEl *) driveQ->qHead) ) {
 481                 if ( driveQ->qTail ) {
 482                         driveQ->qTail->qLink = 0;
 483                 }
 484                 if ( driveElem->dQRefNum != SDL_cdlist[cdrom->id].dRefNum ) {
 485                         continue;
 486                 }
 487         
 488                 /* Does drive contain mounted volume? If not, skip */
 489                 memset(&hpb, 0, sizeof(hpb));
 490                 hpb.volumeParam.ioVRefNum = driveElem->dQDrive;
 491                 if ( PBHGetVInfoSync(&hpb) != noErr ) {
 492                         continue;
 493                 }
 494                 if ( (UnmountVol(0, driveElem->dQDrive) == noErr) && 
 495                      (Eject(0, driveElem->dQDrive) == noErr) ) {
 496                         driveElem = 0; /* Clear pointer to reset our loop */
 497                         disk = true;
 498                 }
 499         }
 500 
 501         /* If no disk is present, just eject the tray */
 502         if (! disk) {
 503                 memset(&cpb, 0, sizeof(cpb));
 504                 cpb.cntrlParam.ioVRefNum = 0; /* No Drive */
 505                 cpb.cntrlParam.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum;
 506                 cpb.cntrlParam.csCode = kEjectTheDisc;
 507                 if ( PBControlSync((ParmBlkPtr)&cpb) != noErr ) {
 508                         SDL_SetError("PBControlSync() failed");
 509                         return(-1);
 510                 }
 511         }
 512         return(0);
 513 }
 514 
 515 /* Close the CD-ROM handle */
 516 static void SDL_SYS_CDClose(SDL_CD *cdrom)
     /* [<][>][^][v][top][bottom][index][help] */
 517 {
 518         return;
 519 }
 520 
 521 void SDL_SYS_CDQuit(void)
     /* [<][>][^][v][top][bottom][index][help] */
 522 {
 523         while(SDL_numcds--) 
 524                 memset(SDL_cdlist + SDL_numcds, 0, sizeof(SDL_cdlist[0]));
 525 }
 526 

/* [<][>][^][v][top][bottom][index][help] */