src/cdrom/macosx/AudioFileReaderThread.c
changeset 1487 dc6b59e925a2
parent 1402 d910939febfa
child 1662 782fd950bd46
child 1895 c121d94672cb
child 4159 a1b03ba2fcd0
equal deleted inserted replaced
1486:9d77fc9d0ace 1487:dc6b59e925a2
    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 #include "SDL_config.h"
    25 #include "SDL_config.h"
    26 
    26 
    27 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    27 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    28 // AudioFileManager.cpp
    28    AudioFileManager.cpp
    29 //
    29 */
    30 #include "AudioFilePlayer.h"
    30 #include "AudioFilePlayer.h"
    31 #include <mach/mach.h> //used for setting policy of thread
    31 #include <mach/mach.h> /* used for setting policy of thread */
    32 #include "SDLOSXCAGuard.h"
    32 #include "SDLOSXCAGuard.h"
    33 #include <pthread.h>
    33 #include <pthread.h>
    34 
    34 
    35 //#include <list>
    35 /*#include <list>*/
    36 
    36 
    37 //typedef void *FileData;
    37 /*typedef void *FileData;*/
    38 typedef struct S_FileData
    38 typedef struct S_FileData
    39 {
    39 {
    40     AudioFileManager *obj;
    40     AudioFileManager *obj;
    41     struct S_FileData *next;
    41     struct S_FileData *next;
    42 } FileData;
    42 } FileData;
    43 
    43 
    44 
    44 
    45 typedef struct S_FileReaderThread {
    45 typedef struct S_FileReaderThread {
    46 //public:
    46 /*public:*/
    47     SDLOSXCAGuard*                    (*GetGuard)(struct S_FileReaderThread *frt);
    47     SDLOSXCAGuard*                    (*GetGuard)(struct S_FileReaderThread *frt);
    48     void                        (*AddReader)(struct S_FileReaderThread *frt);
    48     void                        (*AddReader)(struct S_FileReaderThread *frt);
    49     void                        (*RemoveReader)(struct S_FileReaderThread *frt, AudioFileManager* inItem);
    49     void                        (*RemoveReader)(struct S_FileReaderThread *frt, AudioFileManager* inItem);
    50     int                         (*TryNextRead)(struct S_FileReaderThread *frt, AudioFileManager* inItem);
    50     int                         (*TryNextRead)(struct S_FileReaderThread *frt, AudioFileManager* inItem);
    51 
    51 
    52     int     mThreadShouldDie;
    52     int     mThreadShouldDie;
    53     
    53     
    54 //private:
    54 /*private:*/
    55     //typedef std::list<AudioFileManager*> FileData;
    55     /*typedef std::list<AudioFileManager*> FileData;*/
    56 
    56 
    57     SDLOSXCAGuard             *mGuard;
    57     SDLOSXCAGuard             *mGuard;
    58     UInt32              mThreadPriority;
    58     UInt32              mThreadPriority;
    59     
    59     
    60     int                 mNumReaders;    
    60     int                 mNumReaders;    
    61     FileData            *mFileData;
    61     FileData            *mFileData;
    62 
    62 
    63 
    63 
    64     void                        (*ReadNextChunk)(struct S_FileReaderThread *frt);
    64     void                        (*ReadNextChunk)(struct S_FileReaderThread *frt);
    65     int                         (*StartFixedPriorityThread)(struct S_FileReaderThread *frt);
    65     int                         (*StartFixedPriorityThread)(struct S_FileReaderThread *frt);
    66     //static
    66     /*static*/
    67     UInt32               (*GetThreadBasePriority)(pthread_t inThread);
    67     UInt32               (*GetThreadBasePriority)(pthread_t inThread);
    68     //static
    68     /*static*/
    69     void*                (*DiskReaderEntry)(void *inRefCon);
    69     void*                (*DiskReaderEntry)(void *inRefCon);
    70 } FileReaderThread;
    70 } FileReaderThread;
    71 
    71 
    72 
    72 
    73 static SDLOSXCAGuard* FileReaderThread_GetGuard(FileReaderThread *frt)
    73 static SDLOSXCAGuard* FileReaderThread_GetGuard(FileReaderThread *frt)
    74 {
    74 {
    75     return frt->mGuard;
    75     return frt->mGuard;
    76 }
    76 }
    77 
    77 
    78 // returns 1 if succeeded
    78 /* returns 1 if succeeded */
    79 static int FileReaderThread_TryNextRead (FileReaderThread *frt, AudioFileManager* inItem)
    79 static int FileReaderThread_TryNextRead (FileReaderThread *frt, AudioFileManager* inItem)
    80 {
    80 {
    81     int didLock = 0;
    81     int didLock = 0;
    82     int succeeded = 0;
    82     int succeeded = 0;
    83     if (frt->mGuard->Try(frt->mGuard, &didLock))
    83     if (frt->mGuard->Try(frt->mGuard, &didLock))
    84     {
    84     {
    85         //frt->mFileData.push_back (inItem);
    85         /*frt->mFileData.push_back (inItem);*/
    86         // !!! FIXME: this could be faster with a "tail" member. --ryan.
    86         /* !!! FIXME: this could be faster with a "tail" member. --ryan. */
    87         FileData *i = frt->mFileData;
    87         FileData *i = frt->mFileData;
    88         FileData *prev = NULL;
    88         FileData *prev = NULL;
    89 
    89 
    90         FileData *newfd = (FileData *) SDL_malloc(sizeof (FileData));
    90         FileData *newfd = (FileData *) SDL_malloc(sizeof (FileData));
    91         newfd->obj = inItem;
    91         newfd->obj = inItem;
   121 {
   121 {
   122     if (frt->mNumReaders > 0)
   122     if (frt->mNumReaders > 0)
   123     {
   123     {
   124         int bNeedsRelease = frt->mGuard->Lock(frt->mGuard);
   124         int bNeedsRelease = frt->mGuard->Lock(frt->mGuard);
   125         
   125         
   126         //frt->mFileData.remove (inItem);
   126         /*frt->mFileData.remove (inItem);*/
   127         FileData *i = frt->mFileData;
   127         FileData *i = frt->mFileData;
   128         FileData *prev = NULL;
   128         FileData *prev = NULL;
   129         while (i != NULL)
   129         while (i != NULL)
   130         {
   130         {
   131             FileData *next = i->next;
   131             FileData *next = i->next;
   142             i = next;
   142             i = next;
   143         }
   143         }
   144 
   144 
   145         if (--frt->mNumReaders == 0) {
   145         if (--frt->mNumReaders == 0) {
   146             frt->mThreadShouldDie = 1;
   146             frt->mThreadShouldDie = 1;
   147             frt->mGuard->Notify(frt->mGuard); // wake up thread so it will quit
   147             frt->mGuard->Notify(frt->mGuard); /* wake up thread so it will quit */
   148             frt->mGuard->Wait(frt->mGuard);   // wait for thread to die
   148             frt->mGuard->Wait(frt->mGuard);   /* wait for thread to die */
   149         }
   149         }
   150 
   150 
   151         if (bNeedsRelease) frt->mGuard->Unlock(frt->mGuard);
   151         if (bNeedsRelease) frt->mGuard->Unlock(frt->mGuard);
   152     }   
   152     }   
   153 }
   153 }
   156 {
   156 {
   157     pthread_attr_t      theThreadAttrs;
   157     pthread_attr_t      theThreadAttrs;
   158     pthread_t           pThread;
   158     pthread_t           pThread;
   159 
   159 
   160     OSStatus result = pthread_attr_init(&theThreadAttrs);
   160     OSStatus result = pthread_attr_init(&theThreadAttrs);
   161         if (result) return 0; //THROW_RESULT("pthread_attr_init - Thread attributes could not be created.")
   161         if (result) return 0; /*THROW_RESULT("pthread_attr_init - Thread attributes could not be created.")*/
   162     
   162     
   163     result = pthread_attr_setdetachstate(&theThreadAttrs, PTHREAD_CREATE_DETACHED);
   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.")
   164         if (result) return 0; /*THROW_RESULT("pthread_attr_setdetachstate - Thread attributes could not be detached.")*/
   165     
   165     
   166     result = pthread_create (&pThread, &theThreadAttrs, frt->DiskReaderEntry, frt);
   166     result = pthread_create (&pThread, &theThreadAttrs, frt->DiskReaderEntry, frt);
   167         if (result) return 0; //THROW_RESULT("pthread_create - Create and start the thread.")
   167         if (result) return 0; /*THROW_RESULT("pthread_create - Create and start the thread.")*/
   168     
   168     
   169     pthread_attr_destroy(&theThreadAttrs);
   169     pthread_attr_destroy(&theThreadAttrs);
   170     
   170     
   171     // we've now created the thread and started it
   171     /* we've now created the thread and started it
   172     // we'll now set the priority of the thread to the nominated priority
   172        we'll now set the priority of the thread to the nominated priority
   173     // and we'll also make the thread fixed
   173        and we'll also make the thread fixed */
   174     thread_extended_policy_data_t       theFixedPolicy;
   174     thread_extended_policy_data_t       theFixedPolicy;
   175     thread_precedence_policy_data_t     thePrecedencePolicy;
   175     thread_precedence_policy_data_t     thePrecedencePolicy;
   176     SInt32                              relativePriority;
   176     SInt32                              relativePriority;
   177     
   177     
   178     // make thread fixed
   178     /* make thread fixed */
   179     theFixedPolicy.timeshare = 0;   // set to 1 for a non-fixed thread
   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);
   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.")
   181         if (result) return 0; /*THROW_RESULT("thread_policy - Couldn't set thread as fixed priority.")*/
   182     // set priority
   182     /* set priority */
   183     // precedency policy's "importance" value is relative to spawning thread's priority
   183     /* precedency policy's "importance" value is relative to spawning thread's priority */
   184     relativePriority = frt->mThreadPriority - frt->GetThreadBasePriority(pthread_self());
   184     relativePriority = frt->mThreadPriority - frt->GetThreadBasePriority(pthread_self());
   185         
   185         
   186     thePrecedencePolicy.importance = relativePriority;
   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);
   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.")
   188         if (result) return 0; /*THROW_RESULT("thread_policy - Couldn't set thread priority.")*/
   189 
   189 
   190     return 1;
   190     return 1;
   191 }
   191 }
   192 
   192 
   193 static UInt32  FileReaderThread_GetThreadBasePriority (pthread_t inThread)
   193 static UInt32  FileReaderThread_GetThreadBasePriority (pthread_t inThread)
   194 {
   194 {
   195     thread_basic_info_data_t            threadInfo;
   195     thread_basic_info_data_t            threadInfo;
   196     policy_info_data_t                  thePolicyInfo;
   196     policy_info_data_t                  thePolicyInfo;
   197     unsigned int                        count;
   197     unsigned int                        count;
   198     
   198     
   199     // get basic info
   199     /* get basic info */
   200     count = THREAD_BASIC_INFO_COUNT;
   200     count = THREAD_BASIC_INFO_COUNT;
   201     thread_info (pthread_mach_thread_np (inThread), THREAD_BASIC_INFO, (integer_t*)&threadInfo, &count);
   201     thread_info (pthread_mach_thread_np (inThread), THREAD_BASIC_INFO, (integer_t*)&threadInfo, &count);
   202     
   202     
   203     switch (threadInfo.policy) {
   203     switch (threadInfo.policy) {
   204         case POLICY_TIMESHARE:
   204         case POLICY_TIMESHARE:
   248     UInt32  dataChunkSize;
   248     UInt32  dataChunkSize;
   249     AudioFileManager* theItem = 0;
   249     AudioFileManager* theItem = 0;
   250 
   250 
   251     for (;;) 
   251     for (;;) 
   252     {
   252     {
   253         { // this is a scoped based lock
   253         { /* this is a scoped based lock */
   254             int bNeedsRelease = frt->mGuard->Lock(frt->mGuard);
   254             int bNeedsRelease = frt->mGuard->Lock(frt->mGuard);
   255             
   255             
   256             if (frt->mThreadShouldDie) {
   256             if (frt->mThreadShouldDie) {
   257                 frt->mGuard->Notify(frt->mGuard);
   257                 frt->mGuard->Notify(frt->mGuard);
   258                 if (bNeedsRelease) frt->mGuard->Unlock(frt->mGuard);
   258                 if (bNeedsRelease) frt->mGuard->Unlock(frt->mGuard);
   259                 return;
   259                 return;
   260             }
   260             }
   261             
   261             
   262             //if (frt->mFileData.empty())
   262             /*if (frt->mFileData.empty())*/
   263             if (frt->mFileData == NULL)
   263             if (frt->mFileData == NULL)
   264             {
   264             {
   265                 frt->mGuard->Wait(frt->mGuard);
   265                 frt->mGuard->Wait(frt->mGuard);
   266             }
   266             }
   267                         
   267                         
   268             // kill thread
   268             /* kill thread */
   269             if (frt->mThreadShouldDie) {
   269             if (frt->mThreadShouldDie) {
   270             
   270             
   271                 frt->mGuard->Notify(frt->mGuard);
   271                 frt->mGuard->Notify(frt->mGuard);
   272                 if (bNeedsRelease) frt->mGuard->Unlock(frt->mGuard);
   272                 if (bNeedsRelease) frt->mGuard->Unlock(frt->mGuard);
   273                 return;
   273                 return;
   274             }
   274             }
   275 
   275 
   276             //theItem = frt->mFileData.front();
   276             /*theItem = frt->mFileData.front();*/
   277             //frt->mFileData.pop_front();
   277             /*frt->mFileData.pop_front();*/
   278             theItem = NULL;
   278             theItem = NULL;
   279             if (frt->mFileData != NULL)
   279             if (frt->mFileData != NULL)
   280             {
   280             {
   281                 FileData *next = frt->mFileData->next;
   281                 FileData *next = frt->mFileData->next;
   282                 theItem = frt->mFileData->obj;
   282                 theItem = frt->mFileData->obj;
   290         if ((theItem->mFileLength - theItem->mReadFilePosition) < theItem->mChunkSize)
   290         if ((theItem->mFileLength - theItem->mReadFilePosition) < theItem->mChunkSize)
   291             dataChunkSize = theItem->mFileLength - theItem->mReadFilePosition;
   291             dataChunkSize = theItem->mFileLength - theItem->mReadFilePosition;
   292         else
   292         else
   293             dataChunkSize = theItem->mChunkSize;
   293             dataChunkSize = theItem->mChunkSize;
   294         
   294         
   295             // this is the exit condition for the thread
   295             /* this is the exit condition for the thread */
   296         if (dataChunkSize <= 0) {
   296         if (dataChunkSize <= 0) {
   297             theItem->mFinishedReadingData = 1;
   297             theItem->mFinishedReadingData = 1;
   298             continue;
   298             continue;
   299         }
   299         }
   300             // construct pointer
   300             /* construct pointer */
   301         char* writePtr = (char *) (theItem->GetFileBuffer(theItem) +
   301         char* writePtr = (char *) (theItem->GetFileBuffer(theItem) +
   302                                 (theItem->mWriteToFirstBuffer ? 0 : theItem->mChunkSize));
   302                                 (theItem->mWriteToFirstBuffer ? 0 : theItem->mChunkSize));
   303     
   303     
   304             // read data
   304             /* read data */
   305         result = theItem->Read(theItem, writePtr, &dataChunkSize);
   305         result = theItem->Read(theItem, writePtr, &dataChunkSize);
   306         if (result != noErr && result != eofErr) {
   306         if (result != noErr && result != eofErr) {
   307             AudioFilePlayer *afp = (AudioFilePlayer *) theItem->GetParent(theItem);
   307             AudioFilePlayer *afp = (AudioFilePlayer *) theItem->GetParent(theItem);
   308             afp->DoNotification(afp, result);
   308             afp->DoNotification(afp, result);
   309             continue;
   309             continue;
   311         
   311         
   312         if (dataChunkSize != theItem->mChunkSize)
   312         if (dataChunkSize != theItem->mChunkSize)
   313         {
   313         {
   314             writePtr += dataChunkSize;
   314             writePtr += dataChunkSize;
   315 
   315 
   316             // can't exit yet.. we still have to pass the partial buffer back
   316             /* can't exit yet.. we still have to pass the partial buffer back */
   317             memset (writePtr, 0, (theItem->mChunkSize - dataChunkSize));
   317             SDL_memset(writePtr, 0, (theItem->mChunkSize - dataChunkSize));
   318         }
   318         }
   319         
   319         
   320         theItem->mWriteToFirstBuffer = !theItem->mWriteToFirstBuffer;   // switch buffers
   320         theItem->mWriteToFirstBuffer = !theItem->mWriteToFirstBuffer;   /* switch buffers */
   321         
   321         
   322         if (result == eofErr)
   322         if (result == eofErr)
   323             theItem->mReadFilePosition = theItem->mFileLength;
   323             theItem->mReadFilePosition = theItem->mFileLength;
   324         else
   324         else
   325             theItem->mReadFilePosition += dataChunkSize;        // increment count
   325             theItem->mReadFilePosition += dataChunkSize;        /* increment count */
   326     }
   326     }
   327 }
   327 }
   328 
   328 
   329 void delete_FileReaderThread(FileReaderThread *frt)
   329 void delete_FileReaderThread(FileReaderThread *frt)
   330 {
   330 {
   370 
   370 
   371 static int    AudioFileManager_DoConnect (AudioFileManager *afm)
   371 static int    AudioFileManager_DoConnect (AudioFileManager *afm)
   372 {
   372 {
   373     if (!afm->mIsEngaged)
   373     if (!afm->mIsEngaged)
   374     {
   374     {
   375         //afm->mReadFilePosition = 0;
   375         OSStatus result;
       
   376 
       
   377         /*afm->mReadFilePosition = 0;*/
   376         afm->mFinishedReadingData = 0;
   378         afm->mFinishedReadingData = 0;
   377 
   379 
   378         afm->mNumTimesAskedSinceFinished = 0;
   380         afm->mNumTimesAskedSinceFinished = 0;
   379         afm->mLockUnsuccessful = 0;
   381         afm->mLockUnsuccessful = 0;
   380         
   382         
   381         OSStatus result;
       
   382         UInt32 dataChunkSize;
   383         UInt32 dataChunkSize;
   383         
   384         
   384         if ((afm->mFileLength - afm->mReadFilePosition) < afm->mChunkSize)
   385         if ((afm->mFileLength - afm->mReadFilePosition) < afm->mChunkSize)
   385             dataChunkSize = afm->mFileLength - afm->mReadFilePosition;
   386             dataChunkSize = afm->mFileLength - afm->mReadFilePosition;
   386         else
   387         else
   387             dataChunkSize = afm->mChunkSize;
   388             dataChunkSize = afm->mChunkSize;
   388         
   389         
   389         result = afm->Read(afm, afm->mFileBuffer, &dataChunkSize);
   390         result = afm->Read(afm, afm->mFileBuffer, &dataChunkSize);
   390            if (result) return 0; //THROW_RESULT("AudioFileManager::DoConnect(): Read")
   391            if (result) return 0; /*THROW_RESULT("AudioFileManager::DoConnect(): Read")*/
   391 
   392 
   392         afm->mReadFilePosition += dataChunkSize;
   393         afm->mReadFilePosition += dataChunkSize;
   393                 
   394                 
   394         afm->mWriteToFirstBuffer = 0;
   395         afm->mWriteToFirstBuffer = 0;
   395         afm->mReadFromFirstBuffer = 1;
   396         afm->mReadFromFirstBuffer = 1;
   396 
   397 
   397         sReaderThread->AddReader(sReaderThread);
   398         sReaderThread->AddReader(sReaderThread);
   398         
   399         
   399         afm->mIsEngaged = 1;
   400         afm->mIsEngaged = 1;
   400     }
   401     }
   401     //else
   402     /*
   402     //    throw static_cast<OSStatus>(-1); //thread has already been started
   403     else
       
   404         throw static_cast<OSStatus>(-1); */ /* thread has already been started */
   403 
   405 
   404     return 1;
   406     return 1;
   405 }
   407 }
   406 
   408 
   407 static void    AudioFileManager_Disconnect (AudioFileManager *afm)
   409 static void    AudioFileManager_Disconnect (AudioFileManager *afm)