From 06295cd285bf12a7bd09438b663ea62b0c41e7a4 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 4 Jan 2004 16:20:28 +0000 Subject: [PATCH] Max has been reworking this code so it works on MacOS X 10.1 --- configure.in | 8 +- src/cdrom/macosx/AudioFilePlayer.cpp | 217 ++++----- src/cdrom/macosx/AudioFilePlayer.h | 103 ++-- src/cdrom/macosx/AudioFileReaderThread.cpp | 521 +++++++++++---------- src/cdrom/macosx/CAGuard.cpp | 2 +- src/cdrom/macosx/CDPlayer.cpp | 8 +- src/cdrom/macosx/CDPlayer.h | 3 +- src/cdrom/macosx/SDL_syscdrom.c | 76 ++- src/cdrom/macosx/SDL_syscdrom_c.h | 3 + src/video/quartz/SDL_QuartzVideo.m | 2 +- 10 files changed, 464 insertions(+), 479 deletions(-) diff --git a/configure.in b/configure.in index 8d8a7e6ef..966e3158b 100644 --- a/configure.in +++ b/configure.in @@ -2430,11 +2430,9 @@ case "$target" in # Set up files for the cdrom library if test x$enable_cdrom = xyes; then # The CD-ROM code won't work on old versions of MacOS X yet... - #CDROM_SUBDIRS="$CDROM_SUBDIRS macosx" - #CDROM_DRIVERS="$CDROM_DRIVERS macosx/libcdrom_macosx.la" - #SYSTEM_LIBS="$SYSTEM_LIBS -framework AudioToolbox -framework AudioUnit -lstdc++" - CDROM_SUBDIRS="$CDROM_SUBDIRS dummy" - CDROM_DRIVERS="$CDROM_DRIVERS dummy/libcdrom_dummy.la" + CDROM_SUBDIRS="$CDROM_SUBDIRS macosx" + CDROM_DRIVERS="$CDROM_DRIVERS macosx/libcdrom_macosx.la" + SYSTEM_LIBS="$SYSTEM_LIBS -framework AudioToolbox -framework AudioUnit -lstdc++" fi # Set up files for the thread library if test x$enable_threads = xyes; then diff --git a/src/cdrom/macosx/AudioFilePlayer.cpp b/src/cdrom/macosx/AudioFilePlayer.cpp index 6d680f4e3..f0cb6426f 100644 --- a/src/cdrom/macosx/AudioFilePlayer.cpp +++ b/src/cdrom/macosx/AudioFilePlayer.cpp @@ -28,31 +28,9 @@ // #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) { - SDL_SetError ("Error: %s %d (%s)", - str, result, AudioFilePlayerErrorStr(result)); + SDL_SetError ("Error: %s %d", str, result); throw result; } @@ -133,31 +111,25 @@ AudioFilePlayer::AudioFilePlayer (const FSRef *inFileRef) OpenFile (inFileRef, fileDataSize); // 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 printf("File format:\n"); PrintStreamDesc (&mFileDescription); #endif - //round to a 32K boundary - //if ((secsBytes & 0xFFFF8000) > (128 * 1024)) - //secsBytes &= 0xFFFF8000; - //else - //secsBytes = (secsBytes + 0x7FFF) & 0xFFFF8000; - - mAudioFileManager = new AudioFileReaderThread (*this, - mAudioFileID, + mAudioFileManager = new AudioFileManager (*this, + mForkRefNum, fileDataSize, - secsBytes); + bytesPerSecond); } // you can put a rate scalar here to play the file faster or slower // by multiplying the same rate by the desired factor // eg fileSampleRate * 2 -> twice as fast // before you create the AudioConverter -void AudioFilePlayer::SetDestination (AudioUnit &inDestUnit, - int inBusNumber) +void AudioFilePlayer::SetDestination (AudioUnit &inDestUnit, + int inBusNumber) { if (mConnected) throw static_cast(-1); //can't set dest if already engaged @@ -194,43 +166,15 @@ void AudioFilePlayer::SetDestination (AudioUnit &inDestUnit, // 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. - mIsAUNTUnit = (desc.componentType == kAudioUnitComponentType); - - if (!mIsAUNTUnit) { + if (desc.componentType != kAudioUnitComponentType) { result = badComponentInstance; 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); 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 // this uses the better quality SRC UInt32 srcID = kAudioUnitSRCAlgorithm_Polyphase; @@ -272,9 +216,9 @@ AudioFilePlayer::~AudioFilePlayer() mAudioFileManager = 0; } - if (mAudioFileID) { - ::AudioFileClose (mAudioFileID); - mAudioFileID = 0; + if (mForkRefNum) { + FSClose (mForkRefNum); + mForkRefNum = 0; } if (mConverter) { @@ -293,18 +237,16 @@ void AudioFilePlayer::Connect() mAudioFileManager->Connect(mConverter); // set the render callback for the file data to be supplied to the sound converter AU - if (mIsAUNTUnit) { - mInputCallback.inputProc = AudioFileManager::FileInputProc; - mInputCallback.inputProcRefCon = mAudioFileManager; - - OSStatus result = AudioUnitSetProperty (mPlayUnit, - kAudioUnitProperty_SetInputCallback, - kAudioUnitScope_Input, - mBusNumber, - &mInputCallback, - sizeof(mInputCallback)); - THROW_RESULT("AudioUnitSetProperty") - } + mInputCallback.inputProc = AudioFileManager::FileInputProc; + mInputCallback.inputProcRefCon = mAudioFileManager; + + OSStatus result = AudioUnitSetProperty (mPlayUnit, + kAudioUnitProperty_SetInputCallback, + kAudioUnitScope_Input, + mBusNumber, + &mInputCallback, + sizeof(mInputCallback)); + THROW_RESULT("AudioUnitSetProperty") mConnected = true; } } @@ -317,9 +259,7 @@ void AudioFilePlayer::DoNotification (OSStatus inStatus) const if (mNotifier) { (*mNotifier) (mRefCon, inStatus); - } - - else { + } else { SDL_SetError ("Notification posted with no notifier in place"); if (inStatus == kAudioFilePlay_FileIsFinished) @@ -338,40 +278,89 @@ void AudioFilePlayer::Disconnect () { mConnected = false; - if (mIsAUNTUnit) { - mInputCallback.inputProc = 0; - mInputCallback.inputProcRefCon = 0; - OSStatus result = AudioUnitSetProperty (mPlayUnit, - kAudioUnitProperty_SetInputCallback, - kAudioUnitScope_Input, - mBusNumber, - &mInputCallback, - sizeof(mInputCallback)); - if (result) - SDL_SetError ("AudioUnitSetProperty:RemoveInputCallback:%ld", result); - - } - + mInputCallback.inputProc = 0; + mInputCallback.inputProcRefCon = 0; + OSStatus result = AudioUnitSetProperty (mPlayUnit, + kAudioUnitProperty_SetInputCallback, + kAudioUnitScope_Input, + mBusNumber, + &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) -{ - OSStatus result = AudioFileOpen (inRef, fsRdPerm, 0, &mAudioFileID); - THROW_RESULT("AudioFileOpen") - - UInt32 dataSize = sizeof(AudioStreamBasicDescription); - result = AudioFileGetProperty (mAudioFileID, - kAudioFilePropertyDataFormat, - &dataSize, - &mFileDescription); - THROW_RESULT("AudioFileGetProperty") - - dataSize = sizeof (SInt64); - result = AudioFileGetProperty (mAudioFileID, - kAudioFilePropertyAudioDataByteCount, - &dataSize, - &outFileDataSize); - THROW_RESULT("AudioFileGetProperty") -} \ No newline at end of file +{ + 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; + + // 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; +} diff --git a/src/cdrom/macosx/AudioFilePlayer.h b/src/cdrom/macosx/AudioFilePlayer.h index 29bf5400b..be68370a4 100644 --- a/src/cdrom/macosx/AudioFilePlayer.h +++ b/src/cdrom/macosx/AudioFilePlayer.h @@ -31,7 +31,7 @@ #include -#include +#include #include #include "SDL_error.h" @@ -97,12 +97,9 @@ class AudioFilePlayer #if DEBUG void Print() const { - CAShow (mAudioFileID); printf ("Destination Bus:%ld\n", GetBusNumber()); - printf ("Is 'aunt' unit:%s\n", (mIsAUNTUnit ? "true" : "false")); printf ("Is Connected:%s\n", (IsConnected() ? "true" : "false")); - if (mConverter) CAShow (mConverter); - printf ("- - - - - - - - - - - - - - \n"); + printf ("- - - - - - - - - - - - - - \n"); } #endif @@ -111,14 +108,13 @@ class AudioFilePlayer private: AudioUnit mPlayUnit; UInt32 mBusNumber; - AudioFileID mAudioFileID; + SInt16 mForkRefNum; AudioUnitInputCallback mInputCallback; AudioStreamBasicDescription mFileDescription; bool mConnected; - bool mIsAUNTUnit; AudioFileManager* mAudioFileManager; AudioConverterRef mConverter; @@ -137,14 +133,12 @@ class AudioFilePlayer class AudioFileManager { public: - AudioFileManager (AudioFilePlayer& inParent, AudioFileID inFile) - : mParent (inParent), - mAudioFileID (inFile), - mFileBuffer (0), - mByteCounter (0) - {} + AudioFileManager (AudioFilePlayer &inParent, + SInt16 inForkRefNum, + SInt64 inFileLength, + UInt32 inChunkSize); - virtual ~AudioFileManager(); + ~AudioFileManager(); void Connect (AudioConverterRef inConverter) @@ -155,36 +149,51 @@ class AudioFileManager // this method should NOT be called by an object of this class // 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 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: - AudioFilePlayer& mParent; - AudioConverterRef mParentConverter; - const AudioFileID mAudioFileID; + AudioFilePlayer& mParent; + AudioConverterRef mParentConverter; + 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: static OSStatus FileInputProc (void *inRefCon, @@ -199,42 +208,4 @@ class AudioFileManager }; -#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 diff --git a/src/cdrom/macosx/AudioFileReaderThread.cpp b/src/cdrom/macosx/AudioFileReaderThread.cpp index 1551a4601..48961acd8 100644 --- a/src/cdrom/macosx/AudioFileReaderThread.cpp +++ b/src/cdrom/macosx/AudioFileReaderThread.cpp @@ -24,7 +24,7 @@ */ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// AudioFileReaderThread.cpp +// AudioFileManager.cpp // #include "AudioFilePlayer.h" #include //used for setting policy of thread @@ -35,115 +35,110 @@ class FileReaderThread { public: - FileReaderThread (); + FileReaderThread (); - CAGuard& GetGuard() { return mGuard; } + CAGuard& GetGuard() { return mGuard; } - void AddReader(); - - void RemoveReader (const AudioFileReaderThread* inItem); - - // returns true if succeeded - bool TryNextRead (AudioFileReaderThread* 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; + 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 FileData; + typedef std::list FileData; - CAGuard mGuard; - UInt32 mThreadPriority; - - int mNumReaders; - FileData mFileData; + CAGuard mGuard; + UInt32 mThreadPriority; + + int mNumReaders; + FileData mFileData; - void ReadNextChunk (); - - void StartFixedPriorityThread (); - static UInt32 GetThreadBasePriority (pthread_t inThread); + void ReadNextChunk (); + + void StartFixedPriorityThread (); + static UInt32 GetThreadBasePriority (pthread_t inThread); - static void* DiskReaderEntry (void *inRefCon); + static void* DiskReaderEntry (void *inRefCon); }; FileReaderThread::FileReaderThread () - : mThreadPriority (62), - mNumReaders (0) + : mThreadPriority (62), + mNumReaders (0) { } -void FileReaderThread::AddReader() +void FileReaderThread::AddReader() { - if (mNumReaders == 0) - { - mThreadShouldDie = false; - - StartFixedPriorityThread (); - } - mNumReaders++; + if (mNumReaders == 0) + { + mThreadShouldDie = false; + + StartFixedPriorityThread (); + } + mNumReaders++; } -void FileReaderThread::RemoveReader (const AudioFileReaderThread* inItem) +void FileReaderThread::RemoveReader (AudioFileManager* inItem) { - if (mNumReaders > 0) - { - CAGuard::Locker fileReadLock (mGuard); - - for (FileData::iterator iter = mFileData.begin(); iter != mFileData.end(); ++iter) - { - if ((*iter) == inItem) { - mFileData.erase (iter); - } - } - - if (--mNumReaders == 0) { - mThreadShouldDie = true; - mGuard.Notify(); // wake up thread so it will quit + 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 () +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); + 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.") - // 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; + 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 + 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 @@ -155,26 +150,26 @@ void FileReaderThread::StartFixedPriorityThread () 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; - policy_info_data_t thePolicyInfo; - unsigned int count; + 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; + 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); + 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 { @@ -182,225 +177,233 @@ UInt32 FileReaderThread::GetThreadBasePriority (pthread_t inThread) } 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) { + 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) +void *FileReaderThread::DiskReaderEntry (void *inRefCon) { - FileReaderThread *This = (FileReaderThread *)inRefCon; - This->ReadNextChunk(); - #if DEBUG - printf ("finished with reading file\n"); - #endif - - return 0; + FileReaderThread *This = (FileReaderThread *)inRefCon; + This->ReadNextChunk(); + #if DEBUG + printf ("finished with reading file\n"); + #endif + + return 0; } -void FileReaderThread::ReadNextChunk () +void FileReaderThread::ReadNextChunk () { - OSStatus result; - UInt32 dataChunkSize; - AudioFileReaderThread* theItem = 0; - - for (;;) - { - { // this is a scoped based lock - CAGuard::Locker fileReadLock (mGuard); - - if (this->mThreadShouldDie) { + 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) { + + 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(theItem->GetFileBuffer() + - (theItem->mWriteToFirstBuffer ? 0 : theItem->mChunkSize)); - + 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(theItem->GetFileBuffer() + + (theItem->mWriteToFirstBuffer ? 0 : theItem->mChunkSize)); + /* 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->mReadFilePosition, (unsigned int)dataChunkSize, (unsigned int)theItem->mFileLength, (unsigned int)writePtr); */ - result = AudioFileReadBytes (theItem->GetFileID(), - false, - theItem->mReadFilePosition, - &dataChunkSize, - writePtr); - if (result) { - theItem->GetParent().DoNotification(result); - continue; - } - - if (dataChunkSize != theItem->mChunkSize) - { - writePtr += dataChunkSize; + result = theItem->Read(writePtr, &dataChunkSize); + if (result) { + 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 - - theItem->mReadFilePosition += dataChunkSize; // increment count - } + + theItem->mWriteToFirstBuffer = !theItem->mWriteToFirstBuffer; // switch buffers + + theItem->mReadFilePosition += dataChunkSize; // increment count + } } static FileReaderThread sReaderThread; -AudioFileReaderThread::AudioFileReaderThread (AudioFilePlayer &inParent, - AudioFileID &inFile, - SInt64 inFileLength, - UInt32 inChunkSize) - : AudioFileManager (inParent, inFile), - mChunkSize (inChunkSize), - mFileLength (inFileLength), - mReadFilePosition (0), - mWriteToFirstBuffer (false), - mFinishedReadingData (false), - - mLockUnsuccessful (false), - mIsEngaged (false) +AudioFileManager::AudioFileManager (AudioFilePlayer &inParent, + SInt16 inForkRefNum, + SInt64 inFileLength, + UInt32 inChunkSize) + : mParent (inParent), + mForkRefNum (inForkRefNum), + mFileBuffer (0), + mByteCounter (0), + mLockUnsuccessful (false), + mIsEngaged (false), + + mChunkSize (inChunkSize), + mFileLength (inFileLength), + mReadFilePosition (0), + mWriteToFirstBuffer (false), + mFinishedReadingData (false) + { - mFileBuffer = (char*) malloc (mChunkSize * 2); + mFileBuffer = (char*) malloc (mChunkSize * 2); + FSGetForkPosition(mForkRefNum, &mAudioDataOffset); assert (mFileBuffer != NULL); } -void AudioFileReaderThread::DoConnect () +void AudioFileManager::DoConnect () { - if (!mIsEngaged) - { - //mReadFilePosition = 0; - mFinishedReadingData = false; - - mNumTimesAskedSinceFinished = -1; - mLockUnsuccessful = false; - - UInt32 dataChunkSize; + if (!mIsEngaged) + { + //mReadFilePosition = 0; + mFinishedReadingData = false; + + mNumTimesAskedSinceFinished = -1; + mLockUnsuccessful = false; + + OSStatus result; + UInt32 dataChunkSize; if ((mFileLength - mReadFilePosition) < mChunkSize) - dataChunkSize = mFileLength - mReadFilePosition; - else - dataChunkSize = mChunkSize; + dataChunkSize = mFileLength - mReadFilePosition; + else + dataChunkSize = mChunkSize; - OSStatus result = AudioFileReadBytes ( mAudioFileID, - false, - mReadFilePosition, - &dataChunkSize, - mFileBuffer); - THROW_RESULT("AudioFileReadBytes") - - mReadFilePosition += dataChunkSize; - - mWriteToFirstBuffer = false; - mReadFromFirstBuffer = true; - - sReaderThread.AddReader(); - - mIsEngaged = true; - } - else - throw static_cast(-1); //thread has already been started + result = Read(mFileBuffer, &dataChunkSize); + THROW_RESULT("AudioFileManager::DoConnect(): Read") + + mReadFilePosition += dataChunkSize; + + mWriteToFirstBuffer = false; + mReadFromFirstBuffer = true; + + sReaderThread.AddReader(); + + mIsEngaged = true; + } + else + throw static_cast(-1); //thread has already been started +} + +void AudioFileManager::Disconnect () +{ + if (mIsEngaged) + { + sReaderThread.RemoveReader (this); + mIsEngaged = false; + } } -void AudioFileReaderThread::Disconnect () +OSStatus AudioFileManager::Read(char *buffer, UInt32 *len) { - if (mIsEngaged) - { - sReaderThread.RemoveReader (this); - mIsEngaged = false; - } + return FSReadFork (mForkRefNum, + fsFromStart, + mReadFilePosition + mAudioDataOffset, + *len, + buffer, + len); } -OSStatus AudioFileReaderThread::GetFileData (void** inOutData, UInt32 *inOutDataSize) +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:%ld\n", mParent.GetBusNumber()); - #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; + if (mFinishedReadingData) + { + ++mNumTimesAskedSinceFinished; + *inOutDataSize = 0; + *inOutData = 0; + return noErr; + } + + if (mReadFromFirstBuffer == mWriteToFirstBuffer) { + #if DEBUG + printf ("* * * * * * * Can't keep up with reading file:%ld\n", mParent.GetBusNumber()); + #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 AudioFileReaderThread::AfterRender () +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); + 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 AudioFileReaderThread::SetPosition (SInt64 pos) +void AudioFileManager::SetPosition (SInt64 pos) { 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); pos = 0; } @@ -408,10 +411,10 @@ void AudioFileReaderThread::SetPosition (SInt64 pos) mReadFilePosition = pos; } -void AudioFileReaderThread::SetEndOfFile (SInt64 pos) +void AudioFileManager::SetEndOfFile (SInt64 pos) { 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; } diff --git a/src/cdrom/macosx/CAGuard.cpp b/src/cdrom/macosx/CAGuard.cpp index 05aac9f2c..b7574127b 100644 --- a/src/cdrom/macosx/CAGuard.cpp +++ b/src/cdrom/macosx/CAGuard.cpp @@ -70,7 +70,7 @@ #include -#define NDEBUG 1 +//#define NDEBUG 1 #include diff --git a/src/cdrom/macosx/CDPlayer.cpp b/src/cdrom/macosx/CDPlayer.cpp index 1bc989ba1..58a6562c9 100644 --- a/src/cdrom/macosx/CDPlayer.cpp +++ b/src/cdrom/macosx/CDPlayer.cpp @@ -114,9 +114,7 @@ int DetectAudioCDVolumes(FSVolumeRefNum *volumes, int numVolumes) for (volumeIndex = 1; result == noErr || result != nsvErr; volumeIndex++) { FSVolumeRefNum actualVolume; - HFSUniStr255 volumeName; FSVolumeInfo volumeInfo; - FSRef rootDirectory; memset (&volumeInfo, 0, sizeof(volumeInfo)); @@ -125,13 +123,13 @@ int DetectAudioCDVolumes(FSVolumeRefNum *volumes, int numVolumes) &actualVolume, kFSVolInfoFSInfo, &volumeInfo, - &volumeName, - &rootDirectory); + NULL, + NULL); if (result == noErr) { if (volumeInfo.filesystemID == kAudioCDFilesystemID) // It's an audio CD - { + { if (volumes != NULL && cdVolumeCount < numVolumes) volumes[cdVolumeCount] = actualVolume; diff --git a/src/cdrom/macosx/CDPlayer.h b/src/cdrom/macosx/CDPlayer.h index 96fbe23c8..e0fe74254 100644 --- a/src/cdrom/macosx/CDPlayer.h +++ b/src/cdrom/macosx/CDPlayer.h @@ -25,9 +25,8 @@ #include -#include #include - +#include #include #include "SDL.h" diff --git a/src/cdrom/macosx/SDL_syscdrom.c b/src/cdrom/macosx/SDL_syscdrom.c index d10f40aec..dc26266c5 100644 --- a/src/cdrom/macosx/SDL_syscdrom.c +++ b/src/cdrom/macosx/SDL_syscdrom.c @@ -265,19 +265,25 @@ void SDL_SYS_CDQuit(void) /* Get the Unix disk name of the volume */ static const char *SDL_SYS_CDName (int drive) { - CFStringRef diskID; OSStatus err = noErr; - + HParamBlockRec pb; + GetVolParmsInfoBuffer volParmsInfo; + if (fakeCD) 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) { - SDL_SetError ("FSCopyDiskIDForVolume returned %d", err); + SDL_SetError ("PBHGetVolParmsSync returned %d", err); return NULL; } - - return CFStringGetCStringPtr (diskID, 0); + + return volParmsInfo.vMDeviceID; } /* Open the "device" */ @@ -318,14 +324,15 @@ static int SDL_SYS_CDGetTOC (SDL_CD *cdrom) /* Get CD-ROM status */ static CDstatus SDL_SYS_CDStatus (SDL_CD *cdrom, int *position) { - int trackFrame; - - Lock (); - trackFrame = GetCurrentFrame (); - Unlock (); + if (position) { + int trackFrame; + + Lock (); + trackFrame = GetCurrentFrame (); + Unlock (); - if (position) - *position = cdrom->track[currentTrack].offset + trackFrame; + *position = cdrom->track[currentTrack].offset + trackFrame; + } return status; } @@ -383,8 +390,10 @@ static int SDL_SYS_CDPause(SDL_CD *cdrom) Lock (); - if (PauseFile () < 0) + if (PauseFile () < 0) { + Unlock (); return -2; + } status = CD_PAUSED; @@ -403,8 +412,10 @@ static int SDL_SYS_CDResume(SDL_CD *cdrom) Lock (); - if (PlayFile () < 0) + if (PauseFile () < 0) { + Unlock (); return -2; + } status = CD_PLAYING; @@ -423,11 +434,15 @@ static int SDL_SYS_CDStop(SDL_CD *cdrom) Lock (); - if (PauseFile () < 0) + if (PauseFile () < 0) { + Unlock (); return -2; + } - if (ReleaseFile () < 0) + if (ReleaseFile () < 0) { + Unlock (); return -3; + } status = CD_STOPPED; @@ -440,6 +455,7 @@ static int SDL_SYS_CDStop(SDL_CD *cdrom) static int SDL_SYS_CDEject(SDL_CD *cdrom) { OSStatus err; + HParamBlockRec pb; if (fakeCD) { SDL_SetError (kErrorFakeDevice); @@ -448,20 +464,28 @@ static int SDL_SYS_CDEject(SDL_CD *cdrom) Lock (); - if (PauseFile () < 0) + if (PauseFile () < 0) { + Unlock (); return -2; + } - if (ReleaseFile () < 0) + if (ReleaseFile () < 0) { + Unlock (); return -3; + } status = CD_STOPPED; - err = FSEjectVolumeSync (volumes[cdrom->id], 0, NULL); - - if (err != noErr) { - SDL_SetError ("FSEjectVolumeSync returned %d", err); - return -4; - } + // Eject the volume + pb.ioParam.ioNamePtr = NULL; + pb.ioParam.ioVRefNum = volumes[cdrom->id]; + err = PBUnmountVol((ParamBlockRec *) &pb); + + if (err != noErr) { + Unlock (); + SDL_SetError ("PBUnmountVol returned %d", err); + return -4; + } status = CD_TRAYEMPTY; diff --git a/src/cdrom/macosx/SDL_syscdrom_c.h b/src/cdrom/macosx/SDL_syscdrom_c.h index d4474dcc4..72533508a 100644 --- a/src/cdrom/macosx/SDL_syscdrom_c.h +++ b/src/cdrom/macosx/SDL_syscdrom_c.h @@ -20,6 +20,9 @@ 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 diff --git a/src/video/quartz/SDL_QuartzVideo.m b/src/video/quartz/SDL_QuartzVideo.m index 95fc0b20c..d63450125 100644 --- a/src/video/quartz/SDL_QuartzVideo.m +++ b/src/video/quartz/SDL_QuartzVideo.m @@ -1365,7 +1365,7 @@ static void QZ_DrawResizeIcon (_THIS, RgnHandle dirtyRegion) { SDL_RWops *rw; 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); resize_icon = SDL_ConvertSurface (tmp, SDL_VideoSurface->format, SDL_SRCCOLORKEY);