Replaced Mac OS X's C++ cdrom code with almost-direct translation to C. Sam
authorRyan C. Gordon <icculus@icculus.org>
Thu, 22 Sep 2005 08:48:16 +0000
changeset 1143 71a2648acc75
parent 1142 c7376efecdb5
child 1144 509295d5a023
Replaced Mac OS X's C++ cdrom code with almost-direct translation to C. Sam requested this effort on the mailing list, apparently because of binary compatibility issues between 10.4 and earlier systems (or gcc4 and earlier compilers?). Works fine with SDL12/test/testcdrom.c, with this command line: ./testcdrom -status -list -play -sleep 5000 -pause -sleep 3000 -resume \ -sleep 5000 -stop -sleep 3000 -play -sleep 3000 -stop \ -sleep 3000 -eject Unix Makefiles work, XCode project still need updating for new filenames.
src/cdrom/macosx/AudioFilePlayer.c
src/cdrom/macosx/AudioFilePlayer.cpp
src/cdrom/macosx/AudioFilePlayer.h
src/cdrom/macosx/AudioFileReaderThread.c
src/cdrom/macosx/AudioFileReaderThread.cpp
src/cdrom/macosx/CAGuard.cpp
src/cdrom/macosx/CAGuard.h
src/cdrom/macosx/CDPlayer.c
src/cdrom/macosx/CDPlayer.cpp
src/cdrom/macosx/Makefile.am
src/cdrom/macosx/SDLOSXCAGuard.c
src/cdrom/macosx/SDLOSXCAGuard.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cdrom/macosx/AudioFilePlayer.c	Thu Sep 22 08:48:16 2005 +0000
@@ -0,0 +1,352 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 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
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+    Sam Lantinga
+    slouken@libsdl.org
+
+    This file based on Apple sample code. We haven't changed the file name, 
+    so if you want to see the original search for it on apple.com/developer
+*/
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//  AudioFilePlayer.cpp
+//
+#include "AudioFilePlayer.h"
+
+/*
+void ThrowResult (OSStatus result, const char* str)
+{
+    SDL_SetError ("Error: %s %d", str, result);
+    throw result;
+}
+*/
+
+#if DEBUG
+static void PrintStreamDesc (AudioStreamBasicDescription *inDesc)
+{
+    if (!inDesc) {
+        printf ("Can't print a NULL desc!\n");
+        return;
+    }
+    
+    printf ("- - - - - - - - - - - - - - - - - - - -\n");
+    printf ("  Sample Rate:%f\n", inDesc->mSampleRate);
+    printf ("  Format ID:%s\n", (char*)&inDesc->mFormatID);
+    printf ("  Format Flags:%lX\n", inDesc->mFormatFlags);
+    printf ("  Bytes per Packet:%ld\n", inDesc->mBytesPerPacket);
+    printf ("  Frames per Packet:%ld\n", inDesc->mFramesPerPacket);
+    printf ("  Bytes per Frame:%ld\n", inDesc->mBytesPerFrame);
+    printf ("  Channels per Frame:%ld\n", inDesc->mChannelsPerFrame);
+    printf ("  Bits per Channel:%ld\n", inDesc->mBitsPerChannel);
+    printf ("- - - - - - - - - - - - - - - - - - - -\n");
+}
+#endif
+
+
+static int AudioFilePlayer_SetDestination (AudioFilePlayer *afp, AudioUnit  *inDestUnit)
+{
+    //if (afp->mConnected) throw static_cast<OSStatus>(-1); //can't set dest if already engaged
+    if (afp->mConnected)
+        return 0 ;
+
+    memcpy(&afp->mPlayUnit, inDestUnit, sizeof (afp->mPlayUnit));
+
+    OSStatus result = noErr;
+    
+
+        //we can "down" cast a component instance to a component
+    ComponentDescription desc;
+    result = GetComponentInfo ((Component)*inDestUnit, &desc, 0, 0, 0);
+    if (result) return 0; //THROW_RESULT("GetComponentInfo")
+        
+        // we're going to use this to know which convert routine to call
+        // a v1 audio unit will have a type of 'aunt'
+        // a v2 audio unit will have one of several different types.
+    if (desc.componentType != kAudioUnitComponentType) {
+        result = badComponentInstance;
+        //THROW_RESULT("BAD COMPONENT")
+        if (result) return 0;
+    }
+
+    /* Set the input format of the audio unit. */
+    result = AudioUnitSetProperty (*inDestUnit,
+                               kAudioUnitProperty_StreamFormat,
+                               kAudioUnitScope_Input,
+                               0,
+                               &afp->mFileDescription,
+                               sizeof (afp->mFileDescription));
+        //THROW_RESULT("AudioUnitSetProperty")
+    if (result) return 0;
+    return 1;
+}
+
+static void AudioFilePlayer_SetNotifier(AudioFilePlayer *afp, AudioFilePlayNotifier inNotifier, void *inRefCon)
+{
+    afp->mNotifier = inNotifier;
+    afp->mRefCon = inRefCon;
+}
+
+static int AudioFilePlayer_IsConnected(AudioFilePlayer *afp)
+{
+    return afp->mConnected;
+}
+
+static AudioUnit AudioFilePlayer_GetDestUnit(AudioFilePlayer *afp)
+{
+   return afp->mPlayUnit;
+}
+
+static void AudioFilePlayer_Print(AudioFilePlayer *afp)
+{
+#if DEBUG    
+    printf ("Is Connected:%s\n", (IsConnected() ? "true" : "false"));
+    printf ("- - - - - - - - - - - - - - \n");
+#endif
+}
+
+static void    AudioFilePlayer_SetStartFrame (AudioFilePlayer *afp, int frame)
+{
+    SInt64 position = frame * 2352;
+
+    afp->mStartFrame = frame;
+    afp->mAudioFileManager->SetPosition (afp->mAudioFileManager, position);
+}
+
+    
+static int    AudioFilePlayer_GetCurrentFrame (AudioFilePlayer *afp)
+{
+    return afp->mStartFrame + (afp->mAudioFileManager->GetByteCounter(afp->mAudioFileManager) / 2352);
+}
+    
+static void    AudioFilePlayer_SetStopFrame (AudioFilePlayer *afp, int frame)
+{
+    SInt64 position  = frame * 2352;
+    
+    afp->mAudioFileManager->SetEndOfFile (afp->mAudioFileManager, position);
+}
+    
+void delete_AudioFilePlayer(AudioFilePlayer *afp)
+{
+    if (afp != NULL)
+    {
+        afp->Disconnect(afp);
+        
+        if (afp->mAudioFileManager) {
+            delete_AudioFileManager(afp->mAudioFileManager);
+            afp->mAudioFileManager = 0;
+        }
+    
+        if (afp->mForkRefNum) {
+            FSClose (afp->mForkRefNum);
+            afp->mForkRefNum = 0;
+        }
+        free(afp);
+    }
+}
+
+static int    AudioFilePlayer_Connect(AudioFilePlayer *afp)
+{
+#if DEBUG
+    printf ("Connect:%x, engaged=%d\n", (int)afp->mPlayUnit, (afp->mConnected ? 1 : 0));
+#endif
+    if (!afp->mConnected)
+    {           
+        if (!afp->mAudioFileManager->DoConnect(afp->mAudioFileManager))
+            return 0;
+
+        // set the render callback for the file data to be supplied to the sound converter AU
+        afp->mInputCallback.inputProc = afp->mAudioFileManager->FileInputProc;
+        afp->mInputCallback.inputProcRefCon = afp->mAudioFileManager;
+
+        OSStatus result = AudioUnitSetProperty (afp->mPlayUnit, 
+                            kAudioUnitProperty_SetInputCallback, 
+                            kAudioUnitScope_Input, 
+                            0,
+                            &afp->mInputCallback, 
+                            sizeof(afp->mInputCallback));
+        if (result) return 0;  //THROW_RESULT("AudioUnitSetProperty")
+        afp->mConnected = 1;
+    }
+
+    return 1;
+}
+
+// warning noted, now please go away ;-)
+// #warning This should redirect the calling of notification code to some other thread
+static void    AudioFilePlayer_DoNotification (AudioFilePlayer *afp, OSStatus inStatus)
+{
+    if (afp->mNotifier) {
+        (*afp->mNotifier) (afp->mRefCon, inStatus);
+    } else {
+        SDL_SetError ("Notification posted with no notifier in place");
+        
+        if (inStatus == kAudioFilePlay_FileIsFinished)
+            afp->Disconnect(afp);
+        else if (inStatus != kAudioFilePlayErr_FilePlayUnderrun)
+            afp->Disconnect(afp);
+    }
+}
+
+static void    AudioFilePlayer_Disconnect (AudioFilePlayer *afp)
+{
+#if DEBUG
+    printf ("Disconnect:%x,%ld, engaged=%d\n", (int)afp->mPlayUnit, 0, (afp->mConnected ? 1 : 0));
+#endif
+    if (afp->mConnected)
+    {
+        afp->mConnected = 0;
+            
+        afp->mInputCallback.inputProc = 0;
+        afp->mInputCallback.inputProcRefCon = 0;
+        OSStatus result = AudioUnitSetProperty (afp->mPlayUnit, 
+                                        kAudioUnitProperty_SetInputCallback, 
+                                        kAudioUnitScope_Input, 
+                                        0,
+                                        &afp->mInputCallback, 
+                                        sizeof(afp->mInputCallback));
+        if (result) 
+            SDL_SetError ("AudioUnitSetProperty:RemoveInputCallback:%ld", result);
+
+        afp->mAudioFileManager->Disconnect(afp->mAudioFileManager);
+    }
+}
+
+typedef struct {
+    UInt32 offset;
+    UInt32 blockSize;
+} SSNDData;
+
+static int    AudioFilePlayer_OpenFile (AudioFilePlayer *afp, const FSRef *inRef, SInt64 *outFileDataSize)
+{
+    ContainerChunk chunkHeader;
+    ChunkHeader chunk;
+    SSNDData ssndData;
+
+    OSErr result;
+    HFSUniStr255 dfName;
+    ByteCount actual;
+    SInt64 offset;
+
+    // Open the data fork of the input file
+    result = FSGetDataForkName(&dfName);
+       if (result) return 0; //THROW_RESULT("AudioFilePlayer::OpenFile(): FSGetDataForkName")
+
+    result = FSOpenFork(inRef, dfName.length, dfName.unicode, fsRdPerm, &afp->mForkRefNum);
+       if (result) return 0; //THROW_RESULT("AudioFilePlayer::OpenFile(): FSOpenFork")
+ 
+    // Read the file header, and check if it's indeed an AIFC file
+    result = FSReadFork(afp->mForkRefNum, fsAtMark, 0, sizeof(chunkHeader), &chunkHeader, &actual);
+       if (result) return 0; //THROW_RESULT("AudioFilePlayer::OpenFile(): FSReadFork")
+
+    if (chunkHeader.ckID != 'FORM') {
+        result = -1;
+        if (result) return 0; //THROW_RESULT("AudioFilePlayer::OpenFile(): chunk id is not 'FORM'");
+    }
+
+    if (chunkHeader.formType != 'AIFC') {
+        result = -1;
+        if (result) return 0; //THROW_RESULT("AudioFilePlayer::OpenFile(): file format is not 'AIFC'");
+    }
+
+    // Search for the SSND chunk. We ignore all compression etc. information
+    // in other chunks. Of course that is kind of evil, but for now we are lazy
+    // and rely on the cdfs to always give us the same fixed format.
+    // TODO: Parse the COMM chunk we currently skip to fill in mFileDescription.
+    offset = 0;
+    do {
+        result = FSReadFork(afp->mForkRefNum, fsFromMark, offset, sizeof(chunk), &chunk, &actual);
+           if (result) return 0; //THROW_RESULT("AudioFilePlayer::OpenFile(): FSReadFork")
+            
+        // Skip the chunk data
+        offset = chunk.ckSize;
+    } while (chunk.ckID != 'SSND');
+
+    // Read the header of the SSND chunk. After this, we are positioned right
+    // at the start of the audio data.
+    result = FSReadFork(afp->mForkRefNum, fsAtMark, 0, sizeof(ssndData), &ssndData, &actual);
+       if (result) return 0; //THROW_RESULT("AudioFilePlayer::OpenFile(): FSReadFork")
+
+    result = FSSetForkPosition(afp->mForkRefNum, fsFromMark, ssndData.offset);
+       if (result) return 0; //THROW_RESULT("AudioFilePlayer::OpenFile(): FSSetForkPosition")
+
+    // Data size
+    *outFileDataSize = chunk.ckSize - ssndData.offset - 8;
+
+    // File format
+    afp->mFileDescription.mSampleRate = 44100;
+    afp->mFileDescription.mFormatID = kAudioFormatLinearPCM;
+    afp->mFileDescription.mFormatFlags = kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsSignedInteger;
+    afp->mFileDescription.mBytesPerPacket = 4;
+    afp->mFileDescription.mFramesPerPacket = 1;
+    afp->mFileDescription.mBytesPerFrame = 4;
+    afp->mFileDescription.mChannelsPerFrame = 2;
+    afp->mFileDescription.mBitsPerChannel = 16;
+
+    return 1;
+}
+
+AudioFilePlayer *new_AudioFilePlayer (const FSRef *inFileRef)
+{
+    SInt64 fileDataSize  = 0;
+
+    AudioFilePlayer *afp = (AudioFilePlayer *) malloc(sizeof (AudioFilePlayer));
+    if (afp == NULL)
+        return NULL;
+    memset(afp, '\0', sizeof (*afp));
+
+    #define SET_AUDIOFILEPLAYER_METHOD(m) afp->m = AudioFilePlayer_##m
+    SET_AUDIOFILEPLAYER_METHOD(SetDestination);
+    SET_AUDIOFILEPLAYER_METHOD(SetNotifier);
+    SET_AUDIOFILEPLAYER_METHOD(SetStartFrame);
+    SET_AUDIOFILEPLAYER_METHOD(GetCurrentFrame);
+    SET_AUDIOFILEPLAYER_METHOD(SetStopFrame);
+    SET_AUDIOFILEPLAYER_METHOD(Connect);
+    SET_AUDIOFILEPLAYER_METHOD(Disconnect);
+    SET_AUDIOFILEPLAYER_METHOD(DoNotification);
+    SET_AUDIOFILEPLAYER_METHOD(IsConnected);
+    SET_AUDIOFILEPLAYER_METHOD(GetDestUnit);
+    SET_AUDIOFILEPLAYER_METHOD(Print);
+    SET_AUDIOFILEPLAYER_METHOD(OpenFile);
+    #undef SET_AUDIOFILEPLAYER_METHOD
+
+    if (!afp->OpenFile (afp, inFileRef, &fileDataSize))
+    {
+        free(afp);
+        return NULL;
+    }
+        
+    // we want about 4 seconds worth of data for the buffer
+    int bytesPerSecond = (UInt32) (4 * afp->mFileDescription.mSampleRate * afp->mFileDescription.mBytesPerFrame);
+    
+#if DEBUG
+    printf("File format:\n");
+    PrintStreamDesc (&afp->mFileDescription);
+#endif
+    
+    afp->mAudioFileManager = new_AudioFileManager(afp, afp->mForkRefNum,
+                                                  fileDataSize,
+                                                  bytesPerSecond);
+    if (afp->mAudioFileManager == NULL)
+    {
+        delete_AudioFilePlayer(afp);
+        return NULL;
+    }
+
+    return afp;
+}
+
--- a/src/cdrom/macosx/AudioFilePlayer.cpp	Sun Sep 11 04:15:44 2005 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,330 +0,0 @@
-/*
-    SDL - Simple DirectMedia Layer
-    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Library General Public
-    License as published by the Free Software Foundation; either
-    version 2 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
-    Library General Public License for more details.
-
-    You should have received a copy of the GNU Library General Public
-    License along with this library; if not, write to the Free
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-    Sam Lantinga
-    slouken@libsdl.org
-
-    This file based on Apple sample code. We haven't changed the file name, 
-    so if you want to see the original search for it on apple.com/developer
-*/
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-//  AudioFilePlayer.cpp
-//
-#include "AudioFilePlayer.h"
-
-void ThrowResult (OSStatus result, const char* str)
-{
-    SDL_SetError ("Error: %s %d", str, result);
-    throw result;
-}
-
-#if DEBUG
-void PrintStreamDesc (AudioStreamBasicDescription *inDesc)
-{
-    if (!inDesc) {
-        printf ("Can't print a NULL desc!\n");
-        return;
-    }
-    
-    printf ("- - - - - - - - - - - - - - - - - - - -\n");
-    printf ("  Sample Rate:%f\n", inDesc->mSampleRate);
-    printf ("  Format ID:%s\n", (char*)&inDesc->mFormatID);
-    printf ("  Format Flags:%lX\n", inDesc->mFormatFlags);
-    printf ("  Bytes per Packet:%ld\n", inDesc->mBytesPerPacket);
-    printf ("  Frames per Packet:%ld\n", inDesc->mFramesPerPacket);
-    printf ("  Bytes per Frame:%ld\n", inDesc->mBytesPerFrame);
-    printf ("  Channels per Frame:%ld\n", inDesc->mChannelsPerFrame);
-    printf ("  Bits per Channel:%ld\n", inDesc->mBitsPerChannel);
-    printf ("- - - - - - - - - - - - - - - - - - - -\n");
-}
-#endif
-
-OSStatus    AudioFileManager::FileInputProc (void                       *inRefCon, 
-                                             AudioUnitRenderActionFlags inActionFlags,
-                                             const AudioTimeStamp       *inTimeStamp, 
-                                             UInt32                     inBusNumber, 
-                                             AudioBuffer                *ioData)
-{
-    AudioFileManager* THIS = (AudioFileManager*)inRefCon;
-    return THIS->Render(*ioData);
-}
-
-OSStatus    AudioFileManager::Render (AudioBuffer &ioData)
-{
-    OSStatus result = noErr;
-    
-	if (mBufferOffset >= mBufferSize) {
-		result = GetFileData(&mTmpBuffer, &mBufferSize);
-		if (result) {
-			SDL_SetError ("AudioConverterFillBuffer:%ld\n", result);
-			mParent.DoNotification (result);
-			return result;
-		}
-
-		mBufferOffset = 0;
-	}
-    	
-    if (ioData.mDataByteSize > mBufferSize - mBufferOffset)
-    	ioData.mDataByteSize = mBufferSize - mBufferOffset;
-    ioData.mData = (char *)mTmpBuffer + mBufferOffset;
-    mBufferOffset += ioData.mDataByteSize;
-    
-	mByteCounter += ioData.mDataByteSize;
-	AfterRender();
-    return result;
-}
-
-AudioFileManager::~AudioFileManager ()
-{
-    if (mFileBuffer) {
-        free (mFileBuffer);
-        mFileBuffer = 0;
-    }
-}
-
-AudioFilePlayer::AudioFilePlayer (const FSRef           *inFileRef)
-    : mConnected (false),
-      mAudioFileManager (0),
-      mNotifier (0),
-      mStartFrame (0)
-{
-    SInt64 fileDataSize  = 0;
-
-    OpenFile (inFileRef, fileDataSize);
-        
-    // we want about 4 seconds worth of data for the buffer
-    int bytesPerSecond = UInt32 (4 * mFileDescription.mSampleRate * mFileDescription.mBytesPerFrame);
-    
-#if DEBUG
-    printf("File format:\n");
-    PrintStreamDesc (&mFileDescription);
-#endif
-    
-    mAudioFileManager = new AudioFileManager (*this, 
-                                                mForkRefNum, 
-                                                fileDataSize,
-                                                bytesPerSecond);
-}
-
-void    AudioFilePlayer::SetDestination (AudioUnit  &inDestUnit)
-{
-    if (mConnected) throw static_cast<OSStatus>(-1); //can't set dest if already engaged
- 
-    mPlayUnit = inDestUnit;
-
-    OSStatus result = noErr;
-    
-
-        //we can "down" cast a component instance to a component
-    ComponentDescription desc;
-    result = GetComponentInfo ((Component)inDestUnit, &desc, 0, 0, 0);
-        THROW_RESULT("GetComponentInfo")
-        
-        // we're going to use this to know which convert routine to call
-        // a v1 audio unit will have a type of 'aunt'
-        // a v2 audio unit will have one of several different types.
-    if (desc.componentType != kAudioUnitComponentType) {
-        result = badComponentInstance;
-        THROW_RESULT("BAD COMPONENT")
-    }
-
-    /* Set the input format of the audio unit. */
-    result = AudioUnitSetProperty (inDestUnit,
-                               kAudioUnitProperty_StreamFormat,
-                               kAudioUnitScope_Input,
-                               0,
-                               &mFileDescription,
-                               sizeof (mFileDescription));
-        THROW_RESULT("AudioUnitSetProperty")
-}
-
-void    AudioFilePlayer::SetStartFrame (int frame)
-{
-    SInt64 position = frame * 2352;
-
-    mStartFrame = frame;
-    mAudioFileManager->SetPosition (position);
-}
-
-    
-int    AudioFilePlayer::GetCurrentFrame ()
-{
-    return mStartFrame + (mAudioFileManager->GetByteCounter() / 2352);
-}
-    
-void    AudioFilePlayer::SetStopFrame (int frame)
-{
-    SInt64 position  = frame * 2352;
-    
-    mAudioFileManager->SetEndOfFile (position);
-}
-    
-AudioFilePlayer::~AudioFilePlayer()
-{
-    Disconnect();
-        
-    if (mAudioFileManager) {
-        delete mAudioFileManager;
-        mAudioFileManager = 0;
-    }
-    
-    if (mForkRefNum) {
-        FSClose (mForkRefNum);
-        mForkRefNum = 0;
-    }
-}
-
-void    AudioFilePlayer::Connect()
-{
-#if DEBUG
-    printf ("Connect:%x, engaged=%d\n", (int)mPlayUnit, (mConnected ? 1 : 0));
-#endif
-    if (!mConnected)
-    {           
-        mAudioFileManager->DoConnect();
-
-
-        // set the render callback for the file data to be supplied to the sound converter AU
-        mInputCallback.inputProc = AudioFileManager::FileInputProc;
-        mInputCallback.inputProcRefCon = mAudioFileManager;
-
-        OSStatus result = AudioUnitSetProperty (mPlayUnit, 
-                            kAudioUnitProperty_SetInputCallback, 
-                            kAudioUnitScope_Input, 
-                            0,
-                            &mInputCallback, 
-                            sizeof(mInputCallback));
-        THROW_RESULT("AudioUnitSetProperty")
-        mConnected = true;
-    }
-}
-
-// warning noted, now please go away ;-)
-// #warning This should redirect the calling of notification code to some other thread
-void    AudioFilePlayer::DoNotification (OSStatus inStatus) const
-{
-    AudioFilePlayer* THIS = const_cast<AudioFilePlayer*>(this);
-        
-    if (mNotifier) {
-        (*mNotifier) (mRefCon, inStatus);
-    } else {
-        SDL_SetError ("Notification posted with no notifier in place");
-        
-        if (inStatus == kAudioFilePlay_FileIsFinished)
-            THIS->Disconnect();
-        else if (inStatus != kAudioFilePlayErr_FilePlayUnderrun)
-            THIS->Disconnect();
-    }
-}
-
-void    AudioFilePlayer::Disconnect ()
-{
-#if DEBUG
-    printf ("Disconnect:%x,%ld, engaged=%d\n", (int)mPlayUnit, 0, (mConnected ? 1 : 0));
-#endif
-    if (mConnected)
-    {
-        mConnected = false;
-            
-        mInputCallback.inputProc = 0;
-        mInputCallback.inputProcRefCon = 0;
-        OSStatus result = AudioUnitSetProperty (mPlayUnit, 
-                                        kAudioUnitProperty_SetInputCallback, 
-                                        kAudioUnitScope_Input, 
-                                        0,
-                                        &mInputCallback, 
-                                        sizeof(mInputCallback));
-        if (result) 
-            SDL_SetError ("AudioUnitSetProperty:RemoveInputCallback:%ld", result);
-
-        mAudioFileManager->Disconnect();
-    }
-}
-
-struct SSNDData {
-    UInt32 offset;
-    UInt32 blockSize;
-};
-
-void    AudioFilePlayer::OpenFile (const FSRef *inRef, SInt64& outFileDataSize)
-{
-    ContainerChunk chunkHeader;
-    ChunkHeader chunk;
-    SSNDData ssndData;
-
-    OSErr result;
-    HFSUniStr255 dfName;
-    ByteCount actual;
-    SInt64 offset;
-
-    // Open the data fork of the input file
-    result = FSGetDataForkName(&dfName);
-       THROW_RESULT("AudioFilePlayer::OpenFile(): FSGetDataForkName")
-
-    result = FSOpenFork(inRef, dfName.length, dfName.unicode, fsRdPerm, &mForkRefNum);
-       THROW_RESULT("AudioFilePlayer::OpenFile(): FSOpenFork")
- 
-    // Read the file header, and check if it's indeed an AIFC file
-    result = FSReadFork(mForkRefNum, fsAtMark, 0, sizeof(chunkHeader), &chunkHeader, &actual);
-       THROW_RESULT("AudioFilePlayer::OpenFile(): FSReadFork")
-
-    if (chunkHeader.ckID != 'FORM') {
-        result = -1;
-        THROW_RESULT("AudioFilePlayer::OpenFile(): chunk id is not 'FORM'");
-    }
-
-    if (chunkHeader.formType != 'AIFC') {
-        result = -1;
-        THROW_RESULT("AudioFilePlayer::OpenFile(): file format is not 'AIFC'");
-    }
-
-    // Search for the SSND chunk. We ignore all compression etc. information
-    // in other chunks. Of course that is kind of evil, but for now we are lazy
-    // and rely on the cdfs to always give us the same fixed format.
-    // TODO: Parse the COMM chunk we currently skip to fill in mFileDescription.
-    offset = 0;
-    do {
-        result = FSReadFork(mForkRefNum, fsFromMark, offset, sizeof(chunk), &chunk, &actual);
-           THROW_RESULT("AudioFilePlayer::OpenFile(): FSReadFork")
-            
-        // Skip the chunk data
-        offset = chunk.ckSize;
-    } while (chunk.ckID != 'SSND');
-
-    // Read the header of the SSND chunk. After this, we are positioned right
-    // at the start of the audio data.
-    result = FSReadFork(mForkRefNum, fsAtMark, 0, sizeof(ssndData), &ssndData, &actual);
-       THROW_RESULT("AudioFilePlayer::OpenFile(): FSReadFork")
-
-    result = FSSetForkPosition(mForkRefNum, fsFromMark, ssndData.offset);
-       THROW_RESULT("AudioFilePlayer::OpenFile(): FSSetForkPosition")
-
-    // Data size
-    outFileDataSize = chunk.ckSize - ssndData.offset - 8;
-
-    // File format
-    mFileDescription.mSampleRate = 44100;
-    mFileDescription.mFormatID = kAudioFormatLinearPCM;
-    mFileDescription.mFormatFlags = kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsSignedInteger;
-    mFileDescription.mBytesPerPacket = 4;
-    mFileDescription.mFramesPerPacket = 1;
-    mFileDescription.mBytesPerFrame = 4;
-    mFileDescription.mChannelsPerFrame = 2;
-    mFileDescription.mBitsPerChannel = 16;
-}
--- a/src/cdrom/macosx/AudioFilePlayer.h	Sun Sep 11 04:15:44 2005 +0000
+++ b/src/cdrom/macosx/AudioFilePlayer.h	Thu Sep 22 08:48:16 2005 +0000
@@ -37,12 +37,14 @@
 
 const char* AudioFilePlayerErrorStr (OSStatus error);
 
