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