初步修复
This commit is contained in:
parent
8fc4357cc6
commit
e4714f3f0e
46705 changed files with 12004901 additions and 0 deletions
674
Common/FMODEngine/FMOD_static/src/fmod_async.cpp
Normal file
674
Common/FMODEngine/FMOD_static/src/fmod_async.cpp
Normal file
|
|
@ -0,0 +1,674 @@
|
|||
#include "fmod_settings.h"
|
||||
|
||||
#ifdef FMOD_SUPPORT_NONBLOCKING
|
||||
|
||||
#include "fmod_async.h"
|
||||
#include "fmod_dspi.h"
|
||||
#include "fmod_soundi.h"
|
||||
#include "fmod_systemi.h"
|
||||
|
||||
namespace FMOD
|
||||
{
|
||||
|
||||
LinkedListNode AsyncThread::gAsyncHead;
|
||||
|
||||
|
||||
/*
|
||||
[
|
||||
[DESCRIPTION]
|
||||
|
||||
[PARAMETERS]
|
||||
|
||||
[RETURN_VALUE]
|
||||
|
||||
[REMARKS]
|
||||
|
||||
[SEE_ALSO]
|
||||
]
|
||||
*/
|
||||
void asyncThreadFunc(void *data)
|
||||
{
|
||||
AsyncThread *asyncThread = (AsyncThread *)data;
|
||||
asyncThread->threadFunc();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
[
|
||||
[DESCRIPTION]
|
||||
|
||||
[PARAMETERS]
|
||||
|
||||
[RETURN_VALUE]
|
||||
|
||||
[REMARKS]
|
||||
|
||||
[SEE_ALSO]
|
||||
]
|
||||
*/
|
||||
AsyncThread::AsyncThread()
|
||||
{
|
||||
mCrit = 0;
|
||||
mThreadActive = false;
|
||||
mBusy = false;
|
||||
mDone = false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
[
|
||||
[DESCRIPTION]
|
||||
|
||||
[PARAMETERS]
|
||||
|
||||
[RETURN_VALUE]
|
||||
|
||||
[REMARKS]
|
||||
|
||||
[SEE_ALSO]
|
||||
]
|
||||
*/
|
||||
FMOD_RESULT AsyncThread::shutDown()
|
||||
{
|
||||
if (FMOD::gGlobal->gAsyncCrit)
|
||||
{
|
||||
AsyncThread *asyncthread;
|
||||
LinkedListNode *current, *next;
|
||||
|
||||
FMOD_OS_CriticalSection_Enter(FMOD::gGlobal->gAsyncCrit);
|
||||
{
|
||||
current = gAsyncHead.getNext();
|
||||
while (current != &gAsyncHead)
|
||||
{
|
||||
next = current->getNext();
|
||||
|
||||
asyncthread = SAFE_CAST(AsyncThread, current);
|
||||
asyncthread->reallyRelease();
|
||||
|
||||
current = next;
|
||||
}
|
||||
}
|
||||
FMOD_OS_CriticalSection_Leave(FMOD::gGlobal->gAsyncCrit);
|
||||
}
|
||||
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
[
|
||||
[DESCRIPTION]
|
||||
|
||||
[PARAMETERS]
|
||||
|
||||
[RETURN_VALUE]
|
||||
|
||||
[REMARKS]
|
||||
|
||||
[SEE_ALSO]
|
||||
]
|
||||
*/
|
||||
FMOD_RESULT AsyncThread::addCallback(FMOD_ASYNC_CALLBACK callback, AsyncThread **asyncthread)
|
||||
{
|
||||
FMOD_RESULT result;
|
||||
|
||||
if (asyncthread)
|
||||
{
|
||||
*asyncthread = 0;
|
||||
}
|
||||
|
||||
LinkedListNode *node = (LinkedListNode *)FMOD_Object_Alloc(LinkedListNode);
|
||||
if (!node)
|
||||
{
|
||||
return FMOD_ERR_MEMORY;
|
||||
}
|
||||
|
||||
node->setData((void *)callback);
|
||||
|
||||
/*
|
||||
Make sure there's a thread for us
|
||||
*/
|
||||
result = getAsyncThread(0);
|
||||
if (result != FMOD_OK)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
LinkedListNode *threadnode = gAsyncHead.getNext();
|
||||
if (threadnode != &gAsyncHead)
|
||||
{
|
||||
AsyncThread *thread = SAFE_CAST(AsyncThread, threadnode);
|
||||
FMOD_OS_CriticalSection_Enter(FMOD::gGlobal->gAsyncCrit);
|
||||
{
|
||||
node->addBefore(&thread->mCallbackHead);
|
||||
}
|
||||
FMOD_OS_CriticalSection_Leave(FMOD::gGlobal->gAsyncCrit);
|
||||
|
||||
if (asyncthread)
|
||||
{
|
||||
*asyncthread = thread;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return FMOD_ERR_INTERNAL;
|
||||
}
|
||||
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
[
|
||||
[DESCRIPTION]
|
||||
|
||||
[PARAMETERS]
|
||||
|
||||
[RETURN_VALUE]
|
||||
|
||||
[REMARKS]
|
||||
|
||||
[SEE_ALSO]
|
||||
]
|
||||
*/
|
||||
FMOD_RESULT AsyncThread::removeCallback(FMOD_ASYNC_CALLBACK callback)
|
||||
{
|
||||
LinkedListNode *threadnode = gAsyncHead.getNext();
|
||||
|
||||
if (threadnode != &gAsyncHead)
|
||||
{
|
||||
AsyncThread *asyncthread = SAFE_CAST(AsyncThread, threadnode);
|
||||
|
||||
FMOD_OS_CriticalSection_Enter(FMOD::gGlobal->gAsyncCrit);
|
||||
|
||||
LinkedListNode *callbacknode = asyncthread->mCallbackHead.getNext();
|
||||
for (; callbacknode != &asyncthread->mCallbackHead; callbacknode = callbacknode->getNext())
|
||||
{
|
||||
if (callbacknode->getData() == (void *)callback)
|
||||
{
|
||||
callbacknode->removeNode();
|
||||
FMOD_Memory_Free(callbacknode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
FMOD_OS_CriticalSection_Leave(FMOD::gGlobal->gAsyncCrit);
|
||||
}
|
||||
else
|
||||
{
|
||||
return FMOD_ERR_INTERNAL;
|
||||
}
|
||||
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
[
|
||||
[DESCRIPTION]
|
||||
|
||||
[PARAMETERS]
|
||||
|
||||
[RETURN_VALUE]
|
||||
|
||||
[REMARKS]
|
||||
|
||||
[SEE_ALSO]
|
||||
]
|
||||
*/
|
||||
FMOD_RESULT AsyncThread::init(bool owned, SystemI *system)
|
||||
{
|
||||
FMOD_RESULT result;
|
||||
|
||||
mOwned = owned;
|
||||
|
||||
result = FMOD_OS_CriticalSection_Create(&mCrit);
|
||||
if (result != FMOD_OK)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
result = mThread.initThread("FMOD thread for FMOD_NONBLOCKING", asyncThreadFunc, this, ASYNC_THREADPRIORITY, 0, ASYNC_STACKSIZE, true, 0, system);
|
||||
if (result != FMOD_OK)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
mThreadActive = true;
|
||||
|
||||
FMOD_OS_CriticalSection_Enter(FMOD::gGlobal->gAsyncCrit);
|
||||
addBefore(&gAsyncHead);
|
||||
FMOD_OS_CriticalSection_Leave(FMOD::gGlobal->gAsyncCrit);
|
||||
|
||||
FLOG((FMOD_DEBUG_USER_ANDREW, __FILE__, __LINE__, "AsyncThread::init", "created thread for %p %s\n", this, mOwned ? "(owned)" : ""));
|
||||
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
[
|
||||
[DESCRIPTION]
|
||||
|
||||
[PARAMETERS]
|
||||
|
||||
[RETURN_VALUE]
|
||||
|
||||
[REMARKS]
|
||||
|
||||
[SEE_ALSO]
|
||||
]
|
||||
*/
|
||||
FMOD_RESULT AsyncThread::release()
|
||||
{
|
||||
if (mOwned)
|
||||
{
|
||||
if (mHead.getNext() != &mHead)
|
||||
{
|
||||
FLOG((FMOD_DEBUG_USER_ANDREW, __FILE__, __LINE__, "AsyncThread::release", "%p queue not empty\n", this));
|
||||
}
|
||||
|
||||
mDone = true;
|
||||
}
|
||||
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
[
|
||||
[DESCRIPTION]
|
||||
|
||||
[PARAMETERS]
|
||||
|
||||
[RETURN_VALUE]
|
||||
|
||||
[REMARKS]
|
||||
|
||||
[SEE_ALSO]
|
||||
]
|
||||
*/
|
||||
FMOD_RESULT AsyncThread::reallyRelease()
|
||||
{
|
||||
FMOD_OS_CriticalSection_Enter(mCrit);
|
||||
{
|
||||
if (mHead.getNext() != &mHead)
|
||||
{
|
||||
FLOG((FMOD_DEBUG_USER_ANDREW, __FILE__, __LINE__, "AsyncThread::reallyRelease", "%p queue not empty\n", this));
|
||||
}
|
||||
if (mBusy)
|
||||
{
|
||||
FLOG((FMOD_DEBUG_USER_ANDREW, __FILE__, __LINE__, "AsyncThread::reallyRelease", "%p still busy\n", this));
|
||||
}
|
||||
|
||||
LinkedListNode *next, *current = mCallbackHead.getNext();
|
||||
while (current != &mCallbackHead)
|
||||
{
|
||||
next = current->getNext();
|
||||
current->removeNode();
|
||||
FMOD_Memory_Free(current);
|
||||
current = next;
|
||||
}
|
||||
}
|
||||
FMOD_OS_CriticalSection_Leave(mCrit);
|
||||
|
||||
// FMOD_OS_CriticalSection_Enter(FMOD::gGlobal->gAsyncCrit);
|
||||
removeNode();
|
||||
// FMOD_OS_CriticalSection_Leave(FMOD::gGlobal->gAsyncCrit);
|
||||
|
||||
mThreadActive = false;
|
||||
mThread.closeThread();
|
||||
|
||||
if (mCrit)
|
||||
{
|
||||
FMOD_OS_CriticalSection_Free(mCrit);
|
||||
}
|
||||
|
||||
FLOG((FMOD_DEBUG_USER_ANDREW, __FILE__, __LINE__, "AsyncThread::reallyRelease", "released thread for %p %s\n", this, mOwned ? "(owned)" : ""));
|
||||
|
||||
FMOD_Memory_Free(this);
|
||||
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
[
|
||||
[DESCRIPTION]
|
||||
|
||||
[PARAMETERS]
|
||||
|
||||
[RETURN_VALUE]
|
||||
|
||||
[REMARKS]
|
||||
|
||||
[SEE_ALSO]
|
||||
]
|
||||
*/
|
||||
FMOD_RESULT AsyncThread::wakeupThread()
|
||||
{
|
||||
return mThread.wakeupThread();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
[
|
||||
[DESCRIPTION]
|
||||
|
||||
[PARAMETERS]
|
||||
|
||||
[RETURN_VALUE]
|
||||
|
||||
[REMARKS]
|
||||
|
||||
[SEE_ALSO]
|
||||
]
|
||||
*/
|
||||
FMOD_RESULT AsyncThread::update()
|
||||
{
|
||||
if (FMOD::gGlobal->gAsyncCrit)
|
||||
{
|
||||
AsyncThread *asyncthread;
|
||||
LinkedListNode *current, *next;
|
||||
|
||||
FMOD_OS_CriticalSection_Enter(FMOD::gGlobal->gAsyncCrit);
|
||||
{
|
||||
current = gAsyncHead.getNext();
|
||||
while (current != &gAsyncHead)
|
||||
{
|
||||
next = current->getNext();
|
||||
|
||||
asyncthread = SAFE_CAST(AsyncThread, current);
|
||||
if (asyncthread->mDone)
|
||||
{
|
||||
asyncthread->reallyRelease();
|
||||
}
|
||||
|
||||
current = next;
|
||||
}
|
||||
}
|
||||
FMOD_OS_CriticalSection_Leave(FMOD::gGlobal->gAsyncCrit);
|
||||
}
|
||||
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
[
|
||||
[DESCRIPTION]
|
||||
|
||||
[PARAMETERS]
|
||||
|
||||
[RETURN_VALUE]
|
||||
|
||||
[REMARKS]
|
||||
|
||||
[SEE_ALSO]
|
||||
]
|
||||
*/
|
||||
FMOD_RESULT AsyncThread::threadFunc()
|
||||
{
|
||||
FMOD_RESULT result = FMOD_OK;
|
||||
SoundI *sound = 0;
|
||||
SystemI *system;
|
||||
LinkedListNode *current;
|
||||
|
||||
if (mThreadActive)
|
||||
{
|
||||
FMOD_OS_CriticalSection_Enter(mCrit);
|
||||
{
|
||||
current = mHead.getNext();
|
||||
if (current != &mHead)
|
||||
{
|
||||
sound = (SoundI *)current->getData();
|
||||
current->removeNode();
|
||||
mBusy = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
current = 0;
|
||||
}
|
||||
}
|
||||
FMOD_OS_CriticalSection_Leave(mCrit);
|
||||
|
||||
if (sound)
|
||||
{
|
||||
FLOG((FMOD_DEBUG_LEVEL_LOG, __FILE__, __LINE__, "AsyncThread::threadFunc", "Starting Asynchronous operation on sound %p\n", sound));
|
||||
FLOG_INDENT(4);
|
||||
|
||||
system = sound->mSystem;
|
||||
|
||||
if (sound->mOpenState == FMOD_OPENSTATE_LOADING)
|
||||
{
|
||||
if (sound->mMode & (FMOD_OPENMEMORY | FMOD_OPENMEMORY_POINT))
|
||||
{
|
||||
result = system->createSoundInternal((const char *)sound->mAsyncData->mNameData, sound->mMode, sound->mAsyncData->mBufferSize, sound->mAsyncData->mBufferSizeType, sound->mAsyncData->mExInfoExists ? &sound->mAsyncData->mExInfo : 0, true, &sound);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = system->createSoundInternal(sound->mAsyncData->mName, sound->mMode, sound->mAsyncData->mBufferSize, sound->mAsyncData->mBufferSizeType, sound->mAsyncData->mExInfoExists ? &sound->mAsyncData->mExInfo : 0, true, &sound);
|
||||
}
|
||||
}
|
||||
#ifdef FMOD_SUPPORT_STREAMING
|
||||
#ifdef FMOD_SUPPORT_NONBLOCKSETPOS
|
||||
else if (sound->mOpenState == FMOD_OPENSTATE_SETPOSITION)
|
||||
{
|
||||
Stream *stream = SAFE_CAST(Stream, sound);
|
||||
|
||||
/*
|
||||
Block here and wait for stream thread to stop doing stuff.
|
||||
*/
|
||||
while (!(stream->mFlags & (FMOD_SOUND_FLAG_SETPOS_SAFE | FMOD_SOUND_FLAG_THREADFINISHED)))
|
||||
{
|
||||
FMOD_OS_Time_Sleep(10);
|
||||
}
|
||||
|
||||
if (!(stream->mFlags & FMOD_SOUND_FLAG_THREADFINISHED))
|
||||
{
|
||||
result = stream->mChannel->setPositionEx(sound->mAsyncData->mPosition, sound->mAsyncData->mPositionType, true);
|
||||
if (result == FMOD_OK)
|
||||
{
|
||||
stream->mChannel->mFlags &= ~CHANNELREAL_FLAG_PAUSEDFORSETPOS;
|
||||
|
||||
FMOD_OS_CriticalSection_Enter(sound->mSystem->mStreamRealchanCrit);
|
||||
if (stream->mChannel->mRealChannel[0])
|
||||
{
|
||||
stream->mChannel->setPaused(stream->mChannel->mFlags & CHANNELREAL_FLAG_PAUSED ? true : false);
|
||||
}
|
||||
FMOD_OS_CriticalSection_Leave(sound->mSystem->mStreamRealchanCrit);
|
||||
}
|
||||
else if (result == FMOD_ERR_INVALID_HANDLE)
|
||||
{
|
||||
result = FMOD_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else if (sound->mOpenState == FMOD_OPENSTATE_SEEKING)
|
||||
{
|
||||
Stream *stream = SAFE_CAST(Stream, sound);
|
||||
|
||||
if (stream->mSubSoundList)
|
||||
{
|
||||
result = FMOD_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = stream->updateSubSound(stream->mSubSoundIndex, false);
|
||||
}
|
||||
|
||||
if (result == FMOD_OK)
|
||||
{
|
||||
result = stream->setPosition(0, FMOD_TIMEUNIT_PCM);
|
||||
FLOG((FMOD_DEBUG_LEVEL_LOG, __FILE__, __LINE__, "AsyncThread::threadFunc", "done setposition\n"));
|
||||
if (result == FMOD_OK)
|
||||
{
|
||||
result = stream->flush();
|
||||
if (result == FMOD_OK)
|
||||
{
|
||||
FLOG((FMOD_DEBUG_LEVEL_LOG, __FILE__, __LINE__, "AsyncThread::threadFunc", "done flush\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
FLOG((FMOD_DEBUG_LEVEL_LOG, __FILE__, __LINE__, "AsyncThread::threadFunc", "stream->flush returned %d\n", result));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FLOG((FMOD_DEBUG_LEVEL_LOG, __FILE__, __LINE__, "AsyncThread::threadFunc", "stream->setPosition returned %d\n", result));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
FLOG((FMOD_DEBUG_LEVEL_LOG, __FILE__, __LINE__, "AsyncThread::threadFunc", "AsyncThread::threadFunc: unexpected mOpenState (%d). Result = %d\n", sound->mOpenState, result));
|
||||
}
|
||||
|
||||
sound->mAsyncData->mResult = result;
|
||||
sound->mFlags |= FMOD_SOUND_FLAG_DONOTRELEASE; /* Dissalow release... */
|
||||
sound->mOpenState = (result == FMOD_OK) ? FMOD_OPENSTATE_READY : FMOD_OPENSTATE_ERROR; /* .. but allow everything else. */
|
||||
if (sound->mSubSoundParent)
|
||||
{
|
||||
sound->mSubSoundParent->mOpenState = sound->mOpenState;
|
||||
}
|
||||
if (sound->mSubSoundShared)
|
||||
{
|
||||
sound->mSubSoundShared->mOpenState = sound->mOpenState;
|
||||
}
|
||||
mBusy = false;
|
||||
|
||||
if (sound->mAsyncData->mExInfoExists)
|
||||
{
|
||||
if (sound->mAsyncData->mExInfo.nonblockcallback)
|
||||
{
|
||||
sound->mUserData = sound->mAsyncData->mExInfo.userdata;
|
||||
|
||||
sound->mAsyncData->mExInfo.nonblockcallback((FMOD_SOUND *)sound, result);
|
||||
}
|
||||
}
|
||||
|
||||
sound->mFlags &= ~FMOD_SOUND_FLAG_DONOTRELEASE;
|
||||
|
||||
/*
|
||||
Release this thread if it's owned
|
||||
*/
|
||||
release();
|
||||
|
||||
FLOG_INDENT(-4);
|
||||
FLOG((FMOD_DEBUG_LEVEL_LOG, __FILE__, __LINE__, "AsyncThread::threadFunc", "Finished Asynchronous operation on sound %p\n", sound));
|
||||
}
|
||||
|
||||
/*
|
||||
Call any callbacks that have been added
|
||||
*/
|
||||
LinkedListNode *node;
|
||||
|
||||
FMOD_OS_CriticalSection_Enter(mCrit);
|
||||
{
|
||||
node = mCallbackHead.getNext();
|
||||
}
|
||||
FMOD_OS_CriticalSection_Leave(mCrit);
|
||||
|
||||
while (node != &mCallbackHead)
|
||||
{
|
||||
FMOD_ASYNC_CALLBACK callback = (FMOD_ASYNC_CALLBACK)node->getData();
|
||||
|
||||
result = callback();
|
||||
if (result != FMOD_OK)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
FMOD_OS_CriticalSection_Enter(mCrit);
|
||||
{
|
||||
node = node->getNext();
|
||||
}
|
||||
FMOD_OS_CriticalSection_Leave(mCrit);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
[
|
||||
[DESCRIPTION]
|
||||
|
||||
[PARAMETERS]
|
||||
|
||||
[RETURN_VALUE]
|
||||
|
||||
[REMARKS]
|
||||
|
||||
[SEE_ALSO]
|
||||
]
|
||||
*/
|
||||
FMOD_RESULT AsyncThread::getAsyncThread(SoundI *sound)
|
||||
{
|
||||
FMOD_RESULT result;
|
||||
LinkedListNode *current;
|
||||
bool found, owned;
|
||||
AsyncThread *asyncthread = 0;
|
||||
|
||||
owned = false;
|
||||
found = false;
|
||||
|
||||
FMOD_OS_CriticalSection_Enter(FMOD::gGlobal->gAsyncCrit);
|
||||
{
|
||||
current = gAsyncHead.getNext();
|
||||
if (current != &gAsyncHead)
|
||||
{
|
||||
asyncthread = SAFE_CAST(AsyncThread, current);
|
||||
|
||||
FMOD_OS_CriticalSection_Enter(asyncthread->mCrit);
|
||||
{
|
||||
if (0) //(asyncthread->mHead.getNext() != &asyncthread->mHead) || asyncthread->mBusy || asyncthread->mDone)
|
||||
{
|
||||
owned = true; /* The first asyncthread is or will be busy so make a new one */
|
||||
}
|
||||
else
|
||||
{
|
||||
found = true; /* The first asyncthread isn't doing anything so use it */
|
||||
}
|
||||
}
|
||||
FMOD_OS_CriticalSection_Leave(asyncthread->mCrit);
|
||||
}
|
||||
}
|
||||
FMOD_OS_CriticalSection_Leave(FMOD::gGlobal->gAsyncCrit);
|
||||
|
||||
if (!found)
|
||||
{
|
||||
asyncthread = FMOD_Object_Alloc(AsyncThread);
|
||||
if (!asyncthread)
|
||||
{
|
||||
return FMOD_ERR_MEMORY;
|
||||
}
|
||||
|
||||
result = asyncthread->init(owned, sound ? sound->mSystem : 0);
|
||||
if (result != FMOD_OK)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (sound)
|
||||
{
|
||||
if (sound->mAsyncData->mThread)
|
||||
{
|
||||
FLOG((FMOD_DEBUG_USER_ANDREW, __FILE__, __LINE__, "AsyncThread::getAsyncThread", "sound->mAsyncData->Thread not null == %p\n", sound->mAsyncData->mThread));
|
||||
}
|
||||
|
||||
sound->mAsyncData->mThread = asyncthread;
|
||||
}
|
||||
|
||||
return FMOD_OK;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue