Mercurial > sdl-ios-xcode
view src/cdrom/macos/SDL_syscdrom.c @ 1727:90a3e0fccb88 SDL-1.3
Started on the OpenGL API revamp.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Fri, 07 Jul 2006 10:29:16 +0000 |
parents | 4da1ee79c9af |
children |
line wrap: on
line source
/* SDL - Simple DirectMedia Layer Copyright (C) 1997-2006 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Sam Lantinga slouken@libsdl.org */ #include "SDL_config.h" #ifdef SDL_CDROM_MACOS /* MacOS functions for system-level CD-ROM audio control */ #include <Devices.h> #include <Files.h> #include <LowMem.h> /* Use entry table macros, not functions in InterfaceLib */ #include "SDL_cdrom.h" #include "../SDL_syscdrom.h" #include "SDL_syscdrom_c.h" /* Added by Matt Slot */ #if !defined(LMGetUnitTableEntryCount) #define LMGetUnitTableEntryCount() *(short *)0x01D2 #endif /* The maximum number of CD-ROM drives we'll detect */ #define MAX_DRIVES 26 /* A list of available CD-ROM drives */ static long SDL_cdversion = 0; static struct { short dRefNum; short driveNum; long frames; char name[256]; Boolean hasAudio; } SDL_cdlist[MAX_DRIVES]; static StringPtr gDriverName = "\p.AppleCD"; /* The system-dependent CD control functions */ static const char *SDL_SYS_CDName(int drive); static int SDL_SYS_CDOpen(int drive); static int SDL_SYS_CDGetTOC(SDL_CD * cdrom); static CDstatus SDL_SYS_CDStatus(SDL_CD * cdrom, int *position); static int SDL_SYS_CDPlay(SDL_CD * cdrom, int start, int length); static int SDL_SYS_CDPause(SDL_CD * cdrom); static int SDL_SYS_CDResume(SDL_CD * cdrom); static int SDL_SYS_CDStop(SDL_CD * cdrom); static int SDL_SYS_CDEject(SDL_CD * cdrom); static void SDL_SYS_CDClose(SDL_CD * cdrom); static short SDL_SYS_ShortToBCD(short value) { return ((value % 10) + (value / 10) * 0x10); /* Convert value to BCD */ } static short SDL_SYS_BCDToShort(short value) { return ((value % 0x10) + (value / 0x10) * 10); /* Convert value from BCD */ } int SDL_SYS_CDInit(void) { SInt16 dRefNum = 0; SInt16 first, last; SDL_numcds = 0; /* Check that the software is available */ if (Gestalt(kGestaltAudioCDSelector, &SDL_cdversion) || !SDL_cdversion) return (0); /* Fill in our driver capabilities */ SDL_CDcaps.Name = SDL_SYS_CDName; SDL_CDcaps.Open = SDL_SYS_CDOpen; SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC; SDL_CDcaps.Status = SDL_SYS_CDStatus; SDL_CDcaps.Play = SDL_SYS_CDPlay; SDL_CDcaps.Pause = SDL_SYS_CDPause; SDL_CDcaps.Resume = SDL_SYS_CDResume; SDL_CDcaps.Stop = SDL_SYS_CDStop; SDL_CDcaps.Eject = SDL_SYS_CDEject; SDL_CDcaps.Close = SDL_SYS_CDClose; /* Walk the list, count each AudioCD driver, and save the refnums */ first = -1; last = 0 - LMGetUnitTableEntryCount(); for (dRefNum = first; dRefNum >= last; dRefNum--) { Str255 driverName; StringPtr namePtr; DCtlHandle deviceEntry; deviceEntry = GetDCtlEntry(dRefNum); if (!deviceEntry) continue; /* Is this an .AppleCD ? */ namePtr = (*deviceEntry)->dCtlFlags & (1L << dRAMBased) ? ((StringPtr) ((DCtlPtr) deviceEntry)->dCtlDriver + 18) : ((StringPtr) (*deviceEntry)->dCtlDriver + 18); BlockMoveData(namePtr, driverName, namePtr[0] + 1); if (driverName[0] > gDriverName[0]) driverName[0] = gDriverName[0]; if (!EqualString(driverName, gDriverName, false, false)) continue; /* Record the basic info for each drive */ SDL_cdlist[SDL_numcds].dRefNum = dRefNum; BlockMoveData(namePtr + 1, SDL_cdlist[SDL_numcds].name, namePtr[0]); SDL_cdlist[SDL_numcds].name[namePtr[0]] = 0; SDL_cdlist[SDL_numcds].hasAudio = false; SDL_numcds++; } return (0); } static const char * SDL_SYS_CDName(int drive) { return (SDL_cdlist[drive].name); } static int get_drivenum(int drive) { QHdr *driveQ = GetDrvQHdr(); DrvQEl *driveElem; /* Update the drive number */ SDL_cdlist[drive].driveNum = 0; if (driveQ->qTail) { driveQ->qTail->qLink = 0; } for (driveElem = (DrvQEl *) driveQ->qHead; driveElem; driveElem = (DrvQEl *) driveElem->qLink) { if (driveElem->dQRefNum == SDL_cdlist[drive].dRefNum) { SDL_cdlist[drive].driveNum = driveElem->dQDrive; break; } } return (SDL_cdlist[drive].driveNum); } static int SDL_SYS_CDOpen(int drive) { return (drive); } static int SDL_SYS_CDGetTOC(SDL_CD * cdrom) { CDCntrlParam cdpb; CDTrackData tracks[SDL_MAX_TRACKS]; long i, leadout; /* Get the number of tracks on the CD by examining the TOC */ SDL_memset(&cdpb, 0, sizeof(cdpb)); cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum; cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum; cdpb.csCode = kReadTOC; cdpb.csParam.words[0] = kGetTrackRange; if (PBControlSync((ParmBlkPtr) & cdpb) != noErr) { SDL_SetError("PBControlSync() failed"); return (-1); } cdrom->numtracks = SDL_SYS_BCDToShort(cdpb.csParam.bytes[1]) - SDL_SYS_BCDToShort(cdpb.csParam.bytes[0]) + 1; if (cdrom->numtracks > SDL_MAX_TRACKS) cdrom->numtracks = SDL_MAX_TRACKS; cdrom->status = CD_STOPPED; cdrom->cur_track = 0; /* Apparently these are set elsewhere */ cdrom->cur_frame = 0; /* Apparently these are set elsewhere */ /* Get the lead out area of the CD by examining the TOC */ SDL_memset(&cdpb, 0, sizeof(cdpb)); cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum; cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum; cdpb.csCode = kReadTOC; cdpb.csParam.words[0] = kGetLeadOutArea; if (PBControlSync((ParmBlkPtr) & cdpb) != noErr) { SDL_SetError("PBControlSync() failed"); return (-1); } leadout = MSF_TO_FRAMES(SDL_SYS_BCDToShort(cdpb.csParam.bytes[0]), SDL_SYS_BCDToShort(cdpb.csParam.bytes[1]), SDL_SYS_BCDToShort(cdpb.csParam.bytes[2])); /* Get an array of track locations by examining the TOC */ SDL_memset(tracks, 0, sizeof(tracks)); SDL_memset(&cdpb, 0, sizeof(cdpb)); cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum; cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum; cdpb.csCode = kReadTOC; cdpb.csParam.words[0] = kGetTrackEntries; /* Type of Query */ *((long *) (cdpb.csParam.words + 1)) = (long) tracks; cdpb.csParam.words[3] = cdrom->numtracks * sizeof(tracks[0]); *((char *) (cdpb.csParam.words + 4)) = 1; /* First track */ if (PBControlSync((ParmBlkPtr) & cdpb) != noErr) { SDL_SetError("PBControlSync() failed"); return (-1); } /* Read all the track TOC entries */ SDL_cdlist[cdrom->id].hasAudio = false; for (i = 0; i < cdrom->numtracks; ++i) { cdrom->track[i].id = i + 1; if (tracks[i].entry.control & kDataTrackMask) cdrom->track[i].type = SDL_DATA_TRACK; else { cdrom->track[i].type = SDL_AUDIO_TRACK; SDL_cdlist[SDL_numcds].hasAudio = true; } cdrom->track[i].offset = MSF_TO_FRAMES(SDL_SYS_BCDToShort(tracks[i].entry.min), SDL_SYS_BCDToShort(tracks[i].entry.min), SDL_SYS_BCDToShort(tracks[i].entry.frame)); cdrom->track[i].length = MSF_TO_FRAMES(SDL_SYS_BCDToShort(tracks[i + 1].entry.min), SDL_SYS_BCDToShort(tracks[i + 1].entry.min), SDL_SYS_BCDToShort(tracks[i + 1].entry.frame)) - cdrom->track[i].offset; } /* Apparently SDL wants a fake last entry */ cdrom->track[i].offset = leadout; cdrom->track[i].length = 0; return (0); } /* Get CD-ROM status */ static CDstatus SDL_SYS_CDStatus(SDL_CD * cdrom, int *position) { CDCntrlParam cdpb; CDstatus status = CD_ERROR; Boolean spinning = false; if (position) *position = 0; /* Get the number of tracks on the CD by examining the TOC */ if (!get_drivenum(cdrom->id)) { return (CD_TRAYEMPTY); } SDL_memset(&cdpb, 0, sizeof(cdpb)); cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum; cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum; cdpb.csCode = kReadTOC; cdpb.csParam.words[0] = kGetTrackRange; if (PBControlSync((ParmBlkPtr) & cdpb) != noErr) { SDL_SetError("PBControlSync() failed"); return (CD_ERROR); } cdrom->numtracks = SDL_SYS_BCDToShort(cdpb.csParam.bytes[1]) - SDL_SYS_BCDToShort(cdpb.csParam.bytes[0]) + 1; if (cdrom->numtracks > SDL_MAX_TRACKS) cdrom->numtracks = SDL_MAX_TRACKS; cdrom->cur_track = 0; /* Apparently these are set elsewhere */ cdrom->cur_frame = 0; /* Apparently these are set elsewhere */ if (1 || SDL_cdlist[cdrom->id].hasAudio) { /* Get the current playback status */ SDL_memset(&cdpb, 0, sizeof(cdpb)); cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum; cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum; cdpb.csCode = kAudioStatus; if (PBControlSync((ParmBlkPtr) & cdpb) != noErr) { SDL_SetError("PBControlSync() failed"); return (-1); } switch (cdpb.csParam.cd.status) { case kStatusPlaying: status = CD_PLAYING; spinning = true; break; case kStatusPaused: status = CD_PAUSED; spinning = true; break; case kStatusMuted: status = CD_PLAYING; /* What should I do here? */ spinning = true; break; case kStatusDone: status = CD_STOPPED; spinning = true; break; case kStatusStopped: status = CD_STOPPED; spinning = false; break; case kStatusError: default: status = CD_ERROR; spinning = false; break; } if (spinning && position) *position = MSF_TO_FRAMES(SDL_SYS_BCDToShort(cdpb.csParam.cd.minute), SDL_SYS_BCDToShort(cdpb.csParam.cd.second), SDL_SYS_BCDToShort(cdpb.csParam.cd.frame)); } else status = CD_ERROR; /* What should I do here? */ return (status); } /* Start play */ static int SDL_SYS_CDPlay(SDL_CD * cdrom, int start, int length) { CDCntrlParam cdpb; /* Pause the current audio playback to avoid audible artifacts */ if (SDL_SYS_CDPause(cdrom) < 0) { return (-1); } /* Specify the AudioCD playback mode */ SDL_memset(&cdpb, 0, sizeof(cdpb)); cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum; cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum; cdpb.csCode = kSetPlayMode; cdpb.csParam.bytes[0] = false; /* Repeat? */ cdpb.csParam.bytes[1] = kPlayModeSequential; /* Play mode */ /* ¥¥¥ÊTreat as soft error, NEC Drive doesnt support this call ¥¥¥ */ PBControlSync((ParmBlkPtr) & cdpb); #if 1 /* Specify the end of audio playback */ SDL_memset(&cdpb, 0, sizeof(cdpb)); cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum; cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum; cdpb.csCode = kAudioStop; cdpb.csParam.words[0] = kBlockPosition; /* Position Mode */ *(long *) (cdpb.csParam.words + 1) = start + length - 1; /* Search Address */ if (PBControlSync((ParmBlkPtr) & cdpb) != noErr) { SDL_SetError("PBControlSync() failed"); return (-1); } /* Specify the start of audio playback, and start it */ SDL_memset(&cdpb, 0, sizeof(cdpb)); cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum; cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum; cdpb.csCode = kAudioPlay; cdpb.csParam.words[0] = kBlockPosition; /* Position Mode */ *(long *) (cdpb.csParam.words + 1) = start + 1; /* Search Address */ cdpb.csParam.words[3] = false; /* Stop address? */ cdpb.csParam.words[4] = kStereoPlayMode; /* Audio Play Mode */ if (PBControlSync((ParmBlkPtr) & cdpb) != noErr) { SDL_SetError("PBControlSync() failed"); return (-1); } #else /* Specify the end of audio playback */ FRAMES_TO_MSF(start + length, &m, &s, &f); SDL_memset(&cdpb, 0, sizeof(cdpb)); cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum; cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum; cdpb.csCode = kAudioStop; cdpb.csParam.words[0] = kTrackPosition; /* Position Mode */ cdpb.csParam.words[1] = 0; /* Search Address (hiword) */ cdpb.csParam.words[2] = /* Search Address (loword) */ SDL_SYS_ShortToBCD(cdrom->numtracks); if (PBControlSync((ParmBlkPtr) & cdpb) != noErr) { SDL_SetError("PBControlSync() failed"); return (-1); } /* Specify the start of audio playback, and start it */ FRAMES_TO_MSF(start, &m, &s, &f); SDL_memset(&cdpb, 0, sizeof(cdpb)); cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum; cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum; cdpb.csCode = kAudioPlay; cdpb.csParam.words[0] = kTrackPosition; /* Position Mode */ cdpb.csParam.words[1] = 0; /* Search Address (hiword) */ cdpb.csParam.words[2] = SDL_SYS_ShortToBCD(1); /* Search Address (loword) */ cdpb.csParam.words[3] = false; /* Stop address? */ cdpb.csParam.words[4] = kStereoPlayMode; /* Audio Play Mode */ if (PBControlSync((ParmBlkPtr) & cdpb) != noErr) { SDL_SetError("PBControlSync() failed"); return (-1); } #endif return (0); } /* Pause play */ static int SDL_SYS_CDPause(SDL_CD * cdrom) { CDCntrlParam cdpb; SDL_memset(&cdpb, 0, sizeof(cdpb)); cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum; cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum; cdpb.csCode = kAudioPause; cdpb.csParam.words[0] = 0; /* Pause/Continue Flag (hiword) */ cdpb.csParam.words[1] = 1; /* Pause/Continue Flag (loword) */ if (PBControlSync((ParmBlkPtr) & cdpb) != noErr) { SDL_SetError("PBControlSync() failed"); return (-1); } return (0); } /* Resume play */ static int SDL_SYS_CDResume(SDL_CD * cdrom) { CDCntrlParam cdpb; SDL_memset(&cdpb, 0, sizeof(cdpb)); cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum; cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum; cdpb.csCode = kAudioPause; cdpb.csParam.words[0] = 0; /* Pause/Continue Flag (hiword) */ cdpb.csParam.words[1] = 0; /* Pause/Continue Flag (loword) */ if (PBControlSync((ParmBlkPtr) & cdpb) != noErr) { SDL_SetError("PBControlSync() failed"); return (-1); } return (0); } /* Stop play */ static int SDL_SYS_CDStop(SDL_CD * cdrom) { CDCntrlParam cdpb; SDL_memset(&cdpb, 0, sizeof(cdpb)); cdpb.ioVRefNum = SDL_cdlist[cdrom->id].driveNum; cdpb.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum; cdpb.csCode = kAudioStop; cdpb.csParam.words[0] = 0; /* Position Mode */ cdpb.csParam.words[1] = 0; /* Search Address (hiword) */ cdpb.csParam.words[2] = 0; /* Search Address (loword) */ if (PBControlSync((ParmBlkPtr) & cdpb) != noErr) { SDL_SetError("PBControlSync() failed"); return (-1); } return (0); } /* Eject the CD-ROM */ static int SDL_SYS_CDEject(SDL_CD * cdrom) { Boolean disk = false; QHdr *driveQ = GetDrvQHdr(); DrvQEl *driveElem; HParamBlockRec hpb; ParamBlockRec cpb; for (driveElem = (DrvQEl *) driveQ->qHead; driveElem; driveElem = (driveElem) ? ((DrvQEl *) driveElem->qLink) : ((DrvQEl *) driveQ->qHead)) { if (driveQ->qTail) { driveQ->qTail->qLink = 0; } if (driveElem->dQRefNum != SDL_cdlist[cdrom->id].dRefNum) { continue; } /* Does drive contain mounted volume? If not, skip */ SDL_memset(&hpb, 0, sizeof(hpb)); hpb.volumeParam.ioVRefNum = driveElem->dQDrive; if (PBHGetVInfoSync(&hpb) != noErr) { continue; } if ((UnmountVol(0, driveElem->dQDrive) == noErr) && (Eject(0, driveElem->dQDrive) == noErr)) { driveElem = 0; /* Clear pointer to reset our loop */ disk = true; } } /* If no disk is present, just eject the tray */ if (!disk) { SDL_memset(&cpb, 0, sizeof(cpb)); cpb.cntrlParam.ioVRefNum = 0; /* No Drive */ cpb.cntrlParam.ioCRefNum = SDL_cdlist[cdrom->id].dRefNum; cpb.cntrlParam.csCode = kEjectTheDisc; if (PBControlSync((ParmBlkPtr) & cpb) != noErr) { SDL_SetError("PBControlSync() failed"); return (-1); } } return (0); } /* Close the CD-ROM handle */ static void SDL_SYS_CDClose(SDL_CD * cdrom) { return; } void SDL_SYS_CDQuit(void) { while (SDL_numcds--) SDL_memset(SDL_cdlist + SDL_numcds, 0, sizeof(SDL_cdlist[0])); } #endif /* SDL_CDROM_MACOS */ /* vi: set ts=4 sw=4 expandtab: */