|
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 */ |