mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-27 18:54:02 +02:00
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.
This commit is contained in:
+149
-64
@@ -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
|
|||||||
{
|
{
|
||||||
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
|
|||||||
{
|
{
|
||||||
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*
|
|||||||
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
|
|||||||
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
|
|||||||
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
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
|||||||
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
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
|||||||
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
|
|||||||
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
|
|||||||
/* 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
|
|||||||
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
|
|||||||
|
|
||||||
/* 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
|
|||||||
|
|
||||||
/* 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
|
|||||||
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
|
|||||||
/* 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
|
|||||||
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
|
|||||||
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
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
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
|
|||||||
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
|
|||||||
/* 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
|
|||||||
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
|
|||||||
|
|
||||||
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
|
|||||||
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
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
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
|
|||||||
|
|
||||||
/* 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:
|
|||||||
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:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 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
|
|||||||
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
|
|||||||
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:
|
|||||||
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
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 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*
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 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. */
|
||||||
|
|||||||
Reference in New Issue
Block a user