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