Commit f4df35b9 authored by Sam Lantinga's avatar Sam Lantinga

Max has been reworking this code so it works on MacOS X 10.1

--HG--
extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%40769
parent 86ec9803
...@@ -2430,11 +2430,9 @@ case "$target" in ...@@ -2430,11 +2430,9 @@ case "$target" in
# Set up files for the cdrom library # Set up files for the cdrom library
if test x$enable_cdrom = xyes; then if test x$enable_cdrom = xyes; then
# The CD-ROM code won't work on old versions of MacOS X yet... # The CD-ROM code won't work on old versions of MacOS X yet...
#CDROM_SUBDIRS="$CDROM_SUBDIRS macosx" CDROM_SUBDIRS="$CDROM_SUBDIRS macosx"
#CDROM_DRIVERS="$CDROM_DRIVERS macosx/libcdrom_macosx.la" CDROM_DRIVERS="$CDROM_DRIVERS macosx/libcdrom_macosx.la"
#SYSTEM_LIBS="$SYSTEM_LIBS -framework AudioToolbox -framework AudioUnit -lstdc++" SYSTEM_LIBS="$SYSTEM_LIBS -framework AudioToolbox -framework AudioUnit -lstdc++"
CDROM_SUBDIRS="$CDROM_SUBDIRS dummy"
CDROM_DRIVERS="$CDROM_DRIVERS dummy/libcdrom_dummy.la"
fi fi
# Set up files for the thread library # Set up files for the thread library
if test x$enable_threads = xyes; then if test x$enable_threads = xyes; then
......
...@@ -28,31 +28,9 @@ ...@@ -28,31 +28,9 @@
// //
#include "AudioFilePlayer.h" #include "AudioFilePlayer.h"
extern const char* AudioFilePlayerErrorStr (OSStatus error)
{
const char *str;
switch (error) {
case kAudioFileUnspecifiedError: str = "wht?"; break;
case kAudioFileUnsupportedFileTypeError: str = "typ?"; break;
case kAudioFileUnsupportedDataFormatError: str = "fmt?"; break;
case kAudioFileUnsupportedPropertyError: str = "pty?"; break;
case kAudioFileBadPropertySizeError: str = "!siz"; break;
case kAudioFileNotOptimizedError: str = "optm"; break;
case kAudioFilePermissionsError: str = "prm?"; break;
case kAudioFileFormatNameUnavailableError: str = "nme?"; break;
case kAudioFileInvalidChunkError: str = "chk?"; break;
case kAudioFileDoesNotAllow64BitDataSizeError: str = "off?"; break;
default: str = "error unspecified";
}
return str;
}
void ThrowResult (OSStatus result, const char* str) void ThrowResult (OSStatus result, const char* str)
{ {
SDL_SetError ("Error: %s %d (%s)", SDL_SetError ("Error: %s %d", str, result);
str, result, AudioFilePlayerErrorStr(result));
throw result; throw result;
} }
...@@ -133,31 +111,25 @@ AudioFilePlayer::AudioFilePlayer (const FSRef *inFileRef) ...@@ -133,31 +111,25 @@ AudioFilePlayer::AudioFilePlayer (const FSRef *inFileRef)
OpenFile (inFileRef, fileDataSize); OpenFile (inFileRef, fileDataSize);
// we want about a seconds worth of data for the buffer // we want about a seconds worth of data for the buffer
int secsBytes = UInt32 (mFileDescription.mSampleRate * mFileDescription.mBytesPerFrame); int bytesPerSecond = UInt32 (mFileDescription.mSampleRate * mFileDescription.mBytesPerFrame);
#if DEBUG #if DEBUG
printf("File format:\n"); printf("File format:\n");
PrintStreamDesc (&mFileDescription); PrintStreamDesc (&mFileDescription);
#endif #endif
//round to a 32K boundary mAudioFileManager = new AudioFileManager (*this,
//if ((secsBytes & 0xFFFF8000) > (128 * 1024)) mForkRefNum,
//secsBytes &= 0xFFFF8000;
//else
//secsBytes = (secsBytes + 0x7FFF) & 0xFFFF8000;
mAudioFileManager = new AudioFileReaderThread (*this,
mAudioFileID,
fileDataSize, fileDataSize,
secsBytes); bytesPerSecond);
} }
// you can put a rate scalar here to play the file faster or slower // you can put a rate scalar here to play the file faster or slower
// by multiplying the same rate by the desired factor // by multiplying the same rate by the desired factor
// eg fileSampleRate * 2 -> twice as fast // eg fileSampleRate * 2 -> twice as fast
// before you create the AudioConverter // before you create the AudioConverter
void AudioFilePlayer::SetDestination (AudioUnit &inDestUnit, void AudioFilePlayer::SetDestination (AudioUnit &inDestUnit,
int inBusNumber) int inBusNumber)
{ {
if (mConnected) throw static_cast<OSStatus>(-1); //can't set dest if already engaged if (mConnected) throw static_cast<OSStatus>(-1); //can't set dest if already engaged
...@@ -194,43 +166,15 @@ void AudioFilePlayer::SetDestination (AudioUnit &inDestUnit, ...@@ -194,43 +166,15 @@ void AudioFilePlayer::SetDestination (AudioUnit &inDestUnit,
// we're going to use this to know which convert routine to call // we're going to use this to know which convert routine to call
// a v1 audio unit will have a type of 'aunt' // a v1 audio unit will have a type of 'aunt'
// a v2 audio unit will have one of several different types. // a v2 audio unit will have one of several different types.
mIsAUNTUnit = (desc.componentType == kAudioUnitComponentType); if (desc.componentType != kAudioUnitComponentType) {
if (!mIsAUNTUnit) {
result = badComponentInstance; result = badComponentInstance;
THROW_RESULT("BAD COMPONENT") THROW_RESULT("BAD COMPONENT")
} }
// HACK - the AIFF files on CDs are in little endian order!
if (mFileDescription.mFormatFlags == 0xE)
mFileDescription.mFormatFlags &= ~kAudioFormatFlagIsBigEndian;
result = AudioConverterNew (&mFileDescription, &destDesc, &mConverter); result = AudioConverterNew (&mFileDescription, &destDesc, &mConverter);
THROW_RESULT("AudioConverterNew") THROW_RESULT("AudioConverterNew")
/*
// if we have a mono source, we're going to copy each channel into
// the destination's channel source...
if (mFileDescription.mChannelsPerFrame == 1) {
SInt32* channelMap = new SInt32 [destDesc.mChannelsPerFrame];
for (unsigned int i = 0; i < destDesc.mChannelsPerFrame; ++i)
channelMap[i] = 0; //set first channel to all output channels
result = AudioConverterSetProperty(mConverter,
kAudioConverterChannelMap,
(sizeof(SInt32) * destDesc.mChannelsPerFrame),
channelMap);
THROW_RESULT("AudioConverterSetProperty")
delete [] channelMap;
}
*/
assert (mFileDescription.mChannelsPerFrame == 2);
#if 0 #if 0
// this uses the better quality SRC // this uses the better quality SRC
UInt32 srcID = kAudioUnitSRCAlgorithm_Polyphase; UInt32 srcID = kAudioUnitSRCAlgorithm_Polyphase;
...@@ -272,9 +216,9 @@ AudioFilePlayer::~AudioFilePlayer() ...@@ -272,9 +216,9 @@ AudioFilePlayer::~AudioFilePlayer()
mAudioFileManager = 0; mAudioFileManager = 0;
} }
if (mAudioFileID) { if (mForkRefNum) {
::AudioFileClose (mAudioFileID); FSClose (mForkRefNum);
mAudioFileID = 0; mForkRefNum = 0;
} }
if (mConverter) { if (mConverter) {
...@@ -293,18 +237,16 @@ void AudioFilePlayer::Connect() ...@@ -293,18 +237,16 @@ void AudioFilePlayer::Connect()
mAudioFileManager->Connect(mConverter); mAudioFileManager->Connect(mConverter);
// set the render callback for the file data to be supplied to the sound converter AU // set the render callback for the file data to be supplied to the sound converter AU
if (mIsAUNTUnit) { mInputCallback.inputProc = AudioFileManager::FileInputProc;
mInputCallback.inputProc = AudioFileManager::FileInputProc; mInputCallback.inputProcRefCon = mAudioFileManager;
mInputCallback.inputProcRefCon = mAudioFileManager;
OSStatus result = AudioUnitSetProperty (mPlayUnit,
OSStatus result = AudioUnitSetProperty (mPlayUnit, kAudioUnitProperty_SetInputCallback,
kAudioUnitProperty_SetInputCallback, kAudioUnitScope_Input,
kAudioUnitScope_Input, mBusNumber,
mBusNumber, &mInputCallback,
&mInputCallback, sizeof(mInputCallback));
sizeof(mInputCallback)); THROW_RESULT("AudioUnitSetProperty")
THROW_RESULT("AudioUnitSetProperty")
}
mConnected = true; mConnected = true;
} }
} }
...@@ -317,9 +259,7 @@ void AudioFilePlayer::DoNotification (OSStatus inStatus) const ...@@ -317,9 +259,7 @@ void AudioFilePlayer::DoNotification (OSStatus inStatus) const
if (mNotifier) { if (mNotifier) {
(*mNotifier) (mRefCon, inStatus); (*mNotifier) (mRefCon, inStatus);
} } else {
else {
SDL_SetError ("Notification posted with no notifier in place"); SDL_SetError ("Notification posted with no notifier in place");
if (inStatus == kAudioFilePlay_FileIsFinished) if (inStatus == kAudioFilePlay_FileIsFinished)
...@@ -338,40 +278,89 @@ void AudioFilePlayer::Disconnect () ...@@ -338,40 +278,89 @@ void AudioFilePlayer::Disconnect ()
{ {
mConnected = false; mConnected = false;
if (mIsAUNTUnit) { mInputCallback.inputProc = 0;
mInputCallback.inputProc = 0; mInputCallback.inputProcRefCon = 0;
mInputCallback.inputProcRefCon = 0; OSStatus result = AudioUnitSetProperty (mPlayUnit,
OSStatus result = AudioUnitSetProperty (mPlayUnit, kAudioUnitProperty_SetInputCallback,
kAudioUnitProperty_SetInputCallback, kAudioUnitScope_Input,
kAudioUnitScope_Input, mBusNumber,
mBusNumber, &mInputCallback,
&mInputCallback, sizeof(mInputCallback));
sizeof(mInputCallback)); if (result)
if (result) SDL_SetError ("AudioUnitSetProperty:RemoveInputCallback:%ld", result);
SDL_SetError ("AudioUnitSetProperty:RemoveInputCallback:%ld", result);
}
mAudioFileManager->Disconnect(); mAudioFileManager->Disconnect();
} }
} }
struct SSNDData {
UInt32 offset;
UInt32 blockSize;
};
void AudioFilePlayer::OpenFile (const FSRef *inRef, SInt64& outFileDataSize) void AudioFilePlayer::OpenFile (const FSRef *inRef, SInt64& outFileDataSize)
{ {
OSStatus result = AudioFileOpen (inRef, fsRdPerm, 0, &mAudioFileID); ContainerChunk chunkHeader;
THROW_RESULT("AudioFileOpen") ChunkHeader chunk;
SSNDData ssndData;
UInt32 dataSize = sizeof(AudioStreamBasicDescription);
result = AudioFileGetProperty (mAudioFileID, OSErr result;
kAudioFilePropertyDataFormat, HFSUniStr255 dfName;
&dataSize, ByteCount actual;
&mFileDescription); SInt64 offset;
THROW_RESULT("AudioFileGetProperty")
// Open the data fork of the input file
dataSize = sizeof (SInt64); result = FSGetDataForkName(&dfName);
result = AudioFileGetProperty (mAudioFileID, THROW_RESULT("AudioFilePlayer::OpenFile(): FSGetDataForkName")
kAudioFilePropertyAudioDataByteCount,
&dataSize, result = FSOpenFork(inRef, dfName.length, dfName.unicode, fsRdPerm, &mForkRefNum);
&outFileDataSize); THROW_RESULT("AudioFilePlayer::OpenFile(): FSOpenFork")
THROW_RESULT("AudioFileGetProperty")
} // Read the file header, and check if it's indeed an AIFC file
\ No newline at end of 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;
// 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;
}
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#include <CoreServices/CoreServices.h> #include <CoreServices/CoreServices.h>
#include <AudioToolbox/AudioToolbox.h> #include <AudioToolbox/AudioConverter.h>
#include <AudioUnit/AudioUnit.h> #include <AudioUnit/AudioUnit.h>
#include "SDL_error.h" #include "SDL_error.h"
...@@ -97,12 +97,9 @@ public: ...@@ -97,12 +97,9 @@ public:
#if DEBUG #if DEBUG
void Print() const void Print() const
{ {
CAShow (mAudioFileID);
printf ("Destination Bus:%ld\n", GetBusNumber()); printf ("Destination Bus:%ld\n", GetBusNumber());
printf ("Is 'aunt' unit:%s\n", (mIsAUNTUnit ? "true" : "false"));
printf ("Is Connected:%s\n", (IsConnected() ? "true" : "false")); printf ("Is Connected:%s\n", (IsConnected() ? "true" : "false"));
if (mConverter) CAShow (mConverter); printf ("- - - - - - - - - - - - - - \n");
printf ("- - - - - - - - - - - - - - \n");
} }
#endif #endif
...@@ -111,14 +108,13 @@ public: ...@@ -111,14 +108,13 @@ public:
private: private:
AudioUnit mPlayUnit; AudioUnit mPlayUnit;
UInt32 mBusNumber; UInt32 mBusNumber;
AudioFileID mAudioFileID; SInt16 mForkRefNum;
AudioUnitInputCallback mInputCallback; AudioUnitInputCallback mInputCallback;
AudioStreamBasicDescription mFileDescription; AudioStreamBasicDescription mFileDescription;
bool mConnected; bool mConnected;
bool mIsAUNTUnit;
AudioFileManager* mAudioFileManager; AudioFileManager* mAudioFileManager;
AudioConverterRef mConverter; AudioConverterRef mConverter;
...@@ -137,14 +133,12 @@ private: ...@@ -137,14 +133,12 @@ private:
class AudioFileManager class AudioFileManager
{ {
public: public:
AudioFileManager (AudioFilePlayer& inParent, AudioFileID inFile) AudioFileManager (AudioFilePlayer &inParent,
: mParent (inParent), SInt16 inForkRefNum,
mAudioFileID (inFile), SInt64 inFileLength,
mFileBuffer (0), UInt32 inChunkSize);
mByteCounter (0)
{}
virtual ~AudioFileManager(); ~AudioFileManager();
void Connect (AudioConverterRef inConverter) void Connect (AudioConverterRef inConverter)
...@@ -155,36 +149,51 @@ public: ...@@ -155,36 +149,51 @@ public:
// 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
virtual void Disconnect () {} void Disconnect ();
const AudioFileID& GetFileID() const { return mAudioFileID; } OSStatus Read(char *buffer, UInt32 *len);
const char* GetFileBuffer () { return mFileBuffer; } const char* GetFileBuffer () { return mFileBuffer; }
const AudioFilePlayer& GetParent () const { return mParent; } const AudioFilePlayer& GetParent () const { return mParent; }
virtual void SetPosition (SInt64 pos) = 0; // seek/rewind in the file void SetPosition (SInt64 pos); // seek/rewind in the file
virtual int GetByteCounter () { return mByteCounter; } // return actual bytes streamed to audio hardware int GetByteCounter () { return mByteCounter; } // return actual bytes streamed to audio hardware
virtual void SetEndOfFile (SInt64 pos) = 0; // set the "EOF" (will behave just like it reached eof) void SetEndOfFile (SInt64 pos); // set the "EOF" (will behave just like it reached eof)
protected: protected:
AudioFilePlayer& mParent; AudioFilePlayer& mParent;
AudioConverterRef mParentConverter; AudioConverterRef mParentConverter;
const AudioFileID mAudioFileID; SInt16 mForkRefNum;
SInt64 mAudioDataOffset;
char* mFileBuffer; char* mFileBuffer;
OSStatus Render (AudioBuffer &ioData); int mByteCounter;
bool mReadFromFirstBuffer;
bool mLockUnsuccessful;
bool mIsEngaged;
int mNumTimesAskedSinceFinished;
int mByteCounter; public:
const UInt32 mChunkSize;
SInt64 mFileLength;
SInt64 mReadFilePosition;
bool mWriteToFirstBuffer;
bool mFinishedReadingData;
protected:
OSStatus Render (AudioBuffer &ioData);
virtual OSStatus GetFileData (void** inOutData, UInt32 *inOutDataSize) = 0; OSStatus GetFileData (void** inOutData, UInt32 *inOutDataSize);
virtual void DoConnect () = 0; void DoConnect ();
virtual void AfterRender () = 0; void AfterRender ();
public: public:
static OSStatus FileInputProc (void *inRefCon, static OSStatus FileInputProc (void *inRefCon,
...@@ -199,42 +208,4 @@ public: ...@@ -199,42 +208,4 @@ public:
}; };
#pragma mark __________ AudioFileReaderThread
class AudioFileReaderThread
: public AudioFileManager
{
public:
const UInt32 mChunkSize;
SInt64 mFileLength;
SInt64 mReadFilePosition;
bool mWriteToFirstBuffer;
bool mFinishedReadingData;
AudioFileReaderThread (AudioFilePlayer &inParent,
AudioFileID &inFile,
SInt64 inFileLength,
UInt32 inChunkSize);
virtual void Disconnect ();
virtual void SetPosition (SInt64 pos); // seek/rewind in the file
virtual void SetEndOfFile (SInt64 pos); // set the "EOF" (will behave just like it reached eof)
protected:
virtual void DoConnect ();
virtual OSStatus GetFileData (void** inOutData, UInt32 *inOutDataSize);
virtual void AfterRender ();
private:
bool mReadFromFirstBuffer;
bool mLockUnsuccessful;
bool mIsEngaged;
int mNumTimesAskedSinceFinished;
};
#endif #endif
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
*/ */
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// AudioFileReaderThread.cpp // AudioFileManager.cpp
// //
#include "AudioFilePlayer.h" #include "AudioFilePlayer.h"
#include <mach/mach.h> //used for setting policy of thread #include <mach/mach.h> //used for setting policy of thread
...@@ -35,115 +35,110 @@ ...@@ -35,115 +35,110 @@
class FileReaderThread { class FileReaderThread {
public: public:
FileReaderThread (); FileReaderThread ();
CAGuard& GetGuard() { return mGuard; } CAGuard& GetGuard() { return mGuard; }
void AddReader(); void AddReader();
void RemoveReader (const AudioFileReaderThread* inItem); void RemoveReader (AudioFileManager* inItem);
// returns true if succeeded // returns true if succeeded
bool TryNextRead (AudioFileReaderThread* inItem) bool TryNextRead (AudioFileManager* inItem)
{ {
bool didLock = false; bool didLock = false;
bool succeeded = false; bool succeeded = false;
if (mGuard.Try (didLock)) if (mGuard.Try (didLock))
{ {
mFileData.push_back (inItem); mFileData.push_back (inItem);
mGuard.Notify(); mGuard.Notify();
succeeded = true; succeeded = true;
if (didLock) if (didLock)
mGuard.Unlock(); mGuard.Unlock();
} }
return succeeded; return succeeded;
} }
int mThreadShouldDie; int mThreadShouldDie;
private: private:
typedef std::list<AudioFileReaderThread*> FileData; typedef std::list<AudioFileManager*> FileData;
CAGuard mGuard; CAGuard mGuard;
UInt32 mThreadPriority; UInt32 mThreadPriority;
int mNumReaders; int mNumReaders;
FileData mFileData; FileData mFileData;
void ReadNextChunk (); void ReadNextChunk ();
void StartFixedPriorityThread (); void StartFixedPriorityThread ();
static UInt32 GetThreadBasePriority (pthread_t inThread); static UInt32 GetThreadBasePriority (pthread_t inThread);
static void* DiskReaderEntry (void *inRefCon); static void* DiskReaderEntry (void *inRefCon);
}; };
FileReaderThread::FileReaderThread () FileReaderThread::FileReaderThread ()
: mThreadPriority (62), : mThreadPriority (62),
mNumReaders (0) mNumReaders (0)
{ {
} }
void FileReaderThread::AddReader() void FileReaderThread::AddReader()
{ {
if (mNumReaders == 0) if (mNumReaders == 0)
{ {
mThreadShouldDie = false; mThreadShouldDie = false;
StartFixedPriorityThread (); StartFixedPriorityThread ();
} }
mNumReaders++; mNumReaders++;
} }
void FileReaderThread::RemoveReader (const AudioFileReaderThread* inItem) void FileReaderThread::RemoveReader (AudioFileManager* inItem)
{ {
if (mNumReaders > 0) if (mNumReaders > 0)
{ {
CAGuard::Locker fileReadLock (mGuard); CAGuard::Locker fileReadLock (mGuard);
for (FileData::iterator iter = mFileData.begin(); iter != mFileData.end(); ++iter) mFileData.remove (inItem);
{
if ((*iter) == inItem) { if (--mNumReaders == 0) {
mFileData.erase (iter); mThreadShouldDie = true;
} mGuard.Notify(); // wake up thread so it will quit
}
if (--mNumReaders == 0) {
mThreadShouldDie = true;
mGuard.Notify(); // wake up thread so it will quit
mGuard.Wait(); // wait for thread to die mGuard.Wait(); // wait for thread to die
} }
} }
} }
void FileReaderThread::StartFixedPriorityThread () void FileReaderThread::StartFixedPriorityThread ()
{ {
pthread_attr_t theThreadAttrs; pthread_attr_t theThreadAttrs;
pthread_t pThread; pthread_t pThread;
OSStatus result = pthread_attr_init(&theThreadAttrs); OSStatus result = pthread_attr_init(&theThreadAttrs);
THROW_RESULT("pthread_attr_init - Thread attributes could not be created.") THROW_RESULT("pthread_attr_init - Thread attributes could not be created.")
result = pthread_attr_setdetachstate(&theThreadAttrs, PTHREAD_CREATE_DETACHED); result = pthread_attr_setdetachstate(&theThreadAttrs, PTHREAD_CREATE_DETACHED);
THROW_RESULT("pthread_attr_setdetachstate - Thread attributes could not be detached.") THROW_RESULT("pthread_attr_setdetachstate - Thread attributes could not be detached.")
result = pthread_create (&pThread, &theThreadAttrs, DiskReaderEntry, this); result = pthread_create (&pThread, &theThreadAttrs, DiskReaderEntry, this);
THROW_RESULT("pthread_create - Create and start the thread.") THROW_RESULT("pthread_create - Create and start the thread.")
pthread_attr_destroy(&theThreadAttrs);
// we've now created the thread and started it pthread_attr_destroy(&theThreadAttrs);
// we'll now set the priority of the thread to the nominated priority
// and we'll also make the thread fixed // we've now created the thread and started it
thread_extended_policy_data_t theFixedPolicy; // we'll now set the priority of the thread to the nominated priority
thread_precedence_policy_data_t thePrecedencePolicy; // and we'll also make the thread fixed
SInt32 relativePriority; thread_extended_policy_data_t theFixedPolicy;
thread_precedence_policy_data_t thePrecedencePolicy;
SInt32 relativePriority;
// make thread fixed // make thread fixed
theFixedPolicy.timeshare = false; // set to true for a non-fixed thread 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); 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.") THROW_RESULT("thread_policy - Couldn't set thread as fixed priority.")
// set priority // set priority
...@@ -155,26 +150,26 @@ void FileReaderThread::StartFixedPriorityThread () ...@@ -155,26 +150,26 @@ void FileReaderThread::StartFixedPriorityThread ()
THROW_RESULT("thread_policy - Couldn't set thread priority.") THROW_RESULT("thread_policy - Couldn't set thread priority.")
} }
UInt32 FileReaderThread::GetThreadBasePriority (pthread_t inThread) UInt32 FileReaderThread::GetThreadBasePriority (pthread_t inThread)
{ {
thread_basic_info_data_t threadInfo; thread_basic_info_data_t threadInfo;
policy_info_data_t thePolicyInfo; policy_info_data_t thePolicyInfo;
unsigned int count; unsigned int count;
// get basic info // get basic info
count = THREAD_BASIC_INFO_COUNT; count = THREAD_BASIC_INFO_COUNT;
thread_info (pthread_mach_thread_np (inThread), THREAD_BASIC_INFO, (integer_t*)&threadInfo, &count); thread_info (pthread_mach_thread_np (inThread), THREAD_BASIC_INFO, (integer_t*)&threadInfo, &count);
switch (threadInfo.policy) { switch (threadInfo.policy) {
case POLICY_TIMESHARE: case POLICY_TIMESHARE:
count = POLICY_TIMESHARE_INFO_COUNT; count = POLICY_TIMESHARE_INFO_COUNT;
thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_TIMESHARE_INFO, (integer_t*)&(thePolicyInfo.ts), &count); thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_TIMESHARE_INFO, (integer_t*)&(thePolicyInfo.ts), &count);
return thePolicyInfo.ts.base_priority; return thePolicyInfo.ts.base_priority;
break; break;
case POLICY_FIFO: case POLICY_FIFO:
count = POLICY_FIFO_INFO_COUNT; count = POLICY_FIFO_INFO_COUNT;
thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_FIFO_INFO, (integer_t*)&(thePolicyInfo.fifo), &count); thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_FIFO_INFO, (integer_t*)&(thePolicyInfo.fifo), &count);
if (thePolicyInfo.fifo.depressed) { if (thePolicyInfo.fifo.depressed) {
return thePolicyInfo.fifo.depress_priority; return thePolicyInfo.fifo.depress_priority;
} else { } else {
...@@ -182,225 +177,233 @@ UInt32 FileReaderThread::GetThreadBasePriority (pthread_t inThread) ...@@ -182,225 +177,233 @@ UInt32 FileReaderThread::GetThreadBasePriority (pthread_t inThread)
} }
break; break;
case POLICY_RR: case POLICY_RR:
count = POLICY_RR_INFO_COUNT; count = POLICY_RR_INFO_COUNT;
thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_RR_INFO, (integer_t*)&(thePolicyInfo.rr), &count); thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_RR_INFO, (integer_t*)&(thePolicyInfo.rr), &count);
if (thePolicyInfo.rr.depressed) { if (thePolicyInfo.rr.depressed) {
return thePolicyInfo.rr.depress_priority; return thePolicyInfo.rr.depress_priority;
} else { } else {
return thePolicyInfo.rr.base_priority; return thePolicyInfo.rr.base_priority;
} }
break; break;
} }
return 0; return 0;
} }
void *FileReaderThread::DiskReaderEntry (void *inRefCon) void *FileReaderThread::DiskReaderEntry (void *inRefCon)
{ {
FileReaderThread *This = (FileReaderThread *)inRefCon; FileReaderThread *This = (FileReaderThread *)inRefCon;
This->ReadNextChunk(); This->ReadNextChunk();
#if DEBUG #if DEBUG
printf ("finished with reading file\n"); printf ("finished with reading file\n");
#endif #endif
return 0; return 0;
} }
void FileReaderThread::ReadNextChunk () void FileReaderThread::ReadNextChunk ()
{ {
OSStatus result; OSStatus result;
UInt32 dataChunkSize; UInt32 dataChunkSize;
AudioFileReaderThread* theItem = 0; AudioFileManager* theItem = 0;
for (;;) for (;;)
{ {
{ // this is a scoped based lock { // this is a scoped based lock
CAGuard::Locker fileReadLock (mGuard); CAGuard::Locker fileReadLock (mGuard);
if (this->mThreadShouldDie) { if (this->mThreadShouldDie) {
mGuard.Notify(); mGuard.Notify();
return; return;
} }
if (mFileData.empty()) if (mFileData.empty())
{ {
mGuard.Wait(); mGuard.Wait();
} }
// kill thread // kill thread
if (this->mThreadShouldDie) { if (this->mThreadShouldDie) {
mGuard.Notify(); mGuard.Notify();
return; return;
} }
theItem = mFileData.front(); theItem = mFileData.front();
mFileData.pop_front(); mFileData.pop_front();
} }
if ((theItem->mFileLength - theItem->mReadFilePosition) < theItem->mChunkSize) if ((theItem->mFileLength - theItem->mReadFilePosition) < theItem->mChunkSize)
dataChunkSize = theItem->mFileLength - theItem->mReadFilePosition; dataChunkSize = theItem->mFileLength - theItem->mReadFilePosition;
else else
dataChunkSize = theItem->mChunkSize; dataChunkSize = theItem->mChunkSize;
// this is the exit condition for the thread // this is the exit condition for the thread
if (dataChunkSize == 0) { if (dataChunkSize == 0) {
theItem->mFinishedReadingData = true; theItem->mFinishedReadingData = true;
continue; continue;
} }
// construct pointer // construct pointer
char* writePtr = const_cast<char*>(theItem->GetFileBuffer() + char* writePtr = const_cast<char*>(theItem->GetFileBuffer() +
(theItem->mWriteToFirstBuffer ? 0 : theItem->mChunkSize)); (theItem->mWriteToFirstBuffer ? 0 : theItem->mChunkSize));
/* /*
printf ("AudioFileReadBytes: theItem=%.8X fileID=%.8X pos=%.8X sz=%.8X flen=%.8X ptr=%.8X\n", printf ("AudioFileReadBytes: theItem=%.8X fileID=%.8X pos=%.8X sz=%.8X flen=%.8X ptr=%.8X\n",
(unsigned int)theItem, (unsigned int)theItem->GetFileID(), (unsigned int)theItem, (unsigned int)theItem->GetFileID(),
(unsigned int)theItem->mReadFilePosition, (unsigned int)dataChunkSize, (unsigned int)theItem->mReadFilePosition, (unsigned int)dataChunkSize,
(unsigned int)theItem->mFileLength, (unsigned int)writePtr); (unsigned int)theItem->mFileLength, (unsigned int)writePtr);
*/ */
result = AudioFileReadBytes (theItem->GetFileID(), result = theItem->Read(writePtr, &dataChunkSize);
false, if (result) {
theItem->mReadFilePosition, theItem->GetParent().DoNotification(result);
&dataChunkSize, continue;
writePtr); }
if (result) {
theItem->GetParent().DoNotification(result); if (dataChunkSize != theItem->mChunkSize)
continue; {
} writePtr += dataChunkSize;
if (dataChunkSize != theItem->mChunkSize)
{
writePtr += dataChunkSize;
// can't exit yet.. we still have to pass the partial buffer back // can't exit yet.. we still have to pass the partial buffer back
memset (writePtr, 0, (theItem->mChunkSize - dataChunkSize)); memset (writePtr, 0, (theItem->mChunkSize - dataChunkSize));
} }
theItem->mWriteToFirstBuffer = !theItem->mWriteToFirstBuffer; // switch buffers theItem->mWriteToFirstBuffer = !theItem->mWriteToFirstBuffer; // switch buffers
theItem->mReadFilePosition += dataChunkSize; // increment count theItem->mReadFilePosition += dataChunkSize; // increment count
} }
} }
static FileReaderThread sReaderThread; static FileReaderThread sReaderThread;
AudioFileReaderThread::AudioFileReaderThread (AudioFilePlayer &inParent, AudioFileManager::AudioFileManager (AudioFilePlayer &inParent,
AudioFileID &inFile, SInt16 inForkRefNum,
SInt64 inFileLength, SInt64 inFileLength,
UInt32 inChunkSize) UInt32 inChunkSize)
: AudioFileManager (inParent, inFile), : mParent (inParent),
mChunkSize (inChunkSize), mForkRefNum (inForkRefNum),
mFileLength (inFileLength), mFileBuffer (0),
mReadFilePosition (0), mByteCounter (0),
mWriteToFirstBuffer (false), mLockUnsuccessful (false),
mFinishedReadingData (false), mIsEngaged (false),
mLockUnsuccessful (false), mChunkSize (inChunkSize),
mIsEngaged (false) mFileLength (inFileLength),
mReadFilePosition (0),
mWriteToFirstBuffer (false),
mFinishedReadingData (false)
{ {
mFileBuffer = (char*) malloc (mChunkSize * 2); mFileBuffer = (char*) malloc (mChunkSize * 2);
FSGetForkPosition(mForkRefNum, &mAudioDataOffset);
assert (mFileBuffer != NULL); assert (mFileBuffer != NULL);
} }
void AudioFileReaderThread::DoConnect () void AudioFileManager::DoConnect ()
{ {
if (!mIsEngaged) if (!mIsEngaged)
{ {
//mReadFilePosition = 0; //mReadFilePosition = 0;
mFinishedReadingData = false; mFinishedReadingData = false;
mNumTimesAskedSinceFinished = -1; mNumTimesAskedSinceFinished = -1;
mLockUnsuccessful = false; mLockUnsuccessful = false;
UInt32 dataChunkSize; OSStatus result;
UInt32 dataChunkSize;
if ((mFileLength - mReadFilePosition) < mChunkSize) if ((mFileLength - mReadFilePosition) < mChunkSize)
dataChunkSize = mFileLength - mReadFilePosition; dataChunkSize = mFileLength - mReadFilePosition;
else else
dataChunkSize = mChunkSize; dataChunkSize = mChunkSize;
OSStatus result = AudioFileReadBytes ( mAudioFileID, result = Read(mFileBuffer, &dataChunkSize);
false, THROW_RESULT("AudioFileManager::DoConnect(): Read")
mReadFilePosition,
&dataChunkSize, mReadFilePosition += dataChunkSize;
mFileBuffer);
THROW_RESULT("AudioFileReadBytes") mWriteToFirstBuffer = false;
mReadFromFirstBuffer = true;
mReadFilePosition += dataChunkSize;
sReaderThread.AddReader();
mWriteToFirstBuffer = false;
mReadFromFirstBuffer = true; mIsEngaged = true;
}
sReaderThread.AddReader(); else
throw static_cast<OSStatus>(-1); //thread has already been started
mIsEngaged = true; }
}
else void AudioFileManager::Disconnect ()
throw static_cast<OSStatus>(-1); //thread has already been started {
if (mIsEngaged)
{
sReaderThread.RemoveReader (this);
mIsEngaged = false;
}
} }
void AudioFileReaderThread::Disconnect () OSStatus AudioFileManager::Read(char *buffer, UInt32 *len)
{ {
if (mIsEngaged) return FSReadFork (mForkRefNum,
{ fsFromStart,
sReaderThread.RemoveReader (this); mReadFilePosition + mAudioDataOffset,
mIsEngaged = false; *len,
} buffer,
len);
} }
OSStatus AudioFileReaderThread::GetFileData (void** inOutData, UInt32 *inOutDataSize) OSStatus AudioFileManager::GetFileData (void** inOutData, UInt32 *inOutDataSize)
{ {
if (mFinishedReadingData) if (mFinishedReadingData)
{ {
++mNumTimesAskedSinceFinished; ++mNumTimesAskedSinceFinished;
*inOutDataSize = 0; *inOutDataSize = 0;
*inOutData = 0; *inOutData = 0;
return noErr; return noErr;
} }
if (mReadFromFirstBuffer == mWriteToFirstBuffer) { if (mReadFromFirstBuffer == mWriteToFirstBuffer) {
#if DEBUG #if DEBUG
printf ("* * * * * * * Can't keep up with reading file:%ld\n", mParent.GetBusNumber()); printf ("* * * * * * * Can't keep up with reading file:%ld\n", mParent.GetBusNumber());
#endif #endif
mParent.DoNotification (kAudioFilePlayErr_FilePlayUnderrun); mParent.DoNotification (kAudioFilePlayErr_FilePlayUnderrun);
*inOutDataSize = 0; *inOutDataSize = 0;
*inOutData = 0; *inOutData = 0;
} else { } else {
*inOutDataSize = mChunkSize; *inOutDataSize = mChunkSize;
*inOutData = mReadFromFirstBuffer ? mFileBuffer : (mFileBuffer + mChunkSize); *inOutData = mReadFromFirstBuffer ? mFileBuffer : (mFileBuffer + mChunkSize);
} }
mLockUnsuccessful = !sReaderThread.TryNextRead (this); mLockUnsuccessful = !sReaderThread.TryNextRead (this);
mReadFromFirstBuffer = !mReadFromFirstBuffer; mReadFromFirstBuffer = !mReadFromFirstBuffer;
return noErr; return noErr;
} }
void AudioFileReaderThread::AfterRender () void AudioFileManager::AfterRender ()
{ {
if (mNumTimesAskedSinceFinished > 0) if (mNumTimesAskedSinceFinished > 0)
{ {
bool didLock = false; bool didLock = false;
if (sReaderThread.GetGuard().Try (didLock)) { if (sReaderThread.GetGuard().Try (didLock)) {
mParent.DoNotification (kAudioFilePlay_FileIsFinished); mParent.DoNotification (kAudioFilePlay_FileIsFinished);
if (didLock) if (didLock)
sReaderThread.GetGuard().Unlock(); sReaderThread.GetGuard().Unlock();
} }
} }
if (mLockUnsuccessful) if (mLockUnsuccessful)
mLockUnsuccessful = !sReaderThread.TryNextRead (this); mLockUnsuccessful = !sReaderThread.TryNextRead (this);
} }
void AudioFileReaderThread::SetPosition (SInt64 pos) void AudioFileManager::SetPosition (SInt64 pos)
{ {
if (pos < 0 || pos >= mFileLength) { if (pos < 0 || pos >= mFileLength) {
SDL_SetError ("AudioFileReaderThread::SetPosition - position invalid: %d filelen=%d\n", SDL_SetError ("AudioFileManager::SetPosition - position invalid: %d filelen=%d\n",
(unsigned int)pos, (unsigned int)mFileLength); (unsigned int)pos, (unsigned int)mFileLength);
pos = 0; pos = 0;
} }
...@@ -408,10 +411,10 @@ void AudioFileReaderThread::SetPosition (SInt64 pos) ...@@ -408,10 +411,10 @@ void AudioFileReaderThread::SetPosition (SInt64 pos)
mReadFilePosition = pos; mReadFilePosition = pos;
} }
void AudioFileReaderThread::SetEndOfFile (SInt64 pos) void AudioFileManager::SetEndOfFile (SInt64 pos)
{ {
if (pos <= 0 || pos > mFileLength) { if (pos <= 0 || pos > mFileLength) {
SDL_SetError ("AudioFileReaderThread::SetEndOfFile - position beyond actual eof\n"); SDL_SetError ("AudioFileManager::SetEndOfFile - position beyond actual eof\n");
pos = mFileLength; pos = mFileLength;
} }
......
...@@ -70,7 +70,7 @@ ...@@ -70,7 +70,7 @@
#include <stdio.h> #include <stdio.h>
#define NDEBUG 1 //#define NDEBUG 1
#include <assert.h> #include <assert.h>
......
...@@ -114,9 +114,7 @@ int DetectAudioCDVolumes(FSVolumeRefNum *volumes, int numVolumes) ...@@ -114,9 +114,7 @@ int DetectAudioCDVolumes(FSVolumeRefNum *volumes, int numVolumes)
for (volumeIndex = 1; result == noErr || result != nsvErr; volumeIndex++) for (volumeIndex = 1; result == noErr || result != nsvErr; volumeIndex++)
{ {
FSVolumeRefNum actualVolume; FSVolumeRefNum actualVolume;
HFSUniStr255 volumeName;
FSVolumeInfo volumeInfo; FSVolumeInfo volumeInfo;
FSRef rootDirectory;
memset (&volumeInfo, 0, sizeof(volumeInfo)); memset (&volumeInfo, 0, sizeof(volumeInfo));
...@@ -125,13 +123,13 @@ int DetectAudioCDVolumes(FSVolumeRefNum *volumes, int numVolumes) ...@@ -125,13 +123,13 @@ int DetectAudioCDVolumes(FSVolumeRefNum *volumes, int numVolumes)
&actualVolume, &actualVolume,
kFSVolInfoFSInfo, kFSVolInfoFSInfo,
&volumeInfo, &volumeInfo,
&volumeName, NULL,
&rootDirectory); NULL);
if (result == noErr) if (result == noErr)
{ {
if (volumeInfo.filesystemID == kAudioCDFilesystemID) // It's an audio CD if (volumeInfo.filesystemID == kAudioCDFilesystemID) // It's an audio CD
{ {
if (volumes != NULL && cdVolumeCount < numVolumes) if (volumes != NULL && cdVolumeCount < numVolumes)
volumes[cdVolumeCount] = actualVolume; volumes[cdVolumeCount] = actualVolume;
......
...@@ -25,9 +25,8 @@ ...@@ -25,9 +25,8 @@
#include <string.h> #include <string.h>
#include <CoreFoundation/CoreFoundation.h>
#include <Carbon/Carbon.h> #include <Carbon/Carbon.h>
#include <CoreFoundation/CoreFoundation.h>
#include <AudioUnit/AudioUnit.h> #include <AudioUnit/AudioUnit.h>
#include "SDL.h" #include "SDL.h"
......
...@@ -265,19 +265,25 @@ void SDL_SYS_CDQuit(void) ...@@ -265,19 +265,25 @@ void SDL_SYS_CDQuit(void)
/* Get the Unix disk name of the volume */ /* Get the Unix disk name of the volume */
static const char *SDL_SYS_CDName (int drive) static const char *SDL_SYS_CDName (int drive)
{ {
CFStringRef diskID;
OSStatus err = noErr; OSStatus err = noErr;
HParamBlockRec pb;
GetVolParmsInfoBuffer volParmsInfo;
if (fakeCD) if (fakeCD)
return "Fake CD-ROM Device"; return "Fake CD-ROM Device";
err = FSCopyDiskIDForVolume (volumes[drive], &diskID); pb.ioParam.ioNamePtr = NULL;
pb.ioParam.ioVRefNum = volumes[drive];
pb.ioParam.ioBuffer = (Ptr)&volParmsInfo;
pb.ioParam.ioReqCount = (SInt32)sizeof(volParmsInfo);
err = PBHGetVolParmsSync(&pb);
if (err != noErr) { if (err != noErr) {
SDL_SetError ("FSCopyDiskIDForVolume returned %d", err); SDL_SetError ("PBHGetVolParmsSync returned %d", err);
return NULL; return NULL;
} }
return CFStringGetCStringPtr (diskID, 0); return volParmsInfo.vMDeviceID;
} }
/* Open the "device" */ /* Open the "device" */
...@@ -318,14 +324,15 @@ static int SDL_SYS_CDGetTOC (SDL_CD *cdrom) ...@@ -318,14 +324,15 @@ static int SDL_SYS_CDGetTOC (SDL_CD *cdrom)
/* Get CD-ROM status */ /* Get CD-ROM status */
static CDstatus SDL_SYS_CDStatus (SDL_CD *cdrom, int *position) static CDstatus SDL_SYS_CDStatus (SDL_CD *cdrom, int *position)
{ {
int trackFrame; if (position) {
int trackFrame;
Lock ();
trackFrame = GetCurrentFrame (); Lock ();
Unlock (); trackFrame = GetCurrentFrame ();
Unlock ();
if (position) *position = cdrom->track[currentTrack].offset + trackFrame;
*position = cdrom->track[currentTrack].offset + trackFrame; }
return status; return status;
} }
...@@ -383,8 +390,10 @@ static int SDL_SYS_CDPause(SDL_CD *cdrom) ...@@ -383,8 +390,10 @@ static int SDL_SYS_CDPause(SDL_CD *cdrom)
Lock (); Lock ();
if (PauseFile () < 0) if (PauseFile () < 0) {
Unlock ();
return -2; return -2;
}
status = CD_PAUSED; status = CD_PAUSED;
...@@ -403,8 +412,10 @@ static int SDL_SYS_CDResume(SDL_CD *cdrom) ...@@ -403,8 +412,10 @@ static int SDL_SYS_CDResume(SDL_CD *cdrom)
Lock (); Lock ();
if (PlayFile () < 0) if (PauseFile () < 0) {
Unlock ();
return -2; return -2;
}
status = CD_PLAYING; status = CD_PLAYING;
...@@ -423,11 +434,15 @@ static int SDL_SYS_CDStop(SDL_CD *cdrom) ...@@ -423,11 +434,15 @@ static int SDL_SYS_CDStop(SDL_CD *cdrom)
Lock (); Lock ();
if (PauseFile () < 0) if (PauseFile () < 0) {
Unlock ();
return -2; return -2;
}
if (ReleaseFile () < 0) if (ReleaseFile () < 0) {
Unlock ();
return -3; return -3;
}
status = CD_STOPPED; status = CD_STOPPED;
...@@ -440,6 +455,7 @@ static int SDL_SYS_CDStop(SDL_CD *cdrom) ...@@ -440,6 +455,7 @@ static int SDL_SYS_CDStop(SDL_CD *cdrom)
static int SDL_SYS_CDEject(SDL_CD *cdrom) static int SDL_SYS_CDEject(SDL_CD *cdrom)
{ {
OSStatus err; OSStatus err;
HParamBlockRec pb;
if (fakeCD) { if (fakeCD) {
SDL_SetError (kErrorFakeDevice); SDL_SetError (kErrorFakeDevice);
...@@ -448,20 +464,28 @@ static int SDL_SYS_CDEject(SDL_CD *cdrom) ...@@ -448,20 +464,28 @@ static int SDL_SYS_CDEject(SDL_CD *cdrom)
Lock (); Lock ();
if (PauseFile () < 0) if (PauseFile () < 0) {
Unlock ();
return -2; return -2;
}
if (ReleaseFile () < 0) if (ReleaseFile () < 0) {
Unlock ();
return -3; return -3;
}
status = CD_STOPPED; status = CD_STOPPED;
err = FSEjectVolumeSync (volumes[cdrom->id], 0, NULL); // Eject the volume
pb.ioParam.ioNamePtr = NULL;
if (err != noErr) { pb.ioParam.ioVRefNum = volumes[cdrom->id];
SDL_SetError ("FSEjectVolumeSync returned %d", err); err = PBUnmountVol((ParamBlockRec *) &pb);
return -4;
} if (err != noErr) {
Unlock ();
SDL_SetError ("PBUnmountVol returned %d", err);
return -4;
}
status = CD_TRAYEMPTY; status = CD_TRAYEMPTY;
......
...@@ -20,6 +20,9 @@ ...@@ -20,6 +20,9 @@
slouken@libsdl.org slouken@libsdl.org
*/ */
/* This is the Mac OS X / CoreAudio specific header for the SDL CD-ROM API
Contributed by Darrell Walisser and Max Horn
*/
/*********************************************************************************** /***********************************************************************************
Implementation Notes Implementation Notes
......
...@@ -1365,7 +1365,7 @@ static void QZ_DrawResizeIcon (_THIS, RgnHandle dirtyRegion) { ...@@ -1365,7 +1365,7 @@ static void QZ_DrawResizeIcon (_THIS, RgnHandle dirtyRegion) {
SDL_RWops *rw; SDL_RWops *rw;
SDL_Surface *tmp; SDL_Surface *tmp;
rw = SDL_RWFromMem (QZ_ResizeIcon, sizeof(QZ_ResizeIcon)); rw = SDL_RWFromConstMem (QZ_ResizeIcon, sizeof(QZ_ResizeIcon));
tmp = SDL_LoadBMP_RW (rw, SDL_TRUE); tmp = SDL_LoadBMP_RW (rw, SDL_TRUE);
resize_icon = SDL_ConvertSurface (tmp, SDL_VideoSurface->format, SDL_SRCCOLORKEY); resize_icon = SDL_ConvertSurface (tmp, SDL_VideoSurface->format, SDL_SRCCOLORKEY);
......
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