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 @@
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 @@ enum {
};
class AudioFileManager;
struct S_AudioFileManager;
#pragma mark __________ AudioFilePlayer
class AudioFilePlayer
typedef struct S_AudioFilePlayer
{
public:
AudioFilePlayer (const FSRef *inFileRef);
~AudioFilePlayer();
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:
//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);
//private:
AudioUnit mPlayUnit;
SInt16 mForkRefNum;
......@@ -104,9 +82,9 @@ private:
AudioStreamBasicDescription mFileDescription;
bool mConnected;
int mConnected;
AudioFileManager* mAudioFileManager;
struct S_AudioFileManager* mAudioFileManager;
AudioFilePlayNotifier mNotifier;
void* mRefCon;
......@@ -115,41 +93,32 @@ private:
#pragma mark __________ Private_Methods
void OpenFile (const FSRef *inRef, SInt64& outFileSize);
};
int (*OpenFile)(struct S_AudioFilePlayer *afp, const FSRef *inRef, SInt64 *outFileSize);
} AudioFilePlayer;
#pragma mark __________ AudioFileManager
class AudioFileManager
{
public:
AudioFileManager (AudioFilePlayer &inParent,
SInt16 inForkRefNum,
SInt64 inFileLength,
UInt32 inChunkSize);
~AudioFileManager();
AudioFilePlayer *new_AudioFilePlayer(const FSRef *inFileRef);
void delete_AudioFilePlayer(AudioFilePlayer *afp);
#pragma mark __________ AudioFileManager
typedef struct S_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)
protected:
AudioFilePlayer& mParent;
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;
SInt16 mForkRefNum;
SInt64 mAudioDataOffset;
......@@ -157,9 +126,9 @@ protected:
int mByteCounter;
bool mReadFromFirstBuffer;
bool mLockUnsuccessful;
bool mIsEngaged;
int mReadFromFirstBuffer;
int mLockUnsuccessful;
int mIsEngaged;
int mNumTimesAskedSinceFinished;
......@@ -167,27 +136,34 @@ protected:
void* mTmpBuffer;
UInt32 mBufferSize;
UInt32 mBufferOffset;
public:
const UInt32 mChunkSize;
//public:
UInt32 mChunkSize;
SInt64 mFileLength;
SInt64 mReadFilePosition;
bool mWriteToFirstBuffer;
bool mFinishedReadingData;
protected:
OSStatus Render (AudioBuffer &ioData);
int mWriteToFirstBuffer;
int mFinishedReadingData;
OSStatus GetFileData (void** inOutData, UInt32 *inOutDataSize);
//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);
void AfterRender ();
public:
static OSStatus FileInputProc (void *inRefCon,
//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
......@@ -22,10 +22,10 @@
#include "CDPlayer.h"
#include "AudioFilePlayer.h"
#include "CAGuard.h"
#include "SDLOSXCAGuard.h"
// we're exporting these functions into C land for SDL_syscdrom.c
extern "C" {
//extern "C" {
//
// Constants
......@@ -52,7 +52,7 @@ extern "C" {
#pragma mark -- Globals --
static bool playBackWasInit = false;
static int playBackWasInit = 0;
static AudioUnit theUnit;
static AudioFilePlayer* thePlayer = NULL;
static CDPlayerCompletionProc completionProc = NULL;
......@@ -411,38 +411,40 @@ int LoadFile (const FSRef *ref, int startFrame, int stopFrame)
printf ("LoadFile: %d %d\n", startFrame, stopFrame);
#endif
try {
//try {
// create a new player, and attach to the audio unit
thePlayer = new AudioFilePlayer(ref);
thePlayer = new_AudioFilePlayer(ref);
if (thePlayer == NULL) {
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)
thePlayer->SetStartFrame (startFrame);
thePlayer->SetStartFrame (thePlayer, startFrame);
if (stopFrame >= 0 && stopFrame > startFrame)
thePlayer->SetStopFrame (stopFrame);
thePlayer->SetStopFrame (thePlayer, stopFrame);
// 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
thePlayer->Print();
thePlayer->Print(thePlayer);
fflush (stdout);
#endif
}
catch (...)
{
goto bail;
}
//}
//catch (...)
//{
// goto bail;
//}
error = 0;
......@@ -458,24 +460,25 @@ int ReleaseFile ()
{
int error = -1;
try {
// (Don't see any way that the original C++ code could throw here.) --ryan.
//try {
if (thePlayer != NULL) {
thePlayer->Disconnect();
thePlayer->Disconnect(thePlayer);
delete thePlayer;
delete_AudioFilePlayer(thePlayer);
thePlayer = NULL;
}
}
catch (...)
{
goto bail;
}
//}
//catch (...)
//{
// goto bail;
//}
error = 0;
bail:
// bail:
return error;
}
......@@ -490,17 +493,17 @@ int PlayFile ()
if (CheckInit () < 0)
goto bail;
try {
// try {
// start processing of the audio unit
result = AudioOutputUnitStart (theUnit);
THROW_RESULT("PlayFile: AudioOutputUnitStart")
if (result) goto bail; //THROW_RESULT("PlayFile: AudioOutputUnitStart")
}
catch (...)
{
goto bail;
}
// }
// catch (...)
// {
// goto bail;
// }
result = 0;
......@@ -519,16 +522,16 @@ int PauseFile ()
if (CheckInit () < 0)
goto bail;
try {
//try {
// stop processing the audio unit
result = AudioOutputUnitStop (theUnit);
THROW_RESULT("PauseFile: AudioOutputUnitStop")
}
catch (...)
{
goto bail;
}
if (result) goto bail; //THROW_RESULT("PauseFile: AudioOutputUnitStop")
//}
//catch (...)
//{
// goto bail;
//}
result = 0;
bail:
......@@ -545,7 +548,7 @@ void SetCompletionProc (CDPlayerCompletionProc proc, SDL_CD *cdrom)
theCDROM = cdrom;
completionProc = proc;
thePlayer->SetNotifier (FilePlayNotificationHandler, cdrom);
thePlayer->SetNotifier (thePlayer, FilePlayNotificationHandler, cdrom);
}
//
......@@ -559,7 +562,7 @@ int GetCurrentFrame ()
if (thePlayer == NULL)
frame = 0;
else
frame = thePlayer->GetCurrentFrame ();
frame = thePlayer->GetCurrentFrame (thePlayer);
return frame;
}
......@@ -580,7 +583,7 @@ static OSStatus CheckInit ()
// Start callback thread
SDL_CreateThread(RunCallBackThread, NULL);
try {
{ //try {
ComponentDescription desc;
desc.componentType = kAudioUnitComponentType;
......@@ -592,23 +595,23 @@ static OSStatus CheckInit ()
Component comp = FindNextComponent (NULL, &desc);
if (comp == NULL) {
SDL_SetError ("CheckInit: FindNextComponent returned NULL");
throw(internalComponentErr);
if (result) return -1; //throw(internalComponentErr);
}
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
result = AudioUnitInitialize (theUnit);
THROW_RESULT("CheckInit: AudioUnitInitialize")
if (result) return -1; //THROW_RESULT("CheckInit: AudioUnitInitialize")
playBackWasInit = true;
}
catch (...)
{
return -1;
}
//catch (...)
//{
// return -1;
//}
return 0;
}
......@@ -657,4 +660,4 @@ static int RunCallBackThread (void *param)
return 0;
}
}; // extern "C"
//}; // extern "C"
......@@ -9,9 +9,8 @@ SRCS = \
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
......@@ -69,92 +69,114 @@
//=============================================================================
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#define NDEBUG 1
#include <assert.h>
#include "CAGuard.h"
#include "SDLOSXCAGuard.h"
//#warning Need a try-based Locker too
//=============================================================================
// CAGuard
// SDLOSXCAGuard
//=============================================================================
CAGuard::CAGuard()
static int SDLOSXCAGuard_Lock(SDLOSXCAGuard *cag)
{
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;
int theAnswer = 0;
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);
mOwner = pthread_self();
theAnswer = true;
cag->mOwner = pthread_self();
theAnswer = 1;
}
return theAnswer;
}
void CAGuard::Unlock()
static void SDLOSXCAGuard_Unlock(SDLOSXCAGuard *cag)
{
assert(pthread_self() == mOwner);
assert(pthread_self() == cag->mOwner);
mOwner = 0;
OSStatus theError = pthread_mutex_unlock(&mMutex);
cag->mOwner = 0;
OSStatus theError = pthread_mutex_unlock(&cag->mMutex);
assert(theError == 0);
}
bool CAGuard::Try (bool& outWasLocked)
static int SDLOSXCAGuard_Try (SDLOSXCAGuard *cag, int *outWasLocked)
{
bool theAnswer = false;
outWasLocked = false;
int theAnswer = 0;
*outWasLocked = 0;
if (pthread_self() == mOwner) {
theAnswer = true;
outWasLocked = false;
if (pthread_self() == cag->mOwner) {
theAnswer = 1;
*outWasLocked = 0;
} else {
OSStatus theError = pthread_mutex_trylock(&mMutex);
OSStatus theError = pthread_mutex_trylock(&cag->mMutex);
if (theError == 0) {
mOwner = pthread_self();
theAnswer = true;
outWasLocked = true;
cag->mOwner = pthread_self();
theAnswer = 1;
*outWasLocked = 1;
}
}
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);
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);
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 @@
// return false if they receive notification any other way.
//=============================================================================
class CAGuard
typedef struct S_SDLOSXCAGuard
{
// Construction/Destruction
public:
CAGuard();
virtual ~CAGuard();
//public:
// 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();
//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:
//protected:
pthread_mutex_t mMutex;
pthread_cond_t mCondVar;
pthread_t mOwner;
} SDLOSXCAGuard;
// 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;
};
};
SDLOSXCAGuard *new_SDLOSXCAGuard(void);
void delete_SDLOSXCAGuard(SDLOSXCAGuard *cag);
#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