SDL 1.2 is moving to a branch, and SDL 1.3 is becoming the head.
--HG-- extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%401938
This commit is contained in:
parent
91a32b77a2
commit
0f030a1802
686 changed files with 117556 additions and 98661 deletions
|
@ -28,7 +28,7 @@
|
|||
AudioFileManager.cpp
|
||||
*/
|
||||
#include "AudioFilePlayer.h"
|
||||
#include <mach/mach.h> /* used for setting policy of thread */
|
||||
#include <mach/mach.h> /* used for setting policy of thread */
|
||||
#include "SDLOSXCAGuard.h"
|
||||
#include <pthread.h>
|
||||
|
||||
|
@ -42,56 +42,64 @@ typedef struct S_FileData
|
|||
} FileData;
|
||||
|
||||
|
||||
typedef struct S_FileReaderThread {
|
||||
typedef struct S_FileReaderThread
|
||||
{
|
||||
/*public:*/
|
||||
SDLOSXCAGuard* (*GetGuard)(struct S_FileReaderThread *frt);
|
||||
void (*AddReader)(struct S_FileReaderThread *frt);
|
||||
void (*RemoveReader)(struct S_FileReaderThread *frt, AudioFileManager* inItem);
|
||||
int (*TryNextRead)(struct S_FileReaderThread *frt, AudioFileManager* inItem);
|
||||
SDLOSXCAGuard *(*GetGuard) (struct S_FileReaderThread * frt);
|
||||
void (*AddReader) (struct S_FileReaderThread * frt);
|
||||
void (*RemoveReader) (struct S_FileReaderThread * frt,
|
||||
AudioFileManager * inItem);
|
||||
int (*TryNextRead) (struct S_FileReaderThread * frt,
|
||||
AudioFileManager * inItem);
|
||||
|
||||
int mThreadShouldDie;
|
||||
|
||||
int mThreadShouldDie;
|
||||
|
||||
/*private:*/
|
||||
/*typedef std::list<AudioFileManager*> FileData;*/
|
||||
/*typedef std::list<AudioFileManager*> FileData; */
|
||||
|
||||
SDLOSXCAGuard *mGuard;
|
||||
UInt32 mThreadPriority;
|
||||
|
||||
int mNumReaders;
|
||||
FileData *mFileData;
|
||||
SDLOSXCAGuard *mGuard;
|
||||
UInt32 mThreadPriority;
|
||||
|
||||
int mNumReaders;
|
||||
FileData *mFileData;
|
||||
|
||||
|
||||
void (*ReadNextChunk)(struct S_FileReaderThread *frt);
|
||||
int (*StartFixedPriorityThread)(struct S_FileReaderThread *frt);
|
||||
/*static*/
|
||||
UInt32 (*GetThreadBasePriority)(pthread_t inThread);
|
||||
/*static*/
|
||||
void* (*DiskReaderEntry)(void *inRefCon);
|
||||
void (*ReadNextChunk) (struct S_FileReaderThread * frt);
|
||||
int (*StartFixedPriorityThread) (struct S_FileReaderThread * frt);
|
||||
/*static */
|
||||
UInt32(*GetThreadBasePriority) (pthread_t inThread);
|
||||
/*static */
|
||||
void *(*DiskReaderEntry) (void *inRefCon);
|
||||
} FileReaderThread;
|
||||
|
||||
|
||||
static SDLOSXCAGuard* FileReaderThread_GetGuard(FileReaderThread *frt)
|
||||
static SDLOSXCAGuard *
|
||||
FileReaderThread_GetGuard(FileReaderThread * frt)
|
||||
{
|
||||
return frt->mGuard;
|
||||
}
|
||||
|
||||
/* returns 1 if succeeded */
|
||||
static int FileReaderThread_TryNextRead (FileReaderThread *frt, AudioFileManager* inItem)
|
||||
static int
|
||||
FileReaderThread_TryNextRead(FileReaderThread * frt,
|
||||
AudioFileManager * inItem)
|
||||
{
|
||||
int didLock = 0;
|
||||
int succeeded = 0;
|
||||
if (frt->mGuard->Try(frt->mGuard, &didLock))
|
||||
{
|
||||
/*frt->mFileData.push_back (inItem);*/
|
||||
if (frt->mGuard->Try(frt->mGuard, &didLock)) {
|
||||
/*frt->mFileData.push_back (inItem); */
|
||||
/* !!! FIXME: this could be faster with a "tail" member. --ryan. */
|
||||
FileData *i = frt->mFileData;
|
||||
FileData *prev = NULL;
|
||||
|
||||
FileData *newfd = (FileData *) SDL_malloc(sizeof (FileData));
|
||||
FileData *newfd = (FileData *) SDL_malloc(sizeof(FileData));
|
||||
newfd->obj = inItem;
|
||||
newfd->next = NULL;
|
||||
|
||||
while (i != NULL) { prev = i; i = i->next; }
|
||||
while (i != NULL) {
|
||||
prev = i;
|
||||
i = i->next;
|
||||
}
|
||||
if (prev == NULL)
|
||||
frt->mFileData = newfd;
|
||||
else
|
||||
|
@ -103,36 +111,35 @@ static int FileReaderThread_TryNextRead (FileReaderThread *frt, AudioFileManager
|
|||
if (didLock)
|
||||
frt->mGuard->Unlock(frt->mGuard);
|
||||
}
|
||||
|
||||
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
static void FileReaderThread_AddReader(FileReaderThread *frt)
|
||||
static void
|
||||
FileReaderThread_AddReader(FileReaderThread * frt)
|
||||
{
|
||||
if (frt->mNumReaders == 0)
|
||||
{
|
||||
if (frt->mNumReaders == 0) {
|
||||
frt->mThreadShouldDie = 0;
|
||||
frt->StartFixedPriorityThread (frt);
|
||||
frt->StartFixedPriorityThread(frt);
|
||||
}
|
||||
frt->mNumReaders++;
|
||||
}
|
||||
|
||||
static void FileReaderThread_RemoveReader (FileReaderThread *frt, AudioFileManager* inItem)
|
||||
static void
|
||||
FileReaderThread_RemoveReader(FileReaderThread * frt,
|
||||
AudioFileManager * inItem)
|
||||
{
|
||||
if (frt->mNumReaders > 0)
|
||||
{
|
||||
if (frt->mNumReaders > 0) {
|
||||
int bNeedsRelease = frt->mGuard->Lock(frt->mGuard);
|
||||
|
||||
/*frt->mFileData.remove (inItem);*/
|
||||
|
||||
/*frt->mFileData.remove (inItem); */
|
||||
FileData *i = frt->mFileData;
|
||||
FileData *prev = NULL;
|
||||
while (i != NULL)
|
||||
{
|
||||
while (i != NULL) {
|
||||
FileData *next = i->next;
|
||||
if (i->obj != inItem)
|
||||
prev = i;
|
||||
else
|
||||
{
|
||||
else {
|
||||
if (prev == NULL)
|
||||
frt->mFileData = next;
|
||||
else
|
||||
|
@ -144,181 +151,212 @@ static void FileReaderThread_RemoveReader (FileReaderThread *frt, AudioFileMa
|
|||
|
||||
if (--frt->mNumReaders == 0) {
|
||||
frt->mThreadShouldDie = 1;
|
||||
frt->mGuard->Notify(frt->mGuard); /* wake up thread so it will quit */
|
||||
frt->mGuard->Wait(frt->mGuard); /* wait for thread to die */
|
||||
frt->mGuard->Notify(frt->mGuard); /* wake up thread so it will quit */
|
||||
frt->mGuard->Wait(frt->mGuard); /* wait for thread to die */
|
||||
}
|
||||
|
||||
if (bNeedsRelease) frt->mGuard->Unlock(frt->mGuard);
|
||||
}
|
||||
if (bNeedsRelease)
|
||||
frt->mGuard->Unlock(frt->mGuard);
|
||||
}
|
||||
}
|
||||
|
||||
static int FileReaderThread_StartFixedPriorityThread (FileReaderThread *frt)
|
||||
static int
|
||||
FileReaderThread_StartFixedPriorityThread(FileReaderThread * frt)
|
||||
{
|
||||
pthread_attr_t theThreadAttrs;
|
||||
pthread_t pThread;
|
||||
pthread_attr_t theThreadAttrs;
|
||||
pthread_t pThread;
|
||||
|
||||
OSStatus result = pthread_attr_init(&theThreadAttrs);
|
||||
if (result) return 0; /*THROW_RESULT("pthread_attr_init - Thread attributes could not be created.")*/
|
||||
|
||||
result = pthread_attr_setdetachstate(&theThreadAttrs, PTHREAD_CREATE_DETACHED);
|
||||
if (result) return 0; /*THROW_RESULT("pthread_attr_setdetachstate - Thread attributes could not be detached.")*/
|
||||
|
||||
result = pthread_create (&pThread, &theThreadAttrs, frt->DiskReaderEntry, frt);
|
||||
if (result) return 0; /*THROW_RESULT("pthread_create - Create and start the thread.")*/
|
||||
|
||||
if (result)
|
||||
return 0; /*THROW_RESULT("pthread_attr_init - Thread attributes could not be created.") */
|
||||
|
||||
result =
|
||||
pthread_attr_setdetachstate(&theThreadAttrs, PTHREAD_CREATE_DETACHED);
|
||||
if (result)
|
||||
return 0; /*THROW_RESULT("pthread_attr_setdetachstate - Thread attributes could not be detached.") */
|
||||
|
||||
result =
|
||||
pthread_create(&pThread, &theThreadAttrs, frt->DiskReaderEntry, frt);
|
||||
if (result)
|
||||
return 0; /*THROW_RESULT("pthread_create - Create and start the thread.") */
|
||||
|
||||
pthread_attr_destroy(&theThreadAttrs);
|
||||
|
||||
|
||||
/* we've now created the thread and started it
|
||||
we'll now set the priority of the thread to the nominated priority
|
||||
and we'll also make the thread fixed */
|
||||
thread_extended_policy_data_t theFixedPolicy;
|
||||
thread_precedence_policy_data_t thePrecedencePolicy;
|
||||
SInt32 relativePriority;
|
||||
|
||||
thread_extended_policy_data_t theFixedPolicy;
|
||||
thread_precedence_policy_data_t thePrecedencePolicy;
|
||||
SInt32 relativePriority;
|
||||
|
||||
/* make thread fixed */
|
||||
theFixedPolicy.timeshare = 0; /* set to 1 for a non-fixed thread */
|
||||
result = thread_policy_set (pthread_mach_thread_np(pThread), THREAD_EXTENDED_POLICY, (thread_policy_t)&theFixedPolicy, THREAD_EXTENDED_POLICY_COUNT);
|
||||
if (result) return 0; /*THROW_RESULT("thread_policy - Couldn't set thread as fixed priority.")*/
|
||||
theFixedPolicy.timeshare = 0; /* set to 1 for a non-fixed thread */
|
||||
result =
|
||||
thread_policy_set(pthread_mach_thread_np(pThread),
|
||||
THREAD_EXTENDED_POLICY,
|
||||
(thread_policy_t) & theFixedPolicy,
|
||||
THREAD_EXTENDED_POLICY_COUNT);
|
||||
if (result)
|
||||
return 0; /*THROW_RESULT("thread_policy - Couldn't set thread as fixed priority.") */
|
||||
/* set priority */
|
||||
/* precedency policy's "importance" value is relative to spawning thread's priority */
|
||||
relativePriority = frt->mThreadPriority - frt->GetThreadBasePriority(pthread_self());
|
||||
|
||||
relativePriority =
|
||||
frt->mThreadPriority - frt->GetThreadBasePriority(pthread_self());
|
||||
|
||||
thePrecedencePolicy.importance = relativePriority;
|
||||
result = thread_policy_set (pthread_mach_thread_np(pThread), THREAD_PRECEDENCE_POLICY, (thread_policy_t)&thePrecedencePolicy, THREAD_PRECEDENCE_POLICY_COUNT);
|
||||
if (result) return 0; /*THROW_RESULT("thread_policy - Couldn't set thread priority.")*/
|
||||
result =
|
||||
thread_policy_set(pthread_mach_thread_np(pThread),
|
||||
THREAD_PRECEDENCE_POLICY,
|
||||
(thread_policy_t) & thePrecedencePolicy,
|
||||
THREAD_PRECEDENCE_POLICY_COUNT);
|
||||
if (result)
|
||||
return 0; /*THROW_RESULT("thread_policy - Couldn't set thread priority.") */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static UInt32 FileReaderThread_GetThreadBasePriority (pthread_t inThread)
|
||||
static UInt32
|
||||
FileReaderThread_GetThreadBasePriority(pthread_t inThread)
|
||||
{
|
||||
thread_basic_info_data_t threadInfo;
|
||||
policy_info_data_t thePolicyInfo;
|
||||
unsigned int count;
|
||||
|
||||
thread_basic_info_data_t threadInfo;
|
||||
policy_info_data_t thePolicyInfo;
|
||||
unsigned int count;
|
||||
|
||||
/* get basic info */
|
||||
count = THREAD_BASIC_INFO_COUNT;
|
||||
thread_info (pthread_mach_thread_np (inThread), THREAD_BASIC_INFO, (integer_t*)&threadInfo, &count);
|
||||
|
||||
thread_info(pthread_mach_thread_np(inThread), THREAD_BASIC_INFO,
|
||||
(integer_t *) & threadInfo, &count);
|
||||
|
||||
switch (threadInfo.policy) {
|
||||
case POLICY_TIMESHARE:
|
||||
count = POLICY_TIMESHARE_INFO_COUNT;
|
||||
thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_TIMESHARE_INFO, (integer_t*)&(thePolicyInfo.ts), &count);
|
||||
return thePolicyInfo.ts.base_priority;
|
||||
break;
|
||||
|
||||
case POLICY_FIFO:
|
||||
count = POLICY_FIFO_INFO_COUNT;
|
||||
thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_FIFO_INFO, (integer_t*)&(thePolicyInfo.fifo), &count);
|
||||
if (thePolicyInfo.fifo.depressed) {
|
||||
return thePolicyInfo.fifo.depress_priority;
|
||||
} else {
|
||||
return thePolicyInfo.fifo.base_priority;
|
||||
}
|
||||
break;
|
||||
|
||||
case POLICY_RR:
|
||||
count = POLICY_RR_INFO_COUNT;
|
||||
thread_info(pthread_mach_thread_np (inThread), THREAD_SCHED_RR_INFO, (integer_t*)&(thePolicyInfo.rr), &count);
|
||||
if (thePolicyInfo.rr.depressed) {
|
||||
return thePolicyInfo.rr.depress_priority;
|
||||
} else {
|
||||
return thePolicyInfo.rr.base_priority;
|
||||
}
|
||||
break;
|
||||
case POLICY_TIMESHARE:
|
||||
count = POLICY_TIMESHARE_INFO_COUNT;
|
||||
thread_info(pthread_mach_thread_np(inThread),
|
||||
THREAD_SCHED_TIMESHARE_INFO,
|
||||
(integer_t *) & (thePolicyInfo.ts), &count);
|
||||
return thePolicyInfo.ts.base_priority;
|
||||
break;
|
||||
|
||||
case POLICY_FIFO:
|
||||
count = POLICY_FIFO_INFO_COUNT;
|
||||
thread_info(pthread_mach_thread_np(inThread),
|
||||
THREAD_SCHED_FIFO_INFO,
|
||||
(integer_t *) & (thePolicyInfo.fifo), &count);
|
||||
if (thePolicyInfo.fifo.depressed) {
|
||||
return thePolicyInfo.fifo.depress_priority;
|
||||
} else {
|
||||
return thePolicyInfo.fifo.base_priority;
|
||||
}
|
||||
break;
|
||||
|
||||
case POLICY_RR:
|
||||
count = POLICY_RR_INFO_COUNT;
|
||||
thread_info(pthread_mach_thread_np(inThread),
|
||||
THREAD_SCHED_RR_INFO,
|
||||
(integer_t *) & (thePolicyInfo.rr), &count);
|
||||
if (thePolicyInfo.rr.depressed) {
|
||||
return thePolicyInfo.rr.depress_priority;
|
||||
} else {
|
||||
return thePolicyInfo.rr.base_priority;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *FileReaderThread_DiskReaderEntry (void *inRefCon)
|
||||
static void *
|
||||
FileReaderThread_DiskReaderEntry(void *inRefCon)
|
||||
{
|
||||
FileReaderThread *frt = (FileReaderThread *)inRefCon;
|
||||
FileReaderThread *frt = (FileReaderThread *) inRefCon;
|
||||
frt->ReadNextChunk(frt);
|
||||
#if DEBUG
|
||||
printf ("finished with reading file\n");
|
||||
#endif
|
||||
|
||||
#if DEBUG
|
||||
printf("finished with reading file\n");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void FileReaderThread_ReadNextChunk (FileReaderThread *frt)
|
||||
static void
|
||||
FileReaderThread_ReadNextChunk(FileReaderThread * frt)
|
||||
{
|
||||
OSStatus result;
|
||||
UInt32 dataChunkSize;
|
||||
AudioFileManager* theItem = 0;
|
||||
UInt32 dataChunkSize;
|
||||
AudioFileManager *theItem = 0;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
{ /* this is a scoped based lock */
|
||||
for (;;) {
|
||||
{ /* this is a scoped based lock */
|
||||
int bNeedsRelease = frt->mGuard->Lock(frt->mGuard);
|
||||
|
||||
|
||||
if (frt->mThreadShouldDie) {
|
||||
frt->mGuard->Notify(frt->mGuard);
|
||||
if (bNeedsRelease) frt->mGuard->Unlock(frt->mGuard);
|
||||
if (bNeedsRelease)
|
||||
frt->mGuard->Unlock(frt->mGuard);
|
||||
return;
|
||||
}
|
||||
|
||||
/*if (frt->mFileData.empty())*/
|
||||
if (frt->mFileData == NULL)
|
||||
{
|
||||
|
||||
/*if (frt->mFileData.empty()) */
|
||||
if (frt->mFileData == NULL) {
|
||||
frt->mGuard->Wait(frt->mGuard);
|
||||
}
|
||||
|
||||
|
||||
/* kill thread */
|
||||
if (frt->mThreadShouldDie) {
|
||||
|
||||
|
||||
frt->mGuard->Notify(frt->mGuard);
|
||||
if (bNeedsRelease) frt->mGuard->Unlock(frt->mGuard);
|
||||
if (bNeedsRelease)
|
||||
frt->mGuard->Unlock(frt->mGuard);
|
||||
return;
|
||||
}
|
||||
|
||||
/*theItem = frt->mFileData.front();*/
|
||||
/*frt->mFileData.pop_front();*/
|
||||
/*theItem = frt->mFileData.front(); */
|
||||
/*frt->mFileData.pop_front(); */
|
||||
theItem = NULL;
|
||||
if (frt->mFileData != NULL)
|
||||
{
|
||||
if (frt->mFileData != NULL) {
|
||||
FileData *next = frt->mFileData->next;
|
||||
theItem = frt->mFileData->obj;
|
||||
SDL_free(frt->mFileData);
|
||||
frt->mFileData = next;
|
||||
}
|
||||
|
||||
if (bNeedsRelease) frt->mGuard->Unlock(frt->mGuard);
|
||||
if (bNeedsRelease)
|
||||
frt->mGuard->Unlock(frt->mGuard);
|
||||
}
|
||||
|
||||
if ((theItem->mFileLength - theItem->mReadFilePosition) < theItem->mChunkSize)
|
||||
|
||||
if ((theItem->mFileLength - theItem->mReadFilePosition) <
|
||||
theItem->mChunkSize)
|
||||
dataChunkSize = theItem->mFileLength - theItem->mReadFilePosition;
|
||||
else
|
||||
dataChunkSize = theItem->mChunkSize;
|
||||
|
||||
/* this is the exit condition for the thread */
|
||||
|
||||
/* this is the exit condition for the thread */
|
||||
if (dataChunkSize <= 0) {
|
||||
theItem->mFinishedReadingData = 1;
|
||||
continue;
|
||||
}
|
||||
/* construct pointer */
|
||||
char* writePtr = (char *) (theItem->GetFileBuffer(theItem) +
|
||||
(theItem->mWriteToFirstBuffer ? 0 : theItem->mChunkSize));
|
||||
|
||||
/* read data */
|
||||
/* construct pointer */
|
||||
char *writePtr = (char *) (theItem->GetFileBuffer(theItem) +
|
||||
(theItem->
|
||||
mWriteToFirstBuffer ? 0 : theItem->
|
||||
mChunkSize));
|
||||
|
||||
/* read data */
|
||||
result = theItem->Read(theItem, writePtr, &dataChunkSize);
|
||||
if (result != noErr && result != eofErr) {
|
||||
AudioFilePlayer *afp = (AudioFilePlayer *) theItem->GetParent(theItem);
|
||||
AudioFilePlayer *afp =
|
||||
(AudioFilePlayer *) theItem->GetParent(theItem);
|
||||
afp->DoNotification(afp, result);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dataChunkSize != theItem->mChunkSize)
|
||||
{
|
||||
|
||||
if (dataChunkSize != theItem->mChunkSize) {
|
||||
writePtr += dataChunkSize;
|
||||
|
||||
/* can't exit yet.. we still have to pass the partial buffer back */
|
||||
SDL_memset(writePtr, 0, (theItem->mChunkSize - dataChunkSize));
|
||||
}
|
||||
|
||||
|
||||
theItem->mWriteToFirstBuffer = !theItem->mWriteToFirstBuffer; /* switch buffers */
|
||||
|
||||
|
||||
if (result == eofErr)
|
||||
theItem->mReadFilePosition = theItem->mFileLength;
|
||||
else
|
||||
|
@ -326,30 +364,30 @@ static void FileReaderThread_ReadNextChunk (FileReaderThread *frt)
|
|||
}
|
||||
}
|
||||
|
||||
void delete_FileReaderThread(FileReaderThread *frt)
|
||||
void
|
||||
delete_FileReaderThread(FileReaderThread * frt)
|
||||
{
|
||||
if (frt != NULL)
|
||||
{
|
||||
if (frt != NULL) {
|
||||
delete_SDLOSXCAGuard(frt->mGuard);
|
||||
SDL_free(frt);
|
||||
}
|
||||
}
|
||||
|
||||
FileReaderThread *new_FileReaderThread ()
|
||||
FileReaderThread *
|
||||
new_FileReaderThread()
|
||||
{
|
||||
FileReaderThread *frt = (FileReaderThread *) SDL_malloc(sizeof (FileReaderThread));
|
||||
FileReaderThread *frt =
|
||||
(FileReaderThread *) SDL_malloc(sizeof(FileReaderThread));
|
||||
if (frt == NULL)
|
||||
return NULL;
|
||||
SDL_memset(frt, '\0', sizeof (*frt));
|
||||
SDL_memset(frt, '\0', sizeof(*frt));
|
||||
|
||||
frt->mGuard = new_SDLOSXCAGuard();
|
||||
if (frt->mGuard == NULL)
|
||||
{
|
||||
if (frt->mGuard == NULL) {
|
||||
SDL_free(frt);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define SET_FILEREADERTHREAD_METHOD(m) frt->m = FileReaderThread_##m
|
||||
#define SET_FILEREADERTHREAD_METHOD(m) frt->m = FileReaderThread_##m
|
||||
SET_FILEREADERTHREAD_METHOD(GetGuard);
|
||||
SET_FILEREADERTHREAD_METHOD(AddReader);
|
||||
SET_FILEREADERTHREAD_METHOD(RemoveReader);
|
||||
|
@ -358,7 +396,7 @@ FileReaderThread *new_FileReaderThread ()
|
|||
SET_FILEREADERTHREAD_METHOD(StartFixedPriorityThread);
|
||||
SET_FILEREADERTHREAD_METHOD(GetThreadBasePriority);
|
||||
SET_FILEREADERTHREAD_METHOD(DiskReaderEntry);
|
||||
#undef SET_FILEREADERTHREAD_METHOD
|
||||
#undef SET_FILEREADERTHREAD_METHOD
|
||||
|
||||
frt->mThreadPriority = 62;
|
||||
return frt;
|
||||
|
@ -368,184 +406,200 @@ FileReaderThread *new_FileReaderThread ()
|
|||
static FileReaderThread *sReaderThread;
|
||||
|
||||
|
||||
static int AudioFileManager_DoConnect (AudioFileManager *afm)
|
||||
static int
|
||||
AudioFileManager_DoConnect(AudioFileManager * afm)
|
||||
{
|
||||
if (!afm->mIsEngaged)
|
||||
{
|
||||
if (!afm->mIsEngaged) {
|
||||
OSStatus result;
|
||||
|
||||
/*afm->mReadFilePosition = 0;*/
|
||||
/*afm->mReadFilePosition = 0; */
|
||||
afm->mFinishedReadingData = 0;
|
||||
|
||||
afm->mNumTimesAskedSinceFinished = 0;
|
||||
afm->mLockUnsuccessful = 0;
|
||||
|
||||
|
||||
UInt32 dataChunkSize;
|
||||
|
||||
|
||||
if ((afm->mFileLength - afm->mReadFilePosition) < afm->mChunkSize)
|
||||
dataChunkSize = afm->mFileLength - afm->mReadFilePosition;
|
||||
else
|
||||
dataChunkSize = afm->mChunkSize;
|
||||
|
||||
|
||||
result = afm->Read(afm, afm->mFileBuffer, &dataChunkSize);
|
||||
if (result) return 0; /*THROW_RESULT("AudioFileManager::DoConnect(): Read")*/
|
||||
if (result)
|
||||
return 0; /*THROW_RESULT("AudioFileManager::DoConnect(): Read") */
|
||||
|
||||
afm->mReadFilePosition += dataChunkSize;
|
||||
|
||||
|
||||
afm->mWriteToFirstBuffer = 0;
|
||||
afm->mReadFromFirstBuffer = 1;
|
||||
|
||||
sReaderThread->AddReader(sReaderThread);
|
||||
|
||||
|
||||
afm->mIsEngaged = 1;
|
||||
}
|
||||
/*
|
||||
else
|
||||
throw static_cast<OSStatus>(-1); */ /* thread has already been started */
|
||||
else
|
||||
throw static_cast<OSStatus>(-1); *//* thread has already been started */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void AudioFileManager_Disconnect (AudioFileManager *afm)
|
||||
static void
|
||||
AudioFileManager_Disconnect(AudioFileManager * afm)
|
||||
{
|
||||
if (afm->mIsEngaged)
|
||||
{
|
||||
sReaderThread->RemoveReader (sReaderThread, afm);
|
||||
if (afm->mIsEngaged) {
|
||||
sReaderThread->RemoveReader(sReaderThread, afm);
|
||||
afm->mIsEngaged = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static OSStatus AudioFileManager_Read(AudioFileManager *afm, char *buffer, UInt32 *len)
|
||||
static OSStatus
|
||||
AudioFileManager_Read(AudioFileManager * afm, char *buffer, UInt32 * len)
|
||||
{
|
||||
return FSReadFork (afm->mForkRefNum,
|
||||
fsFromStart,
|
||||
afm->mReadFilePosition + afm->mAudioDataOffset,
|
||||
*len,
|
||||
buffer,
|
||||
len);
|
||||
return FSReadFork(afm->mForkRefNum,
|
||||
fsFromStart,
|
||||
afm->mReadFilePosition + afm->mAudioDataOffset,
|
||||
*len, buffer, len);
|
||||
}
|
||||
|
||||
static OSStatus AudioFileManager_GetFileData (AudioFileManager *afm, void** inOutData, UInt32 *inOutDataSize)
|
||||
static OSStatus
|
||||
AudioFileManager_GetFileData(AudioFileManager * afm, void **inOutData,
|
||||
UInt32 * inOutDataSize)
|
||||
{
|
||||
if (afm->mFinishedReadingData)
|
||||
{
|
||||
if (afm->mFinishedReadingData) {
|
||||
++afm->mNumTimesAskedSinceFinished;
|
||||
*inOutDataSize = 0;
|
||||
*inOutData = 0;
|
||||
return noErr;
|
||||
}
|
||||
|
||||
|
||||
if (afm->mReadFromFirstBuffer == afm->mWriteToFirstBuffer) {
|
||||
#if DEBUG
|
||||
printf ("* * * * * * * Can't keep up with reading file\n");
|
||||
#endif
|
||||
|
||||
afm->mParent->DoNotification (afm->mParent, kAudioFilePlayErr_FilePlayUnderrun);
|
||||
#if DEBUG
|
||||
printf("* * * * * * * Can't keep up with reading file\n");
|
||||
#endif
|
||||
|
||||
afm->mParent->DoNotification(afm->mParent,
|
||||
kAudioFilePlayErr_FilePlayUnderrun);
|
||||
*inOutDataSize = 0;
|
||||
*inOutData = 0;
|
||||
} else {
|
||||
*inOutDataSize = afm->mChunkSize;
|
||||
*inOutData = afm->mReadFromFirstBuffer ? afm->mFileBuffer : (afm->mFileBuffer + afm->mChunkSize);
|
||||
*inOutData =
|
||||
afm->mReadFromFirstBuffer ? afm->mFileBuffer : (afm->
|
||||
mFileBuffer +
|
||||
afm->mChunkSize);
|
||||
}
|
||||
|
||||
afm->mLockUnsuccessful = !sReaderThread->TryNextRead (sReaderThread, afm);
|
||||
|
||||
afm->mLockUnsuccessful = !sReaderThread->TryNextRead(sReaderThread, afm);
|
||||
|
||||
afm->mReadFromFirstBuffer = !afm->mReadFromFirstBuffer;
|
||||
|
||||
return noErr;
|
||||
}
|
||||
|
||||
static void AudioFileManager_AfterRender (AudioFileManager *afm)
|
||||
static void
|
||||
AudioFileManager_AfterRender(AudioFileManager * afm)
|
||||
{
|
||||
if (afm->mNumTimesAskedSinceFinished > 0)
|
||||
{
|
||||
if (afm->mNumTimesAskedSinceFinished > 0) {
|
||||
int didLock = 0;
|
||||
SDLOSXCAGuard *guard = sReaderThread->GetGuard(sReaderThread);
|
||||
if (guard->Try(guard, &didLock)) {
|
||||
afm->mParent->DoNotification (afm->mParent, kAudioFilePlay_FileIsFinished);
|
||||
afm->mParent->DoNotification(afm->mParent,
|
||||
kAudioFilePlay_FileIsFinished);
|
||||
if (didLock)
|
||||
guard->Unlock(guard);
|
||||
}
|
||||
}
|
||||
|
||||
if (afm->mLockUnsuccessful)
|
||||
afm->mLockUnsuccessful = !sReaderThread->TryNextRead (sReaderThread, afm);
|
||||
afm->mLockUnsuccessful =
|
||||
!sReaderThread->TryNextRead(sReaderThread, afm);
|
||||
}
|
||||
|
||||
static void AudioFileManager_SetPosition (AudioFileManager *afm, SInt64 pos)
|
||||
static void
|
||||
AudioFileManager_SetPosition(AudioFileManager * afm, SInt64 pos)
|
||||
{
|
||||
if (pos < 0 || pos >= afm->mFileLength) {
|
||||
SDL_SetError ("AudioFileManager::SetPosition - position invalid: %d filelen=%d\n",
|
||||
(unsigned int)pos, (unsigned int)afm->mFileLength);
|
||||
SDL_SetError
|
||||
("AudioFileManager::SetPosition - position invalid: %d filelen=%d\n",
|
||||
(unsigned int) pos, (unsigned int) afm->mFileLength);
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
|
||||
afm->mReadFilePosition = pos;
|
||||
}
|
||||
|
||||
static void AudioFileManager_SetEndOfFile (AudioFileManager *afm, SInt64 pos)
|
||||
|
||||
static void
|
||||
AudioFileManager_SetEndOfFile(AudioFileManager * afm, SInt64 pos)
|
||||
{
|
||||
if (pos <= 0 || pos > afm->mFileLength) {
|
||||
SDL_SetError ("AudioFileManager::SetEndOfFile - position beyond actual eof\n");
|
||||
SDL_SetError
|
||||
("AudioFileManager::SetEndOfFile - position beyond actual eof\n");
|
||||
pos = afm->mFileLength;
|
||||
}
|
||||
|
||||
|
||||
afm->mFileLength = pos;
|
||||
}
|
||||
|
||||
static const char *AudioFileManager_GetFileBuffer(AudioFileManager *afm)
|
||||
static const char *
|
||||
AudioFileManager_GetFileBuffer(AudioFileManager * afm)
|
||||
{
|
||||
return afm->mFileBuffer;
|
||||
}
|
||||
|
||||
const AudioFilePlayer *AudioFileManager_GetParent(AudioFileManager *afm)
|
||||
const AudioFilePlayer *
|
||||
AudioFileManager_GetParent(AudioFileManager * afm)
|
||||
{
|
||||
return afm->mParent;
|
||||
}
|
||||
|
||||
static int AudioFileManager_GetByteCounter(AudioFileManager *afm)
|
||||
static int
|
||||
AudioFileManager_GetByteCounter(AudioFileManager * afm)
|
||||
{
|
||||
return afm->mByteCounter;
|
||||
}
|
||||
|
||||
|
||||
static OSStatus AudioFileManager_FileInputProc (void *inRefCon,
|
||||
AudioUnitRenderActionFlags inActionFlags,
|
||||
const AudioTimeStamp *inTimeStamp,
|
||||
UInt32 inBusNumber,
|
||||
AudioBuffer *ioData)
|
||||
static OSStatus
|
||||
AudioFileManager_FileInputProc(void *inRefCon,
|
||||
AudioUnitRenderActionFlags inActionFlags,
|
||||
const AudioTimeStamp * inTimeStamp,
|
||||
UInt32 inBusNumber, AudioBuffer * ioData)
|
||||
{
|
||||
AudioFileManager* afm = (AudioFileManager*)inRefCon;
|
||||
AudioFileManager *afm = (AudioFileManager *) inRefCon;
|
||||
return afm->Render(afm, ioData);
|
||||
}
|
||||
|
||||
static OSStatus AudioFileManager_Render (AudioFileManager *afm, AudioBuffer *ioData)
|
||||
static OSStatus
|
||||
AudioFileManager_Render(AudioFileManager * afm, AudioBuffer * ioData)
|
||||
{
|
||||
OSStatus result = noErr;
|
||||
|
||||
if (afm->mBufferOffset >= afm->mBufferSize) {
|
||||
result = afm->GetFileData(afm, &afm->mTmpBuffer, &afm->mBufferSize);
|
||||
if (result) {
|
||||
SDL_SetError ("AudioConverterFillBuffer:%ld\n", result);
|
||||
afm->mParent->DoNotification(afm->mParent, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
afm->mBufferOffset = 0;
|
||||
}
|
||||
|
||||
if (afm->mBufferOffset >= afm->mBufferSize) {
|
||||
result = afm->GetFileData(afm, &afm->mTmpBuffer, &afm->mBufferSize);
|
||||
if (result) {
|
||||
SDL_SetError("AudioConverterFillBuffer:%ld\n", result);
|
||||
afm->mParent->DoNotification(afm->mParent, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
afm->mBufferOffset = 0;
|
||||
}
|
||||
|
||||
if (ioData->mDataByteSize > afm->mBufferSize - afm->mBufferOffset)
|
||||
ioData->mDataByteSize = afm->mBufferSize - afm->mBufferOffset;
|
||||
ioData->mData = (char *)afm->mTmpBuffer + afm->mBufferOffset;
|
||||
ioData->mDataByteSize = afm->mBufferSize - afm->mBufferOffset;
|
||||
ioData->mData = (char *) afm->mTmpBuffer + afm->mBufferOffset;
|
||||
afm->mBufferOffset += ioData->mDataByteSize;
|
||||
|
||||
afm->mByteCounter += ioData->mDataByteSize;
|
||||
afm->AfterRender(afm);
|
||||
|
||||
afm->mByteCounter += ioData->mDataByteSize;
|
||||
afm->AfterRender(afm);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void delete_AudioFileManager (AudioFileManager *afm)
|
||||
void
|
||||
delete_AudioFileManager(AudioFileManager * afm)
|
||||
{
|
||||
if (afm != NULL) {
|
||||
if (afm->mFileBuffer) {
|
||||
|
@ -557,26 +611,25 @@ void delete_AudioFileManager (AudioFileManager *afm)
|
|||
}
|
||||
|
||||
|
||||
AudioFileManager *new_AudioFileManager(AudioFilePlayer *inParent,
|
||||
SInt16 inForkRefNum,
|
||||
SInt64 inFileLength,
|
||||
UInt32 inChunkSize)
|
||||
AudioFileManager *
|
||||
new_AudioFileManager(AudioFilePlayer * inParent,
|
||||
SInt16 inForkRefNum,
|
||||
SInt64 inFileLength, UInt32 inChunkSize)
|
||||
{
|
||||
AudioFileManager *afm;
|
||||
|
||||
if (sReaderThread == NULL)
|
||||
{
|
||||
if (sReaderThread == NULL) {
|
||||
sReaderThread = new_FileReaderThread();
|
||||
if (sReaderThread == NULL)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
afm = (AudioFileManager *) SDL_malloc(sizeof (AudioFileManager));
|
||||
afm = (AudioFileManager *) SDL_malloc(sizeof(AudioFileManager));
|
||||
if (afm == NULL)
|
||||
return NULL;
|
||||
SDL_memset(afm, '\0', sizeof (*afm));
|
||||
SDL_memset(afm, '\0', sizeof(*afm));
|
||||
|
||||
#define SET_AUDIOFILEMANAGER_METHOD(m) afm->m = AudioFileManager_##m
|
||||
#define SET_AUDIOFILEMANAGER_METHOD(m) afm->m = AudioFileManager_##m
|
||||
SET_AUDIOFILEMANAGER_METHOD(Disconnect);
|
||||
SET_AUDIOFILEMANAGER_METHOD(DoConnect);
|
||||
SET_AUDIOFILEMANAGER_METHOD(Read);
|
||||
|
@ -589,7 +642,7 @@ AudioFileManager *new_AudioFileManager(AudioFilePlayer *inParent,
|
|||
SET_AUDIOFILEMANAGER_METHOD(GetFileData);
|
||||
SET_AUDIOFILEMANAGER_METHOD(AfterRender);
|
||||
SET_AUDIOFILEMANAGER_METHOD(FileInputProc);
|
||||
#undef SET_AUDIOFILEMANAGER_METHOD
|
||||
#undef SET_AUDIOFILEMANAGER_METHOD
|
||||
|
||||
afm->mParent = inParent;
|
||||
afm->mForkRefNum = inForkRefNum;
|
||||
|
@ -597,9 +650,10 @@ AudioFileManager *new_AudioFileManager(AudioFilePlayer *inParent,
|
|||
afm->mBufferOffset = inChunkSize;
|
||||
afm->mChunkSize = inChunkSize;
|
||||
afm->mFileLength = inFileLength;
|
||||
afm->mFileBuffer = (char*) SDL_malloc(afm->mChunkSize * 2);
|
||||
afm->mFileBuffer = (char *) SDL_malloc(afm->mChunkSize * 2);
|
||||
FSGetForkPosition(afm->mForkRefNum, &afm->mAudioDataOffset);
|
||||
assert (afm->mFileBuffer != NULL);
|
||||
assert(afm->mFileBuffer != NULL);
|
||||
return afm;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue