Commit 7be238c6 authored by Ryan C. Gordon's avatar Ryan C. Gordon

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.

--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%401146
parent cddfe242
...@@ -37,12 +37,14 @@ ...@@ -37,12 +37,14 @@
const char* AudioFilePlayerErrorStr (OSStatus error); const char* AudioFilePlayerErrorStr (OSStatus error);
/*
void ThrowResult (OSStatus result, const char *str); void ThrowResult (OSStatus result, const char *str);
#define THROW_RESULT(str) \ #define THROW_RESULT(str) \
if (result) { \ if (result) { \
ThrowResult (result, str); \ ThrowResult (result, str); \
} }
*/
typedef void (*AudioFilePlayNotifier)(void *inRefCon, typedef void (*AudioFilePlayNotifier)(void *inRefCon,
OSStatus inStatus); OSStatus inStatus);
...@@ -54,49 +56,25 @@ enum { ...@@ -54,49 +56,25 @@ enum {
}; };
class AudioFileManager; struct S_AudioFileManager;
#pragma mark __________ AudioFilePlayer #pragma mark __________ AudioFilePlayer
class AudioFilePlayer typedef struct S_AudioFilePlayer
{ {
public: //public:
AudioFilePlayer (const FSRef *inFileRef); int (*SetDestination)(struct S_AudioFilePlayer *afp, AudioUnit *inDestUnit);
void (*SetNotifier)(struct S_AudioFilePlayer *afp, AudioFilePlayNotifier inNotifier, void *inRefCon);
~AudioFilePlayer(); void (*SetStartFrame)(struct S_AudioFilePlayer *afp, int frame); // seek in the file
int (*GetCurrentFrame)(struct S_AudioFilePlayer *afp); // get the current frame position
void SetDestination (AudioUnit &inDestUnit); void (*SetStopFrame)(struct S_AudioFilePlayer *afp, int frame); // set limit in the file
int (*Connect)(struct S_AudioFilePlayer *afp);
void SetNotifier (AudioFilePlayNotifier inNotifier, void *inRefCon) void (*Disconnect)(struct S_AudioFilePlayer *afp);
{ void (*DoNotification)(struct S_AudioFilePlayer *afp, OSStatus inError);
mNotifier = inNotifier; int (*IsConnected)(struct S_AudioFilePlayer *afp);
mRefCon = inRefCon; AudioUnit (*GetDestUnit)(struct S_AudioFilePlayer *afp);
} void (*Print)(struct S_AudioFilePlayer *afp);
void SetStartFrame (int frame); // seek in the file //private:
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:
AudioUnit mPlayUnit; AudioUnit mPlayUnit;
SInt16 mForkRefNum; SInt16 mForkRefNum;
...@@ -104,9 +82,9 @@ private: ...@@ -104,9 +82,9 @@ private:
AudioStreamBasicDescription mFileDescription; AudioStreamBasicDescription mFileDescription;
bool mConnected; int mConnected;
AudioFileManager* mAudioFileManager; struct S_AudioFileManager* mAudioFileManager;
AudioFilePlayNotifier mNotifier; AudioFilePlayNotifier mNotifier;
void* mRefCon; void* mRefCon;
...@@ -115,41 +93,32 @@ private: ...@@ -115,41 +93,32 @@ private:
#pragma mark __________ Private_Methods #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 #pragma mark __________ AudioFileManager
class AudioFileManager typedef struct S_AudioFileManager
{ {
public: //public:
AudioFileManager (AudioFilePlayer &inParent,
SInt16 inForkRefNum,
SInt64 inFileLength,
UInt32 inChunkSize);
~AudioFileManager();
// this method should NOT be called by an object of this class // this method should NOT be called by an object of this class
// as it is called by the parent's Disconnect() method // as it is called by the parent's Disconnect() method
void Disconnect (); void (*Disconnect)(struct S_AudioFileManager *afm);
int (*DoConnect)(struct S_AudioFileManager *afm);
void DoConnect (); OSStatus (*Read)(struct S_AudioFileManager *afm, char *buffer, UInt32 *len);
const char* (*GetFileBuffer)(struct S_AudioFileManager *afm);
OSStatus Read(char *buffer, UInt32 *len); const AudioFilePlayer *(*GetParent)(struct S_AudioFileManager *afm);
void (*SetPosition)(struct S_AudioFileManager *afm, SInt64 pos); // seek/rewind in the file
const char* GetFileBuffer () { return mFileBuffer; } 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)
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)
protected: //protected:
AudioFilePlayer& mParent; AudioFilePlayer* mParent;
SInt16 mForkRefNum; SInt16 mForkRefNum;
SInt64 mAudioDataOffset; SInt64 mAudioDataOffset;
...@@ -157,9 +126,9 @@ protected: ...@@ -157,9 +126,9 @@ protected:
int mByteCounter; int mByteCounter;
bool mReadFromFirstBuffer; int mReadFromFirstBuffer;
bool mLockUnsuccessful; int mLockUnsuccessful;
bool mIsEngaged; int mIsEngaged;
int mNumTimesAskedSinceFinished; int mNumTimesAskedSinceFinished;
...@@ -167,27 +136,34 @@ protected: ...@@ -167,27 +136,34 @@ protected:
void* mTmpBuffer; void* mTmpBuffer;
UInt32 mBufferSize; UInt32 mBufferSize;
UInt32 mBufferOffset; UInt32 mBufferOffset;
public: //public:
const UInt32 mChunkSize; UInt32 mChunkSize;
SInt64 mFileLength; SInt64 mFileLength;
SInt64 mReadFilePosition; SInt64 mReadFilePosition;
bool mWriteToFirstBuffer; int mWriteToFirstBuffer;
bool mFinishedReadingData; int mFinishedReadingData;
protected: //protected:
OSStatus Render (AudioBuffer &ioData); OSStatus (*Render)(struct S_AudioFileManager *afm, AudioBuffer *ioData);
OSStatus (*GetFileData)(struct S_AudioFileManager *afm, void** inOutData, UInt32 *inOutDataSize);
OSStatus GetFileData (void** inOutData, UInt32 *inOutDataSize); void (*AfterRender)(struct S_AudioFileManager *afm);
void AfterRender (); //public:
//static
public: OSStatus (*FileInputProc)(void *inRefCon,
static OSStatus FileInputProc (void *inRefCon, AudioUnitRenderActionFlags inActionFlags,
AudioUnitRenderActionFlags inActionFlags, const AudioTimeStamp *inTimeStamp,
const AudioTimeStamp *inTimeStamp, UInt32 inBusNumber,
UInt32 inBusNumber, AudioBuffer *ioData);
AudioBuffer *ioData); } AudioFileManager;
};
AudioFileManager *new_AudioFileManager (AudioFilePlayer *inParent,
SInt16 inForkRefNum,
SInt64 inFileLength,
UInt32 inChunkSize);
void delete_AudioFileManager(AudioFileManager *afm);
#endif #endif
...@@ -22,10 +22,10 @@ ...@@ -22,10 +22,10 @@
#include "CDPlayer.h" #include "CDPlayer.h"
#include "AudioFilePlayer.h" #include "AudioFilePlayer.h"
#include "CAGuard.h" #include "SDLOSXCAGuard.h"
// we're exporting these functions into C land for SDL_syscdrom.c // we're exporting these functions into C land for SDL_syscdrom.c
extern "C" { //extern "C" {
// //
// Constants // Constants
...@@ -52,7 +52,7 @@ extern "C" { ...@@ -52,7 +52,7 @@ extern "C" {
#pragma mark -- Globals -- #pragma mark -- Globals --
static bool playBackWasInit = false; static int playBackWasInit = 0;
static AudioUnit theUnit; static AudioUnit theUnit;
static AudioFilePlayer* thePlayer = NULL; static AudioFilePlayer* thePlayer = NULL;
static CDPlayerCompletionProc completionProc = NULL; static CDPlayerCompletionProc completionProc = NULL;
...@@ -411,38 +411,40 @@ int LoadFile (const FSRef *ref, int startFrame, int stopFrame) ...@@ -411,38 +411,40 @@ int LoadFile (const FSRef *ref, int startFrame, int stopFrame)
printf ("LoadFile: %d %d\n", startFrame, stopFrame); printf ("LoadFile: %d %d\n", startFrame, stopFrame);
#endif #endif
try { //try {
// create a new player, and attach to the audio unit // create a new player, and attach to the audio unit
thePlayer = new AudioFilePlayer(ref); thePlayer = new_AudioFilePlayer(ref);
if (thePlayer == NULL) { if (thePlayer == NULL) {
SDL_SetError ("LoadFile: Could not create player"); SDL_SetError ("LoadFile: Could not create player");
throw (-3); return -3; //throw (-3);
} }
thePlayer->SetDestination(theUnit); if (!thePlayer->SetDestination(thePlayer, &theUnit))
goto bail;
if (startFrame >= 0) if (startFrame >= 0)
thePlayer->SetStartFrame (startFrame); thePlayer->SetStartFrame (thePlayer, startFrame);
if (stopFrame >= 0 && stopFrame > startFrame) if (stopFrame >= 0 && stopFrame > startFrame)
thePlayer->SetStopFrame (stopFrame); thePlayer->SetStopFrame (thePlayer, stopFrame);
// we set the notifier later // we set the notifier later
//thePlayer->SetNotifier(FilePlayNotificationHandler, NULL); //thePlayer->SetNotifier(thePlayer, FilePlayNotificationHandler, NULL);
thePlayer->Connect(); if (!thePlayer->Connect(thePlayer))
goto bail;
#if DEBUG_CDROM #if DEBUG_CDROM
thePlayer->Print(); thePlayer->Print(thePlayer);
fflush (stdout); fflush (stdout);
#endif #endif
} //}
catch (...) //catch (...)
{ //{
goto bail; // goto bail;
} //}
error = 0; error = 0;
...@@ -458,24 +460,25 @@ int ReleaseFile () ...@@ -458,24 +460,25 @@ int ReleaseFile ()
{ {
int error = -1; int error = -1;
try { // (Don't see any way that the original C++ code could throw here.) --ryan.
//try {
if (thePlayer != NULL) { if (thePlayer != NULL) {
thePlayer->Disconnect(); thePlayer->Disconnect(thePlayer);
delete thePlayer; delete_AudioFilePlayer(thePlayer);
thePlayer = NULL; thePlayer = NULL;
} }
} //}
catch (...) //catch (...)
{ //{
goto bail; // goto bail;
} //}
error = 0; error = 0;
bail: // bail:
return error; return error;
} }
...@@ -490,17 +493,17 @@ int PlayFile () ...@@ -490,17 +493,17 @@ int PlayFile ()
if (CheckInit () < 0) if (CheckInit () < 0)
goto bail; goto bail;
try { // try {
// start processing of the audio unit // start processing of the audio unit
result = AudioOutputUnitStart (theUnit); result = AudioOutputUnitStart (theUnit);
THROW_RESULT("PlayFile: AudioOutputUnitStart") if (result) goto bail; //THROW_RESULT("PlayFile: AudioOutputUnitStart")
} // }
catch (...) // catch (...)
{ // {
goto bail; // goto bail;
} // }
result = 0; result = 0;
...@@ -519,16 +522,16 @@ int PauseFile () ...@@ -519,16 +522,16 @@ int PauseFile ()
if (CheckInit () < 0) if (CheckInit () < 0)
goto bail; goto bail;
try { //try {
// stop processing the audio unit // stop processing the audio unit
result = AudioOutputUnitStop (theUnit); result = AudioOutputUnitStop (theUnit);
THROW_RESULT("PauseFile: AudioOutputUnitStop") if (result) goto bail; //THROW_RESULT("PauseFile: AudioOutputUnitStop")
} //}
catch (...) //catch (...)
{ //{
goto bail; // goto bail;
} //}
result = 0; result = 0;
bail: bail:
...@@ -545,7 +548,7 @@ void SetCompletionProc (CDPlayerCompletionProc proc, SDL_CD *cdrom) ...@@ -545,7 +548,7 @@ void SetCompletionProc (CDPlayerCompletionProc proc, SDL_CD *cdrom)
theCDROM = cdrom; theCDROM = cdrom;
completionProc = proc; completionProc = proc;
thePlayer->SetNotifier (FilePlayNotificationHandler, cdrom); thePlayer->SetNotifier (thePlayer, FilePlayNotificationHandler, cdrom);
} }
// //
...@@ -559,7 +562,7 @@ int GetCurrentFrame () ...@@ -559,7 +562,7 @@ int GetCurrentFrame ()
if (thePlayer == NULL) if (thePlayer == NULL)
frame = 0; frame = 0;
else else
frame = thePlayer->GetCurrentFrame (); frame = thePlayer->GetCurrentFrame (thePlayer);
return frame; return frame;
} }
...@@ -580,7 +583,7 @@ static OSStatus CheckInit () ...@@ -580,7 +583,7 @@ static OSStatus CheckInit ()
// Start callback thread // Start callback thread
SDL_CreateThread(RunCallBackThread, NULL); SDL_CreateThread(RunCallBackThread, NULL);
try { { //try {
ComponentDescription desc; ComponentDescription desc;
desc.componentType = kAudioUnitComponentType; desc.componentType = kAudioUnitComponentType;
...@@ -592,23 +595,23 @@ static OSStatus CheckInit () ...@@ -592,23 +595,23 @@ static OSStatus CheckInit ()
Component comp = FindNextComponent (NULL, &desc); Component comp = FindNextComponent (NULL, &desc);
if (comp == NULL) { if (comp == NULL) {
SDL_SetError ("CheckInit: FindNextComponent returned NULL"); SDL_SetError ("CheckInit: FindNextComponent returned NULL");
throw(internalComponentErr); if (result) return -1; //throw(internalComponentErr);
} }
result = OpenAComponent (comp, &theUnit); result = OpenAComponent (comp, &theUnit);
THROW_RESULT("CheckInit: OpenAComponent") if (result) return -1; //THROW_RESULT("CheckInit: OpenAComponent")
// you need to initialize the output unit before you set it as a destination // you need to initialize the output unit before you set it as a destination
result = AudioUnitInitialize (theUnit); result = AudioUnitInitialize (theUnit);
THROW_RESULT("CheckInit: AudioUnitInitialize") if (result) return -1; //THROW_RESULT("CheckInit: AudioUnitInitialize")
playBackWasInit = true; playBackWasInit = true;
} }
catch (...) //catch (...)
{ //{
return -1; // return -1;
} //}
return 0; return 0;
} }
...@@ -657,4 +660,4 @@ static int RunCallBackThread (void *param) ...@@ -657,4 +660,4 @@ static int RunCallBackThread (void *param)
return 0; return 0;
} }
}; // extern "C" //}; // extern "C"
...@@ -9,9 +9,8 @@ SRCS = \ ...@@ -9,9 +9,8 @@ SRCS = \
SDL_syscdrom_c.h \ SDL_syscdrom_c.h \
SDL_syscdrom.c \ SDL_syscdrom.c \
AudioFilePlayer.h \ AudioFilePlayer.h \
AudioFilePlayer.cpp \ AudioFilePlayer.c \
AudioFileReaderThread.cpp \ AudioFileReaderThread.c \
CAGuard.h \ SDLOSXCAGuard.c \
CAGuard.cpp \
CDPlayer.h \ CDPlayer.h \
CDPlayer.cpp CDPlayer.c
...@@ -69,92 +69,114 @@ ...@@ -69,92 +69,114 @@
//============================================================================= //=============================================================================
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#define NDEBUG 1 //#define NDEBUG 1
#include <assert.h> #include <assert.h>
#include "CAGuard.h" #include "SDLOSXCAGuard.h"
//#warning Need a try-based Locker too //#warning Need a try-based Locker too
//============================================================================= //=============================================================================
// CAGuard // SDLOSXCAGuard
//============================================================================= //=============================================================================
CAGuard::CAGuard() static int SDLOSXCAGuard_Lock(SDLOSXCAGuard *cag)
{ {
OSStatus theError = pthread_mutex_init(&mMutex, NULL); int theAnswer = 0;
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) if(pthread_self() != cag->mOwner)
{ {
OSStatus theError = pthread_mutex_lock(&mMutex); OSStatus theError = pthread_mutex_lock(&cag->mMutex);
assert(theError == 0); assert(theError == 0);
mOwner = pthread_self(); cag->mOwner = pthread_self();
theAnswer = true; theAnswer = 1;
} }
return theAnswer; return theAnswer;
} }
void CAGuard::Unlock() static void SDLOSXCAGuard_Unlock(SDLOSXCAGuard *cag)
{ {
assert(pthread_self() == mOwner); assert(pthread_self() == cag->mOwner);
mOwner = 0; cag->mOwner = 0;
OSStatus theError = pthread_mutex_unlock(&mMutex); OSStatus theError = pthread_mutex_unlock(&cag->mMutex);
assert(theError == 0); assert(theError == 0);
} }
bool CAGuard::Try (bool& outWasLocked) static int SDLOSXCAGuard_Try (SDLOSXCAGuard *cag, int *outWasLocked)
{ {
bool theAnswer = false; int theAnswer = 0;
outWasLocked = false; *outWasLocked = 0;
if (pthread_self() == mOwner) { if (pthread_self() == cag->mOwner) {
theAnswer = true; theAnswer = 1;
outWasLocked = false; *outWasLocked = 0;
} else { } else {
OSStatus theError = pthread_mutex_trylock(&mMutex); OSStatus theError = pthread_mutex_trylock(&cag->mMutex);
if (theError == 0) { if (theError == 0) {
mOwner = pthread_self(); cag->mOwner = pthread_self();
theAnswer = true; theAnswer = 1;
outWasLocked = true; *outWasLocked = 1;
} }
} }
return theAnswer; return theAnswer;
} }
void CAGuard::Wait() static void SDLOSXCAGuard_Wait(SDLOSXCAGuard *cag)
{ {
assert(pthread_self() == mOwner); assert(pthread_self() == cag->mOwner);
cag->mOwner = 0;
mOwner = 0; OSStatus theError = pthread_cond_wait(&cag->mCondVar, &cag->mMutex);
assert(theError == 0);
cag->mOwner = pthread_self();
}
OSStatus theError = pthread_cond_wait(&mCondVar, &mMutex); static void SDLOSXCAGuard_Notify(SDLOSXCAGuard *cag)
{
OSStatus theError = pthread_cond_signal(&cag->mCondVar);
assert(theError == 0); assert(theError == 0);
mOwner = pthread_self();
} }
void CAGuard::Notify()
SDLOSXCAGuard *new_SDLOSXCAGuard(void)
{ {
OSStatus theError = pthread_cond_signal(&mCondVar); 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); 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);
}
}
...@@ -87,57 +87,28 @@ ...@@ -87,57 +87,28 @@
// return false if they receive notification any other way. // return false if they receive notification any other way.
//============================================================================= //=============================================================================
class CAGuard typedef struct S_SDLOSXCAGuard
{ {
// Construction/Destruction // Construction/Destruction
public: //public:
CAGuard();
virtual ~CAGuard();
// Actions // Actions
public: //public:
virtual bool Lock(); int (*Lock)(struct S_SDLOSXCAGuard *cag);
virtual void Unlock(); void (*Unlock)(struct S_SDLOSXCAGuard *cag);
virtual bool Try(bool& outWasLocked); // returns true if lock is free, false if not int (*Try)(struct S_SDLOSXCAGuard *cag, int *outWasLocked); // returns true if lock is free, false if not
void (*Wait)(struct S_SDLOSXCAGuard *cag);
virtual void Wait(); void (*Notify)(struct S_SDLOSXCAGuard *cag);
virtual void Notify();
// Implementation // Implementation
protected: //protected:
pthread_mutex_t mMutex; pthread_mutex_t mMutex;
pthread_cond_t mCondVar; pthread_cond_t mCondVar;
pthread_t mOwner; pthread_t mOwner;
} SDLOSXCAGuard;
// Helper class to manage taking and releasing recursively
public: SDLOSXCAGuard *new_SDLOSXCAGuard(void);
class Locker void delete_SDLOSXCAGuard(SDLOSXCAGuard *cag);
{
// 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 #endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment