void FileReaderThread::RemoveReader (const FileThreadVariables* 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(); } } }
void FileReaderThread::ReadNextChunk () { OSStatus result; UInt32 dataChunkSize; UInt32 dataChunkSizeInPackets; AudioStreamPacketDescription *packetDescriptions = NULL; FileThreadVariables* theItem = 0; for (;;) { { // this is a scoped based lock CAGuard::Locker fileReadLock (mGuard); if (mThreadShouldDie) return; while (mFileData.empty()) { fileReadLock.Wait(); } // kill thread if (mThreadShouldDie) return; theItem = mFileData[0]; mFileData.erase (mFileData.begin()); } packetDescriptions = theItem->mPacketDescriptions; if (!theItem->mWriteToFirstBuffer) packetDescriptions += theItem->mChunkSizeInPackets; if ((theItem->mPacketCount - theItem->mReadPacketPosition) < theItem->mChunkSizeInPackets) { dataChunkSizeInPackets = theItem->mPacketCount - theItem->mReadPacketPosition; if (!theItem->IsLooping()) { theItem->mFinishedReadingData = true; } } else dataChunkSizeInPackets = theItem->mChunkSizeInPackets; // this is the exit condition for the thread if (dataChunkSizeInPackets == 0 && !theItem->IsLooping()) { theItem->mFinishedReadingData = true; continue; } // construct pointer char* writePtr = const_cast<char*>(theItem->GetFileBuffer() + (theItem->mWriteToFirstBuffer ? 0 : theItem->mChunkSizeInPackets * theItem->mMaxPacketSize)); #if LOG_DATA_FLOW fprintf(stdout, "***** ReadNextChunk(1) - AFReadPackets (pkts/offset) = %ld/%qd\n", dataChunkSizeInPackets, theItem->mReadPacketPosition); #endif result = AudioFileReadPackets (theItem->GetFileID(), false, &dataChunkSize, packetDescriptions, theItem->mReadPacketPosition, &dataChunkSizeInPackets, writePtr); if (result) { theItem->GetParent().DoNotification(result); continue; } theItem->mCurrentPacketCountInBuffer = dataChunkSizeInPackets; theItem->mCurrentByteCountInBuffer = dataChunkSize; if (dataChunkSizeInPackets != theItem->mChunkSizeInPackets) { writePtr += dataChunkSize; packetDescriptions += dataChunkSizeInPackets; if (theItem->IsLooping()) { packetDescriptions = theItem->mPacketDescriptions + dataChunkSizeInPackets; dataChunkSizeInPackets = theItem->mChunkSizeInPackets - dataChunkSizeInPackets; theItem->mReadPacketPosition = 0; #if LOG_DATA_FLOW fprintf(stdout, "***** ReadNextChunk(2) - AFReadPackets (pkts/offset) = %ld/%qd\n", dataChunkSizeInPackets, theItem->mReadPacketPosition); #endif result = AudioFileReadPackets (theItem->GetFileID(), false, &dataChunkSize, packetDescriptions, theItem->mReadPacketPosition, &dataChunkSizeInPackets, writePtr); if (result) { theItem->GetParent().DoNotification(result); continue; } theItem->mCurrentPacketCountInBuffer += dataChunkSizeInPackets; theItem->mCurrentByteCountInBuffer += dataChunkSize; } else { // can't exit yet.. we still have to pass the partial buffer back memset (writePtr, 0, ((theItem->mChunkSizeInPackets - dataChunkSizeInPackets) * theItem->mMaxPacketSize)); } } theItem->mWriteToFirstBuffer = !theItem->mWriteToFirstBuffer; // switch buffers theItem->mReadPacketPosition += dataChunkSizeInPackets; // increment count } }