Mercurial > sdl-ios-xcode
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 } |