Mercurial > sdl-ios-xcode
annotate src/cdrom/macos/SDL_syscdrom.c @ 874:9719e7f51a3a
Date: Thu, 11 Mar 2004 18:45:17 +0900
From: Hayashi Naoyuki
Subject: Re: Tru64 cdrom and pthread option fix
I wrote
/* Some CD-ROM drives cannot play the first 150 frames. */
in src/cdrom/osf/SDL_syscdrom.c
and
Some CD-ROM drives(ex. TEAC CD-532E) cannot play first 150 frames(aka gap).
but this is not right.
It is written in MMC that LBA = 4500*M + 75*S + F - 150.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Thu, 11 Mar 2004 12:59:41 +0000 |
parents | b8d311d90021 |
children | c9b51268668f |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
769
b8d311d90021
Updated copyright information for 2004 (Happy New Year!)
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
3 Copyright (C) 1997-2004 Sam Lantinga |
0 | 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 | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
22 | |
23 #ifdef SAVE_RCSID | |
24 static char rcsid = | |
25 "@(#) $Id$"; | |
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 | |
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) | |
70 { | |
71 return((value % 10) + (value / 10) * 0x10); /* Convert value to BCD */ | |
72 } | |
73 | |
74 static short SDL_SYS_BCDToShort(short value) | |
75 { | |
76 return((value % 0x10) + (value / 0x10) * 10); /* Convert value from BCD */ | |
77 } | |
78 | |
79 int SDL_SYS_CDInit(void) | |
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) | |
132 { | |
133 return(SDL_cdlist[drive].name); | |
134 } | |
135 | |
136 static int get_drivenum(int drive) | |
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) | |
157 { | |
158 return(drive); | |
159 } | |
160 | |
161 static int SDL_SYS_CDGetTOC(SDL_CD *cdrom) | |
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) | |
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) | |
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) | |
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) | |
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) | |
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) | |
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) | |
517 { | |
518 return; | |
519 } | |
520 | |
521 void SDL_SYS_CDQuit(void) | |
522 { | |
523 while(SDL_numcds--) | |
524 memset(SDL_cdlist + SDL_numcds, 0, sizeof(SDL_cdlist[0])); | |
525 } | |
526 |