+/*
 void ThrowResult (OSStatus result, const char *str);
 
 #define THROW_RESULT(str)                                       \
     if (result) {                                               \
         ThrowResult (result, str);                              \
     }
+*/
 
 typedef void (*AudioFilePlayNotifier)(void          *inRefCon,
                                     OSStatus        inStatus);
@@ -54,49 +56,25 @@
 };
 
 
-class AudioFileManager;
+struct S_AudioFileManager;
 
 #pragma mark __________ AudioFilePlayer
-class AudioFilePlayer
+typedef struct S_AudioFilePlayer
 {
-public:
-    AudioFilePlayer (const FSRef    *inFileRef);
-    
-    ~AudioFilePlayer();
+//public:
+    int             (*SetDestination)(struct S_AudioFilePlayer *afp, AudioUnit *inDestUnit);
+    void            (*SetNotifier)(struct S_AudioFilePlayer *afp, AudioFilePlayNotifier inNotifier, void *inRefCon);
+    void            (*SetStartFrame)(struct S_AudioFilePlayer *afp, int frame); // seek in the file
+    int             (*GetCurrentFrame)(struct S_AudioFilePlayer *afp); // get the current frame position
+    void            (*SetStopFrame)(struct S_AudioFilePlayer *afp, int frame);   // set limit in the file
+    int             (*Connect)(struct S_AudioFilePlayer *afp);
+    void            (*Disconnect)(struct S_AudioFilePlayer *afp);
+    void            (*DoNotification)(struct S_AudioFilePlayer *afp, OSStatus inError);
+    int             (*IsConnected)(struct S_AudioFilePlayer *afp);
+    AudioUnit       (*GetDestUnit)(struct S_AudioFilePlayer *afp);
+    void            (*Print)(struct S_AudioFilePlayer *afp);
 
-    void            SetDestination (AudioUnit &inDestUnit);
-    
-    void            SetNotifier (AudioFilePlayNotifier inNotifier, void *inRefCon)
-    {
-        mNotifier = inNotifier;
-        mRefCon = inRefCon;
-    }
-    
-    void            SetStartFrame (int frame); // seek in the file
-    
-    int             GetCurrentFrame (); // get the current frame position
-    
-    void            SetStopFrame (int frame);   // set limit in the file
-    
-    void            Connect();
-    
-    void            Disconnect();
-
-    void            DoNotification (OSStatus inError) const;
-    
-    bool            IsConnected () const { return mConnected; }
-
-    AudioUnit       GetDestUnit () const { return mPlayUnit; }
-    
-#if DEBUG    
-    void            Print() const 
-    {
-        printf ("Is Connected:%s\n", (IsConnected() ? "true" : "false"));
-        printf ("- - - - - - - - - - - - - - \n");
-    }
-#endif
-    
-private:
+//private:
     AudioUnit                       mPlayUnit;
     SInt16                          mForkRefNum;
     
@@ -104,9 +82,9 @@
 
     AudioStreamBasicDescription     mFileDescription;
     
-    bool                            mConnected;
+    int                             mConnected;
     
-    AudioFileManager*               mAudioFileManager;
+    struct S_AudioFileManager*      mAudioFileManager;
     
     AudioFilePlayNotifier           mNotifier;
     void*                           mRefCon;
@@ -115,41 +93,32 @@
     
 #pragma mark __________ Private_Methods
     
-    void        OpenFile (const FSRef *inRef, SInt64& outFileSize);
-};
+    int          (*OpenFile)(struct S_AudioFilePlayer *afp, const FSRef *inRef, SInt64 *outFileSize);
+} AudioFilePlayer;
+
+
+AudioFilePlayer *new_AudioFilePlayer(const FSRef    *inFileRef);
+void delete_AudioFilePlayer(AudioFilePlayer *afp);
+
+
 
 #pragma mark __________ AudioFileManager
