comparison src/cdrom/macosx/AudioFileReaderThread.cpp @ 768:de1b2c3063b9

Max has been reworking this code so it works on MacOS X 10.1
author Sam Lantinga <slouken@libsdl.org>
date Sun, 04 Jan 2004 16:20:28 +0000
parents 9c6717a1c66f
children da0a2ad35bf4
comparison
equal deleted inserted replaced
767:d9e79e31a7b7 768:de1b2c3063b9
22 This file based on Apple sample code. We haven't changed the file name, 22 This file based on Apple sample code. We haven't changed the file name,
23 so if you want to see the original search for it on apple.com/developer 23 so if you want to see the original search for it on apple.com/developer
24 */ 24 */
25 25
26 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 26 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27 // AudioFileReaderThread.cpp 27 // AudioFileManager.cpp
28 // 28 //
29 #include "AudioFilePlayer.h" 29 #include "AudioFilePlayer.h"
30 #include <mach/mach.h> //used for setting policy of thread 30 #include <mach/mach.h> //used for setting policy of thread
31 #include "CAGuard.h" 31 #include "CAGuard.h"
32 #include <pthread.h> 32 #include <pthread.h>
33 33
34 #include <list> 34 #include <list>
35 35
36 class FileReaderThread { 36 class FileReaderThread {
37 public: 37 public:
38 FileReaderThread (); 38 FileReaderThread ();
39 39
40 CAGuard& GetGuard() { return mGuard; } 40 CAGuard& GetGuard() { return mGuard; }
41 41
42 void AddReader(); 42 void AddReader();
43 43
44 void RemoveReader (const AudioFileReaderThread* inItem); 44 void RemoveReader (AudioFileManager* inItem);
45 45
46 // returns true if succeeded 46 // returns true if succeeded
47 bool TryNextRead (AudioFileReaderThread* inItem) 47 bool TryNextRead (AudioFileManager* inItem)
48 { 48 {
49 bool didLock = false; 49 bool didLock = false;
50 bool succeeded = false; 50 bool succeeded = false;
51 if (mGuard.Try (didLock)) 51 if (mGuard.Try (didLock))
52 { 52 {
53 mFileData.push_back (inItem); 53 mFileData.push_back (inItem);
54 mGuard.Notify(); 54 mGuard.Notify();
55 succeeded = true; 55 succeeded = true;
56 56
57 if (didLock) 57 if (didLock)
58 mGuard.Unlock(); 58 mGuard.Unlock();
59 } 59 }
60 60
61 return succeeded; 61 return succeeded;
62 } 62 }
63 63
64 int mThreadShouldDie; 64 int mThreadShouldDie;
65 65
66 private: 66 private:
67 typedef std::list<AudioFileReaderThread*> FileData; 67 typedef std::list<AudioFileManager*> FileData;
68 68
69 CAGuard mGuard; 69 CAGuard mGuard;
70 UInt32 mThreadPriority; 70 UInt32 mThreadPriority;
71 71
72 int mNumReaders; 72 int mNumReaders;
73 FileData mFileData; 73 FileData mFileData;
74 74
75 75
76 void ReadNextChunk (); 76 void ReadNextChunk ();
77 77
78 void StartFixedPriorityThread (); 78 void StartFixedPriorityThread ();
79 static UInt32 GetThreadBasePriority (pthread_t inThread); 79 static UInt32 GetThreadBasePriority (pthread_t inThread);
80 80
81 static void* DiskReaderEntry (void *inRefCon); 81 static void* DiskReaderEntry (void *inRefCon);
82 }; 82 };
83 83
84 FileReaderThread::FileReaderThread () 84 FileReaderThread::FileReaderThread ()
85 : mThreadPriority (62), 85 : mThreadPriority (62),
86 mNumReaders (0) 86 mNumReaders (0)
87 { 87 {
88 } 88 }
89 89
90 void FileReaderThread::AddReader() 90 void FileReaderThread::AddReader()
91 { 91 {
92 if (mNumReaders == 0) 92 if (mNumReaders == 0)
93 { 93 {
94 mThreadShouldDie = false; 94 mThreadShouldDie = false;
95 95
96 StartFixedPriorityThread (); 96 StartFixedPriorityThread ();
97 } 97 }
98 mNumReaders++; 98 mNumReaders++;
99 } 99 }
100 100
101 void FileReaderThread::RemoveReader (const AudioFileReaderThread* inItem) 101 void FileReaderThread::RemoveReader (AudioFileManager* inItem)
102 { 102 {
103 if (mNumReaders > 0) 103 if (mNumReaders > 0)
104 { 104 {
105 CAGuard::Locker fileReadLock (mGuard); 105 CAGuard::Locker fileReadLock (mGuard);
106 106
107 for (FileData::iterator iter = mFileData.begin(); iter != mFileData.end(); ++iter) 107 mFileData.remove (inItem);
108 { 108
109 if ((*iter) == inItem) { 109 if (--mNumReaders == 0) {
110 mFileData.erase (iter); 110 mThreadShouldDie = true;
111 } 111 mGuard.Notify(); // wake up thread so it will quit
112 }
113
114 if (--mNumReaders == 0) {
115 mThreadShouldDie = true;
116 mGuard.Notify(); // wake up thread so it will quit
117 mGuard.Wait(); // wait for thread to die 112 mGuard.Wait(); // wait for thread to die
118 } 113 }
119 } 114 }
120 } 115 }
121 116
122 void FileReaderThread::StartFixedPriorityThread () 117 void FileReaderThread::StartFixedPriorityThread ()
123 { 118 {
124 pthread_attr_t theThreadAttrs; 119 pthread_attr_t theThreadAttrs;
125 pthread_t pThread; 120 pthread_t pThread;
126 121
127 OSStatus result = pthread_attr_init(&theThreadAttrs); 122 OSStatus result = pthread_attr_init(&theThreadAttrs);
128 THROW_RESULT("pthread_attr_init - Thread attributes could not be created.") 123 THROW_RESULT("pthread_attr_init - Thread attributes could not be created.")
129 124
130 result = pthread_attr_setdetachstate(&theThreadAttrs, PTHREAD_CREATE_DETACHED); 125 result = pthread_attr_setdetachstate(&theThreadAttrs, PTHREAD_CREATE_DETACHED);
131 THROW_RESULT("pthread_attr_setdetachstate - Thread attributes could not be detached.") 126 THROW_RESULT("pthread_attr_setdetachstate - Thread attributes could not be detached.")
132 127
133 result = pthread_create (&pThread, &theThreadAttrs, DiskReaderEntry, this); 128 result = pthread_create (&pThread, &theThreadAttrs, DiskReaderEntry, this);
134 THROW_RESULT("pthread_create - Create and start the thread.") 129 THROW_RESULT("pthread_create - Create and start the thread.")
135 130
136 pthread_attr_destroy(&theThreadAttrs); 131 pthread_attr_destroy(&theThreadAttrs);
137 132
138 // we've now created the thread and started it 133 // we've now created the thread and started it
139 // we'll now set the priority of the thread to the nominated priority 134 // we'll now set the priority of the thread to the nominated priority
140 // and we'll also make the thread fixed 135 // and we'll also make the thread fixed
141 thread_extended_policy_data_t theFixedPolicy; 136 thread_extended_policy_data_t theFixedPolicy;
142 thread_precedence_policy_data_t thePrecedencePolicy; 137 thread_precedence_policy_data_t thePrecedencePolicy;
143 SInt32 relativePriority; 138 SInt32 relativePriority;
144 139
145 // make thread fixed 140 // make thread fixed
146 theFixedPolicy.timeshare = false; // set to true for a non-fixed thread 141 theFixedPolicy.timeshare = false; // set to true for a non-fixed thread
147 result = thread_policy_set (pthread_mach_thread_np(pThread), THREAD_EXTENDED_POLICY, (thread_policy_t)&theFixedPolicy, THREAD_EXTENDED_POLICY_COUNT); 142 result = thread_policy_set (pthread_mach_thread_np(pThread), THREAD_EXTENDED_POLICY, (thread_policy_t)&theFixedPolicy, THREAD_EXTENDED_POLICY_COUNT);
148 THROW_RESULT("thread_policy - Couldn't set thread as fixed priority.") 143 THROW_RESULT("thread_policy - Couldn't set thread as fixed priority.")
149 // set priority 144 // set priority
150 // precedency policy's "importance" value is relative to spawning thread's priority 145 // precedency policy's "importance" value is relative to spawning thread's priority
151 relativePriority = mThreadPriority - FileReaderThread::GetThreadBasePriority (pthread_self()); 146 relativePriority = mThreadPriority - FileReaderThread::GetThreadBasePriority (pthread_self());
153 thePrecedencePolicy.importance = relativePriority; 148 thePrecedencePolicy.importance = relativePriority;
154 result = thread_policy_set (pthread_mach_thread_np(pThread), THREAD_PRECEDENCE_POLICY, (thread_policy_t)&thePrecedencePolicy, THREAD_PRECEDENCE_POLICY_COUNT); 149 result = thread_policy_set (pthread_mach_thread_np(pThread), THREAD_PRECEDENCE_POLICY, (thread_policy_t)&thePrecedencePolicy, THREAD_PRECEDENCE_POLICY_COUNT);
155 THROW_RESULT("thread_policy - Couldn't set thread priority.") 150 THROW_RESULT("thread_policy - Couldn't set thread priority.")
156 } 151 }
157 152
158 UInt32 FileReaderThread::GetThreadBasePriority (pthread_t inThread) 153 UInt32 FileReaderThread::GetThreadBasePriority (pthread_t inThread)
159 { 154 {
160 thread_basic_info_data_t threadInfo; 155 thread_basic_info_data_t threadInfo;
161 policy_info_data_t thePolicyInfo; 156 policy_info_data_t thePolicyInfo;
162 unsigned int count; 157 unsigned int count;
163 158
164 // get basic info 159 // get basic info
165 count = THREAD_BASIC_INFO_COUNT; 160 count = THREAD_BASIC_INFO_COUNT;
166 thread_info (pthread_mach_thread_np (inThread), THREAD_BASIC_INFO, (integer_t*)&threadInfo, &count); 161 thread_info (pthread_mach_thread_np (inThread), THREAD_BASIC_INFO, (integer_t*)&threadInfo, &count);
167 162
168 switch (threadInfo.policy) { 163 switch (threadInfo.policy) {
169 case POLICY_TIMESHARE: 164 case POLICY_TIMESHARE:
170 count = POLICY_TIMESHARE_INFO_COUNT; 165 count = POLICY_TIMESHARE_INFO_COUNT;
171 thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_TIMESHARE_INFO, (integer_t*)&(thePolicyInfo.ts), &count); 166 thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_TIMESHARE_INFO, (integer_t*)&(thePolicyInfo.ts), &count);
172 return thePolicyInfo.ts.base_priority; 167 return thePolicyInfo.ts.base_priority;
173 break; 168 break;
174 169
175 case POLICY_FIFO: 170 case POLICY_FIFO:
176 count = POLICY_FIFO_INFO_COUNT; 171 count = POLICY_FIFO_INFO_COUNT;
177 thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_FIFO_INFO, (integer_t*)&(thePolicyInfo.fifo), &count); 172 thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_FIFO_INFO, (integer_t*)&(thePolicyInfo.fifo), &count);
178 if (thePolicyInfo.fifo.depressed) { 173 if (thePolicyInfo.fifo.depressed) {
179 return thePolicyInfo.fifo.depress_priority; 174 return thePolicyInfo.fifo.depress_priority;
180 } else { 175 } else {
181 return thePolicyInfo.fifo.base_priority; 176 return thePolicyInfo.fifo.base_priority;
182 } 177 }
183 break; 178 break;
184 179
185 case POLICY_RR: 180 case POLICY_RR:
186 count = POLICY_RR_INFO_COUNT; 181 count = POLICY_RR_INFO_COUNT;
187 thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_RR_INFO, (integer_t*)&(thePolicyInfo.rr), &count); 182 thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_RR_INFO, (integer_t*)&(thePolicyInfo.rr), &count);
188 if (thePolicyInfo.rr.depressed) { 183 if (thePolicyInfo.rr.depressed) {
189 return thePolicyInfo.rr.depress_priority; 184 return thePolicyInfo.rr.depress_priority;
190 } else { 185 } else {
191 return thePolicyInfo.rr.base_priority; 186 return thePolicyInfo.rr.base_priority;
192 } 187 }
193 break; 188 break;
194 } 189 }
195 190
196 return 0; 191 return 0;
197 } 192 }
198 193
199 void *FileReaderThread::DiskReaderEntry (void *inRefCon) 194 void *FileReaderThread::DiskReaderEntry (void *inRefCon)
200 { 195 {
201 FileReaderThread *This = (FileReaderThread *)inRefCon; 196 FileReaderThread *This = (FileReaderThread *)inRefCon;
202 This->ReadNextChunk(); 197 This->ReadNextChunk();
203 #if DEBUG 198 #if DEBUG
204 printf ("finished with reading file\n"); 199 printf ("finished with reading file\n");
205 #endif 200 #endif
206 201
207 return 0; 202 return 0;
208 } 203 }
209 204
210 void FileReaderThread::ReadNextChunk () 205 void FileReaderThread::ReadNextChunk ()
211 { 206 {
212 OSStatus result; 207 OSStatus result;
213 UInt32 dataChunkSize; 208 UInt32 dataChunkSize;
214 AudioFileReaderThread* theItem = 0; 209 AudioFileManager* theItem = 0;
215 210
216 for (;;) 211 for (;;)
217 { 212 {
218 { // this is a scoped based lock 213 { // this is a scoped based lock
219 CAGuard::Locker fileReadLock (mGuard); 214 CAGuard::Locker fileReadLock (mGuard);
220 215
221 if (this->mThreadShouldDie) { 216 if (this->mThreadShouldDie) {
222 217
223 mGuard.Notify(); 218 mGuard.Notify();
224 return; 219 return;
225 } 220 }
226 221
227 if (mFileData.empty()) 222 if (mFileData.empty())
228 { 223 {
229 mGuard.Wait(); 224 mGuard.Wait();
230 } 225 }
231 226
232 // kill thread 227 // kill thread
233 if (this->mThreadShouldDie) { 228 if (this->mThreadShouldDie) {
234 229
235 mGuard.Notify(); 230 mGuard.Notify();
236 return; 231 return;
237 } 232 }
238 233
239 theItem = mFileData.front(); 234 theItem = mFileData.front();
240 mFileData.pop_front(); 235 mFileData.pop_front();
241 } 236 }
242 237
243 if ((theItem->mFileLength - theItem->mReadFilePosition) < theItem->mChunkSize) 238 if ((theItem->mFileLength - theItem->mReadFilePosition) < theItem->mChunkSize)
244 dataChunkSize = theItem->mFileLength - theItem->mReadFilePosition; 239 dataChunkSize = theItem->mFileLength - theItem->mReadFilePosition;
245 else 240 else
246 dataChunkSize = theItem->mChunkSize; 241 dataChunkSize = theItem->mChunkSize;
247 242
248 // this is the exit condition for the thread 243 // this is the exit condition for the thread
249 if (dataChunkSize == 0) { 244 if (dataChunkSize == 0) {
250 theItem->mFinishedReadingData = true; 245 theItem->mFinishedReadingData = true;
251 continue; 246 continue;
252 } 247 }
253 // construct pointer 248 // construct pointer
254 char* writePtr = const_cast<char*>(theItem->GetFileBuffer() + 249 char* writePtr = const_cast<char*>(theItem->GetFileBuffer() +
255 (theItem->mWriteToFirstBuffer ? 0 : theItem->mChunkSize)); 250 (theItem->mWriteToFirstBuffer ? 0 : theItem->mChunkSize));
256 251
257 /* 252 /*
258 printf ("AudioFileReadBytes: theItem=%.8X fileID=%.8X pos=%.8X sz=%.8X flen=%.8X ptr=%.8X\n", 253 printf ("AudioFileReadBytes: theItem=%.8X fileID=%.8X pos=%.8X sz=%.8X flen=%.8X ptr=%.8X\n",
259 (unsigned int)theItem, (unsigned int)theItem->GetFileID(), 254 (unsigned int)theItem, (unsigned int)theItem->GetFileID(),
260 (unsigned int)theItem->mReadFilePosition, (unsigned int)dataChunkSize, 255 (unsigned int)theItem->mReadFilePosition, (unsigned int)dataChunkSize,
261 (unsigned int)theItem->mFileLength, (unsigned int)writePtr); 256 (unsigned int)theItem->mFileLength, (unsigned int)writePtr);
262 */ 257 */
263 result = AudioFileReadBytes (theItem->GetFileID(), 258 result = theItem->Read(writePtr, &dataChunkSize);
264 false, 259 if (result) {
265 theItem->mReadFilePosition, 260 theItem->GetParent().DoNotification(result);
266 &dataChunkSize, 261 continue;
267 writePtr); 262 }
268 if (result) { 263
269 theItem->GetParent().DoNotification(result); 264 if (dataChunkSize != theItem->mChunkSize)
270 continue; 265 {
271 } 266 writePtr += dataChunkSize;
272
273 if (dataChunkSize != theItem->mChunkSize)
274 {
275 writePtr += dataChunkSize;
276 267
277 // can't exit yet.. we still have to pass the partial buffer back 268 // can't exit yet.. we still have to pass the partial buffer back
278 memset (writePtr, 0, (theItem->mChunkSize - dataChunkSize)); 269 memset (writePtr, 0, (theItem->mChunkSize - dataChunkSize));
279 } 270 }
280 271
281 theItem->mWriteToFirstBuffer = !theItem->mWriteToFirstBuffer; // switch buffers 272 theItem->mWriteToFirstBuffer = !theItem->mWriteToFirstBuffer; // switch buffers
282 273
283 theItem->mReadFilePosition += dataChunkSize; // increment count 274 theItem->mReadFilePosition += dataChunkSize; // increment count
284 } 275 }
285 } 276 }
286 277
287 278
288 static FileReaderThread sReaderThread; 279 static FileReaderThread sReaderThread;
289 280
290 AudioFileReaderThread::AudioFileReaderThread (AudioFilePlayer &inParent, 281 AudioFileManager::AudioFileManager (AudioFilePlayer &inParent,
291 AudioFileID &inFile, 282 SInt16 inForkRefNum,
292 SInt64 inFileLength, 283 SInt64 inFileLength,
293 UInt32 inChunkSize) 284 UInt32 inChunkSize)
294 : AudioFileManager (inParent, inFile), 285 : mParent (inParent),
295 mChunkSize (inChunkSize), 286 mForkRefNum (inForkRefNum),
296 mFileLength (inFileLength), 287 mFileBuffer (0),
297 mReadFilePosition (0), 288 mByteCounter (0),
298 mWriteToFirstBuffer (false), 289 mLockUnsuccessful (false),
299 mFinishedReadingData (false), 290 mIsEngaged (false),
300 291
301 mLockUnsuccessful (false), 292 mChunkSize (inChunkSize),
302 mIsEngaged (false) 293 mFileLength (inFileLength),
303 { 294 mReadFilePosition (0),
304 mFileBuffer = (char*) malloc (mChunkSize * 2); 295 mWriteToFirstBuffer (false),
296 mFinishedReadingData (false)
297
298 {
299 mFileBuffer = (char*) malloc (mChunkSize * 2);
300 FSGetForkPosition(mForkRefNum, &mAudioDataOffset);
305 assert (mFileBuffer != NULL); 301 assert (mFileBuffer != NULL);
306 } 302 }
307 303
308 void AudioFileReaderThread::DoConnect () 304 void AudioFileManager::DoConnect ()
309 { 305 {
310 if (!mIsEngaged) 306 if (!mIsEngaged)
311 { 307 {
312 //mReadFilePosition = 0; 308 //mReadFilePosition = 0;
313 mFinishedReadingData = false; 309 mFinishedReadingData = false;
314 310
315 mNumTimesAskedSinceFinished = -1; 311 mNumTimesAskedSinceFinished = -1;
316 mLockUnsuccessful = false; 312 mLockUnsuccessful = false;
317 313
318 UInt32 dataChunkSize; 314 OSStatus result;
315 UInt32 dataChunkSize;
319 316
320 if ((mFileLength - mReadFilePosition) < mChunkSize) 317 if ((mFileLength - mReadFilePosition) < mChunkSize)
321 dataChunkSize = mFileLength - mReadFilePosition; 318 dataChunkSize = mFileLength - mReadFilePosition;
322 else 319 else
323 dataChunkSize = mChunkSize; 320 dataChunkSize = mChunkSize;
324 321
325 OSStatus result = AudioFileReadBytes ( mAudioFileID, 322 result = Read(mFileBuffer, &dataChunkSize);
326 false, 323 THROW_RESULT("AudioFileManager::DoConnect(): Read")
327 mReadFilePosition, 324
328 &dataChunkSize, 325 mReadFilePosition += dataChunkSize;
329 mFileBuffer); 326
330 THROW_RESULT("AudioFileReadBytes") 327 mWriteToFirstBuffer = false;
331 328 mReadFromFirstBuffer = true;
332 mReadFilePosition += dataChunkSize; 329
333 330 sReaderThread.AddReader();
334 mWriteToFirstBuffer = false; 331
335 mReadFromFirstBuffer = true; 332 mIsEngaged = true;
336 333 }
337 sReaderThread.AddReader(); 334 else
338 335 throw static_cast<OSStatus>(-1); //thread has already been started
339 mIsEngaged = true; 336 }
340 } 337
341 else 338 void AudioFileManager::Disconnect ()
342 throw static_cast<OSStatus>(-1); //thread has already been started 339 {
343 } 340 if (mIsEngaged)
344 341 {
345 void AudioFileReaderThread::Disconnect () 342 sReaderThread.RemoveReader (this);
346 { 343 mIsEngaged = false;
347 if (mIsEngaged) 344 }
348 { 345 }
349 sReaderThread.RemoveReader (this); 346
350 mIsEngaged = false; 347 OSStatus AudioFileManager::Read(char *buffer, UInt32 *len)
351 } 348 {
352 } 349 return FSReadFork (mForkRefNum,
353 350 fsFromStart,
354 OSStatus AudioFileReaderThread::GetFileData (void** inOutData, UInt32 *inOutDataSize) 351 mReadFilePosition + mAudioDataOffset,
355 { 352 *len,
356 if (mFinishedReadingData) 353 buffer,
357 { 354 len);
358 ++mNumTimesAskedSinceFinished; 355 }
359 *inOutDataSize = 0; 356
360 *inOutData = 0; 357 OSStatus AudioFileManager::GetFileData (void** inOutData, UInt32 *inOutDataSize)
361 return noErr; 358 {
362 } 359 if (mFinishedReadingData)
363 360 {
364 if (mReadFromFirstBuffer == mWriteToFirstBuffer) { 361 ++mNumTimesAskedSinceFinished;
365 #if DEBUG 362 *inOutDataSize = 0;
366 printf ("* * * * * * * Can't keep up with reading file:%ld\n", mParent.GetBusNumber()); 363 *inOutData = 0;
367 #endif 364 return noErr;
368 365 }
369 mParent.DoNotification (kAudioFilePlayErr_FilePlayUnderrun); 366
370 *inOutDataSize = 0; 367 if (mReadFromFirstBuffer == mWriteToFirstBuffer) {
371 *inOutData = 0; 368 #if DEBUG
372 } else { 369 printf ("* * * * * * * Can't keep up with reading file:%ld\n", mParent.GetBusNumber());
373 *inOutDataSize = mChunkSize; 370 #endif
374 *inOutData = mReadFromFirstBuffer ? mFileBuffer : (mFileBuffer + mChunkSize); 371
375 } 372 mParent.DoNotification (kAudioFilePlayErr_FilePlayUnderrun);
376 373 *inOutDataSize = 0;
377 mLockUnsuccessful = !sReaderThread.TryNextRead (this); 374 *inOutData = 0;
378 375 } else {
379 mReadFromFirstBuffer = !mReadFromFirstBuffer; 376 *inOutDataSize = mChunkSize;
380 377 *inOutData = mReadFromFirstBuffer ? mFileBuffer : (mFileBuffer + mChunkSize);
381 return noErr; 378 }
382 } 379
383 380 mLockUnsuccessful = !sReaderThread.TryNextRead (this);
384 void AudioFileReaderThread::AfterRender () 381
385 { 382 mReadFromFirstBuffer = !mReadFromFirstBuffer;
386 if (mNumTimesAskedSinceFinished > 0) 383
387 { 384 return noErr;
388 bool didLock = false; 385 }
389 if (sReaderThread.GetGuard().Try (didLock)) { 386
390 mParent.DoNotification (kAudioFilePlay_FileIsFinished); 387 void AudioFileManager::AfterRender ()
391 if (didLock) 388 {
392 sReaderThread.GetGuard().Unlock(); 389 if (mNumTimesAskedSinceFinished > 0)
393 } 390 {
394 } 391 bool didLock = false;
395 392 if (sReaderThread.GetGuard().Try (didLock)) {
396 if (mLockUnsuccessful) 393 mParent.DoNotification (kAudioFilePlay_FileIsFinished);
397 mLockUnsuccessful = !sReaderThread.TryNextRead (this); 394 if (didLock)
398 } 395 sReaderThread.GetGuard().Unlock();
399 396 }
400 void AudioFileReaderThread::SetPosition (SInt64 pos) 397 }
398
399 if (mLockUnsuccessful)
400 mLockUnsuccessful = !sReaderThread.TryNextRead (this);
401 }
402
403 void AudioFileManager::SetPosition (SInt64 pos)
401 { 404 {
402 if (pos < 0 || pos >= mFileLength) { 405 if (pos < 0 || pos >= mFileLength) {
403 SDL_SetError ("AudioFileReaderThread::SetPosition - position invalid: %d filelen=%d\n", 406 SDL_SetError ("AudioFileManager::SetPosition - position invalid: %d filelen=%d\n",
404 (unsigned int)pos, (unsigned int)mFileLength); 407 (unsigned int)pos, (unsigned int)mFileLength);
405 pos = 0; 408 pos = 0;
406 } 409 }
407 410
408 mReadFilePosition = pos; 411 mReadFilePosition = pos;
409 } 412 }
410 413
411 void AudioFileReaderThread::SetEndOfFile (SInt64 pos) 414 void AudioFileManager::SetEndOfFile (SInt64 pos)
412 { 415 {
413 if (pos <= 0 || pos > mFileLength) { 416 if (pos <= 0 || pos > mFileLength) {
414 SDL_SetError ("AudioFileReaderThread::SetEndOfFile - position beyond actual eof\n"); 417 SDL_SetError ("AudioFileManager::SetEndOfFile - position beyond actual eof\n");
415 pos = mFileLength; 418 pos = mFileLength;
416 } 419 }
417 420
418 mFileLength = pos; 421 mFileLength = pos;
419 } 422 }