symbian-qemu-0.9.1-12/libsdl-trunk/src/cdrom/macosx/AudioFileReaderThread.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /*
       
     2     SDL - Simple DirectMedia Layer
       
     3     Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
       
     4 
       
     5     This library is free software; you can redistribute it and/or
       
     6     modify it under the terms of the GNU Library General Public
       
     7     License as published by the Free Software Foundation; either
       
     8     version 2 of the License, or (at your option) any later version.
       
     9 
       
    10     This library is distributed in the hope that it will be useful,
       
    11     but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    13     Library General Public License for more details.
       
    14 
       
    15     You should have received a copy of the GNU Library General Public
       
    16     License along with this library; if not, write to the Free
       
    17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    18 
       
    19     Sam Lantinga
       
    20     slouken@libsdl.org
       
    21 
       
    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
       
    24 */
       
    25 #include "SDL_config.h"
       
    26 
       
    27 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       
    28    AudioFileManager.cpp
       
    29 */
       
    30 #include "AudioFilePlayer.h"
       
    31 #include <mach/mach.h> /* used for setting policy of thread */
       
    32 #include "SDLOSXCAGuard.h"
       
    33 #include <pthread.h>
       
    34 
       
    35 /*#include <list>*/
       
    36 
       
    37 /*typedef void *FileData;*/
       
    38 typedef struct S_FileData
       
    39 {
       
    40     AudioFileManager *obj;
       
    41     struct S_FileData *next;
       
    42 } FileData;
       
    43 
       
    44 
       
    45 typedef struct S_FileReaderThread {
       
    46 /*public:*/
       
    47     SDLOSXCAGuard*                    (*GetGuard)(struct S_FileReaderThread *frt);
       
    48     void                        (*AddReader)(struct S_FileReaderThread *frt);
       
    49     void                        (*RemoveReader)(struct S_FileReaderThread *frt, AudioFileManager* inItem);
       
    50     int                         (*TryNextRead)(struct S_FileReaderThread *frt, AudioFileManager* inItem);
       
    51 
       
    52     int     mThreadShouldDie;
       
    53     
       
    54 /*private:*/
       
    55     /*typedef std::list<AudioFileManager*> FileData;*/
       
    56 
       
    57     SDLOSXCAGuard             *mGuard;
       
    58     UInt32              mThreadPriority;
       
    59     
       
    60     int                 mNumReaders;    
       
    61     FileData            *mFileData;
       
    62 
       
    63 
       
    64     void                        (*ReadNextChunk)(struct S_FileReaderThread *frt);
       
    65     int                         (*StartFixedPriorityThread)(struct S_FileReaderThread *frt);
       
    66     /*static*/
       
    67     UInt32               (*GetThreadBasePriority)(pthread_t inThread);
       
    68     /*static*/
       
    69     void*                (*DiskReaderEntry)(void *inRefCon);
       
    70 } FileReaderThread;
       
    71 
       
    72 
       
    73 static SDLOSXCAGuard* FileReaderThread_GetGuard(FileReaderThread *frt)
       
    74 {
       
    75     return frt->mGuard;
       
    76 }
       
    77 
       
    78 /* returns 1 if succeeded */
       
    79 static int FileReaderThread_TryNextRead (FileReaderThread *frt, AudioFileManager* inItem)
       
    80 {
       
    81     int didLock = 0;
       
    82     int succeeded = 0;
       
    83     if (frt->mGuard->Try(frt->mGuard, &didLock))
       
    84     {
       
    85         /*frt->mFileData.push_back (inItem);*/
       
    86         /* !!! FIXME: this could be faster with a "tail" member. --ryan. */
       
    87         FileData *i = frt->mFileData;
       
    88         FileData *prev = NULL;
       
    89 
       
    90         FileData *newfd = (FileData *) SDL_malloc(sizeof (FileData));
       
    91         newfd->obj = inItem;
       
    92         newfd->next = NULL;
       
    93 
       
    94         while (i != NULL) { prev = i; i = i->next; }
       
    95         if (prev == NULL)
       
    96             frt->mFileData = newfd;
       
    97         else
       
    98             prev->next = newfd;
       
    99 
       
   100         frt->mGuard->Notify(frt->mGuard);
       
   101         succeeded = 1;
       
   102 
       
   103         if (didLock)
       
   104             frt->mGuard->Unlock(frt->mGuard);
       
   105     }
       
   106                 
       
   107     return succeeded;
       
   108 }
       
   109 
       
   110 static void    FileReaderThread_AddReader(FileReaderThread *frt)
       
   111 {
       
   112     if (frt->mNumReaders == 0)
       
   113     {
       
   114         frt->mThreadShouldDie = 0;
       
   115         frt->StartFixedPriorityThread (frt);
       
   116     }
       
   117     frt->mNumReaders++;
       
   118 }
       
   119 
       
   120 static void    FileReaderThread_RemoveReader (FileReaderThread *frt, AudioFileManager* inItem)
       
   121 {
       
   122     if (frt->mNumReaders > 0)
       
   123     {
       
   124         int bNeedsRelease = frt->mGuard->Lock(frt->mGuard);
       
   125         
       
   126         /*frt->mFileData.remove (inItem);*/
       
   127         FileData *i = frt->mFileData;
       
   128         FileData *prev = NULL;
       
   129         while (i != NULL)
       
   130         {
       
   131             FileData *next = i->next;
       
   132             if (i->obj != inItem)
       
   133                 prev = i;
       
   134             else
       
   135             {
       
   136                 if (prev == NULL)
       
   137                     frt->mFileData = next;
       
   138                 else
       
   139                     prev->next = next;
       
   140                 SDL_free(i);
       
   141             }
       
   142             i = next;
       
   143         }
       
   144 
       
   145         if (--frt->mNumReaders == 0) {
       
   146             frt->mThreadShouldDie = 1;
       
   147             frt->mGuard->Notify(frt->mGuard); /* wake up thread so it will quit */
       
   148             frt->mGuard->Wait(frt->mGuard);   /* wait for thread to die */
       
   149         }
       
   150 
       
   151         if (bNeedsRelease) frt->mGuard->Unlock(frt->mGuard);
       
   152     }   
       
   153 }
       
   154 
       
   155 static int    FileReaderThread_StartFixedPriorityThread (FileReaderThread *frt)
       
   156 {
       
   157     pthread_attr_t      theThreadAttrs;
       
   158     pthread_t           pThread;
       
   159 
       
   160     OSStatus result = pthread_attr_init(&theThreadAttrs);
       
   161         if (result) return 0; /*THROW_RESULT("pthread_attr_init - Thread attributes could not be created.")*/
       
   162     
       
   163     result = pthread_attr_setdetachstate(&theThreadAttrs, PTHREAD_CREATE_DETACHED);
       
   164         if (result) return 0; /*THROW_RESULT("pthread_attr_setdetachstate - Thread attributes could not be detached.")*/
       
   165     
       
   166     result = pthread_create (&pThread, &theThreadAttrs, frt->DiskReaderEntry, frt);
       
   167         if (result) return 0; /*THROW_RESULT("pthread_create - Create and start the thread.")*/
       
   168     
       
   169     pthread_attr_destroy(&theThreadAttrs);
       
   170     
       
   171     /* we've now created the thread and started it
       
   172        we'll now set the priority of the thread to the nominated priority
       
   173        and we'll also make the thread fixed */
       
   174     thread_extended_policy_data_t       theFixedPolicy;
       
   175     thread_precedence_policy_data_t     thePrecedencePolicy;
       
   176     SInt32                              relativePriority;
       
   177     
       
   178     /* make thread fixed */
       
   179     theFixedPolicy.timeshare = 0;   /* set to 1 for a non-fixed thread */
       
   180     result = thread_policy_set (pthread_mach_thread_np(pThread), THREAD_EXTENDED_POLICY, (thread_policy_t)&theFixedPolicy, THREAD_EXTENDED_POLICY_COUNT);
       
   181         if (result) return 0; /*THROW_RESULT("thread_policy - Couldn't set thread as fixed priority.")*/
       
   182     /* set priority */
       
   183     /* precedency policy's "importance" value is relative to spawning thread's priority */
       
   184     relativePriority = frt->mThreadPriority - frt->GetThreadBasePriority(pthread_self());
       
   185         
       
   186     thePrecedencePolicy.importance = relativePriority;
       
   187     result = thread_policy_set (pthread_mach_thread_np(pThread), THREAD_PRECEDENCE_POLICY, (thread_policy_t)&thePrecedencePolicy, THREAD_PRECEDENCE_POLICY_COUNT);
       
   188         if (result) return 0; /*THROW_RESULT("thread_policy - Couldn't set thread priority.")*/
       
   189 
       
   190     return 1;
       
   191 }
       
   192 
       
   193 static UInt32  FileReaderThread_GetThreadBasePriority (pthread_t inThread)
       
   194 {
       
   195     thread_basic_info_data_t            threadInfo;
       
   196     policy_info_data_t                  thePolicyInfo;
       
   197     unsigned int                        count;
       
   198     
       
   199     /* get basic info */
       
   200     count = THREAD_BASIC_INFO_COUNT;
       
   201     thread_info (pthread_mach_thread_np (inThread), THREAD_BASIC_INFO, (integer_t*)&threadInfo, &count);
       
   202     
       
   203     switch (threadInfo.policy) {
       
   204         case POLICY_TIMESHARE:
       
   205             count = POLICY_TIMESHARE_INFO_COUNT;
       
   206             thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_TIMESHARE_INFO, (integer_t*)&(thePolicyInfo.ts), &count);
       
   207             return thePolicyInfo.ts.base_priority;
       
   208             break;
       
   209             
       
   210         case POLICY_FIFO:
       
   211             count = POLICY_FIFO_INFO_COUNT;
       
   212             thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_FIFO_INFO, (integer_t*)&(thePolicyInfo.fifo), &count);
       
   213             if (thePolicyInfo.fifo.depressed) {
       
   214                 return thePolicyInfo.fifo.depress_priority;
       
   215             } else {
       
   216                 return thePolicyInfo.fifo.base_priority;
       
   217             }
       
   218             break;
       
   219             
       
   220         case POLICY_RR:
       
   221             count = POLICY_RR_INFO_COUNT;
       
   222             thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_RR_INFO, (integer_t*)&(thePolicyInfo.rr), &count);
       
   223             if (thePolicyInfo.rr.depressed) {
       
   224                 return thePolicyInfo.rr.depress_priority;
       
   225             } else {
       
   226                 return thePolicyInfo.rr.base_priority;
       
   227             }
       
   228             break;
       
   229     }
       
   230     
       
   231     return 0;
       
   232 }
       
   233 
       
   234 static void    *FileReaderThread_DiskReaderEntry (void *inRefCon)
       
   235 {
       
   236     FileReaderThread *frt = (FileReaderThread *)inRefCon;
       
   237     frt->ReadNextChunk(frt);
       
   238     #if DEBUG
       
   239     printf ("finished with reading file\n");
       
   240     #endif
       
   241     
       
   242     return 0;
       
   243 }
       
   244 
       
   245 static void    FileReaderThread_ReadNextChunk (FileReaderThread *frt)
       
   246 {
       
   247     OSStatus result;
       
   248     UInt32  dataChunkSize;
       
   249     AudioFileManager* theItem = 0;
       
   250 
       
   251     for (;;) 
       
   252     {
       
   253         { /* this is a scoped based lock */
       
   254             int bNeedsRelease = frt->mGuard->Lock(frt->mGuard);
       
   255             
       
   256             if (frt->mThreadShouldDie) {
       
   257                 frt->mGuard->Notify(frt->mGuard);
       
   258                 if (bNeedsRelease) frt->mGuard->Unlock(frt->mGuard);
       
   259                 return;
       
   260             }
       
   261             
       
   262             /*if (frt->mFileData.empty())*/
       
   263             if (frt->mFileData == NULL)
       
   264             {
       
   265                 frt->mGuard->Wait(frt->mGuard);
       
   266             }
       
   267                         
       
   268             /* kill thread */
       
   269             if (frt->mThreadShouldDie) {
       
   270             
       
   271                 frt->mGuard->Notify(frt->mGuard);
       
   272                 if (bNeedsRelease) frt->mGuard->Unlock(frt->mGuard);
       
   273                 return;
       
   274             }
       
   275 
       
   276             /*theItem = frt->mFileData.front();*/
       
   277             /*frt->mFileData.pop_front();*/
       
   278             theItem = NULL;
       
   279             if (frt->mFileData != NULL)
       
   280             {
       
   281                 FileData *next = frt->mFileData->next;
       
   282                 theItem = frt->mFileData->obj;
       
   283                 SDL_free(frt->mFileData);
       
   284                 frt->mFileData = next;
       
   285             }
       
   286 
       
   287             if (bNeedsRelease) frt->mGuard->Unlock(frt->mGuard);
       
   288         }
       
   289     
       
   290         if ((theItem->mFileLength - theItem->mReadFilePosition) < theItem->mChunkSize)
       
   291             dataChunkSize = theItem->mFileLength - theItem->mReadFilePosition;
       
   292         else
       
   293             dataChunkSize = theItem->mChunkSize;
       
   294         
       
   295             /* this is the exit condition for the thread */
       
   296         if (dataChunkSize <= 0) {
       
   297             theItem->mFinishedReadingData = 1;
       
   298             continue;
       
   299         }
       
   300             /* construct pointer */
       
   301         char* writePtr = (char *) (theItem->GetFileBuffer(theItem) +
       
   302                                 (theItem->mWriteToFirstBuffer ? 0 : theItem->mChunkSize));
       
   303     
       
   304             /* read data */
       
   305         result = theItem->Read(theItem, writePtr, &dataChunkSize);
       
   306         if (result != noErr && result != eofErr) {
       
   307             AudioFilePlayer *afp = (AudioFilePlayer *) theItem->GetParent(theItem);
       
   308             afp->DoNotification(afp, result);
       
   309             continue;
       
   310         }
       
   311         
       
   312         if (dataChunkSize != theItem->mChunkSize)
       
   313         {
       
   314             writePtr += dataChunkSize;
       
   315 
       
   316             /* can't exit yet.. we still have to pass the partial buffer back */
       
   317             SDL_memset(writePtr, 0, (theItem->mChunkSize - dataChunkSize));
       
   318         }
       
   319         
       
   320         theItem->mWriteToFirstBuffer = !theItem->mWriteToFirstBuffer;   /* switch buffers */
       
   321         
       
   322         if (result == eofErr)
       
   323             theItem->mReadFilePosition = theItem->mFileLength;
       
   324         else
       
   325             theItem->mReadFilePosition += dataChunkSize;        /* increment count */
       
   326     }
       
   327 }
       
   328 
       
   329 void delete_FileReaderThread(FileReaderThread *frt)
       
   330 {
       
   331     if (frt != NULL)
       
   332     {
       
   333         delete_SDLOSXCAGuard(frt->mGuard);
       
   334         SDL_free(frt);
       
   335     }
       
   336 }
       
   337 
       
   338 FileReaderThread *new_FileReaderThread ()
       
   339 {
       
   340     FileReaderThread *frt = (FileReaderThread *) SDL_malloc(sizeof (FileReaderThread));
       
   341     if (frt == NULL)
       
   342         return NULL;
       
   343     SDL_memset(frt, '\0', sizeof (*frt));
       
   344 
       
   345     frt->mGuard = new_SDLOSXCAGuard();
       
   346     if (frt->mGuard == NULL)
       
   347     {
       
   348         SDL_free(frt);
       
   349         return NULL;
       
   350     }
       
   351 
       
   352     #define SET_FILEREADERTHREAD_METHOD(m) frt->m = FileReaderThread_##m
       
   353     SET_FILEREADERTHREAD_METHOD(GetGuard);
       
   354     SET_FILEREADERTHREAD_METHOD(AddReader);
       
   355     SET_FILEREADERTHREAD_METHOD(RemoveReader);
       
   356     SET_FILEREADERTHREAD_METHOD(TryNextRead);
       
   357     SET_FILEREADERTHREAD_METHOD(ReadNextChunk);
       
   358     SET_FILEREADERTHREAD_METHOD(StartFixedPriorityThread);
       
   359     SET_FILEREADERTHREAD_METHOD(GetThreadBasePriority);
       
   360     SET_FILEREADERTHREAD_METHOD(DiskReaderEntry);
       
   361     #undef SET_FILEREADERTHREAD_METHOD
       
   362 
       
   363     frt->mThreadPriority = 62;
       
   364     return frt;
       
   365 }
       
   366 
       
   367 
       
   368 static FileReaderThread *sReaderThread;
       
   369 
       
   370 
       
   371 static int    AudioFileManager_DoConnect (AudioFileManager *afm)
       
   372 {
       
   373     if (!afm->mIsEngaged)
       
   374     {
       
   375         OSStatus result;
       
   376 
       
   377         /*afm->mReadFilePosition = 0;*/
       
   378         afm->mFinishedReadingData = 0;
       
   379 
       
   380         afm->mNumTimesAskedSinceFinished = 0;
       
   381         afm->mLockUnsuccessful = 0;
       
   382         
       
   383         UInt32 dataChunkSize;
       
   384         
       
   385         if ((afm->mFileLength - afm->mReadFilePosition) < afm->mChunkSize)
       
   386             dataChunkSize = afm->mFileLength - afm->mReadFilePosition;
       
   387         else
       
   388             dataChunkSize = afm->mChunkSize;
       
   389         
       
   390         result = afm->Read(afm, afm->mFileBuffer, &dataChunkSize);
       
   391            if (result) return 0; /*THROW_RESULT("AudioFileManager::DoConnect(): Read")*/
       
   392 
       
   393         afm->mReadFilePosition += dataChunkSize;
       
   394                 
       
   395         afm->mWriteToFirstBuffer = 0;
       
   396         afm->mReadFromFirstBuffer = 1;
       
   397 
       
   398         sReaderThread->AddReader(sReaderThread);
       
   399         
       
   400         afm->mIsEngaged = 1;
       
   401     }
       
   402     /*
       
   403     else
       
   404         throw static_cast<OSStatus>(-1); */ /* thread has already been started */
       
   405 
       
   406     return 1;
       
   407 }
       
   408 
       
   409 static void    AudioFileManager_Disconnect (AudioFileManager *afm)
       
   410 {
       
   411     if (afm->mIsEngaged)
       
   412     {
       
   413         sReaderThread->RemoveReader (sReaderThread, afm);
       
   414         afm->mIsEngaged = 0;
       
   415     }
       
   416 }
       
   417 
       
   418 static OSStatus AudioFileManager_Read(AudioFileManager *afm, char *buffer, UInt32 *len)
       
   419 {
       
   420     return FSReadFork (afm->mForkRefNum,
       
   421                        fsFromStart,
       
   422                        afm->mReadFilePosition + afm->mAudioDataOffset,
       
   423                        *len,
       
   424                        buffer,
       
   425                        len);
       
   426 }
       
   427 
       
   428 static OSStatus AudioFileManager_GetFileData (AudioFileManager *afm, void** inOutData, UInt32 *inOutDataSize)
       
   429 {
       
   430     if (afm->mFinishedReadingData)
       
   431     {
       
   432         ++afm->mNumTimesAskedSinceFinished;
       
   433         *inOutDataSize = 0;
       
   434         *inOutData = 0;
       
   435         return noErr;
       
   436     }
       
   437     
       
   438     if (afm->mReadFromFirstBuffer == afm->mWriteToFirstBuffer) {
       
   439         #if DEBUG
       
   440         printf ("* * * * * * * Can't keep up with reading file\n");
       
   441         #endif
       
   442         
       
   443         afm->mParent->DoNotification (afm->mParent, kAudioFilePlayErr_FilePlayUnderrun);
       
   444         *inOutDataSize = 0;
       
   445         *inOutData = 0;
       
   446     } else {
       
   447         *inOutDataSize = afm->mChunkSize;
       
   448         *inOutData = afm->mReadFromFirstBuffer ? afm->mFileBuffer : (afm->mFileBuffer + afm->mChunkSize);
       
   449     }
       
   450 
       
   451     afm->mLockUnsuccessful = !sReaderThread->TryNextRead (sReaderThread, afm);
       
   452     
       
   453     afm->mReadFromFirstBuffer = !afm->mReadFromFirstBuffer;
       
   454 
       
   455     return noErr;
       
   456 }
       
   457 
       
   458 static void    AudioFileManager_AfterRender (AudioFileManager *afm)
       
   459 {
       
   460     if (afm->mNumTimesAskedSinceFinished > 0)
       
   461     {
       
   462         int didLock = 0;
       
   463         SDLOSXCAGuard *guard = sReaderThread->GetGuard(sReaderThread);
       
   464         if (guard->Try(guard, &didLock)) {
       
   465             afm->mParent->DoNotification (afm->mParent, kAudioFilePlay_FileIsFinished);
       
   466             if (didLock)
       
   467                 guard->Unlock(guard);
       
   468         }
       
   469     }
       
   470 
       
   471     if (afm->mLockUnsuccessful)
       
   472         afm->mLockUnsuccessful = !sReaderThread->TryNextRead (sReaderThread, afm);
       
   473 }
       
   474 
       
   475 static void    AudioFileManager_SetPosition (AudioFileManager *afm, SInt64 pos)
       
   476 {
       
   477     if (pos < 0 || pos >= afm->mFileLength) {
       
   478         SDL_SetError ("AudioFileManager::SetPosition - position invalid: %d filelen=%d\n", 
       
   479             (unsigned int)pos, (unsigned int)afm->mFileLength);
       
   480         pos = 0;
       
   481     }
       
   482         
       
   483     afm->mReadFilePosition = pos;
       
   484 }
       
   485     
       
   486 static void    AudioFileManager_SetEndOfFile (AudioFileManager *afm, SInt64 pos)
       
   487 {
       
   488     if (pos <= 0 || pos > afm->mFileLength) {
       
   489         SDL_SetError ("AudioFileManager::SetEndOfFile - position beyond actual eof\n");
       
   490         pos = afm->mFileLength;
       
   491     }
       
   492     
       
   493     afm->mFileLength = pos;
       
   494 }
       
   495 
       
   496 static const char *AudioFileManager_GetFileBuffer(AudioFileManager *afm)
       
   497 {
       
   498     return afm->mFileBuffer;
       
   499 }
       
   500 
       
   501 const AudioFilePlayer *AudioFileManager_GetParent(AudioFileManager *afm)
       
   502 {
       
   503     return afm->mParent;
       
   504 }
       
   505 
       
   506 static int AudioFileManager_GetByteCounter(AudioFileManager *afm)
       
   507 {
       
   508     return afm->mByteCounter;
       
   509 }
       
   510 
       
   511 
       
   512 static OSStatus    AudioFileManager_FileInputProc (void                       *inRefCon,
       
   513                                              AudioUnitRenderActionFlags inActionFlags,
       
   514                                              const AudioTimeStamp       *inTimeStamp, 
       
   515                                              UInt32                     inBusNumber, 
       
   516                                              AudioBuffer                *ioData)
       
   517 {
       
   518     AudioFileManager* afm = (AudioFileManager*)inRefCon;
       
   519     return afm->Render(afm, ioData);
       
   520 }
       
   521 
       
   522 static OSStatus    AudioFileManager_Render (AudioFileManager *afm, AudioBuffer *ioData)
       
   523 {
       
   524     OSStatus result = noErr;
       
   525     
       
   526 	if (afm->mBufferOffset >= afm->mBufferSize) {
       
   527 		result = afm->GetFileData(afm, &afm->mTmpBuffer, &afm->mBufferSize);
       
   528 		if (result) {
       
   529 			SDL_SetError ("AudioConverterFillBuffer:%ld\n", result);
       
   530 			afm->mParent->DoNotification(afm->mParent, result);
       
   531 			return result;
       
   532 		}
       
   533 
       
   534 		afm->mBufferOffset = 0;
       
   535 	}
       
   536     	
       
   537     if (ioData->mDataByteSize > afm->mBufferSize - afm->mBufferOffset)
       
   538     	ioData->mDataByteSize = afm->mBufferSize - afm->mBufferOffset;
       
   539     ioData->mData = (char *)afm->mTmpBuffer + afm->mBufferOffset;
       
   540     afm->mBufferOffset += ioData->mDataByteSize;
       
   541     
       
   542 	afm->mByteCounter += ioData->mDataByteSize;
       
   543 	afm->AfterRender(afm);
       
   544     return result;
       
   545 }
       
   546 
       
   547 
       
   548 void delete_AudioFileManager (AudioFileManager *afm)
       
   549 {
       
   550     if (afm != NULL) {
       
   551         if (afm->mFileBuffer) {
       
   552             free(afm->mFileBuffer);
       
   553         }
       
   554 
       
   555         SDL_free(afm);
       
   556     }
       
   557 }
       
   558 
       
   559 
       
   560 AudioFileManager *new_AudioFileManager(AudioFilePlayer *inParent,
       
   561                                        SInt16          inForkRefNum,
       
   562                                        SInt64          inFileLength,
       
   563                                        UInt32          inChunkSize)
       
   564 {
       
   565     AudioFileManager *afm;
       
   566 
       
   567     if (sReaderThread == NULL)
       
   568     {
       
   569         sReaderThread = new_FileReaderThread();
       
   570         if (sReaderThread == NULL)
       
   571             return NULL;
       
   572     }
       
   573 
       
   574     afm = (AudioFileManager *) SDL_malloc(sizeof (AudioFileManager));
       
   575     if (afm == NULL)
       
   576         return NULL;
       
   577     SDL_memset(afm, '\0', sizeof (*afm));
       
   578 
       
   579     #define SET_AUDIOFILEMANAGER_METHOD(m) afm->m = AudioFileManager_##m
       
   580     SET_AUDIOFILEMANAGER_METHOD(Disconnect);
       
   581     SET_AUDIOFILEMANAGER_METHOD(DoConnect);
       
   582     SET_AUDIOFILEMANAGER_METHOD(Read);
       
   583     SET_AUDIOFILEMANAGER_METHOD(GetFileBuffer);
       
   584     SET_AUDIOFILEMANAGER_METHOD(GetParent);
       
   585     SET_AUDIOFILEMANAGER_METHOD(SetPosition);
       
   586     SET_AUDIOFILEMANAGER_METHOD(GetByteCounter);
       
   587     SET_AUDIOFILEMANAGER_METHOD(SetEndOfFile);
       
   588     SET_AUDIOFILEMANAGER_METHOD(Render);
       
   589     SET_AUDIOFILEMANAGER_METHOD(GetFileData);
       
   590     SET_AUDIOFILEMANAGER_METHOD(AfterRender);
       
   591     SET_AUDIOFILEMANAGER_METHOD(FileInputProc);
       
   592     #undef SET_AUDIOFILEMANAGER_METHOD
       
   593 
       
   594     afm->mParent = inParent;
       
   595     afm->mForkRefNum = inForkRefNum;
       
   596     afm->mBufferSize = inChunkSize;
       
   597     afm->mBufferOffset = inChunkSize;
       
   598     afm->mChunkSize = inChunkSize;
       
   599     afm->mFileLength = inFileLength;
       
   600     afm->mFileBuffer = (char*) SDL_malloc(afm->mChunkSize * 2);
       
   601     FSGetForkPosition(afm->mForkRefNum, &afm->mAudioDataOffset);
       
   602     assert (afm->mFileBuffer != NULL);
       
   603     return afm;
       
   604 }
       
   605