-class AudioFileManager
+typedef struct S_AudioFileManager
 {
-public:
-    AudioFileManager (AudioFilePlayer &inParent, 
-                      SInt16          inForkRefNum, 
-                      SInt64          inFileLength,
-                      UInt32          inChunkSize);
-    
-    ~AudioFileManager();
-    
-    
+//public:
         // this method should NOT be called by an object of this class
         // as it is called by the parent's Disconnect() method
-    void                Disconnect ();
-    
-    void                DoConnect ();
-
-    OSStatus            Read(char *buffer, UInt32 *len);
-
-    const char*         GetFileBuffer () { return mFileBuffer; }
-
-    const AudioFilePlayer&  GetParent () const { return mParent; }
-    
-    void                SetPosition (SInt64 pos);  // seek/rewind in the file
-    
-    int                 GetByteCounter () { return mByteCounter; } // return actual bytes streamed to audio hardware
-    
-    void                SetEndOfFile (SInt64 pos);  // set the "EOF" (will behave just like it reached eof)
+    void                (*Disconnect)(struct S_AudioFileManager *afm);
+    int                 (*DoConnect)(struct S_AudioFileManager *afm);
+    OSStatus            (*Read)(struct S_AudioFileManager *afm, char *buffer, UInt32 *len);
+    const char*         (*GetFileBuffer)(struct S_AudioFileManager *afm);
+    const AudioFilePlayer *(*GetParent)(struct S_AudioFileManager *afm);
+    void                (*SetPosition)(struct S_AudioFileManager *afm, SInt64 pos);  // seek/rewind in the file
+    int                 (*GetByteCounter)(struct S_AudioFileManager *afm);  // return actual bytes streamed to audio hardware
+    void                (*SetEndOfFile)(struct S_AudioFileManager *afm, SInt64 pos);  // set the "EOF" (will behave just like it reached eof)
    
-protected:
-    AudioFilePlayer&    mParent;
+//protected:
+    AudioFilePlayer*    mParent;
     SInt16              mForkRefNum;
     SInt64              mAudioDataOffset;
     
@@ -157,9 +126,9 @@
 
     int                 mByteCounter;
 
-    bool                mReadFromFirstBuffer;
-    bool                mLockUnsuccessful;
-    bool                mIsEngaged;
+    int                mReadFromFirstBuffer;
+    int                mLockUnsuccessful;
+    int                mIsEngaged;
     
     int                 mNumTimesAskedSinceFinished;
 
@@ -167,27 +136,34 @@
 	void*               mTmpBuffer;
 	UInt32              mBufferSize;
 	UInt32              mBufferOffset;
-public:
-    const UInt32        mChunkSize;
+//public:
+    UInt32              mChunkSize;
     SInt64              mFileLength;
     SInt64              mReadFilePosition;
-    bool                mWriteToFirstBuffer;
-    bool                mFinishedReadingData;
+    int                 mWriteToFirstBuffer;
+    int                 mFinishedReadingData;
+
+//protected:
+    OSStatus            (*Render)(struct S_AudioFileManager *afm, AudioBuffer *ioData);
+    OSStatus            (*GetFileData)(struct S_AudioFileManager *afm, void** inOutData, UInt32 *inOutDataSize);
+    void                (*AfterRender)(struct S_AudioFileManager *afm);
 
-protected:
-    OSStatus            Render (AudioBuffer &ioData);
-    
-    OSStatus            GetFileData (void** inOutData, UInt32 *inOutDataSize);
-        
-    void                AfterRender ();
-
-public:
-    static OSStatus     FileInputProc (void                             *inRefCon, 
-                                        AudioUnitRenderActionFlags      inActionFlags,
-                                        const AudioTimeStamp            *inTimeStamp, 
-                                        UInt32                          inBusNumber, 
-                                        AudioBuffer                     *ioData);
-};
+//public:
+    //static
+    OSStatus            (*FileInputProc)(void                             *inRefCon,
+                                         AudioUnitRenderActionFlags      inActionFlags,
+                                         const AudioTimeStamp            *inTimeStamp,
+                                         UInt32                          inBusNumber,
+                                         AudioBuffer                     *ioData);
+} AudioFileManager;
 
 
+AudioFileManager *new_AudioFileManager (AudioFilePlayer *inParent,
+                      SInt16          inForkRefNum, 
+                      SInt64          inFileLength,
+                      UInt32          inChunkSize);
+    
+void delete_AudioFileManager(AudioFileManager *afm);
+
 #endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cdrom/macosx/AudioFileReaderThread.c	Thu Sep 22 08:48:16 2005 +0000
