Commit 0cbd8c2c authored by David Reid's avatar David Reid

Resource Manager: Add support for flexible async notifications.

The ma_async_notification object is used for notifying the application
that an asynchronous operation has completed.

Custom notifications can be implemented by implementing the callback in
ma_async_notification_callbacks. There is currently only a single
callback called onSignal which is fired when the operation completes. A
helper notification which wraps around an ma_event object called
ma_async_notification_event is implemented which you can use as an
example for building your own notifications.
parent f5284505
...@@ -410,6 +410,27 @@ MA_API ma_result ma_slot_allocator_alloc(ma_slot_allocator* pAllocator, ma_uint6 ...@@ -410,6 +410,27 @@ MA_API ma_result ma_slot_allocator_alloc(ma_slot_allocator* pAllocator, ma_uint6
MA_API ma_result ma_slot_allocator_free(ma_slot_allocator* pAllocator, ma_uint64 slot); MA_API ma_result ma_slot_allocator_free(ma_slot_allocator* pAllocator, ma_uint64 slot);
typedef void ma_async_notification;
typedef struct
{
void (* onSignal)(ma_async_notification* pNotification);
} ma_async_notification_callbacks;
MA_API ma_result ma_async_notification_signal(ma_async_notification* pNotification);
typedef struct
{
ma_async_notification_callbacks cb;
ma_event e;
} ma_async_notification_event;
MA_API ma_result ma_async_notification_event_init(ma_async_notification_event* pNotificationEvent);
MA_API ma_result ma_async_notification_event_uninit(ma_async_notification_event* pNotificationEvent);
MA_API ma_result ma_async_notification_event_wait(ma_async_notification_event* pNotificationEvent);
MA_API ma_result ma_async_notification_event_signal(ma_async_notification_event* pNotificationEvent);
typedef struct typedef struct
{ {
union union
...@@ -432,18 +453,18 @@ typedef struct ...@@ -432,18 +453,18 @@ typedef struct
{ {
ma_resource_manager_data_buffer* pDataBuffer; ma_resource_manager_data_buffer* pDataBuffer;
char* pFilePath; char* pFilePath;
ma_event* pEvent; ma_async_notification* pNotification; /* Signalled when the data buffer has been fully decoded. */
} loadDataBuffer; } loadDataBuffer;
struct struct
{ {
ma_resource_manager_data_buffer* pDataBuffer; ma_resource_manager_data_buffer* pDataBuffer;
ma_event* pEvent; ma_async_notification* pNotification;
} freeDataBuffer; } freeDataBuffer;
struct struct
{ {
ma_resource_manager_data_buffer* pDataBuffer; ma_resource_manager_data_buffer* pDataBuffer;
ma_decoder* pDecoder; ma_decoder* pDecoder;
ma_event* pCompletedEvent; /* Signalled when the data buffer has been fully decoded. */ ma_async_notification* pCompletedNotification; /* Signalled when the data buffer has been fully decoded. */
void* pData; void* pData;
size_t dataSizeInBytes; size_t dataSizeInBytes;
ma_uint64 decodedFrameCount; ma_uint64 decodedFrameCount;
...@@ -454,12 +475,12 @@ typedef struct ...@@ -454,12 +475,12 @@ typedef struct
{ {
ma_resource_manager_data_stream* pDataStream; ma_resource_manager_data_stream* pDataStream;
char* pFilePath; /* Allocated when the job is posted, freed by the job thread after loading. */ char* pFilePath; /* Allocated when the job is posted, freed by the job thread after loading. */
ma_event* pEvent; ma_async_notification* pNotification; /* Signalled after the first two pages have been decoded and frames can be read from the stream. */
} loadDataStream; } loadDataStream;
struct struct
{ {
ma_resource_manager_data_stream* pDataStream; ma_resource_manager_data_stream* pDataStream;
ma_event* pEvent; ma_async_notification* pNotification;
} freeDataStream; } freeDataStream;
struct struct
{ {
...@@ -638,7 +659,7 @@ MA_API ma_result ma_resource_manager_register_encoded_data(ma_resource_manager* ...@@ -638,7 +659,7 @@ MA_API ma_result ma_resource_manager_register_encoded_data(ma_resource_manager*
MA_API ma_result ma_resource_manager_unregister_data(ma_resource_manager* pResourceManager, const char* pName); MA_API ma_result ma_resource_manager_unregister_data(ma_resource_manager* pResourceManager, const char* pName);
/* Data Buffers. */ /* Data Buffers. */
MA_API ma_result ma_resource_manager_data_buffer_init(ma_resource_manager* pResourceManager, const char* pFilePath, ma_uint32 flags, ma_event* pEvent, ma_resource_manager_data_buffer* pDataBuffer); MA_API ma_result ma_resource_manager_data_buffer_init(ma_resource_manager* pResourceManager, const char* pFilePath, ma_uint32 flags, ma_async_notification* pNotification, ma_resource_manager_data_buffer* pDataBuffer);
MA_API ma_result ma_resource_manager_data_buffer_uninit(ma_resource_manager_data_buffer* pDataBuffer); MA_API ma_result ma_resource_manager_data_buffer_uninit(ma_resource_manager_data_buffer* pDataBuffer);
MA_API ma_result ma_resource_manager_data_buffer_read_pcm_frames(ma_resource_manager_data_buffer* pDataBuffer, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead); MA_API ma_result ma_resource_manager_data_buffer_read_pcm_frames(ma_resource_manager_data_buffer* pDataBuffer, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead);
MA_API ma_result ma_resource_manager_data_buffer_seek_to_pcm_frame(ma_resource_manager_data_buffer* pDataBuffer, ma_uint64 frameIndex); MA_API ma_result ma_resource_manager_data_buffer_seek_to_pcm_frame(ma_resource_manager_data_buffer* pDataBuffer, ma_uint64 frameIndex);
...@@ -651,7 +672,7 @@ MA_API ma_result ma_resource_manager_data_buffer_get_looping(const ma_resource_m ...@@ -651,7 +672,7 @@ MA_API ma_result ma_resource_manager_data_buffer_get_looping(const ma_resource_m
MA_API ma_result ma_resource_manager_data_buffer_get_available_frames(ma_resource_manager_data_buffer* pDataBuffer, ma_uint64* pAvailableFrames); MA_API ma_result ma_resource_manager_data_buffer_get_available_frames(ma_resource_manager_data_buffer* pDataBuffer, ma_uint64* pAvailableFrames);
/* Data Streams. */ /* Data Streams. */
MA_API ma_result ma_resource_manager_data_stream_init(ma_resource_manager* pResourceManager, const char* pFilePath, ma_uint32 flags, ma_event* pEvent, ma_resource_manager_data_stream* pDataStream); MA_API ma_result ma_resource_manager_data_stream_init(ma_resource_manager* pResourceManager, const char* pFilePath, ma_uint32 flags, ma_async_notification* pNotification, ma_resource_manager_data_stream* pDataStream);
MA_API ma_result ma_resource_manager_data_stream_uninit(ma_resource_manager_data_stream* pDataStream); MA_API ma_result ma_resource_manager_data_stream_uninit(ma_resource_manager_data_stream* pDataStream);
MA_API ma_result ma_resource_manager_data_stream_read_pcm_frames(ma_resource_manager_data_stream* pDataStream, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead); MA_API ma_result ma_resource_manager_data_stream_read_pcm_frames(ma_resource_manager_data_stream* pDataStream, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead);
MA_API ma_result ma_resource_manager_data_stream_seek_to_pcm_frame(ma_resource_manager_data_stream* pDataStream, ma_uint64 frameIndex); MA_API ma_result ma_resource_manager_data_stream_seek_to_pcm_frame(ma_resource_manager_data_stream* pDataStream, ma_uint64 frameIndex);
...@@ -664,7 +685,7 @@ MA_API ma_result ma_resource_manager_data_stream_get_looping(const ma_resource_m ...@@ -664,7 +685,7 @@ MA_API ma_result ma_resource_manager_data_stream_get_looping(const ma_resource_m
MA_API ma_result ma_resource_manager_data_stream_get_available_frames(ma_resource_manager_data_stream* pDataStream, ma_uint64* pAvailableFrames); MA_API ma_result ma_resource_manager_data_stream_get_available_frames(ma_resource_manager_data_stream* pDataStream, ma_uint64* pAvailableFrames);
/* Data Sources. */ /* Data Sources. */
MA_API ma_result ma_resource_manager_data_source_init(ma_resource_manager* pResourceManager, const char* pName, ma_uint32 flags, ma_resource_manager_data_source* pDataSource); MA_API ma_result ma_resource_manager_data_source_init(ma_resource_manager* pResourceManager, const char* pName, ma_uint32 flags, ma_async_notification* pNotification, ma_resource_manager_data_source* pDataSource);
MA_API ma_result ma_resource_manager_data_source_uninit(ma_resource_manager_data_source* pDataSource); MA_API ma_result ma_resource_manager_data_source_uninit(ma_resource_manager_data_source* pDataSource);
MA_API ma_result ma_resource_manager_data_source_read_pcm_frames(ma_resource_manager_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead); MA_API ma_result ma_resource_manager_data_source_read_pcm_frames(ma_resource_manager_data_source* pDataSource, void* pFramesOut, ma_uint64 frameCount, ma_uint64* pFramesRead);
MA_API ma_result ma_resource_manager_data_source_seek_to_pcm_frame(ma_resource_manager_data_source* pDataSource, ma_uint64 frameIndex); MA_API ma_result ma_resource_manager_data_source_seek_to_pcm_frame(ma_resource_manager_data_source* pDataSource, ma_uint64 frameIndex);
...@@ -1060,6 +1081,72 @@ MA_API ma_result ma_slot_allocator_free(ma_slot_allocator* pAllocator, ma_uint64 ...@@ -1060,6 +1081,72 @@ MA_API ma_result ma_slot_allocator_free(ma_slot_allocator* pAllocator, ma_uint64
} }
MA_API ma_result ma_async_notification_signal(ma_async_notification* pNotification)
{
ma_async_notification_callbacks* pNotificationCallbacks = (ma_async_notification*)pNotification;
if (pNotification == NULL) {
return MA_INVALID_ARGS;
}
if (pNotificationCallbacks->onSignal == NULL) {
return MA_NOT_IMPLEMENTED;
}
pNotificationCallbacks->onSignal(pNotification);
return MA_INVALID_ARGS;
}
MA_API ma_result ma_async_notification_event_init(ma_async_notification_event* pNotificationEvent)
{
ma_result result;
if (pNotificationEvent == NULL) {
return MA_INVALID_ARGS;
}
pNotificationEvent->cb.onSignal = ma_async_notification_event_signal;
result = ma_event_init(&pNotificationEvent->e);
if (result != MA_SUCCESS) {
return result;
}
return MA_SUCCESS;
}
MA_API ma_result ma_async_notification_event_uninit(ma_async_notification_event* pNotificationEvent)
{
if (pNotificationEvent == NULL) {
return MA_INVALID_ARGS;
}
ma_event_uninit(&pNotificationEvent->e);
return MA_SUCCESS;
}
MA_API ma_result ma_async_notification_event_wait(ma_async_notification_event* pNotificationEvent)
{
if (pNotificationEvent == NULL) {
return MA_INVALID_ARGS;
}
return ma_event_wait(&pNotificationEvent->e);
}
MA_API ma_result ma_async_notification_event_signal(ma_async_notification_event* pNotificationEvent)
{
if (pNotificationEvent == NULL) {
return MA_INVALID_ARGS;
}
return ma_event_signal(&pNotificationEvent->e);
}
#define MA_JOB_ID_NONE ~((ma_uint64)0) #define MA_JOB_ID_NONE ~((ma_uint64)0)
static MA_INLINE ma_uint32 ma_job_extract_refcount(ma_uint64 toc) static MA_INLINE ma_uint32 ma_job_extract_refcount(ma_uint64 toc)
...@@ -1123,8 +1210,6 @@ MA_API ma_result ma_job_queue_init(ma_uint32 flags, ma_job_queue* pQueue) ...@@ -1123,8 +1210,6 @@ MA_API ma_result ma_job_queue_init(ma_uint32 flags, ma_job_queue* pQueue)
pQueue->jobs[ma_job_extract_slot(pQueue->head)].next = MA_JOB_ID_NONE; pQueue->jobs[ma_job_extract_slot(pQueue->head)].next = MA_JOB_ID_NONE;
pQueue->tail = pQueue->head; pQueue->tail = pQueue->head;
return MA_SUCCESS; return MA_SUCCESS;
} }
...@@ -1967,7 +2052,7 @@ static ma_data_source* ma_resource_manager_data_buffer_get_connector(ma_resource ...@@ -1967,7 +2052,7 @@ static ma_data_source* ma_resource_manager_data_buffer_get_connector(ma_resource
} }
} }
static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager* pResourceManager, const char* pFilePath, ma_uint32 hashedName32, ma_uint32 flags, ma_resource_manager_memory_buffer* pExistingData, ma_event* pEvent, ma_resource_manager_data_buffer* pDataBuffer) static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager* pResourceManager, const char* pFilePath, ma_uint32 hashedName32, ma_uint32 flags, ma_resource_manager_memory_buffer* pExistingData, ma_async_notification* pNotification, ma_resource_manager_data_buffer* pDataBuffer)
{ {
ma_result result; ma_result result;
ma_resource_manager_data_buffer_node* pInsertPoint; ma_resource_manager_data_buffer_node* pInsertPoint;
...@@ -2016,8 +2101,8 @@ static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager ...@@ -2016,8 +2101,8 @@ static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager
return result; /* Should never happen. Failed to increment the reference count. */ return result; /* Should never happen. Failed to increment the reference count. */
} }
if (pEvent != NULL) { if (pNotification != NULL) {
ma_event_signal(pEvent); ma_async_notification_signal(pNotification);
} }
} else { } else {
/* Slow path. The data for this buffer has not yet been initialized. The first thing to do is allocate the new data buffer and insert it into the BST. */ /* Slow path. The data for this buffer has not yet been initialized. The first thing to do is allocate the new data buffer and insert it into the BST. */
...@@ -2052,8 +2137,8 @@ static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager ...@@ -2052,8 +2137,8 @@ static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager
pDataBuffer->pNode->result = MA_SUCCESS; pDataBuffer->pNode->result = MA_SUCCESS;
/* Fire the event if we have one. */ /* Fire the event if we have one. */
if (pEvent != NULL) { if (pNotification != NULL) {
ma_event_signal(pEvent); ma_async_notification_signal(pNotification);
} }
} else { } else {
/* /*
...@@ -2070,8 +2155,8 @@ static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager ...@@ -2070,8 +2155,8 @@ static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager
/* We need a copy of the file path. We should probably make this more efficient, but for now we'll do a transient memory allocation. */ /* We need a copy of the file path. We should probably make this more efficient, but for now we'll do a transient memory allocation. */
pFilePathCopy = ma_copy_string(pFilePath, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_TRANSIENT_STRING*/); pFilePathCopy = ma_copy_string(pFilePath, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_TRANSIENT_STRING*/);
if (pFilePathCopy == NULL) { if (pFilePathCopy == NULL) {
if (pEvent != NULL) { if (pNotification != NULL) {
ma_event_signal(pEvent); ma_async_notification_signal(pNotification);
} }
ma_resource_manager_data_buffer_node_remove(pResourceManager, pDataBuffer->pNode); ma_resource_manager_data_buffer_node_remove(pResourceManager, pDataBuffer->pNode);
...@@ -2084,12 +2169,12 @@ static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager ...@@ -2084,12 +2169,12 @@ static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager
job.order = ma_resource_manager_data_buffer_next_execution_order(pDataBuffer); job.order = ma_resource_manager_data_buffer_next_execution_order(pDataBuffer);
job.loadDataBuffer.pDataBuffer = pDataBuffer; job.loadDataBuffer.pDataBuffer = pDataBuffer;
job.loadDataBuffer.pFilePath = pFilePathCopy; job.loadDataBuffer.pFilePath = pFilePathCopy;
job.loadDataBuffer.pEvent = pEvent; job.loadDataBuffer.pNotification = pNotification;
result = ma_resource_manager_post_job(pResourceManager, &job); result = ma_resource_manager_post_job(pResourceManager, &job);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
/* Failed to post the job to the queue. Probably ran out of space. */ /* Failed to post the job to the queue. Probably ran out of space. */
if (pEvent != NULL) { if (pNotification != NULL) {
ma_event_signal(pEvent); ma_async_notification_signal(pNotification);
} }
ma_resource_manager_data_buffer_node_remove(pResourceManager, pDataBuffer->pNode); ma_resource_manager_data_buffer_node_remove(pResourceManager, pDataBuffer->pNode);
...@@ -2222,8 +2307,8 @@ static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager ...@@ -2222,8 +2307,8 @@ static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager
/* If we failed to initialize make sure we fire the event and free memory. */ /* If we failed to initialize make sure we fire the event and free memory. */
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
if (pEvent != NULL) { if (pNotification != NULL) {
ma_event_signal(pEvent); ma_async_notification_signal(pNotification);
} }
ma_resource_manager_data_buffer_node_remove(pResourceManager, pDataBuffer->pNode); ma_resource_manager_data_buffer_node_remove(pResourceManager, pDataBuffer->pNode);
...@@ -2234,8 +2319,8 @@ static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager ...@@ -2234,8 +2319,8 @@ static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager
/* It's not really necessary, but for completeness we'll want to fire the event if we have one in synchronous mode. */ /* It's not really necessary, but for completeness we'll want to fire the event if we have one in synchronous mode. */
if (async == MA_FALSE) { if (async == MA_FALSE) {
if (pEvent != NULL) { if (pNotification != NULL) {
ma_event_signal(pEvent); ma_async_notification_signal(pNotification);
} }
} }
} }
...@@ -2243,7 +2328,7 @@ static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager ...@@ -2243,7 +2328,7 @@ static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager
return MA_SUCCESS; return MA_SUCCESS;
} }
MA_API ma_result ma_resource_manager_data_buffer_init(ma_resource_manager* pResourceManager, const char* pFilePath, ma_uint32 flags, ma_event* pEvent, ma_resource_manager_data_buffer* pDataBuffer) MA_API ma_result ma_resource_manager_data_buffer_init(ma_resource_manager* pResourceManager, const char* pFilePath, ma_uint32 flags, ma_async_notification* pNotification, ma_resource_manager_data_buffer* pDataBuffer)
{ {
ma_result result; ma_result result;
ma_uint32 hashedName32; ma_uint32 hashedName32;
...@@ -2262,7 +2347,7 @@ MA_API ma_result ma_resource_manager_data_buffer_init(ma_resource_manager* pReso ...@@ -2262,7 +2347,7 @@ MA_API ma_result ma_resource_manager_data_buffer_init(ma_resource_manager* pReso
/* At this point we can now enter the critical section. */ /* At this point we can now enter the critical section. */
ma_mutex_lock(&pResourceManager->dataBufferLock); ma_mutex_lock(&pResourceManager->dataBufferLock);
{ {
result = ma_resource_manager_data_buffer_init_nolock(pResourceManager, pFilePath, hashedName32, flags, NULL, pEvent, pDataBuffer); result = ma_resource_manager_data_buffer_init_nolock(pResourceManager, pFilePath, hashedName32, flags, NULL, pNotification, pDataBuffer);
} }
ma_mutex_unlock(&pResourceManager->dataBufferLock); ma_mutex_unlock(&pResourceManager->dataBufferLock);
...@@ -2323,10 +2408,10 @@ static ma_result ma_resource_manager_data_buffer_uninit_nolock(ma_resource_manag ...@@ -2323,10 +2408,10 @@ static ma_result ma_resource_manager_data_buffer_uninit_nolock(ma_resource_manag
be loaded and the uninitialization should happen fairly quickly. Since the caller owns the data buffer, we need to wait for this event be loaded and the uninitialization should happen fairly quickly. Since the caller owns the data buffer, we need to wait for this event
to get processed before returning. to get processed before returning.
*/ */
ma_event waitEvent; ma_async_notification_event waitEvent;
ma_job job; ma_job job;
result = ma_event_init(&waitEvent); result = ma_async_notification_event_init(&waitEvent);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
return result; /* Failed to create the wait event. This should rarely if ever happen. */ return result; /* Failed to create the wait event. This should rarely if ever happen. */
} }
...@@ -2334,16 +2419,16 @@ static ma_result ma_resource_manager_data_buffer_uninit_nolock(ma_resource_manag ...@@ -2334,16 +2419,16 @@ static ma_result ma_resource_manager_data_buffer_uninit_nolock(ma_resource_manag
job = ma_job_init(MA_JOB_FREE_DATA_BUFFER); job = ma_job_init(MA_JOB_FREE_DATA_BUFFER);
job.order = ma_resource_manager_data_buffer_next_execution_order(pDataBuffer); job.order = ma_resource_manager_data_buffer_next_execution_order(pDataBuffer);
job.freeDataBuffer.pDataBuffer = pDataBuffer; job.freeDataBuffer.pDataBuffer = pDataBuffer;
job.freeDataBuffer.pEvent = &waitEvent; job.freeDataBuffer.pNotification = &waitEvent;
result = ma_resource_manager_post_job(pDataBuffer->pResourceManager, &job); result = ma_resource_manager_post_job(pDataBuffer->pResourceManager, &job);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
ma_event_uninit(&waitEvent); ma_async_notification_event_uninit(&waitEvent);
return result; return result;
} }
ma_event_wait(&waitEvent); ma_async_notification_event_wait(&waitEvent);
ma_event_uninit(&waitEvent); ma_async_notification_event_uninit(&waitEvent);
} }
} }
...@@ -2699,15 +2784,15 @@ static ma_uint32 ma_resource_manager_data_stream_next_execution_order(ma_resourc ...@@ -2699,15 +2784,15 @@ static ma_uint32 ma_resource_manager_data_stream_next_execution_order(ma_resourc
MA_API ma_result ma_resource_manager_data_stream_init(ma_resource_manager* pResourceManager, const char* pFilePath, ma_uint32 flags, ma_event* pEvent, ma_resource_manager_data_stream* pDataStream) MA_API ma_result ma_resource_manager_data_stream_init(ma_resource_manager* pResourceManager, const char* pFilePath, ma_uint32 flags, ma_async_notification* pNotification, ma_resource_manager_data_stream* pDataStream)
{ {
ma_result result; ma_result result;
char* pFilePathCopy; char* pFilePathCopy;
ma_job job; ma_job job;
if (pDataStream == NULL) { if (pDataStream == NULL) {
if (pEvent != NULL) { if (pNotification != NULL) {
ma_event_signal(pEvent); ma_async_notification_signal(pNotification);
} }
return MA_INVALID_ARGS; return MA_INVALID_ARGS;
...@@ -2725,8 +2810,8 @@ MA_API ma_result ma_resource_manager_data_stream_init(ma_resource_manager* pReso ...@@ -2725,8 +2810,8 @@ MA_API ma_result ma_resource_manager_data_stream_init(ma_resource_manager* pReso
pDataStream->result = MA_BUSY; pDataStream->result = MA_BUSY;
if (pResourceManager == NULL || pFilePath == NULL) { if (pResourceManager == NULL || pFilePath == NULL) {
if (pEvent != NULL) { if (pNotification != NULL) {
ma_event_signal(pEvent); ma_async_notification_signal(pNotification);
} }
return MA_INVALID_ARGS; return MA_INVALID_ARGS;
...@@ -2737,8 +2822,8 @@ MA_API ma_result ma_resource_manager_data_stream_init(ma_resource_manager* pReso ...@@ -2737,8 +2822,8 @@ MA_API ma_result ma_resource_manager_data_stream_init(ma_resource_manager* pReso
/* We need a copy of the file path. We should probably make this more efficient, but for now we'll do a transient memory allocation. */ /* We need a copy of the file path. We should probably make this more efficient, but for now we'll do a transient memory allocation. */
pFilePathCopy = ma_copy_string(pFilePath, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_TRANSIENT_STRING*/); pFilePathCopy = ma_copy_string(pFilePath, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_TRANSIENT_STRING*/);
if (pFilePathCopy == NULL) { if (pFilePathCopy == NULL) {
if (pEvent != NULL) { if (pNotification != NULL) {
ma_event_signal(pEvent); ma_async_notification_signal(pNotification);
} }
return MA_OUT_OF_MEMORY; return MA_OUT_OF_MEMORY;
...@@ -2749,11 +2834,11 @@ MA_API ma_result ma_resource_manager_data_stream_init(ma_resource_manager* pReso ...@@ -2749,11 +2834,11 @@ MA_API ma_result ma_resource_manager_data_stream_init(ma_resource_manager* pReso
job.order = ma_resource_manager_data_stream_next_execution_order(pDataStream); job.order = ma_resource_manager_data_stream_next_execution_order(pDataStream);
job.loadDataStream.pDataStream = pDataStream; job.loadDataStream.pDataStream = pDataStream;
job.loadDataStream.pFilePath = pFilePathCopy; job.loadDataStream.pFilePath = pFilePathCopy;
job.loadDataStream.pEvent = pEvent; job.loadDataStream.pNotification = pNotification;
result = ma_resource_manager_post_job(pResourceManager, &job); result = ma_resource_manager_post_job(pResourceManager, &job);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
if (pEvent != NULL) { if (pNotification != NULL) {
ma_event_signal(pEvent); ma_async_notification_signal(pNotification);
} }
ma__free_from_callbacks(pFilePathCopy, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_TRANSIENT_STRING*/); ma__free_from_callbacks(pFilePathCopy, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_TRANSIENT_STRING*/);
...@@ -2765,7 +2850,7 @@ MA_API ma_result ma_resource_manager_data_stream_init(ma_resource_manager* pReso ...@@ -2765,7 +2850,7 @@ MA_API ma_result ma_resource_manager_data_stream_init(ma_resource_manager* pReso
MA_API ma_result ma_resource_manager_data_stream_uninit(ma_resource_manager_data_stream* pDataStream) MA_API ma_result ma_resource_manager_data_stream_uninit(ma_resource_manager_data_stream* pDataStream)
{ {
ma_event freeEvent; ma_async_notification_event freeEvent;
ma_job job; ma_job job;
if (pDataStream == NULL) { if (pDataStream == NULL) {
...@@ -2779,17 +2864,17 @@ MA_API ma_result ma_resource_manager_data_stream_uninit(ma_resource_manager_data ...@@ -2779,17 +2864,17 @@ MA_API ma_result ma_resource_manager_data_stream_uninit(ma_resource_manager_data
We need to post a job to ensure we're not in the middle or decoding or anything. Because the object is owned by the caller, we'll need We need to post a job to ensure we're not in the middle or decoding or anything. Because the object is owned by the caller, we'll need
to wait for it to complete before returning which means we need an event. to wait for it to complete before returning which means we need an event.
*/ */
ma_event_init(&freeEvent); ma_async_notification_event_init(&freeEvent);
job = ma_job_init(MA_JOB_FREE_DATA_STREAM); job = ma_job_init(MA_JOB_FREE_DATA_STREAM);
job.order = ma_resource_manager_data_stream_next_execution_order(pDataStream); job.order = ma_resource_manager_data_stream_next_execution_order(pDataStream);
job.freeDataStream.pDataStream = pDataStream; job.freeDataStream.pDataStream = pDataStream;
job.freeDataStream.pEvent = &freeEvent; job.freeDataStream.pNotification = &freeEvent;
ma_resource_manager_post_job(pDataStream->pResourceManager, &job); ma_resource_manager_post_job(pDataStream->pResourceManager, &job);
/* We need to wait for the job to finish processing before we return. */ /* We need to wait for the job to finish processing before we return. */
ma_event_wait(&freeEvent); ma_async_notification_event_wait(&freeEvent);
ma_event_uninit(&freeEvent); ma_async_notification_event_uninit(&freeEvent);
return MA_SUCCESS; return MA_SUCCESS;
} }
...@@ -3158,7 +3243,7 @@ MA_API ma_result ma_resource_manager_data_stream_get_available_frames(ma_resourc ...@@ -3158,7 +3243,7 @@ MA_API ma_result ma_resource_manager_data_stream_get_available_frames(ma_resourc
MA_API ma_result ma_resource_manager_data_source_init(ma_resource_manager* pResourceManager, const char* pName, ma_uint32 flags, ma_resource_manager_data_source* pDataSource) MA_API ma_result ma_resource_manager_data_source_init(ma_resource_manager* pResourceManager, const char* pName, ma_uint32 flags, ma_async_notification* pNotification, ma_resource_manager_data_source* pDataSource)
{ {
if (pDataSource == NULL) { if (pDataSource == NULL) {
return MA_INVALID_ARGS; return MA_INVALID_ARGS;
...@@ -3174,9 +3259,9 @@ MA_API ma_result ma_resource_manager_data_source_init(ma_resource_manager* pReso ...@@ -3174,9 +3259,9 @@ MA_API ma_result ma_resource_manager_data_source_init(ma_resource_manager* pReso
/* The data source itself is just a data stream or a data buffer. */ /* The data source itself is just a data stream or a data buffer. */
if ((flags & MA_DATA_SOURCE_FLAG_STREAM) != 0) { if ((flags & MA_DATA_SOURCE_FLAG_STREAM) != 0) {
return ma_resource_manager_data_stream_init(pResourceManager, pName, flags, NULL, &pDataSource->stream); return ma_resource_manager_data_stream_init(pResourceManager, pName, flags, pNotification, &pDataSource->stream);
} else { } else {
return ma_resource_manager_data_buffer_init(pResourceManager, pName, flags, NULL, &pDataSource->buffer); return ma_resource_manager_data_buffer_init(pResourceManager, pName, flags, pNotification, &pDataSource->buffer);
} }
} }
...@@ -3512,7 +3597,7 @@ done: ...@@ -3512,7 +3597,7 @@ done:
pageDataBufferJob.order = ma_resource_manager_data_buffer_next_execution_order(pDataBuffer); pageDataBufferJob.order = ma_resource_manager_data_buffer_next_execution_order(pDataBuffer);
pageDataBufferJob.pageDataBuffer.pDataBuffer = pDataBuffer; pageDataBufferJob.pageDataBuffer.pDataBuffer = pDataBuffer;
pageDataBufferJob.pageDataBuffer.pDecoder = pDecoder; pageDataBufferJob.pageDataBuffer.pDecoder = pDecoder;
pageDataBufferJob.pageDataBuffer.pCompletedEvent = pJob->loadDataBuffer.pEvent; pageDataBufferJob.pageDataBuffer.pCompletedNotification = pJob->loadDataBuffer.pNotification;
pageDataBufferJob.pageDataBuffer.pData = pData; pageDataBufferJob.pageDataBuffer.pData = pData;
pageDataBufferJob.pageDataBuffer.dataSizeInBytes = (size_t)dataSizeInBytes; /* Safe cast. Was checked for > MA_SIZE_MAX earlier. */ pageDataBufferJob.pageDataBuffer.dataSizeInBytes = (size_t)dataSizeInBytes; /* Safe cast. Was checked for > MA_SIZE_MAX earlier. */
pageDataBufferJob.pageDataBuffer.decodedFrameCount = framesRead; pageDataBufferJob.pageDataBuffer.decodedFrameCount = framesRead;
...@@ -3555,15 +3640,15 @@ done: ...@@ -3555,15 +3640,15 @@ done:
} }
/* We want to make sure we don't signal the event here. It needs to be delayed until the last page. */ /* We want to make sure we don't signal the event here. It needs to be delayed until the last page. */
pJob->loadDataBuffer.pEvent = NULL; pJob->loadDataBuffer.pNotification = NULL;
/* Make sure the buffer's status is updated appropriately, but make sure we never move away from a MA_BUSY state to ensure we don't overwrite any error codes. */ /* Make sure the buffer's status is updated appropriately, but make sure we never move away from a MA_BUSY state to ensure we don't overwrite any error codes. */
c89atomic_compare_and_swap_32(&pDataBuffer->pNode->result, MA_BUSY, result); c89atomic_compare_and_swap_32(&pDataBuffer->pNode->result, MA_BUSY, result);
} }
/* Only signal the other threads after the result has been set just for cleanliness sake. */ /* Only signal the other threads after the result has been set just for cleanliness sake. */
if (pJob->loadDataBuffer.pEvent != NULL) { if (pJob->loadDataBuffer.pNotification != NULL) {
ma_event_signal(pJob->loadDataBuffer.pEvent); ma_async_notification_signal(pJob->loadDataBuffer.pNotification);
} }
c89atomic_fetch_add_32(&pDataBuffer->pNode->executionPointer, 1); c89atomic_fetch_add_32(&pDataBuffer->pNode->executionPointer, 1);
...@@ -3585,8 +3670,8 @@ static ma_result ma_resource_manager_process_job__free_data_buffer(ma_resource_m ...@@ -3585,8 +3670,8 @@ static ma_result ma_resource_manager_process_job__free_data_buffer(ma_resource_m
ma_resource_manager_data_buffer_uninit_internal(pJob->freeDataBuffer.pDataBuffer); ma_resource_manager_data_buffer_uninit_internal(pJob->freeDataBuffer.pDataBuffer);
/* The event needs to be signalled last. */ /* The event needs to be signalled last. */
if (pJob->freeDataBuffer.pEvent != NULL) { if (pJob->freeDataBuffer.pNotification != NULL) {
ma_event_signal(pJob->freeDataBuffer.pEvent); ma_async_notification_event_signal(pJob->freeDataBuffer.pNotification);
} }
/*c89atomic_fetch_add_32(&pJob->freeDataBuffer.pDataBuffer->pNode->executionPointer, 1);*/ /*c89atomic_fetch_add_32(&pJob->freeDataBuffer.pDataBuffer->pNode->executionPointer, 1);*/
...@@ -3712,8 +3797,8 @@ static ma_result ma_resource_manager_process_job__page_data_buffer(ma_resource_m ...@@ -3712,8 +3797,8 @@ static ma_result ma_resource_manager_process_job__page_data_buffer(ma_resource_m
c89atomic_compare_and_swap_32(&pDataBuffer->pNode->result, MA_BUSY, result); c89atomic_compare_and_swap_32(&pDataBuffer->pNode->result, MA_BUSY, result);
/* We need to signal an event to indicate that we're done. */ /* We need to signal an event to indicate that we're done. */
if (jobCopy.pageDataBuffer.pCompletedEvent != NULL) { if (jobCopy.pageDataBuffer.pCompletedNotification != NULL) {
ma_event_signal(jobCopy.pageDataBuffer.pCompletedEvent); ma_async_notification_signal(jobCopy.pageDataBuffer.pCompletedNotification);
} }
} }
...@@ -3777,8 +3862,8 @@ done: ...@@ -3777,8 +3862,8 @@ done:
c89atomic_compare_and_swap_32(&pDataStream->result, MA_BUSY, result); c89atomic_compare_and_swap_32(&pDataStream->result, MA_BUSY, result);
/* Only signal the other threads after the result has been set just for cleanliness sake. */ /* Only signal the other threads after the result has been set just for cleanliness sake. */
if (pJob->loadDataStream.pEvent != NULL) { if (pJob->loadDataStream.pNotification != NULL) {
ma_event_signal(pJob->loadDataStream.pEvent); ma_async_notification_signal(pJob->loadDataStream.pNotification);
} }
c89atomic_fetch_add_32(&pDataStream->executionPointer, 1); c89atomic_fetch_add_32(&pDataStream->executionPointer, 1);
...@@ -3812,8 +3897,8 @@ static ma_result ma_resource_manager_process_job__free_data_stream(ma_resource_m ...@@ -3812,8 +3897,8 @@ static ma_result ma_resource_manager_process_job__free_data_stream(ma_resource_m
} }
/* The event needs to be signalled last. */ /* The event needs to be signalled last. */
if (pJob->freeDataStream.pEvent != NULL) { if (pJob->freeDataStream.pNotification != NULL) {
ma_event_signal(pJob->freeDataStream.pEvent); ma_async_notification_signal(pJob->freeDataStream.pNotification);
} }
/*c89atomic_fetch_add_32(&pDataStream->executionPointer, 1);*/ /*c89atomic_fetch_add_32(&pDataStream->executionPointer, 1);*/
...@@ -5094,7 +5179,7 @@ MA_API ma_result ma_engine_sound_init_from_file(ma_engine* pEngine, const char* ...@@ -5094,7 +5179,7 @@ MA_API ma_result ma_engine_sound_init_from_file(ma_engine* pEngine, const char*
} }
/* We need to user the resource manager to load the data source. */ /* We need to user the resource manager to load the data source. */
result = ma_resource_manager_data_source_init(pEngine->pResourceManager, pFilePath, flags, &pSound->resourceManagerDataSource); result = ma_resource_manager_data_source_init(pEngine->pResourceManager, pFilePath, flags, NULL, &pSound->resourceManagerDataSource);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
return result; return result;
} }
...@@ -5359,7 +5444,7 @@ MA_API ma_result ma_engine_play_sound(ma_engine* pEngine, const char* pFilePath, ...@@ -5359,7 +5444,7 @@ MA_API ma_result ma_engine_play_sound(ma_engine* pEngine, const char* pFilePath,
} }
/* The old data source has been uninitialized so now we need to initialize the new one. */ /* The old data source has been uninitialized so now we need to initialize the new one. */
result = ma_resource_manager_data_source_init(pEngine->pResourceManager, pFilePath, dataSourceFlags, &pSound->resourceManagerDataSource); result = ma_resource_manager_data_source_init(pEngine->pResourceManager, pFilePath, dataSourceFlags, NULL, &pSound->resourceManagerDataSource);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
/* We failed to load the resource. We need to return an error. We must also put this sound back up for recycling by setting the at-end flag to true. */ /* We failed to load the resource. We need to return an error. We must also put this sound back up for recycling by setting the at-end flag to true. */
c89atomic_exchange_32(&pSound->atEnd, MA_TRUE); /* <-- Put the sound back up for recycling. */ c89atomic_exchange_32(&pSound->atEnd, MA_TRUE); /* <-- Put the sound back up for recycling. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment