aboutsummaryrefslogtreecommitdiffstats
path: root/distrib/sdl-1.2.15/src/cdrom/macosx/SDL_syscdrom.c
diff options
context:
space:
mode:
Diffstat (limited to 'distrib/sdl-1.2.15/src/cdrom/macosx/SDL_syscdrom.c')
-rw-r--r--distrib/sdl-1.2.15/src/cdrom/macosx/SDL_syscdrom.c514
1 files changed, 514 insertions, 0 deletions
diff --git a/distrib/sdl-1.2.15/src/cdrom/macosx/SDL_syscdrom.c b/distrib/sdl-1.2.15/src/cdrom/macosx/SDL_syscdrom.c
new file mode 100644
index 0000000..5018750
--- /dev/null
+++ b/distrib/sdl-1.2.15/src/cdrom/macosx/SDL_syscdrom.c
@@ -0,0 +1,514 @@
+/*
+ SDL - Simple DirectMedia Layer
+ Copyright (C) 1997-2012 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_MACOSX
+
+#include "SDL_syscdrom_c.h"
+
+#pragma mark -- Globals --
+
+static FSRef** tracks;
+static FSVolumeRefNum* volumes;
+static CDstatus status;
+static int nextTrackFrame;
+static int nextTrackFramesRemaining;
+static int fakeCD;
+static int currentTrack;
+static int didReadTOC;
+static int cacheTOCNumTracks;
+static int currentDrive; /* Only allow 1 drive in use at a time */
+
+#pragma mark -- Prototypes --
+
+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);
+
+#pragma mark -- Helper Functions --
+
+/* Read a list of tracks from the volume */
+static int LoadTracks (SDL_CD *cdrom)
+{
+ /* Check if tracks are already loaded */
+ if ( tracks[cdrom->id] != NULL )
+ return 0;
+
+ /* Allocate memory for tracks */
+ tracks[cdrom->id] = (FSRef*) SDL_calloc (1, sizeof(**tracks) * cdrom->numtracks);
+ if (tracks[cdrom->id] == NULL) {
+ SDL_OutOfMemory ();
+ return -1;
+ }
+
+ /* Load tracks */
+ if (ListTrackFiles (volumes[cdrom->id], tracks[cdrom->id], cdrom->numtracks) < 0)
+ return -1;
+
+ return 0;
+}
+
+/* Find a file for a given start frame and length */
+static FSRef* GetFileForOffset (SDL_CD *cdrom, int start, int length, int *outStartFrame, int *outStopFrame)
+{
+ int i;
+
+ for (i = 0; i < cdrom->numtracks; i++) {
+
+ if (cdrom->track[i].offset <= start &&
+ start < (cdrom->track[i].offset + cdrom->track[i].length))
+ break;
+ }
+
+ if (i == cdrom->numtracks)
+ return NULL;
+
+ currentTrack = i;
+
+ *outStartFrame = start - cdrom->track[i].offset;
+
+ if ((*outStartFrame + length) < cdrom->track[i].length) {
+ *outStopFrame = *outStartFrame + length;
+ length = 0;
+ nextTrackFrame = -1;
+ nextTrackFramesRemaining = -1;
+ }
+ else {
+ *outStopFrame = -1;
+ length -= cdrom->track[i].length - *outStartFrame;
+ nextTrackFrame = cdrom->track[i+1].offset;
+ nextTrackFramesRemaining = length;
+ }
+
+ return &tracks[cdrom->id][i];
+}
+
+/* Setup another file for playback, or stop playback (called from another thread) */
+static void CompletionProc (SDL_CD *cdrom)
+{
+
+ Lock ();
+
+ if (nextTrackFrame > 0 && nextTrackFramesRemaining > 0) {
+
+ /* Load the next file to play */
+ int startFrame, stopFrame;
+ FSRef *file;
+
+ PauseFile ();
+ ReleaseFile ();
+
+ file = GetFileForOffset (cdrom, nextTrackFrame,
+ nextTrackFramesRemaining, &startFrame, &stopFrame);
+
+ if (file == NULL) {
+ status = CD_STOPPED;
+ Unlock ();
+ return;
+ }
+
+ LoadFile (file, startFrame, stopFrame);
+
+ SetCompletionProc (CompletionProc, cdrom);
+
+ PlayFile ();
+ }
+ else {
+
+ /* Release the current file */
+ PauseFile ();
+ ReleaseFile ();
+ status = CD_STOPPED;
+ }
+
+ Unlock ();
+}
+
+
+#pragma mark -- Driver Functions --
+
+/* Initialize */
+int SDL_SYS_CDInit (void)
+{
+ /* Initialize globals */
+ volumes = NULL;
+ tracks = NULL;
+ status = CD_STOPPED;
+ nextTrackFrame = -1;
+ nextTrackFramesRemaining = -1;
+ fakeCD = SDL_FALSE;
+ currentTrack = -1;
+ didReadTOC = SDL_FALSE;
+ cacheTOCNumTracks = -1;
+ currentDrive = -1;
+
+ /* Fill in function pointers */
+ 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;
+
+ /*
+ Read the list of "drives"
+
+ This is currently a hack that infers drives from
+ mounted audio CD volumes, rather than
+ actual CD-ROM devices - which means it may not
+ act as expected sometimes.
+ */
+
+ /* Find out how many cd volumes are mounted */
+ SDL_numcds = DetectAudioCDVolumes (NULL, 0);
+
+ /*
+ If there are no volumes, fake a cd device
+ so tray empty can be reported.
+ */
+ if (SDL_numcds == 0) {
+
+ fakeCD = SDL_TRUE;
+ SDL_numcds = 1;
+ status = CD_TRAYEMPTY;
+
+ return 0;
+ }
+
+ /* Allocate space for volumes */
+ volumes = (FSVolumeRefNum*) SDL_calloc (1, sizeof(*volumes) * SDL_numcds);
+ if (volumes == NULL) {
+ SDL_OutOfMemory ();
+ return -1;
+ }
+
+ /* Allocate space for tracks */
+ tracks = (FSRef**) SDL_calloc (1, sizeof(*tracks) * (SDL_numcds + 1));
+ if (tracks == NULL) {
+ SDL_OutOfMemory ();
+ return -1;
+ }
+
+ /* Mark the end of the tracks array */
+ tracks[ SDL_numcds ] = (FSRef*)-1;
+
+ /*
+ Redetect, now save all volumes for later
+ Update SDL_numcds just in case it changed
+ */
+ {
+ int numVolumes = SDL_numcds;
+
+ SDL_numcds = DetectAudioCDVolumes (volumes, numVolumes);
+
+ /* If more cds suddenly show up, ignore them */
+ if (SDL_numcds > numVolumes) {
+ SDL_SetError ("Some CD's were added but they will be ignored");
+ SDL_numcds = numVolumes;
+ }
+ }
+
+ return 0;
+}
+
+/* Shutdown and cleanup */
+void SDL_SYS_CDQuit(void)
+{
+ ReleaseFile();
+
+ if (volumes != NULL)
+ free (volumes);
+
+ if (tracks != NULL) {
+
+ FSRef **ptr;
+ for (ptr = tracks; *ptr != (FSRef*)-1; ptr++)
+ if (*ptr != NULL)
+ free (*ptr);
+
+ free (tracks);
+ }
+}
+
+/* Get the Unix disk name of the volume */
+static const char *SDL_SYS_CDName (int drive)
+{
+ /*
+ * !!! FIXME: PBHGetVolParmsSync() is gone in 10.6,
+ * !!! FIXME: replaced with FSGetVolumeParms(), which
+ * !!! FIXME: isn't available before 10.5. :/
+ */
+ return "Mac OS X CD-ROM Device";
+
+#if 0
+ OSStatus err = noErr;
+ HParamBlockRec pb;
+ GetVolParmsInfoBuffer volParmsInfo;
+
+ if (fakeCD)
+ return "Fake CD-ROM Device";
+
+ pb.ioParam.ioNamePtr = NULL;
+ pb.ioParam.ioVRefNum = volumes[drive];
+ pb.ioParam.ioBuffer = (Ptr)&volParmsInfo;
+ pb.ioParam.ioReqCount = (SInt32)sizeof(volParmsInfo);
+ err = PBHGetVolParmsSync(&pb);
+
+ if (err != noErr) {
+ SDL_SetError ("PBHGetVolParmsSync returned %d", err);
+ return NULL;
+ }
+
+ return volParmsInfo.vMDeviceID;
+#endif
+}
+
+/* Open the "device" */
+static int SDL_SYS_CDOpen (int drive)
+{
+ /* Only allow 1 device to be open */
+ if (currentDrive >= 0) {
+ SDL_SetError ("Only one cdrom is supported");
+ return -1;
+ }
+ else
+ currentDrive = drive;
+
+ return drive;
+}
+
+/* Get the table of contents */
+static int SDL_SYS_CDGetTOC (SDL_CD *cdrom)
+{
+ if (fakeCD) {
+ SDL_SetError (kErrorFakeDevice);
+ return -1;
+ }
+
+ if (didReadTOC) {
+ cdrom->numtracks = cacheTOCNumTracks;
+ return 0;
+ }
+
+
+ ReadTOCData (volumes[cdrom->id], cdrom);
+ didReadTOC = SDL_TRUE;
+ cacheTOCNumTracks = cdrom->numtracks;
+
+ return 0;
+}
+
+/* Get CD-ROM status */
+static CDstatus SDL_SYS_CDStatus (SDL_CD *cdrom, int *position)
+{
+ if (position) {
+ int trackFrame;
+
+ Lock ();
+ trackFrame = GetCurrentFrame ();
+ Unlock ();
+
+ *position = cdrom->track[currentTrack].offset + trackFrame;
+ }
+
+ return status;
+}
+
+/* Start playback */
+static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
+{
+ int startFrame, stopFrame;
+ FSRef *ref;
+
+ if (fakeCD) {
+ SDL_SetError (kErrorFakeDevice);
+ return -1;
+ }
+
+ Lock();
+
+ if (LoadTracks (cdrom) < 0)
+ return -2;
+
+ if (PauseFile () < 0)
+ return -3;
+
+ if (ReleaseFile () < 0)
+ return -4;
+
+ ref = GetFileForOffset (cdrom, start, length, &startFrame, &stopFrame);
+ if (ref == NULL) {
+ SDL_SetError ("SDL_SYS_CDPlay: No file for start=%d, length=%d", start, length);
+ return -5;
+ }
+
+ if (LoadFile (ref, startFrame, stopFrame) < 0)
+ return -6;
+
+ SetCompletionProc (CompletionProc, cdrom);
+
+ if (PlayFile () < 0)
+ return -7;
+
+ status = CD_PLAYING;
+
+ Unlock();
+
+ return 0;
+}
+
+/* Pause playback */
+static int SDL_SYS_CDPause(SDL_CD *cdrom)
+{
+ if (fakeCD) {
+ SDL_SetError (kErrorFakeDevice);
+ return -1;
+ }
+
+ Lock ();
+
+ if (PauseFile () < 0) {
+ Unlock ();
+ return -2;
+ }
+
+ status = CD_PAUSED;
+
+ Unlock ();
+
+ return 0;
+}
+
+/* Resume playback */
+static int SDL_SYS_CDResume(SDL_CD *cdrom)
+{
+ if (fakeCD) {
+ SDL_SetError (kErrorFakeDevice);
+ return -1;
+ }
+
+ Lock ();
+
+ if (PlayFile () < 0) {
+ Unlock ();
+ return -2;
+ }
+
+ status = CD_PLAYING;
+
+ Unlock ();
+
+ return 0;
+}
+
+/* Stop playback */
+static int SDL_SYS_CDStop(SDL_CD *cdrom)
+{
+ if (fakeCD) {
+ SDL_SetError (kErrorFakeDevice);
+ return -1;
+ }
+
+ Lock ();
+
+ if (PauseFile () < 0) {
+ Unlock ();
+ return -2;
+ }
+
+ if (ReleaseFile () < 0) {
+ Unlock ();
+ return -3;
+ }
+
+ status = CD_STOPPED;
+
+ Unlock ();
+
+ return 0;
+}
+
+/* Eject the CD-ROM (Unmount the volume) */
+static int SDL_SYS_CDEject(SDL_CD *cdrom)
+{
+ OSStatus err;
+ pid_t dissenter;
+
+ if (fakeCD) {
+ SDL_SetError (kErrorFakeDevice);
+ return -1;
+ }
+
+ Lock ();
+
+ if (PauseFile () < 0) {
+ Unlock ();
+ return -2;
+ }
+
+ if (ReleaseFile () < 0) {
+ Unlock ();
+ return -3;
+ }
+
+ status = CD_STOPPED;
+
+ /* Eject the volume */
+ err = FSEjectVolumeSync(volumes[cdrom->id], kNilOptions, &dissenter);
+
+ if (err != noErr) {
+ Unlock ();
+ SDL_SetError ("PBUnmountVol returned %d", err);
+ return -4;
+ }
+
+ status = CD_TRAYEMPTY;
+
+ /* Invalidate volume and track info */
+ volumes[cdrom->id] = 0;
+ free (tracks[cdrom->id]);
+ tracks[cdrom->id] = NULL;
+
+ Unlock ();
+
+ return 0;
+}
+
+/* Close the CD-ROM */
+static void SDL_SYS_CDClose(SDL_CD *cdrom)
+{
+ currentDrive = -1;
+ return;
+}
+
+#endif /* SDL_CDROM_MACOSX */