@@ -0,0 +1,602 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 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
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+    Sam Lantinga
+    slouken@libsdl.org
+
+    This file based on Apple sample code. We haven't changed the file name, 
+    so if you want to see the original search for it on apple.com/developer
+*/
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// AudioFileManager.cpp
+//
+#include "AudioFilePlayer.h"
+#include <mach/mach.h> //used for setting policy of thread
+#include "SDLOSXCAGuard.h"
+#include <pthread.h>
+
+//#include <list>
+
+//typedef void *FileData;
+typedef struct S_FileData
+{
+    AudioFileManager *obj;
+    struct S_FileData *next;
+} FileData;
+
+
+typedef struct S_FileReaderThread {
+//public:
+    SDLOSXCAGuard*                    (*GetGuard)(struct S_FileReaderThread *frt);
+    void                        (*AddReader)(struct S_FileReaderThread *frt);
+    void                        (*RemoveReader)(struct S_FileReaderThread *frt, AudioFileManager* inItem);
+    int                         (*TryNextRead)(struct S_FileReaderThread *frt, AudioFileManager* inItem);
+
+    int     mThreadShouldDie;
+    
+//private:
+    //typedef std::list<AudioFileManager*> FileData;
+
+    SDLOSXCAGuard             *mGuard;
+    UInt32              mThreadPriority;
+    
+    int                 mNumReaders;    
+    FileData            *mFileData;
+
+
+    void                        (*ReadNextChunk)(struct S_FileReaderThread *frt);
+    int                         (*StartFixedPriorityThread)(struct S_FileReaderThread *frt);
+    //static
+    UInt32               (*GetThreadBasePriority)(pthread_t inThread);
+    //static
+    void*                (*DiskReaderEntry)(void *inRefCon);
+} FileReaderThread;
+
+
+static SDLOSXCAGuard* FileReaderThread_GetGuard(FileReaderThread *frt)
+{
+    return frt->mGuard;
+}
+
+// returns 1 if succeeded
+static int FileReaderThread_TryNextRead (FileReaderThread *frt, AudioFileManager* inItem)
+{
+    int didLock = 0;
+    int succeeded = 0;
+    if (frt->mGuard->Try(frt->mGuard, &didLock))
+    {
+        //frt->mFileData.push_back (inItem);
+        // !!! FIXME: this could be faster with a "tail" member. --ryan.
+        FileData *i = frt->mFileData;
+        FileData *prev = NULL;
+
+        FileData *newfd = (FileData *) malloc(sizeof (FileData));
+        newfd->obj = inItem;
+        newfd->next = NULL;
+
+        while (i != NULL) { prev = i; i = i->next; }
+        if (prev == NULL)
+            frt->mFileData = newfd;
+        else
+            prev->next = newfd;
+
+        frt->mGuard->Notify(frt->mGuard);
+        succeeded = 1;
+
+        if (didLock)
+            frt->mGuard->Unlock(frt->mGuard);
+    }
+                
+    return succeeded;
+}
+
+static void    FileReaderThread_AddReader(FileReaderThread *frt)
+{
+    if (frt->mNumReaders == 0)
+    {
+        frt->mThreadShouldDie = 0;
+        frt->StartFixedPriorityThread (frt);
+    }
+    frt->mNumReaders++;
+}
+
+static void    FileReaderThread_RemoveReader (FileReaderThread *frt, AudioFileManager* inItem)
+{
+    if (frt->mNumReaders > 0)
+    {
+        int bNeedsRelease = frt->mGuard->Lock(frt->mGuard);
+        
+        //frt->mFileData.remove (inItem);
+        FileData *i = frt->mFileData;
+        FileData *prev = NULL;
+        while (i != NULL)
+        {
+            FileData *next = i->next;
+            if (i->obj != inItem)
+                prev = i;
+            else
+            {
+                if (prev == NULL)
+                    frt->mFileData = next;
+                else
+                    prev->next = next;
+                free(i);
+            }
+            i = next;
+        }
+
+        if (--frt->mNumReaders == 0) {
+            frt->mThreadShouldDie = 1;
+            frt->mGuard->Notify(frt->mGuard); // wake up thread so it will quit
+            frt->mGuard->Wait(frt->mGuard);   // wait for thread to die
+        }
+
+        if (bNeedsRelease) frt->mGuard->Unlock(frt->mGuard);
+    }   
+}
+
+static int    FileReaderThread_StartFixedPriorityThread (FileReaderThread *frt)
+{
+    pthread_attr_t      theThreadAttrs;
+    pthread_t           pThread;
+
+    OSStatus result = pthread_attr_init(&theThreadAttrs);
+        if (result) return 0; //THROW_RESULT("pthread_attr_init - Thread attributes could not be created.")
+    
+    result = pthread_attr_setdetachstate(&theThreadAttrs, PTHREAD_CREATE_DETACHED);
+        if (result) return 0; //THROW_RESULT("pthread_attr_setdetachstate - Thread attributes could not be detached.")
+    
+    result = pthread_create (&pThread, &theThreadAttrs, frt->DiskReaderEntry, frt);
+        if (result) return 0; //THROW_RESULT("pthread_create - Create and start the thread.")
+    
+    pthread_attr_destroy(&theThreadAttrs);
+    
+    // we've now created the thread and started it
+    // we'll now set the priority of the thread to the nominated priority
+    // and we'll also make the thread fixed
+    thread_extended_policy_data_t       theFixedPolicy;
+    thread_precedence_policy_data_t     thePrecedencePolicy;
+    SInt32                              relativePriority;
+    
+    // make thread fixed
+    theFixedPolicy.timeshare = 0;   // set to 1 for a non-fixed thread
+    result = thread_policy_set (pthread_mach_thread_np(pThread), THREAD_EXTENDED_POLICY, (thread_policy_t)&theFixedPolicy, THREAD_EXTENDED_POLICY_COUNT);
+        if (result) return 0; //THROW_RESULT("thread_policy - Couldn't set thread as fixed priority.")
+    // set priority
+    // precedency policy's "importance" value is relative to spawning thread's priority
+    relativePriority = frt->mThreadPriority - frt->GetThreadBasePriority(pthread_self());
+        
+    thePrecedencePolicy.importance = relativePriority;
+    result = thread_policy_set (pthread_mach_thread_np(pThread), THREAD_PRECEDENCE_POLICY, (thread_policy_t)&thePrecedencePolicy, THREAD_PRECEDENCE_POLICY_COUNT);
+        if (result) return 0; //THROW_RESULT("thread_policy - Couldn't set thread priority.")
+
+    return 1;
+}
+
+static UInt32  FileReaderThread_GetThreadBasePriority (pthread_t inThread)
+{
+    thread_basic_info_data_t            threadInfo;
+    policy_info_data_t                  thePolicyInfo;
+    unsigned int                        count;
+    
+    // get basic info
+    count = THREAD_BASIC_INFO_COUNT;
+    thread_info (pthread_mach_thread_np (inThread), THREAD_BASIC_INFO, (integer_t*)&threadInfo, &count);
+    
+    switch (threadInfo.policy) {
+        case POLICY_TIMESHARE:
+            count = POLICY_TIMESHARE_INFO_COUNT;
+            thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_TIMESHARE_INFO, (integer_t*)&(thePolicyInfo.ts), &count);
+            return thePolicyInfo.ts.base_priority;
+            break;
+            
+        case POLICY_FIFO:
+            count = POLICY_FIFO_INFO_COUNT;
+            thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_FIFO_INFO, (integer_t*)&(thePolicyInfo.fifo), &count);
+            if (thePolicyInfo.fifo.depressed) {
+                return thePolicyInfo.fifo.depress_priority;
+            } else {
+                return thePolicyInfo.fifo.base_priority;
+            }
+            break;
+            
+        case POLICY_RR:
+            count = POLICY_RR_INFO_COUNT;
+            thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_RR_INFO, (integer_t*)&(thePolicyInfo.rr), &count);
+            if (thePolicyInfo.rr.depressed) {
+                return thePolicyInfo.rr.depress_priority;
+            } else {
+                return thePolicyInfo.rr.base_priority;
+            }
+            break;
+    }
+    
+    return 0;
+}
+
+static void    *FileReaderThread_DiskReaderEntry (void *inRefCon)
+{
+    FileReaderThread *frt = (FileReaderThread *)inRefCon;
+    frt->ReadNextChunk(frt);
+    #if DEBUG
+    printf ("finished with reading file\n");
+    #endif
+    
+    return 0;
+}
+
+static void    FileReaderThread_ReadNextChunk (FileReaderThread *frt)
+{
+    OSStatus result;
+    UInt32  dataChunkSize;
+    AudioFileManager* theItem = 0;
+
+    for (;;) 
+    {
+        { // this is a scoped based lock
+            int bNeedsRelease = frt->mGuard->Lock(frt->mGuard);
+            
+            if (frt->mThreadShouldDie) {
+                frt->mGuard->Notify(frt->mGuard);
+                if (bNeedsRelease) frt->mGuard->Unlock(frt->mGuard);
+                return;
+            }
+            
+            //if (frt->mFileData.empty())
+            if (frt->mFileData == NULL)
+            {
+                frt->mGuard->Wait(frt->mGuard);
+            }
+                        
+            // kill thread
+            if (frt->mThreadShouldDie) {
+            
+                frt->mGuard->Notify(frt->mGuard);
+                if (bNeedsRelease) frt->mGuard->Unlock(frt->mGuard);
+                return;
+            }
+
+            //theItem = frt->mFileData.front();
+            //frt->mFileData.pop_front();
+            theItem = NULL;
+            if (frt->mFileData != NULL)
+            {
+                FileData *next = frt->mFileData->next;
+                theItem = frt->mFileData->obj;
+                free(frt->mFileData);
+                frt->mFileData = next;
+            }
+
+            if (bNeedsRelease) frt->mGuard->Unlock(frt->mGuard);
+        }
+    
+        if ((theItem->mFileLength - theItem->mReadFilePosition) < theItem->mChunkSize)
+            dataChunkSize = theItem->mFileLength - theItem->mReadFilePosition;
+        else
+            dataChunkSize = theItem->mChunkSize;
+        
+            // this is the exit condition for the thread
+        if (dataChunkSize <= 0) {
+            theItem->mFinishedReadingData = 1;
+            continue;
+        }
+            // construct pointer
+        char* writePtr = (char *) (theItem->GetFileBuffer(theItem) +
+                                (theItem->mWriteToFirstBuffer ? 0 : theItem->mChunkSize));
+    
+            // read data
+        result = theItem->Read(theItem, writePtr, &dataChunkSize);
+        if (result != noErr && result != eofErr) {
+            AudioFilePlayer *afp = (AudioFilePlayer *) theItem->GetParent(theItem);
+            afp->DoNotification(afp, result);
+            continue;
+        }
+        
+        if (dataChunkSize != theItem->mChunkSize)
+        {
+            writePtr += dataChunkSize;
+
+            // can't exit yet.. we still have to pass the partial buffer back
+            memset (writePtr, 0, (theItem->mChunkSize - dataChunkSize));
+        }
+        
+        theItem->mWriteToFirstBuffer = !theItem->mWriteToFirstBuffer;   // switch buffers
+        
+        if (result == eofErr)
+            theItem->mReadFilePosition = theItem->mFileLength;
+        else
+            theItem->mReadFilePosition += dataChunkSize;        // increment count
+    }
+}
+
+void delete_FileReaderThread(FileReaderThread *frt)
+{
+    if (frt != NULL)
+    {
+        delete_SDLOSXCAGuard(frt->mGuard);
+        free(frt);
+    }
+}
+
+FileReaderThread *new_FileReaderThread ()
+{
+    FileReaderThread *frt = (FileReaderThread *) malloc(sizeof (FileReaderThread));
+    if (frt == NULL)
+        return NULL;
+    memset(frt, '\0', sizeof (*frt));
+
+    frt->mGuard = new_SDLOSXCAGuard();
+    if (frt->mGuard == NULL)
+    {
+        free(frt);
+        return NULL;
+    }
+
+    #define SET_FILEREADERTHREAD_METHOD(m) frt->m = FileReaderThread_##m
+    SET_FILEREADERTHREAD_METHOD(GetGuard);
+    SET_FILEREADERTHREAD_METHOD(AddReader);
+    SET_FILEREADERTHREAD_METHOD(RemoveReader);
+    SET_FILEREADERTHREAD_METHOD(TryNextRead);
+    SET_FILEREADERTHREAD_METHOD(ReadNextChunk);
+    SET_FILEREADERTHREAD_METHOD(StartFixedPriorityThread);
+    SET_FILEREADERTHREAD_METHOD(GetThreadBasePriority);
+    SET_FILEREADERTHREAD_METHOD(DiskReaderEntry);
+    #undef SET_FILEREADERTHREAD_METHOD
+
+    frt->mThreadPriority = 62;
+    return frt;
+}
+
+
+static FileReaderThread *sReaderThread;
+
+
+static int    AudioFileManager_DoConnect (AudioFileManager *afm)
+{
+    if (!afm->mIsEngaged)
+    {
+        //afm->mReadFilePosition = 0;
+        afm->mFinishedReadingData = 0;
+
+        afm->mNumTimesAskedSinceFinished = 0;
+        afm->mLockUnsuccessful = 0;
+        
+        OSStatus result;
+        UInt32 dataChunkSize;
+        
+        if ((afm->mFileLength - afm->mReadFilePosition) < afm->mChunkSize)
+            dataChunkSize = afm->mFileLength - afm->mReadFilePosition;
+        else
+            dataChunkSize = afm->mChunkSize;
+        
+        result = afm->Read(afm, afm->mFileBuffer, &dataChunkSize);
+           if (result) return 0; //THROW_RESULT("AudioFileManager::DoConnect(): Read")
+
+        afm->mReadFilePosition += dataChunkSize;
+                
+        afm->mWriteToFirstBuffer = 0;
+        afm->mReadFromFirstBuffer = 1;
+
+        sReaderThread->AddReader(sReaderThread);
+        
+        afm->mIsEngaged = 1;
+    }
+    //else
+    //    throw static_cast<OSStatus>(-1); //thread has already been started
+
+    return 1;
+}
+
+static void    AudioFileManager_Disconnect (AudioFileManager *afm)
+{
+    if (afm->mIsEngaged)
+    {
+        sReaderThread->RemoveReader (sReaderThread, afm);
+        afm->mIsEngaged = 0;
+    }
+}
+
+static OSStatus AudioFileManager_Read(AudioFileManager *afm, char *buffer, UInt32 *len)
+{
+    return FSReadFork (afm->mForkRefNum,
+                       fsFromStart,
+                       afm->mReadFilePosition + afm->mAudioDataOffset,
+                       *len,
+                       buffer,
+                       len);
+}
+
+static OSStatus AudioFileManager_GetFileData (AudioFileManager *afm, void** inOutData, UInt32 *inOutDataSize)
+{
+    if (afm->mFinishedReadingData)
+    {
+        ++afm->mNumTimesAskedSinceFinished;
+        *inOutDataSize = 0;
+        *inOutData = 0;
+        return noErr;
+    }
+    
+    if (afm->mReadFromFirstBuffer == afm->mWriteToFirstBuffer) {
+        #if DEBUG
+        printf ("* * * * * * * Can't keep up with reading file\n");
+        #endif
+        
+        afm->mParent->DoNotification (afm->mParent, kAudioFilePlayErr_FilePlayUnderrun);
+        *inOutDataSize = 0;
+        *inOutData = 0;
+    } else {
+        *inOutDataSize = afm->mChunkSize;
+        *inOutData = afm->mReadFromFirstBuffer ? afm->mFileBuffer : (afm->mFileBuffer + afm->mChunkSize);
+    }
+
+    afm->mLockUnsuccessful = !sReaderThread->TryNextRead (sReaderThread, afm);
+    
+    afm->mReadFromFirstBuffer = !afm->mReadFromFirstBuffer;
+
+    return noErr;
+}
+
+static void    AudioFileManager_AfterRender (AudioFileManager *afm)
+{
+    if (afm->mNumTimesAskedSinceFinished > 0)
+    {
+        int didLock = 0;
+        SDLOSXCAGuard *guard = sReaderThread->GetGuard(sReaderThread);
+        if (guard->Try(guard, &didLock)) {
+            afm->mParent->DoNotification (afm->mParent, kAudioFilePlay_FileIsFinished);
+            if (didLock)
+                guard->Unlock(guard);
+        }
+    }
+
+    if (afm->mLockUnsuccessful)
+        afm->mLockUnsuccessful = !sReaderThread->TryNextRead (sReaderThread, afm);
+}
+
+static void    AudioFileManager_SetPosition (AudioFileManager *afm, SInt64 pos)
+{
+    if (pos < 0 || pos >= afm->mFileLength) {
+        SDL_SetError ("AudioFileManager::SetPosition - position invalid: %d filelen=%d\n", 
+            (unsigned int)pos, (unsigned int)afm->mFileLength);
+        pos = 0;
+    }
+        
+    afm->mReadFilePosition = pos;
+}
+    
+static void    AudioFileManager_SetEndOfFile (AudioFileManager *afm, SInt64 pos)
+{
+    if (pos <= 0 || pos > afm->mFileLength) {
+        SDL_SetError ("AudioFileManager::SetEndOfFile - position beyond actual eof\n");
+        pos = afm->mFileLength;
+    }
+    
+    afm->mFileLength = pos;
+}
+
+static const char *AudioFileManager_GetFileBuffer(AudioFileManager *afm)
+{
+    return afm->mFileBuffer;
+}
+
+const AudioFilePlayer *AudioFileManager_GetParent(AudioFileManager *afm)
+{
+    return afm->mParent;
+}
+
+static int AudioFileManager_GetByteCounter(AudioFileManager *afm)
+{
+    return afm->mByteCounter;
+}
+
+
+static OSStatus    AudioFileManager_FileInputProc (void                       *inRefCon,
+                                             AudioUnitRenderActionFlags inActionFlags,
+                                             const AudioTimeStamp       *inTimeStamp, 
+                                             UInt32                     inBusNumber, 
+                                             AudioBuffer                *ioData)
+{
+    AudioFileManager* afm = (AudioFileManager*)inRefCon;
+    return afm->Render(afm, ioData);
+}
+
+static OSStatus    AudioFileManager_Render (AudioFileManager *afm, AudioBuffer *ioData)
+{
+    OSStatus result = noErr;
+    
+	if (afm->mBufferOffset >= afm->mBufferSize) {
+		result = afm->GetFileData(afm, &afm->mTmpBuffer, &afm->mBufferSize);
+		if (result) {
+			SDL_SetError ("AudioConverterFillBuffer:%ld\n", result);
+			afm->mParent->DoNotification(afm->mParent, result);
+			return result;
+		}
+
+		afm->mBufferOffset = 0;
+	}
+    	
+    if (ioData->mDataByteSize > afm->mBufferSize - afm->mBufferOffset)
+    	ioData->mDataByteSize = afm->mBufferSize - afm->mBufferOffset;
+    ioData->mData = (char *)afm->mTmpBuffer + afm->mBufferOffset;
+    afm->mBufferOffset += ioData->mDataByteSize;
+    
+	afm->mByteCounter += ioData->mDataByteSize;
+	afm->AfterRender(afm);
+    return result;
+}
+
+
+void delete_AudioFileManager (AudioFileManager *afm)
+{
+    if (afm != NULL) {
+        if (afm->mFileBuffer) {
+            free (afm->mFileBuffer);
+        }
+
+        free(afm);
+    }
+}
+
+
+AudioFileManager *new_AudioFileManager(AudioFilePlayer *inParent,
+                                       SInt16          inForkRefNum,
+                                       SInt64          inFileLength,
+                                       UInt32          inChunkSize)
+{
+    AudioFileManager *afm;
+
+    if (sReaderThread == NULL)
+    {
+        sReaderThread = new_FileReaderThread();
+        if (sReaderThread == NULL)
+            return NULL;
+    }
+
+    afm = (AudioFileManager *) malloc(sizeof (AudioFileManager));
+    if (afm == NULL)
+        return NULL;
+    memset(afm, '\0', sizeof (*afm));
+
+    #define SET_AUDIOFILEMANAGER_METHOD(m) afm->m = AudioFileManager_##m
+    SET_AUDIOFILEMANAGER_METHOD(Disconnect);
+    SET_AUDIOFILEMANAGER_METHOD(DoConnect);
+    SET_AUDIOFILEMANAGER_METHOD(Read);
+    SET_AUDIOFILEMANAGER_METHOD(GetFileBuffer);
+    SET_AUDIOFILEMANAGER_METHOD(GetParent);
+    SET_AUDIOFILEMANAGER_METHOD(SetPosition);
+    SET_AUDIOFILEMANAGER_METHOD(GetByteCounter);
+    SET_AUDIOFILEMANAGER_METHOD(SetEndOfFile);
+    SET_AUDIOFILEMANAGER_METHOD(Render);
+    SET_AUDIOFILEMANAGER_METHOD(GetFileData);
+    SET_AUDIOFILEMANAGER_METHOD(AfterRender);
+    SET_AUDIOFILEMANAGER_METHOD(FileInputProc);
+    #undef SET_AUDIOFILEMANAGER_METHOD
+
+    afm->mParent = inParent;
+    afm->mForkRefNum = inForkRefNum;
+    afm->mBufferSize = inChunkSize;
+    afm->mBufferOffset = inChunkSize;
+    afm->mChunkSize = inChunkSize;
+    afm->mFileLength = inFileLength;
+    afm->mFileBuffer = (char*) malloc (afm->mChunkSize * 2);
+    FSGetForkPosition(afm->mForkRefNum, &afm->mAudioDataOffset);
+    assert (afm->mFileBuffer != NULL);
+    return afm;
+}
+
--- a/src/cdrom/macosx/AudioFileReaderThread.cpp	Sun Sep 11 04:15:44 2005 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,422 +0,0 @@
-/*
-    SDL - Simple DirectMedia Layer
-    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Library General Public
-    License as published by the Free Software Foundation; either
-    version 2 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
-    Library General Public License for more details.
-
-    You should have received a copy of the GNU Library General Public
-    License along with this library; if not, write to the Free
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-    Sam Lantinga
-    slouken@libsdl.org
-
-    This file based on Apple sample code. We haven't changed the file name, 
-    so if you want to see the original search for it on apple.com/developer
-*/
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// AudioFileManager.cpp
-//
-#include "AudioFilePlayer.h"
-#include <mach/mach.h> //used for setting policy of thread
-#include "CAGuard.h"
-#include <pthread.h>
-
-#include <list>
-
-class FileReaderThread {
-public:
-    FileReaderThread ();
-
-    CAGuard&                    GetGuard() { return mGuard; }
-    
-    void                        AddReader();
-    
-    void                        RemoveReader (AudioFileManager* inItem);
-        
-        // returns true if succeeded
-    bool                        TryNextRead (AudioFileManager* inItem)
-    {
-        bool didLock = false;
-        bool succeeded = false;
-        if (mGuard.Try (didLock))
-        {
-            mFileData.push_back (inItem);
-            mGuard.Notify();
-            succeeded = true;
-
-            if (didLock)
-                mGuard.Unlock();
-        }
-                
-        return succeeded;
-    }   
-    
-    int     mThreadShouldDie;
-    
-private:
-    typedef std::list<AudioFileManager*> FileData;
-
-    CAGuard             mGuard;
-    UInt32              mThreadPriority;
-    
-    int                 mNumReaders;    
-    FileData            mFileData;
-
-
-    void                        ReadNextChunk ();
-    
-    void                        StartFixedPriorityThread ();
-    static UInt32               GetThreadBasePriority (pthread_t inThread);
-    
-    static void*                DiskReaderEntry (void *inRefCon);
-};
-
-FileReaderThread::FileReaderThread ()
-      : mThreadPriority (62),
-        mNumReaders (0)
-{
-}
-
-void    FileReaderThread::AddReader()
-{
-    if (mNumReaders == 0)
-    {
-        mThreadShouldDie = false;
-    
-        StartFixedPriorityThread ();
-    }
-    mNumReaders++;
-}
-
-void    FileReaderThread::RemoveReader (AudioFileManager* inItem)
-{
-    if (mNumReaders > 0)
-    {
-        CAGuard::Locker fileReadLock (mGuard);
-        
-        mFileData.remove (inItem);
-        
-        if (--mNumReaders == 0) {
-            mThreadShouldDie = true;
-            mGuard.Notify(); // wake up thread so it will quit
-            mGuard.Wait();   // wait for thread to die
-        }
-    }   
-}
-
-void    FileReaderThread::StartFixedPriorityThread ()
-{
-    pthread_attr_t      theThreadAttrs;
-    pthread_t           pThread;
-    
-    OSStatus result = pthread_attr_init(&theThreadAttrs);
-        THROW_RESULT("pthread_attr_init - Thread attributes could not be created.")
-    
-    result = pthread_attr_setdetachstate(&theThreadAttrs, PTHREAD_CREATE_DETACHED);
-        THROW_RESULT("pthread_attr_setdetachstate - Thread attributes could not be detached.")
-    
-    result = pthread_create (&pThread, &theThreadAttrs, DiskReaderEntry, this);
-        THROW_RESULT("pthread_create - Create and start the thread.")
-    
-    pthread_attr_destroy(&theThreadAttrs);
-    
-    // we've now created the thread and started it
-    // we'll now set the priority of the thread to the nominated priority
-    // and we'll also make the thread fixed
-    thread_extended_policy_data_t       theFixedPolicy;
-    thread_precedence_policy_data_t     thePrecedencePolicy;
-    SInt32                              relativePriority;
-    
-    // make thread fixed
-    theFixedPolicy.timeshare = false;   // set to true for a non-fixed thread
-    result = thread_policy_set (pthread_mach_thread_np(pThread), THREAD_EXTENDED_POLICY, (thread_policy_t)&theFixedPolicy, THREAD_EXTENDED_POLICY_COUNT);
-        THROW_RESULT("thread_policy - Couldn't set thread as fixed priority.")
-    // set priority
-    // precedency policy's "importance" value is relative to spawning thread's priority
-    relativePriority = mThreadPriority - FileReaderThread::GetThreadBasePriority (pthread_self());
-        
-    thePrecedencePolicy.importance = relativePriority;
-    result = thread_policy_set (pthread_mach_thread_np(pThread), THREAD_PRECEDENCE_POLICY, (thread_policy_t)&thePrecedencePolicy, THREAD_PRECEDENCE_POLICY_COUNT);
-        THROW_RESULT("thread_policy - Couldn't set thread priority.")
-}
-
-UInt32  FileReaderThread::GetThreadBasePriority (pthread_t inThread)
-{
-    thread_basic_info_data_t            threadInfo;
-    policy_info_data_t                  thePolicyInfo;
-    unsigned int                        count;
-    
-    // get basic info
-    count = THREAD_BASIC_INFO_COUNT;
-    thread_info (pthread_mach_thread_np (inThread), THREAD_BASIC_INFO, (integer_t*)&threadInfo, &count);
-    
-    switch (threadInfo.policy) {
-        case POLICY_TIMESHARE:
-            count = POLICY_TIMESHARE_INFO_COUNT;
-            thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_TIMESHARE_INFO, (integer_t*)&(thePolicyInfo.ts), &count);
-            return thePolicyInfo.ts.base_priority;
-            break;
-            
-        case POLICY_FIFO:
-            count = POLICY_FIFO_INFO_COUNT;
-            thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_FIFO_INFO, (integer_t*)&(thePolicyInfo.fifo), &count);
-            if (thePolicyInfo.fifo.depressed) {
-                return thePolicyInfo.fifo.depress_priority;
-            } else {
-                return thePolicyInfo.fifo.base_priority;
-            }
-            break;
-            
-        case POLICY_RR:
-            count = POLICY_RR_INFO_COUNT;
-            thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_RR_INFO, (integer_t*)&(thePolicyInfo.rr), &count);
-            if (thePolicyInfo.rr.depressed) {
-                return thePolicyInfo.rr.depress_priority;
-            } else {
-                return thePolicyInfo.rr.base_priority;
-            }
-            break;
-    }
-    
-    return 0;
-}
-
-void    *FileReaderThread::DiskReaderEntry (void *inRefCon)
-{
-    FileReaderThread *This = (FileReaderThread *)inRefCon;
-    This->ReadNextChunk();
-    #if DEBUG
-    printf ("finished with reading file\n");
-    #endif
-    
-    return 0;
-}
-
-void    FileReaderThread::ReadNextChunk ()
-{
-    OSStatus result;
-    UInt32  dataChunkSize;
-    AudioFileManager* theItem = 0;
-
-    for (;;) 
-    {
-        { // this is a scoped based lock
-            CAGuard::Locker fileReadLock (mGuard);
-            
-            if (this->mThreadShouldDie) {
-            
-                mGuard.Notify();
-                return;
-            }
-            
-            if (mFileData.empty())
-            {
-                mGuard.Wait();
-            }
-                        
-            // kill thread
-            if (this->mThreadShouldDie) {
-            
-                mGuard.Notify();
-                return;
-            }
-
-            theItem = mFileData.front();
-            mFileData.pop_front();
-        }
-    
-        if ((theItem->mFileLength - theItem->mReadFilePosition) < theItem->mChunkSize)
-            dataChunkSize = theItem->mFileLength - theItem->mReadFilePosition;
-        else
-            dataChunkSize = theItem->mChunkSize;
-        
-            // this is the exit condition for the thread
-        if (dataChunkSize <= 0) {
-            theItem->mFinishedReadingData = true;
-            continue;
-        }
-            // construct pointer
-        char* writePtr = const_cast<char*>(theItem->GetFileBuffer() + 
-                                (theItem->mWriteToFirstBuffer ? 0 : theItem->mChunkSize));
-    
-            // read data
-        result = theItem->Read(writePtr, &dataChunkSize);
-        if (result != noErr && result != eofErr) {
-            theItem->GetParent().DoNotification(result);
-            continue;
-        }
-        
-        if (dataChunkSize != theItem->mChunkSize)
-        {
-            writePtr += dataChunkSize;
-
-            // can't exit yet.. we still have to pass the partial buffer back
-            memset (writePtr, 0, (theItem->mChunkSize - dataChunkSize));
-        }
-        
-        theItem->mWriteToFirstBuffer = !theItem->mWriteToFirstBuffer;   // switch buffers
-        
-        if (result == eofErr)
-            theItem->mReadFilePosition = theItem->mFileLength;
-        else
-            theItem->mReadFilePosition += dataChunkSize;        // increment count
-    }
-}
-
-
-static FileReaderThread sReaderThread;
-
-AudioFileManager::AudioFileManager (AudioFilePlayer &inParent, 
-                                    SInt16          inForkRefNum, 
-                                    SInt64          inFileLength,
-                                    UInt32          inChunkSize)
-    : mParent (inParent),
-      mForkRefNum (inForkRefNum),
-      mFileBuffer (0),
-      mByteCounter (0),
-      mLockUnsuccessful (false),
-      mIsEngaged (false),
-
-      mBufferSize (inChunkSize),
-      mBufferOffset (inChunkSize),
-      mChunkSize (inChunkSize),
-      mFileLength (inFileLength),
-      mReadFilePosition (0),
-      mWriteToFirstBuffer (false),
-      mFinishedReadingData (false)
-
-{
-    mFileBuffer = (char*) malloc (mChunkSize * 2);
-    FSGetForkPosition(mForkRefNum, &mAudioDataOffset);
-    assert (mFileBuffer != NULL);
-}
-
-void    AudioFileManager::DoConnect ()
-{
-    if (!mIsEngaged)
-    {
-        //mReadFilePosition = 0;
-        mFinishedReadingData = false;
-
-        mNumTimesAskedSinceFinished = 0;
-        mLockUnsuccessful = false;
-        
-        OSStatus result;
-        UInt32 dataChunkSize;
-        
-        if ((mFileLength - mReadFilePosition) < mChunkSize)
-            dataChunkSize = mFileLength - mReadFilePosition;
-        else
-            dataChunkSize = mChunkSize;
-        
-        result = Read(mFileBuffer, &dataChunkSize);
-           THROW_RESULT("AudioFileManager::DoConnect(): Read")
-
-        mReadFilePosition += dataChunkSize;
-                
-        mWriteToFirstBuffer = false;
-        mReadFromFirstBuffer = true;
-
-        sReaderThread.AddReader();
-        
-        mIsEngaged = true;
-    }
-    else
-        throw static_cast<OSStatus>(-1); //thread has already been started
-}
-
-void    AudioFileManager::Disconnect ()
-{
-    if (mIsEngaged) 
-    {
-        sReaderThread.RemoveReader (this);
-        mIsEngaged = false;
-    }
-}
-
-OSStatus AudioFileManager::Read(char *buffer, UInt32 *len)
-{
-    return FSReadFork (mForkRefNum,
-                       fsFromStart,
-                       mReadFilePosition + mAudioDataOffset,
-                       *len,
-                       buffer,
-                       len);
-}
-
-OSStatus AudioFileManager::GetFileData (void** inOutData, UInt32 *inOutDataSize)
-{
-    if (mFinishedReadingData) 
-    {
-        ++mNumTimesAskedSinceFinished;
-        *inOutDataSize = 0;
-        *inOutData = 0;
-        return noErr;
-    }
-    
-    if (mReadFromFirstBuffer == mWriteToFirstBuffer) {
-        #if DEBUG
-        printf ("* * * * * * * Can't keep up with reading file\n");
-        #endif
-        
-        mParent.DoNotification (kAudioFilePlayErr_FilePlayUnderrun);
-        *inOutDataSize = 0;
-        *inOutData = 0;
-    } else {
-        *inOutDataSize = mChunkSize;
-        *inOutData = mReadFromFirstBuffer ? mFileBuffer : (mFileBuffer + mChunkSize);
-    }
-
-    mLockUnsuccessful = !sReaderThread.TryNextRead (this);
-    
-    mReadFromFirstBuffer = !mReadFromFirstBuffer;
-
-    return noErr;
-}
-
-void    AudioFileManager::AfterRender ()
-{
-    if (mNumTimesAskedSinceFinished > 0)
-    {
-        bool didLock = false;
-        if (sReaderThread.GetGuard().Try (didLock)) {
-            mParent.DoNotification (kAudioFilePlay_FileIsFinished);
-            if (didLock)
-                sReaderThread.GetGuard().Unlock();
-        }
-    }
-
-    if (mLockUnsuccessful)
-        mLockUnsuccessful = !sReaderThread.TryNextRead (this);
-}
-
-void    AudioFileManager::SetPosition (SInt64 pos)
-{
-    if (pos < 0 || pos >= mFileLength) {
-        SDL_SetError ("AudioFileManager::SetPosition - position invalid: %d filelen=%d\n", 
-            (unsigned int)pos, (unsigned int)mFileLength);
-        pos = 0;
-    }
-        
-    mReadFilePosition = pos;
-}
-    
-void    AudioFileManager::SetEndOfFile (SInt64 pos)
-{
-    if (pos <= 0 || pos > mFileLength) {
-        SDL_SetError ("AudioFileManager::SetEndOfFile - position beyond actual eof\n");
-        pos = mFileLength;
-    }
-    
-    mFileLength = pos;
-}
--- a/src/cdrom/macosx/CAGuard.cpp	Sun Sep 11 04:15:44 2005 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,160 +0,0 @@
-/*
-    SDL - Simple DirectMedia Layer
-    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Library General Public
-    License as published by the Free Software Foundation; either
-    version 2 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
-    Library General Public License for more details.
-
-    You should have received a copy of the GNU Library General Public
-    License along with this library; if not, write to the Free
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-    Sam Lantinga
-    slouken@libsdl.org
-*/
-/*  
-    Note: This file hasn't been modified so technically we have to keep the disclaimer :-(
-    
-    Copyright:  © Copyright 2002 Apple Computer, Inc. All rights reserved.
-
-    Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
-            ("Apple") in consideration of your agreement to the following terms, and your
-            use, installation, modification or redistribution of this Apple software
-            constitutes acceptance of these terms.  If you do not agree with these terms,
-            please do not use, install, modify or redistribute this Apple software.
-
-            In consideration of your agreement to abide by the following terms, and subject
-            to these terms, Apple grants you a personal, non-exclusive license, under AppleΥs
-            copyrights in this original Apple software (the "Apple Software"), to use,
-            reproduce, modify and redistribute the Apple Software, with or without
-            modifications, in source and/or binary forms; provided that if you redistribute
-            the Apple Software in its entirety and without modifications, you must retain
-            this notice and the following text and disclaimers in all such redistributions of
-            the Apple Software.  Neither the name, trademarks, service marks or logos of
-            Apple Computer, Inc. may be used to endorse or promote products derived from the
-            Apple Software without specific prior written permission from Apple.  Except as
-            expressly stated in this notice, no other rights or licenses, express or implied,
-            are granted by Apple herein, including but not limited to any patent rights that
-            may be infringed by your derivative works or by other works in which the Apple
-            Software may be incorporated.
-
-            The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
-            WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
-            WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-            PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
-            COMBINATION WITH YOUR PRODUCTS.
-
-            IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
-            CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
-            GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-            ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
-            OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
-            (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
-            ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-/*=============================================================================
-    CAGuard.cp
-
-=============================================================================*/
-
-//=============================================================================
-//  Includes
-//=============================================================================
-
-#include <stdio.h>
-
-//#define NDEBUG 1
-#include <assert.h>
-
-
-#include "CAGuard.h"
-
-//#warning      Need a try-based Locker too
-//=============================================================================
-//  CAGuard
-//=============================================================================
-
-CAGuard::CAGuard()
-{
-    OSStatus theError = pthread_mutex_init(&mMutex, NULL);
-    assert(theError == 0);
-    
-    theError = pthread_cond_init(&mCondVar, NULL);
-    assert(theError == 0);
-    
-    mOwner = 0;
-}
-
-CAGuard::~CAGuard()
-{
-    pthread_mutex_destroy(&mMutex);
-    pthread_cond_destroy(&mCondVar);
-}
-
-bool    CAGuard::Lock()
-{
-    bool theAnswer = false;
-    
-    if(pthread_self() != mOwner)
-    {
-        OSStatus theError = pthread_mutex_lock(&mMutex);
-        assert(theError == 0);
-        mOwner = pthread_self();
-        theAnswer = true;
-    }
-
-    return theAnswer;
-}
-
-void    CAGuard::Unlock()
-{
-    assert(pthread_self() == mOwner);
-
-    mOwner = 0;
-    OSStatus theError = pthread_mutex_unlock(&mMutex);
-    assert(theError == 0);
-}
-
-bool    CAGuard::Try (bool& outWasLocked)
-{
-    bool theAnswer = false;
-    outWasLocked = false;
-    
-    if (pthread_self() == mOwner) {
-        theAnswer = true;
-        outWasLocked = false;
-    } else {
-        OSStatus theError = pthread_mutex_trylock(&mMutex);
-        if (theError == 0) {
-            mOwner = pthread_self();
-            theAnswer = true;
-            outWasLocked = true;
-        }
-    }
-    
-    return theAnswer;
-}
-
-void    CAGuard::Wait()
-{
-    assert(pthread_self() == mOwner);
-
-    mOwner = 0;
-
-    OSStatus theError = pthread_cond_wait(&mCondVar, &mMutex);
-    assert(theError == 0);
-    mOwner = pthread_self();
-}
-
-void    CAGuard::Notify()
-{
-    OSStatus theError = pthread_cond_signal(&mCondVar);
-    assert(theError == 0);
-}
--- a/src/cdrom/macosx/CAGuard.h	Sun Sep 11 04:15:44 2005 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,143 +0,0 @@
-/*
-    SDL - Simple DirectMedia Layer
-    Copyright (C) 1997-2004 Sam Lantinga
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Library General Public
-    License as published by the Free Software Foundation; either
-    version 2 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
-    Library General Public License for more details.
-
-    You should have received a copy of the GNU Library General Public
-    License along with this library; if not, write to the Free
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-    Sam Lantinga
-    slouken@libsdl.org
-*/
-/*  
-    Note: This file hasn't been modified so technically we have to keep the disclaimer :-(
-
-
-    Copyright:  © Copyright 2002 Apple Computer, Inc. All rights reserved.
-
-    Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
-            ("Apple") in consideration of your agreement to the following terms, and your
-            use, installation, modification or redistribution of this Apple software
-            constitutes acceptance of these terms.  If you do not agree with these terms,
-            please do not use, install, modify or redistribute this Apple software.
-
-            In consideration of your agreement to abide by the following terms, and subject
-            to these terms, Apple grants you a personal, non-exclusive license, under AppleΥs
-            copyrights in this original Apple software (the "Apple Software"), to use,
-            reproduce, modify and redistribute the Apple Software, with or without
-            modifications, in source and/or binary forms; provided that if you redistribute
-            the Apple Software in its entirety and without modifications, you must retain
-            this notice and the following text and disclaimers in all such redistributions of
-            the Apple Software.  Neither the name, trademarks, service marks or logos of
-            Apple Computer, Inc. may be used to endorse or promote products derived from the
-            Apple Software without specific prior written permission from Apple.  Except as
-            expressly stated in this notice, no other rights or licenses, express or implied,
-            are granted by Apple herein, including but not limited to any patent rights that
-            may be infringed by your derivative works or by other works in which the Apple
-            Software may be incorporated.
-
-            The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
-            WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
-            WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-            PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
-            COMBINATION WITH YOUR PRODUCTS.
-
-            IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
-            CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
-            GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-            ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
-            OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
-            (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
-            ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-/*=============================================================================
-    CAGuard.h
-
-=============================================================================*/
-#if !defined(__CAGuard_h__)
-#define __CAGuard_h__
-
-//=============================================================================
-//  Includes
-//=============================================================================
-
-#include <CoreAudio/CoreAudioTypes.h>
-#include <pthread.h>
-
-
-//=============================================================================
-//  CAGuard
-//
-//  This is your typical mutex with signalling implemented via pthreads.
-//  Lock() will return true if and only if the guard is locked on that call.
-//  A thread that already has the guard will receive 'false' if it locks it
-//  again. Use of the stack-based CAGuard::Locker class is highly recommended
-//  to properly manage the recursive nesting. The Wait calls with timeouts
-//  will return true if and only if the timeout period expired. They will
-//  return false if they receive notification any other way.
-//=============================================================================
-
-class   CAGuard
-{
-
-//  Construction/Destruction
-public:
-                    CAGuard();
-    virtual         ~CAGuard();
-
-//  Actions
-public:
-    virtual bool    Lock();
-    virtual void    Unlock();
-    virtual bool    Try(bool& outWasLocked);    // returns true if lock is free, false if not
-        
-    virtual void    Wait();
-    
-    virtual void    Notify();
-
-//  Implementation
-protected:
-    pthread_mutex_t mMutex;
-    pthread_cond_t  mCondVar;
-    pthread_t       mOwner;
-    
-//  Helper class to manage taking and releasing recursively
-public:
-    class           Locker
-    {
-    
-    //  Construction/Destruction
-    public:
-                    Locker(CAGuard& inGuard) : mGuard(inGuard), mNeedsRelease(false) { mNeedsRelease = mGuard.Lock(); }
-                    ~Locker() { if(mNeedsRelease) { mGuard.Unlock(); } }
-    
-    private:
-                    Locker(const Locker&);
-        Locker&     operator=(const Locker&);
-    
-    //  Actions
-    public:
-        void        Wait() { mGuard.Wait(); }
-        
-        void        Notify() { mGuard.Notify(); }
-
-    //  Implementation
-    private:
-        CAGuard&    mGuard;
-        bool        mNeedsRelease;
-    
-    };
-
-};
-
-#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cdrom/macosx/CDPlayer.c	Thu Sep 22 08:48:16 2005 +0000
@@ -0,0 +1,663 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 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
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+    Sam Lantinga
+    slouken@libsdl.org
+*/
+
+#include "CDPlayer.h"
+#include "AudioFilePlayer.h"
+#include "SDLOSXCAGuard.h"
+
+// we're exporting these functions into C land for SDL_syscdrom.c
+//extern "C" {
+
+//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
+//  Constants
+//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
+
+#define kAudioCDFilesystemID   (UInt16)(('J' << 8) | 'H') // 'JH'; this avoids compiler warning
+
+// XML PList keys
+#define kRawTOCDataString           "Format 0x02 TOC Data"
+#define kSessionsString             "Sessions"
+#define kSessionTypeString          "Session Type"
+#define kTrackArrayString           "Track Array"
+#define kFirstTrackInSessionString      "First Track"
+#define kLastTrackInSessionString       "Last Track"
+#define kLeadoutBlockString         "Leadout Block"
+#define kDataKeyString              "Data"
+#define kPointKeyString             "Point"
+#define kSessionNumberKeyString         "Session Number"
+#define kStartBlockKeyString            "Start Block"   
+    
+//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
+//  Globals
+//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
+
+#pragma mark -- Globals --
+
+static int             playBackWasInit = 0;
+static AudioUnit        theUnit;
+static AudioFilePlayer* thePlayer = NULL;
+static CDPlayerCompletionProc   completionProc = NULL;
+static SDL_mutex       *apiMutex = NULL;
+static SDL_sem         *callbackSem;
+static SDL_CD*          theCDROM;
+
+//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
+//  Prototypes
+//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
+
+#pragma mark -- Prototypes --
+
+static OSStatus CheckInit ();
+
+static void     FilePlayNotificationHandler (void* inRefCon, OSStatus inStatus);
+
+static int      RunCallBackThread (void* inRefCon);
+
+
+#pragma mark -- Public Functions --
+
+void     Lock ()
+{
+    if (!apiMutex) {
+        apiMutex = SDL_CreateMutex();
+    }
+    SDL_mutexP(apiMutex);
+}
+
+void     Unlock ()
+{
+    SDL_mutexV(apiMutex);
+}
+
+//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
+//  DetectAudioCDVolumes
+//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
+
+int DetectAudioCDVolumes(FSVolumeRefNum *volumes, int numVolumes)
+{
+    int volumeIndex;
+    int cdVolumeCount = 0;
+    OSStatus result = noErr;
+    
+    for (volumeIndex = 1; result == noErr || result != nsvErr; volumeIndex++)
+    {
+        FSVolumeRefNum  actualVolume;
+        FSVolumeInfo    volumeInfo;
+        
+        memset (&volumeInfo, 0, sizeof(volumeInfo));
+        
+        result = FSGetVolumeInfo (kFSInvalidVolumeRefNum,
+                                  volumeIndex,
+                                  &actualVolume,
+                                  kFSVolInfoFSInfo,
+                                  &volumeInfo,
+                                  NULL,
+                                  NULL); 
+         
+        if (result == noErr)
+        {
+            if (volumeInfo.filesystemID == kAudioCDFilesystemID) // It's an audio CD
+            {
+                if (volumes != NULL && cdVolumeCount < numVolumes)
+                    volumes[cdVolumeCount] = actualVolume;
+            
+                cdVolumeCount++;
+            }
+        }
+        else 
+        {
+            // I'm commenting this out because it seems to be harmless
+            //SDL_SetError ("DetectAudioCDVolumes: FSGetVolumeInfo returned %d", result);
+        }
+    }
+        
+    return cdVolumeCount;
+}
+
+//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
+//  ReadTOCData
+//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
+
+int ReadTOCData (FSVolumeRefNum theVolume, SDL_CD *theCD)
+{
+    HFSUniStr255      dataForkName;
+    OSStatus          theErr;
+    SInt16            forkRefNum;
+    SInt64            forkSize;
+    Ptr               forkData = 0;
+    ByteCount         actualRead;
+    CFDataRef         dataRef = 0;
+    CFPropertyListRef propertyListRef = 0;
+
+    FSRefParam      fsRefPB;
+    FSRef           tocPlistFSRef;
+    
+    const char* error = "Unspecified Error";
+    
+    // get stuff from .TOC.plist                                                   
+    fsRefPB.ioCompletion = NULL;
+    fsRefPB.ioNamePtr = "\p.TOC.plist";
+    fsRefPB.ioVRefNum = theVolume;
+    fsRefPB.ioDirID = 0;
+    fsRefPB.newRef = &tocPlistFSRef;
+    
+    theErr = PBMakeFSRefSync (&fsRefPB);
+    if(theErr != noErr) {
+        error = "PBMakeFSRefSync";
+        goto bail;
+    }
+    
+    // Load and parse the TOC XML data
+
+    theErr = FSGetDataForkName (&dataForkName);
+    if (theErr != noErr) {
+        error = "FSGetDataForkName";
+        goto bail;
+    }
+    
+    theErr = FSOpenFork (&tocPlistFSRef, dataForkName.length, dataForkName.unicode, fsRdPerm, &forkRefNum);
+    if (theErr != noErr) {
+        error = "FSOpenFork";
+        goto bail;
+    }
+    
+    theErr = FSGetForkSize (forkRefNum, &forkSize);
+    if (theErr != noErr) {
+        error = "FSGetForkSize";
+        goto bail;
+    }
+    
+    // Allocate some memory for the XML data
+    forkData = NewPtr (forkSize);
+    if(forkData == NULL) {
+        error = "NewPtr";
+        goto bail;
+    }
+    
+    theErr = FSReadFork (forkRefNum, fsFromStart, 0 /* offset location */, forkSize, forkData, &actualRead);
+    if(theErr != noErr) {
+        error = "FSReadFork";
+        goto bail;
+    }
+    
+    dataRef = CFDataCreate (kCFAllocatorDefault, (UInt8 *)forkData, forkSize);
+    if(dataRef == 0) {
+        error = "CFDataCreate";
+        goto bail;
+    }
+
+    propertyListRef = CFPropertyListCreateFromXMLData (kCFAllocatorDefault,
+                                                       dataRef,
+                                                       kCFPropertyListImmutable,
+                                                       NULL);
+    if (propertyListRef == NULL) {
+        error = "CFPropertyListCreateFromXMLData";
+        goto bail;
+    }
+
+    // Now we got the Property List in memory. Parse it.
+    
+    // First, make sure the root item is a CFDictionary. If not, release and bail.
+    if(CFGetTypeID(propertyListRef)== CFDictionaryGetTypeID())
+    {
+        CFDictionaryRef dictRef = (CFDictionaryRef)propertyListRef;
+        
+        CFDataRef   theRawTOCDataRef;
+        CFArrayRef  theSessionArrayRef;
+        CFIndex     numSessions;
+        CFIndex     index;
+        
+        // This is how we get the Raw TOC Data
+        theRawTOCDataRef = (CFDataRef)CFDictionaryGetValue (dictRef, CFSTR(kRawTOCDataString));
+        
+        // Get the session array info.
+        theSessionArrayRef = (CFArrayRef)CFDictionaryGetValue (dictRef, CFSTR(kSessionsString));
+        
+        // Find out how many sessions there are.
+        numSessions = CFArrayGetCount (theSessionArrayRef);
+        
+        // Initialize the total number of tracks to 0
+        theCD->numtracks = 0;
+        
+        // Iterate over all sessions, collecting the track data
+        for(index = 0; index < numSessions; index++)
+        {
+            CFDictionaryRef theSessionDict;
+            CFNumberRef     leadoutBlock;
+            CFArrayRef      trackArray;
+            CFIndex         numTracks;
+            CFIndex         trackIndex;
+            UInt32          value = 0;
+            
+            theSessionDict      = (CFDictionaryRef) CFArrayGetValueAtIndex (theSessionArrayRef, index);
+            leadoutBlock        = (CFNumberRef) CFDictionaryGetValue (theSessionDict, CFSTR(kLeadoutBlockString));
+            
+            trackArray = (CFArrayRef)CFDictionaryGetValue (theSessionDict, CFSTR(kTrackArrayString));
+            
+            numTracks = CFArrayGetCount (trackArray);
+
+            for(trackIndex = 0; trackIndex < numTracks; trackIndex++) {
+                    
+                CFDictionaryRef theTrackDict;
+                CFNumberRef     trackNumber;
+                CFNumberRef     sessionNumber;
+                CFNumberRef     startBlock;
+                CFBooleanRef    isDataTrack;
+                UInt32          value;
+                
+                theTrackDict  = (CFDictionaryRef) CFArrayGetValueAtIndex (trackArray, trackIndex);
+                
+                trackNumber   = (CFNumberRef)  CFDictionaryGetValue (theTrackDict, CFSTR(kPointKeyString));
+                sessionNumber = (CFNumberRef)  CFDictionaryGetValue (theTrackDict, CFSTR(kSessionNumberKeyString));
+                startBlock    = (CFNumberRef)  CFDictionaryGetValue (theTrackDict, CFSTR(kStartBlockKeyString));
+                isDataTrack   = (CFBooleanRef) CFDictionaryGetValue (theTrackDict, CFSTR(kDataKeyString));
+                                                        
+                // Fill in the SDL_CD struct
+                int idx = theCD->numtracks++;
+
+                CFNumberGetValue (trackNumber, kCFNumberSInt32Type, &value);
+                theCD->track[idx].id = value;
+                
+                CFNumberGetValue (startBlock, kCFNumberSInt32Type, &value);
+                theCD->track[idx].offset = value;
+
+                theCD->track[idx].type = (isDataTrack == kCFBooleanTrue) ? SDL_DATA_TRACK : SDL_AUDIO_TRACK;
+
+                // Since the track lengths are not stored in .TOC.plist we compute them.
+                if (trackIndex > 0) {
+                    theCD->track[idx-1].length = theCD->track[idx].offset - theCD->track[idx-1].offset;
+                }
+            }
+            
+            // Compute the length of the last track
+            CFNumberGetValue (leadoutBlock, kCFNumberSInt32Type, &value);
+            
+            theCD->track[theCD->numtracks-1].length = 
+                value - theCD->track[theCD->numtracks-1].offset;
+
+            // Set offset to leadout track
+            theCD->track[theCD->numtracks].offset = value;
+        }
+    
+    }
+
+    theErr = 0;
+    goto cleanup;
+bail:
+    SDL_SetError ("ReadTOCData: %s returned %d", error, theErr);
+    theErr = -1;
+cleanup:
+
+    if (propertyListRef != NULL)
+        CFRelease(propertyListRef);
+    if (dataRef != NULL)
+        CFRelease(dataRef);
+    if (forkData != NULL)
+        DisposePtr(forkData);
+        
+    FSCloseFork (forkRefNum);
+
+    return theErr;
+}
+
+//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
+//  ListTrackFiles
+//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
+
+int ListTrackFiles (FSVolumeRefNum theVolume, FSRef *trackFiles, int numTracks)
+{
+    OSStatus        result = -1;
+    FSIterator      iterator;
+    ItemCount       actualObjects;
+    FSRef           rootDirectory;
+    FSRef           ref;
+    HFSUniStr255    nameStr;
+    
+    result = FSGetVolumeInfo (theVolume,
+                              0,
+                              NULL,
+                              kFSVolInfoFSInfo,
+                              NULL,
+                              NULL,
+                              &rootDirectory); 
+                                 
+    if (result != noErr) {
+        SDL_SetError ("ListTrackFiles: FSGetVolumeInfo returned %d", result);
+        return result;
+    }
+
+    result = FSOpenIterator (&rootDirectory, kFSIterateFlat, &iterator);
+    if (result == noErr) {
+        do
+        {
+            result = FSGetCatalogInfoBulk (iterator, 1, &actualObjects,
+                                           NULL, kFSCatInfoNone, NULL, &ref, NULL, &nameStr);
+            if (result == noErr) {
+                
+                CFStringRef  name;
+                name = CFStringCreateWithCharacters (NULL, nameStr.unicode, nameStr.length);
+                
+                // Look for .aiff extension
+                if (CFStringHasSuffix (name, CFSTR(".aiff")) ||
+                    CFStringHasSuffix (name, CFSTR(".cdda"))) {
+                    
+                    // Extract the track id from the filename
+                    int trackID = 0, i = 0;
+                    while (i < nameStr.length && !isdigit(nameStr.unicode[i])) {
+                        ++i;
+                    }
+                    while (i < nameStr.length && isdigit(nameStr.unicode[i])) {
+                        trackID = 10 * trackID +(nameStr.unicode[i] - '0');
+                        ++i;
+                    }
+
+                    #if DEBUG_CDROM
+                    printf("Found AIFF for track %d: '%s'\n", trackID, 
+                    CFStringGetCStringPtr (name, CFStringGetSystemEncoding()));
+                    #endif
+                    
+                    // Track ID's start at 1, but we want to start at 0
+                    trackID--;
+                    
+                    assert(0 <= trackID && trackID <= SDL_MAX_TRACKS);
+                    
+                    if (trackID < numTracks)
+                        memcpy (&trackFiles[trackID], &ref, sizeof(FSRef));
+                }
+                CFRelease (name);
+            }
+        } while(noErr == result);
+        FSCloseIterator (iterator);
+    }
+    
+    return 0;
+}
+
+//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
+//  LoadFile
+//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
+
+int LoadFile (const FSRef *ref, int startFrame, int stopFrame)
+{
+    int error = -1;
+    
+    if (CheckInit () < 0)
+        goto bail;
+    
+    // release any currently playing file
+    if (ReleaseFile () < 0)
+        goto bail;
+    
+    #if DEBUG_CDROM
+    printf ("LoadFile: %d %d\n", startFrame, stopFrame);
+    #endif
+    
+    //try {
+    
+        // create a new player, and attach to the audio unit
+        
+        thePlayer = new_AudioFilePlayer(ref);
+        if (thePlayer == NULL) {
+            SDL_SetError ("LoadFile: Could not create player");
+            return -3; //throw (-3);
+        }
+            
+        if (!thePlayer->SetDestination(thePlayer, &theUnit))
+            goto bail;
+        
+        if (startFrame >= 0)
+            thePlayer->SetStartFrame (thePlayer, startFrame);
+        
+        if (stopFrame >= 0 && stopFrame > startFrame)
+            thePlayer->SetStopFrame (thePlayer, stopFrame);
+        
+        // we set the notifier later
+        //thePlayer->SetNotifier(thePlayer, FilePlayNotificationHandler, NULL);
+            
+        if (!thePlayer->Connect(thePlayer))
+            goto bail;
+    
+        #if DEBUG_CDROM
+        thePlayer->Print(thePlayer);
+        fflush (stdout);
+        #endif
+    //}
+    //catch (...)
+    //{
+    //    goto bail;
+    //}
+        
+    error = 0;
+
+    bail:
+    return error;
+}
+
+//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
+//  ReleaseFile
+//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
+
+int ReleaseFile ()
+{
+    int error = -1;
+        
+    // (Don't see any way that the original C++ code could throw here.) --ryan.
+    //try {
+        if (thePlayer != NULL) {
+            
+            thePlayer->Disconnect(thePlayer);
+            
+            delete_AudioFilePlayer(thePlayer);
+            
+            thePlayer = NULL;
+        }
+    //}
+    //catch (...)
+    //{
+    //    goto bail;
+    //}
+    
+    error = 0;
+    
+//  bail:
+    return error;
+}
+
+//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
+//  PlayFile
+//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
+
+int PlayFile ()
+{
+    OSStatus result = -1;
+    
+    if (CheckInit () < 0)
+        goto bail;
+        
+//    try {
+    
+        // start processing of the audio unit
+        result = AudioOutputUnitStart (theUnit);
+            if (result) goto bail; //THROW_RESULT("PlayFile: AudioOutputUnitStart")
+        
+//    }
+//    catch (...)
+//    {
+//        goto bail;
+//    }
+    
+    result = 0;
+    
+bail:
+    return result;
+}
+
+//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
+//  PauseFile
+//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
+
+int PauseFile ()
+{
+    OSStatus result = -1;
+    
+    if (CheckInit () < 0)
+        goto bail;
+            
+    //try {
+    
+        // stop processing the audio unit
+        result = AudioOutputUnitStop (theUnit);
+            if (result) goto bail;  //THROW_RESULT("PauseFile: AudioOutputUnitStop")
+    //}
+    //catch (...)
+    //{
+    //    goto bail;
+    //}
+    
+    result = 0;
+bail:
+    return result;
+}
+
+//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
+//  SetCompletionProc
+//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
+
+void SetCompletionProc (CDPlayerCompletionProc proc, SDL_CD *cdrom)
+{
+    assert(thePlayer != NULL);
+
+    theCDROM = cdrom;
+    completionProc = proc;
+    thePlayer->SetNotifier (thePlayer, FilePlayNotificationHandler, cdrom);
+}
+
+//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
+//  GetCurrentFrame
+//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
+
+int GetCurrentFrame ()
+{    
+    int frame;
+    
+    if (thePlayer == NULL)
+        frame = 0;
+    else
+        frame = thePlayer->GetCurrentFrame (thePlayer);
+        
+    return frame; 
+}
+
+
+#pragma mark -- Private Functions --
+
+static OSStatus CheckInit ()
+{    
+    if (playBackWasInit)
+        return 0;
+    
+    OSStatus result = noErr;
+    
+    // Create the callback semaphore
+    callbackSem = SDL_CreateSemaphore(0);
+
+    // Start callback thread
+    SDL_CreateThread(RunCallBackThread, NULL);
+
+    { //try {
+        ComponentDescription desc;
+    
+        desc.componentType = kAudioUnitComponentType;
+        desc.componentSubType = kAudioUnitSubType_Output;
+        desc.componentManufacturer = kAudioUnitID_DefaultOutput;
+        desc.componentFlags = 0;
+        desc.componentFlagsMask = 0;
+        
+        Component comp = FindNextComponent (NULL, &desc);
+        if (comp == NULL) {
+            SDL_SetError ("CheckInit: FindNextComponent returned NULL");
+            if (result) return -1; //throw(internalComponentErr);
+        }
+        
+        result = OpenAComponent (comp, &theUnit);
+            if (result) return -1; //THROW_RESULT("CheckInit: OpenAComponent")
+                    
+        // you need to initialize the output unit before you set it as a destination
+        result = AudioUnitInitialize (theUnit);
+            if (result) return -1; //THROW_RESULT("CheckInit: AudioUnitInitialize")
+        
+                    
+        playBackWasInit = true;
+    }
+    //catch (...)
+    //{
+    //    return -1;
+    //}
+    
+    return 0;
+}
+
+static void FilePlayNotificationHandler(void * inRefCon, OSStatus inStatus)
+{
+    if (inStatus == kAudioFilePlay_FileIsFinished) {
+    
+        // notify non-CA thread to perform the callback
+        SDL_SemPost(callbackSem);
+        
+    } else if (inStatus == kAudioFilePlayErr_FilePlayUnderrun) {
+    
+        SDL_SetError ("CDPlayer Notification: buffer underrun");
+    } else if (inStatus == kAudioFilePlay_PlayerIsUninitialized) {
+    
+        SDL_SetError ("CDPlayer Notification: player is uninitialized");
+    } else {
+        
+        SDL_SetError ("CDPlayer Notification: unknown error %ld", inStatus);
+    }
+}
+
+static int RunCallBackThread (void *param)
+{
+    for (;;) {
+    
+	SDL_SemWait(callbackSem);
+
+        if (completionProc && theCDROM) {
+            #if DEBUG_CDROM
+            printf ("callback!\n");
+            #endif
+            (*completionProc)(theCDROM);
+        } else {
+            #if DEBUG_CDROM
+            printf ("callback?\n");
+            #endif
+        }
+    }
+    
+    #if DEBUG_CDROM
+    printf ("thread dying now...\n");
+    #endif
+    
+    return 0;
+}
+
+//}; // extern "C"
--- a/src/cdrom/macosx/CDPlayer.cpp	Sun Sep 11 04:15:44 2005 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,660 +0,0 @@
-/*
-    SDL - Simple DirectMedia Layer
-    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Library General Public
-    License as published by the Free Software Foundation; either
-    version 2 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
-    Library General Public License for more details.
-
-    You should have received a copy of the GNU Library General Public
-    License along with this library; if not, write to the Free
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-
-    Sam Lantinga
-    slouken@libsdl.org
-*/
-
-#include "CDPlayer.h"
-#include "AudioFilePlayer.h"
-#include "CAGuard.h"
-
-// we're exporting these functions into C land for SDL_syscdrom.c
-extern "C" {
-
-//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
-//  Constants
-//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
-
-#define kAudioCDFilesystemID   (UInt16)(('J' << 8) | 'H') // 'JH'; this avoids compiler warning
-
-// XML PList keys
-#define kRawTOCDataString           "Format 0x02 TOC Data"
-#define kSessionsString             "Sessions"
-#define kSessionTypeString          "Session Type"
-#define kTrackArrayString           "Track Array"
-#define kFirstTrackInSessionString      "First Track"
-#define kLastTrackInSessionString       "Last Track"
-#define kLeadoutBlockString         "Leadout Block"
-#define kDataKeyString              "Data"
-#define kPointKeyString             "Point"
-#define kSessionNumberKeyString         "Session Number"
-#define kStartBlockKeyString            "Start Block"   
-    
-//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
-//  Globals
-//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
-
-#pragma mark -- Globals --
-
-static bool             playBackWasInit = false;
-static AudioUnit        theUnit;
-static AudioFilePlayer* thePlayer = NULL;
-static CDPlayerCompletionProc   completionProc = NULL;
-static SDL_mutex       *apiMutex = NULL;
-static SDL_sem         *callbackSem;
-static SDL_CD*          theCDROM;
-
-//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
-//  Prototypes
-//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
-
-#pragma mark -- Prototypes --
-
-static OSStatus CheckInit ();
-
-static void     FilePlayNotificationHandler (void* inRefCon, OSStatus inStatus);
-
-static int      RunCallBackThread (void* inRefCon);
-
-
-#pragma mark -- Public Functions --
-
-void     Lock ()
-{
-    if (!apiMutex) {
-        apiMutex = SDL_CreateMutex();
-    }
-    SDL_mutexP(apiMutex);
-}
-
-void     Unlock ()
-{
-    SDL_mutexV(apiMutex);
-}
-
-//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
-//  DetectAudioCDVolumes
-//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
-
-int DetectAudioCDVolumes(FSVolumeRefNum *volumes, int numVolumes)
-{
-    int volumeIndex;
-    int cdVolumeCount = 0;
-    OSStatus result = noErr;
-    
-    for (volumeIndex = 1; result == noErr || result != nsvErr; volumeIndex++)
-    {
-        FSVolumeRefNum  actualVolume;
-        FSVolumeInfo    volumeInfo;
-        
-        memset (&volumeInfo, 0, sizeof(volumeInfo));
-        
-        result = FSGetVolumeInfo (kFSInvalidVolumeRefNum,
-                                  volumeIndex,
-                                  &actualVolume,
-                                  kFSVolInfoFSInfo,
-                                  &volumeInfo,
-                                  NULL,
-                                  NULL); 
-         
-        if (result == noErr)
-        {
-            if (volumeInfo.filesystemID == kAudioCDFilesystemID) // It's an audio CD
-            {
-                if (volumes != NULL && cdVolumeCount < numVolumes)
-                    volumes[cdVolumeCount] = actualVolume;
-            
-                cdVolumeCount++;
-            }
-        }
-        else 
-        {
-            // I'm commenting this out because it seems to be harmless
-            //SDL_SetError ("DetectAudioCDVolumes: FSGetVolumeInfo returned %d", result);
-        }
-    }
-        
-    return cdVolumeCount;
-}
-
-//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
-//  ReadTOCData
-//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
-
-int ReadTOCData (FSVolumeRefNum theVolume, SDL_CD *theCD)
-{
-    HFSUniStr255      dataForkName;
-    OSStatus          theErr;
-    SInt16            forkRefNum;
-    SInt64            forkSize;
-    Ptr               forkData = 0;
-    ByteCount         actualRead;
-    CFDataRef         dataRef = 0;
-    CFPropertyListRef propertyListRef = 0;
-
-    FSRefParam      fsRefPB;
-    FSRef           tocPlistFSRef;
-    
-    const char* error = "Unspecified Error";
-    
-    // get stuff from .TOC.plist                                                   
-    fsRefPB.ioCompletion = NULL;
-    fsRefPB.ioNamePtr = "\p.TOC.plist";
-    fsRefPB.ioVRefNum = theVolume;
-    fsRefPB.ioDirID = 0;
-    fsRefPB.newRef = &tocPlistFSRef;
-    
-    theErr = PBMakeFSRefSync (&fsRefPB);
-    if(theErr != noErr) {
-        error = "PBMakeFSRefSync";
-        goto bail;
-    }
-    
-    // Load and parse the TOC XML data
-
-    theErr = FSGetDataForkName (&dataForkName);
-    if (theErr != noErr) {
-        error = "FSGetDataForkName";
-        goto bail;
-    }
-    
-    theErr = FSOpenFork (&tocPlistFSRef, dataForkName.length, dataForkName.unicode, fsRdPerm, &forkRefNum);
-    if (theErr != noErr) {
-        error = "FSOpenFork";
-        goto bail;
-    }
-    
-    theErr = FSGetForkSize (forkRefNum, &forkSize);
-    if (theErr != noErr) {
-        error = "FSGetForkSize";
-        goto bail;
-    }
-    
-    // Allocate some memory for the XML data
-    forkData = NewPtr (forkSize);
-    if(forkData == NULL) {
-        error = "NewPtr";
-        goto bail;
-    }
-    
-    theErr = FSReadFork (forkRefNum, fsFromStart, 0 /* offset location */, forkSize, forkData, &actualRead);
-    if(theErr != noErr) {
-        error = "FSReadFork";
-        goto bail;
-    }
-    
-    dataRef = CFDataCreate (kCFAllocatorDefault, (UInt8 *)forkData, forkSize);
-    if(dataRef == 0) {
-        error = "CFDataCreate";
-        goto bail;
-    }
-
-    propertyListRef = CFPropertyListCreateFromXMLData (kCFAllocatorDefault,
-                                                       dataRef,
-                                                       kCFPropertyListImmutable,
-                                                       NULL);
-    if (propertyListRef == NULL) {
-        error = "CFPropertyListCreateFromXMLData";
-        goto bail;
-    }
-
-    // Now we got the Property List in memory. Parse it.
-    
-    // First, make sure the root item is a CFDictionary. If not, release and bail.
-    if(CFGetTypeID(propertyListRef)== CFDictionaryGetTypeID())
-    {
-        CFDictionaryRef dictRef = (CFDictionaryRef)propertyListRef;
-        
-        CFDataRef   theRawTOCDataRef;
-        CFArrayRef  theSessionArrayRef;
-        CFIndex     numSessions;
-        CFIndex     index;
-        
-        // This is how we get the Raw TOC Data
-        theRawTOCDataRef = (CFDataRef)CFDictionaryGetValue (dictRef, CFSTR(kRawTOCDataString));
-        
-        // Get the session array info.
-        theSessionArrayRef = (CFArrayRef)CFDictionaryGetValue (dictRef, CFSTR(kSessionsString));
-        
-        // Find out how many sessions there are.
-        numSessions = CFArrayGetCount (theSessionArrayRef);
-        
-        // Initialize the total number of tracks to 0
-        theCD->numtracks = 0;
-        
-        // Iterate over all sessions, collecting the track data
-        for(index = 0; index < numSessions; index++)
-        {
-            CFDictionaryRef theSessionDict;
-            CFNumberRef     leadoutBlock;
-            CFArrayRef      trackArray;
-            CFIndex         numTracks;
-            CFIndex         trackIndex;
-            UInt32          value = 0;
-            
-            theSessionDict      = (CFDictionaryRef) CFArrayGetValueAtIndex (theSessionArrayRef, index);
-            leadoutBlock        = (CFNumberRef) CFDictionaryGetValue (theSessionDict, CFSTR(kLeadoutBlockString));
-            
-            trackArray = (CFArrayRef)CFDictionaryGetValue (theSessionDict, CFSTR(kTrackArrayString));
-            
-            numTracks = CFArrayGetCount (trackArray);
-
-            for(trackIndex = 0; trackIndex < numTracks; trackIndex++) {
-                    
-                CFDictionaryRef theTrackDict;
-                CFNumberRef     trackNumber;
-                CFNumberRef     sessionNumber;
-                CFNumberRef     startBlock;
-                CFBooleanRef    isDataTrack;
-                UInt32          value;
-                
-                theTrackDict  = (CFDictionaryRef) CFArrayGetValueAtIndex (trackArray, trackIndex);
-                
-                trackNumber   = (CFNumberRef)  CFDictionaryGetValue (theTrackDict, CFSTR(kPointKeyString));
-                sessionNumber = (CFNumberRef)  CFDictionaryGetValue (theTrackDict, CFSTR(kSessionNumberKeyString));
-                startBlock    = (CFNumberRef)  CFDictionaryGetValue (theTrackDict, CFSTR(kStartBlockKeyString));
-                isDataTrack   = (CFBooleanRef) CFDictionaryGetValue (theTrackDict, CFSTR(kDataKeyString));
-                                                        
-                // Fill in the SDL_CD struct
-                int idx = theCD->numtracks++;
-
-                CFNumberGetValue (trackNumber, kCFNumberSInt32Type, &value);
-                theCD->track[idx].id = value;
-                
-                CFNumberGetValue (startBlock, kCFNumberSInt32Type, &value);
-                theCD->track[idx].offset = value;
-
-                theCD->track[idx].type = (isDataTrack == kCFBooleanTrue) ? SDL_DATA_TRACK : SDL_AUDIO_TRACK;
-
-                // Since the track lengths are not stored in .TOC.plist we compute them.
-                if (trackIndex > 0) {
-                    theCD->track[idx-1].length = theCD->track[idx].offset - theCD->track[idx-1].offset;
-                }
-            }
-            
-            // Compute the length of the last track
-            CFNumberGetValue (leadoutBlock, kCFNumberSInt32Type, &value);
-            
-            theCD->track[theCD->numtracks-1].length = 
-                value - theCD->track[theCD->numtracks-1].offset;
-
-            // Set offset to leadout track
-            theCD->track[theCD->numtracks].offset = value;
-        }
-    
-    }
-
-    theErr = 0;
-    goto cleanup;
-bail:
-    SDL_SetError ("ReadTOCData: %s returned %d", error, theErr);
-    theErr = -1;
-cleanup:
-
-    if (propertyListRef != NULL)
-        CFRelease(propertyListRef);
-    if (dataRef != NULL)
-        CFRelease(dataRef);
-    if (forkData != NULL)
-        DisposePtr(forkData);
-        
-    FSCloseFork (forkRefNum);
-
-    return theErr;
-}
-
-//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
-//  ListTrackFiles
-//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
-
-int ListTrackFiles (FSVolumeRefNum theVolume, FSRef *trackFiles, int numTracks)
-{
-    OSStatus        result = -1;
-    FSIterator      iterator;
-    ItemCount       actualObjects;
-    FSRef           rootDirectory;
-    FSRef           ref;
-    HFSUniStr255    nameStr;
-    
-    result = FSGetVolumeInfo (theVolume,
-                              0,
-                              NULL,
-                              kFSVolInfoFSInfo,
-                              NULL,
-                              NULL,
-                              &rootDirectory); 
-                                 
-    if (result != noErr) {
-        SDL_SetError ("ListTrackFiles: FSGetVolumeInfo returned %d", result);
-        return result;
-    }
-
-    result = FSOpenIterator (&rootDirectory, kFSIterateFlat, &iterator);
-    if (result == noErr) {
-        do
-        {
-            result = FSGetCatalogInfoBulk (iterator, 1, &actualObjects,
-                                           NULL, kFSCatInfoNone, NULL, &ref, NULL, &nameStr);
-            if (result == noErr) {
-                
-                CFStringRef  name;
-                name = CFStringCreateWithCharacters (NULL, nameStr.unicode, nameStr.length);
-                
-                // Look for .aiff extension
-                if (CFStringHasSuffix (name, CFSTR(".aiff")) ||
-                    CFStringHasSuffix (name, CFSTR(".cdda"))) {
-                    
-                    // Extract the track id from the filename
-                    int trackID = 0, i = 0;
-                    while (i < nameStr.length && !isdigit(nameStr.unicode[i])) {
-                        ++i;
-                    }
-                    while (i < nameStr.length && isdigit(nameStr.unicode[i])) {
-                        trackID = 10 * trackID +(nameStr.unicode[i] - '0');
-                        ++i;
-                    }
-
-                    #if DEBUG_CDROM
-                    printf("Found AIFF for track %d: '%s'\n", trackID, 
-                    CFStringGetCStringPtr (name, CFStringGetSystemEncoding()));
-                    #endif
-                    
-                    // Track ID's start at 1, but we want to start at 0
-                    trackID--;
-                    
-                    assert(0 <= trackID && trackID <= SDL_MAX_TRACKS);
-                    
-                    if (trackID < numTracks)
-                        memcpy (&trackFiles[trackID], &ref, sizeof(FSRef));
-                }
-                CFRelease (name);
-            }
-        } while(noErr == result);
-        FSCloseIterator (iterator);
-    }
-    
-    return 0;
-}
-
-//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
-//  LoadFile
-//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
-
-int LoadFile (const FSRef *ref, int startFrame, int stopFrame)
-{
-    int error = -1;
-    
-    if (CheckInit () < 0)
-        goto bail;
-    
-    // release any currently playing file
-    if (ReleaseFile () < 0)
-        goto bail;
-    
-    #if DEBUG_CDROM
-    printf ("LoadFile: %d %d\n", startFrame, stopFrame);
-    #endif
-    
-    try {
-    
-        // create a new player, and attach to the audio unit
-        
-        thePlayer = new AudioFilePlayer(ref);
-        if (thePlayer == NULL) {
-            SDL_SetError ("LoadFile: Could not create player");
-            throw (-3);
-        }
-            
-        thePlayer->SetDestination(theUnit);
-        
-        if (startFrame >= 0)
-            thePlayer->SetStartFrame (startFrame);
-        
-        if (stopFrame >= 0 && stopFrame > startFrame)
-            thePlayer->SetStopFrame (stopFrame);
-        
-        // we set the notifier later
-        //thePlayer->SetNotifier(FilePlayNotificationHandler, NULL);
-            
-        thePlayer->Connect();
-    
-        #if DEBUG_CDROM
-        thePlayer->Print();
-        fflush (stdout);
-        #endif
-    }
-    catch (...)
-    {
-        goto bail;
-    }
-        
-    error = 0;
-
-    bail:
-    return error;
-}
-
-//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
-//  ReleaseFile
-//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
-
-int ReleaseFile ()
-{
-    int error = -1;
-        
-    try {
-        if (thePlayer != NULL) {
-            
-            thePlayer->Disconnect();
-            
-            delete thePlayer;
-            
-            thePlayer = NULL;
-        }
-    }
-    catch (...)
-    {
-        goto bail;
-    }
-    
-    error = 0;
-    
-  bail:
-    return error;
-}
-
-//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
-//  PlayFile
-//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
-
-int PlayFile ()
-{
-    OSStatus result = -1;
-    
-    if (CheckInit () < 0)
-        goto bail;
-        
-    try {
-    
-        // start processing of the audio unit
-        result = AudioOutputUnitStart (theUnit);
-            THROW_RESULT("PlayFile: AudioOutputUnitStart")    
-        
-    }
-    catch (...)
-    {
-        goto bail;
-    }
-    
-    result = 0;
-    
-bail:
-    return result;
-}
-
-//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
-//  PauseFile
-//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
-
-int PauseFile ()
-{
-    OSStatus result = -1;
-    
-    if (CheckInit () < 0)
-        goto bail;
-            
-    try {
-    
-        // stop processing the audio unit
-        result = AudioOutputUnitStop (theUnit);
-            THROW_RESULT("PauseFile: AudioOutputUnitStop")
-    }
-    catch (...)
-    {
-        goto bail;
-    }
-    
-    result = 0;
-bail:
-    return result;
-}
-
-//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
-//  SetCompletionProc
-//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
-
-void SetCompletionProc (CDPlayerCompletionProc proc, SDL_CD *cdrom)
-{
-    assert(thePlayer != NULL);
-
-    theCDROM = cdrom;
-    completionProc = proc;
-    thePlayer->SetNotifier (FilePlayNotificationHandler, cdrom);
-}
-
-//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
-//  GetCurrentFrame
-//ΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡΡ
-
-int GetCurrentFrame ()
-{    
-    int frame;
-    
-    if (thePlayer == NULL)
-        frame = 0;
-    else
-        frame = thePlayer->GetCurrentFrame ();
-        
-    return frame; 
-}
-
-
-#pragma mark -- Private Functions --
-
-static OSStatus CheckInit ()
-{    
-    if (playBackWasInit)
-        return 0;
-    
-    OSStatus result = noErr;
-    
-    // Create the callback semaphore
-    callbackSem = SDL_CreateSemaphore(0);
-
-    // Start callback thread
-    SDL_CreateThread(RunCallBackThread, NULL);
-
-    try {
-        ComponentDescription desc;
-    
-        desc.componentType = kAudioUnitComponentType;
-        desc.componentSubType = kAudioUnitSubType_Output;
-        desc.componentManufacturer = kAudioUnitID_DefaultOutput;
-        desc.componentFlags = 0;
-        desc.componentFlagsMask = 0;
-        
-        Component comp = FindNextComponent (NULL, &desc);
-        if (comp == NULL) {
-            SDL_SetError ("CheckInit: FindNextComponent returned NULL");
-            throw(internalComponentErr);
-        }
-        
-        result = OpenAComponent (comp, &theUnit);
-            THROW_RESULT("CheckInit: OpenAComponent")
-                    
-        // you need to initialize the output unit before you set it as a destination
-        result = AudioUnitInitialize (theUnit);
-            THROW_RESULT("CheckInit: AudioUnitInitialize")
-        
-                    
-        playBackWasInit = true;
-    }
-    catch (...)
-    {
-        return -1;
-    }
-    
-    return 0;
-}
-
-static void FilePlayNotificationHandler(void * inRefCon, OSStatus inStatus)
-{
-    if (inStatus == kAudioFilePlay_FileIsFinished) {
-    
-        // notify non-CA thread to perform the callback
-        SDL_SemPost(callbackSem);
-        
-    } else if (inStatus == kAudioFilePlayErr_FilePlayUnderrun) {
-    
-        SDL_SetError ("CDPlayer Notification: buffer underrun");
-    } else if (inStatus == kAudioFilePlay_PlayerIsUninitialized) {
-    
-        SDL_SetError ("CDPlayer Notification: player is uninitialized");
-    } else {
-        
-        SDL_SetError ("CDPlayer Notification: unknown error %ld", inStatus);
-    }
-}
-
-static int RunCallBackThread (void *param)
-{
-    for (;;) {
-    
-	SDL_SemWait(callbackSem);
-
-        if (completionProc && theCDROM) {
-            #if DEBUG_CDROM
-            printf ("callback!\n");
-            #endif
-            (*completionProc)(theCDROM);
-        } else {
-            #if DEBUG_CDROM
-            printf ("callback?\n");
-            #endif
-        }
-    }
-    
-    #if DEBUG_CDROM
-    printf ("thread dying now...\n");
-    #endif
-    
-    return 0;
-}
-
-}; // extern "C"
--- a/src/cdrom/macosx/Makefile.am	Sun Sep 11 04:15:44 2005 +0000
+++ b/src/cdrom/macosx/Makefile.am	Thu Sep 22 08:48:16 2005 +0000
@@ -9,9 +9,8 @@
 	SDL_syscdrom_c.h \
 	SDL_syscdrom.c \
 	AudioFilePlayer.h \
-	AudioFilePlayer.cpp \
-	AudioFileReaderThread.cpp \
-	CAGuard.h \
-	CAGuard.cpp \
+	AudioFilePlayer.c \
+	AudioFileReaderThread.c \
+	SDLOSXCAGuard.c \
 	CDPlayer.h \
-	CDPlayer.cpp
+	CDPlayer.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cdrom/macosx/SDLOSXCAGuard.c	Thu Sep 22 08:48:16 2005 +0000
@@ -0,0 +1,182 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 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
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+    Sam Lantinga
+    slouken@libsdl.org
+*/
+/*  
+    Note: This file hasn't been modified so technically we have to keep the disclaimer :-(
+    
+    Copyright:  © Copyright 2002 Apple Computer, Inc. All rights reserved.
+
+    Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
+            ("Apple") in consideration of your agreement to the following terms, and your
+            use, installation, modification or redistribution of this Apple software
+            constitutes acceptance of these terms.  If you do not agree with these terms,
+            please do not use, install, modify or redistribute this Apple software.
+
+            In consideration of your agreement to abide by the following terms, and subject
+            to these terms, Apple grants you a personal, non-exclusive license, under AppleΥs
+            copyrights in this original Apple software (the "Apple Software"), to use,
+            reproduce, modify and redistribute the Apple Software, with or without
+            modifications, in source and/or binary forms; provided that if you redistribute
+            the Apple Software in its entirety and without modifications, you must retain
+            this notice and the following text and disclaimers in all such redistributions of
+            the Apple Software.  Neither the name, trademarks, service marks or logos of
+            Apple Computer, Inc. may be used to endorse or promote products derived from the
+            Apple Software without specific prior written permission from Apple.  Except as
+            expressly stated in this notice, no other rights or licenses, express or implied,
+            are granted by Apple herein, including but not limited to any patent rights that
+            may be infringed by your derivative works or by other works in which the Apple
+            Software may be incorporated.
+
+            The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
+            WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+            WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+            PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+            COMBINATION WITH YOUR PRODUCTS.
+
+            IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+            CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+            GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+            ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+            OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+            (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+            ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*=============================================================================
+    CAGuard.cp
+
+=============================================================================*/
+
+//=============================================================================
+//  Includes
+//=============================================================================
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+//#define NDEBUG 1
+#include <assert.h>
+
+
+#include "SDLOSXCAGuard.h"
+
+//#warning      Need a try-based Locker too
+//=============================================================================
+//  SDLOSXCAGuard
+//=============================================================================
+
+static int SDLOSXCAGuard_Lock(SDLOSXCAGuard *cag)
+{
+    int theAnswer = 0;
+    
+    if(pthread_self() != cag->mOwner)
+    {
+        OSStatus theError = pthread_mutex_lock(&cag->mMutex);
+        assert(theError == 0);
+        cag->mOwner = pthread_self();
+        theAnswer = 1;
+    }
+
+    return theAnswer;
+}
+
+static void    SDLOSXCAGuard_Unlock(SDLOSXCAGuard *cag)
+{
+    assert(pthread_self() == cag->mOwner);
+
+    cag->mOwner = 0;
+    OSStatus theError = pthread_mutex_unlock(&cag->mMutex);
+    assert(theError == 0);
+}
+
+static int SDLOSXCAGuard_Try (SDLOSXCAGuard *cag, int *outWasLocked)
+{
+    int theAnswer = 0;
+    *outWasLocked = 0;
+    
+    if (pthread_self() == cag->mOwner) {
+        theAnswer = 1;
+        *outWasLocked = 0;
+    } else {
+        OSStatus theError = pthread_mutex_trylock(&cag->mMutex);
+        if (theError == 0) {
+            cag->mOwner = pthread_self();
+            theAnswer = 1;
+            *outWasLocked = 1;
+        }
+    }
+    
+    return theAnswer;
+}
+
+static void    SDLOSXCAGuard_Wait(SDLOSXCAGuard *cag)
+{
+    assert(pthread_self() == cag->mOwner);
+
+    cag->mOwner = 0;
+
+    OSStatus theError = pthread_cond_wait(&cag->mCondVar, &cag->mMutex);
+    assert(theError == 0);
+    cag->mOwner = pthread_self();
+}
+
+static void    SDLOSXCAGuard_Notify(SDLOSXCAGuard *cag)
+{
+    OSStatus theError = pthread_cond_signal(&cag->mCondVar);
+    assert(theError == 0);
+}
+
+
+SDLOSXCAGuard *new_SDLOSXCAGuard(void)
+{
+    SDLOSXCAGuard *cag = (SDLOSXCAGuard *) malloc(sizeof (SDLOSXCAGuard));
+    if (cag == NULL)
+        return NULL;
+    memset(cag, '\0', sizeof (*cag));
+
+    #define SET_SDLOSXCAGUARD_METHOD(m) cag->m = SDLOSXCAGuard_##m
+    SET_SDLOSXCAGUARD_METHOD(Lock);
+    SET_SDLOSXCAGUARD_METHOD(Unlock);
+    SET_SDLOSXCAGUARD_METHOD(Try);
+    SET_SDLOSXCAGUARD_METHOD(Wait);
+    SET_SDLOSXCAGUARD_METHOD(Notify);
+    #undef SET_SDLOSXCAGUARD_METHOD
+
+    OSStatus theError = pthread_mutex_init(&cag->mMutex, NULL);
+    assert(theError == 0);
+    
+    theError = pthread_cond_init(&cag->mCondVar, NULL);
+    assert(theError == 0);
+    
+    cag->mOwner = 0;
+    return cag;
+}
+
+void delete_SDLOSXCAGuard(SDLOSXCAGuard *cag)
+{
+    if (cag != NULL)
+    {
+        pthread_mutex_destroy(&cag->mMutex);
+        pthread_cond_destroy(&cag->mCondVar);
+        free(cag);
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/cdrom/macosx/SDLOSXCAGuard.h	Thu Sep 22 08:48:16 2005 +0000
@@ -0,0 +1,114 @@
+/*
+    SDL - Simple DirectMedia Layer
+    Copyright (C) 1997-2004 Sam Lantinga
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 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
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public
+    License along with this library; if not, write to the Free
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+    Sam Lantinga
+    slouken@libsdl.org
+*/
+/*  
+    Note: This file hasn't been modified so technically we have to keep the disclaimer :-(
+
+
+    Copyright:  © Copyright 2002 Apple Computer, Inc. All rights reserved.
+
+    Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple Computer, Inc.
+            ("Apple") in consideration of your agreement to the following terms, and your
+            use, installation, modification or redistribution of this Apple software
+            constitutes acceptance of these terms.  If you do not agree with these terms,
+            please do not use, install, modify or redistribute this Apple software.
+
+            In consideration of your agreement to abide by the following terms, and subject
+            to these terms, Apple grants you a personal, non-exclusive license, under AppleΥs
+            copyrights in this original Apple software (the "Apple Software"), to use,
+            reproduce, modify and redistribute the Apple Software, with or without
+            modifications, in source and/or binary forms; provided that if you redistribute
+            the Apple Software in its entirety and without modifications, you must retain
+            this notice and the following text and disclaimers in all such redistributions of
+            the Apple Software.  Neither the name, trademarks, service marks or logos of
+            Apple Computer, Inc. may be used to endorse or promote products derived from the
+            Apple Software without specific prior written permission from Apple.  Except as
+            expressly stated in this notice, no other rights or licenses, express or implied,
+            are granted by Apple herein, including but not limited to any patent rights that
+            may be infringed by your derivative works or by other works in which the Apple
+            Software may be incorporated.
+
+            The Apple Software is provided by Apple on an "AS IS" basis.  APPLE MAKES NO
+            WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED
+            WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+            PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN
+            COMBINATION WITH YOUR PRODUCTS.
+
+            IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR
+            CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+            GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+            ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR DISTRIBUTION
+            OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF CONTRACT, TORT
+            (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN
+            ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+/*=============================================================================
+    CAGuard.h
+
+=============================================================================*/
+#if !defined(__CAGuard_h__)
+#define __CAGuard_h__
+
+//=============================================================================
+//  Includes
+//=============================================================================
+
+#include <CoreAudio/CoreAudioTypes.h>
+#include <pthread.h>
+
+
+//=============================================================================
+//  CAGuard
+//
+//  This is your typical mutex with signalling implemented via pthreads.
+//  Lock() will return true if and only if the guard is locked on that call.
+//  A thread that already has the guard will receive 'false' if it locks it
+//  again. Use of the stack-based CAGuard::Locker class is highly recommended
+//  to properly manage the recursive nesting. The Wait calls with timeouts
+//  will return true if and only if the timeout period expired. They will
+//  return false if they receive notification any other way.
+//=============================================================================
+
+typedef struct S_SDLOSXCAGuard
+{
+
+//  Construction/Destruction
+//public:
+//  Actions
+//public:
+    int     (*Lock)(struct S_SDLOSXCAGuard *cag);
+    void    (*Unlock)(struct S_SDLOSXCAGuard *cag);
+    int     (*Try)(struct S_SDLOSXCAGuard *cag, int *outWasLocked);    // returns true if lock is free, false if not
+    void    (*Wait)(struct S_SDLOSXCAGuard *cag);
+    void    (*Notify)(struct S_SDLOSXCAGuard *cag);
+
+//  Implementation
+//protected:
+    pthread_mutex_t mMutex;
+    pthread_cond_t  mCondVar;
+    pthread_t       mOwner;
+} SDLOSXCAGuard;
+
+SDLOSXCAGuard *new_SDLOSXCAGuard(void);
+void delete_SDLOSXCAGuard(SDLOSXCAGuard *cag);
+
+#endif
+