ma_uint32 hashedName32; /* The hashed name. This is the key. */
ma_uint32 refCount;
MA_ATOMIC ma_result result; /* Result from asynchronous loading. When loading set to MA_BUSY. When fully loaded set to MA_SUCCESS. When deleting set to MA_UNAVAILABLE. */
ma_uint32 executionCounter; /* For allocating execution orders for jobs. */
ma_uint32 executionPointer; /* For managing the order of execution for asynchronous jobs relating to this object. Incremented as jobs complete processing. */
MA_ATOMIC ma_uint32 executionCounter; /* For allocating execution orders for jobs. */
MA_ATOMIC ma_uint32 executionPointer; /* For managing the order of execution for asynchronous jobs relating to this object. Incremented as jobs complete processing. */
ma_bool32 isDataOwnedByResourceManager; /* Set to true when the underlying data buffer was allocated the resource manager. Set to false if it is owned by the application (via ma_resource_manager_register_*()). */
ma_resource_manager* pResourceManager; /* A pointer to the resource manager that owns this buffer. */
ma_resource_manager_data_buffer_node* pNode; /* The data node. This is reference counted and is what supplies the data. */
ma_uint32 flags; /* The flags that were passed used to initialize the buffer. */
ma_uint32 executionCounter; /* For allocating execution orders for jobs. */
ma_uint32 executionPointer; /* For managing the order of execution for asynchronous jobs relating to this object. Incremented as jobs complete processing. */
MA_ATOMIC ma_uint32 executionCounter; /* For allocating execution orders for jobs. */
MA_ATOMIC ma_uint32 executionPointer; /* For managing the order of execution for asynchronous jobs relating to this object. Incremented as jobs complete processing. */
ma_uint64 seekTargetInPCMFrames; /* Only updated by the public API. Never written nor read from the job thread. */
ma_bool32 seekToCursorOnNextRead; /* On the next read we need to seek to the frame cursor. */
MA_ATOMIC ma_result result; /* Keeps track of a result of decoding. Set to MA_BUSY while the buffer is still loading. Set to MA_SUCCESS when loading is finished successfully. Otherwise set to some other code. */
ma_uint32 relativeCursor; /* The playback cursor, relative to the current page. Only ever accessed by the public API. Never accessed by the job thread. */
ma_uint64 absoluteCursor; /* The playback cursor, in absolute position starting from the start of the file. */
ma_uint32 currentPageIndex; /* Toggles between 0 and 1. Index 0 is the first half of pPageData. Index 1 is the second half. Only ever accessed by the public API. Never accessed by the job thread. */
ma_uint32 executionCounter; /* For allocating execution orders for jobs. */
ma_uint32 executionPointer; /* For managing the order of execution for asynchronous jobs relating to this object. Incremented as jobs complete processing. */
MA_ATOMIC ma_uint32 executionCounter; /* For allocating execution orders for jobs. */
MA_ATOMIC ma_uint32 executionPointer; /* For managing the order of execution for asynchronous jobs relating to this object. Incremented as jobs complete processing. */
/* Written by the public API, read by the job thread. */
MA_ATOMIC ma_bool32 isLooping; /* Whether or not the stream is looping. It's important to set the looping flag at the data stream level for smooth loop transitions. */
} backend; /* Must be the first item because we need the first item to be the data source callbacks for the buffer or stream. */
ma_uint32 flags; /* The flags that were passed in to ma_resource_manager_data_source_init(). */
ma_uint32 executionCounter; /* For allocating execution orders for jobs. */
ma_uint32 executionPointer; /* For managing the order of execution for asynchronous jobs relating to this object. Incremented as jobs complete processing. */
ma_uint32 flags; /* The flags that were passed in to ma_resource_manager_data_source_init(). */
MA_ATOMIC ma_uint32 executionCounter; /* For allocating execution orders for jobs. */
MA_ATOMIC ma_uint32 executionPointer; /* For managing the order of execution for asynchronous jobs relating to this object. Incremented as jobs complete processing. */
MA_ASSERT(pJob->data.loadDataBufferNode.pDataBufferNode->isDataOwnedByResourceManager == MA_TRUE); /* The data should always be owned by the resource manager. */
/* First thing we need to do is check whether or not the data buffer is getting deleted. If so we just abort. */
if (ma_resource_manager_data_buffer_node_result(pJob->data.loadDataBufferNode.pDataBufferNode) != MA_BUSY) {
result = ma_resource_manager_data_buffer_node_result(pJob->data.loadDataBufferNode.pDataBufferNode); /* The data buffer may be getting deleted before it's even been loaded. */
MA_ASSERT(pDataBufferNode->isDataOwnedByResourceManager == MA_TRUE); /* The data should always be owned by the resource manager. */
/* The data buffer is not getting deleted, but we may be getting executed out of order. If so, we need to push the job back onto the queue and return. */
if (pJob->order != pJob->data.loadDataBufferNode.pDataBufferNode->executionPointer) {
if (pJob->order != c89atomic_load_32(&pDataBufferNode->executionPointer)) {
return ma_resource_manager_post_job(pResourceManager, pJob); /* Attempting to execute out of order. Probably interleaved with a MA_RESOURCE_MANAGER_JOB_FREE_DATA_BUFFER job. */
}
/* First thing we need to do is check whether or not the data buffer is getting deleted. If so we just abort. */
if (ma_resource_manager_data_buffer_node_result(pDataBufferNode) != MA_BUSY) {
result = ma_resource_manager_data_buffer_node_result(pDataBufferNode); /* The data buffer may be getting deleted before it's even been loaded. */
goto done;
}
/*
We're ready to start loading. Essentially what we're doing here is initializing the data supply
of the node. Once this is complete, data buffers can have their connectors initialized which
if (pJob->order != pJob->data.pageDataBufferNode.pDataBufferNode->executionPointer) {
if (pJob->order != c89atomic_load_32(&pDataBufferNode->executionPointer)) {
return ma_resource_manager_post_job(pResourceManager, pJob); /* Out of order. */
}
/* Don't do any more decoding if the data buffer has started the uninitialization process. */
result = ma_resource_manager_data_buffer_node_result(pDataBufferNode);
if (result != MA_BUSY) {
goto done;
}
/* We're ready to decode the next page. */
result = ma_resource_manager_data_buffer_node_decode_next_page(pResourceManager, pJob->data.pageDataBufferNode.pDataBufferNode, pJob->data.pageDataBufferNode.pDecoder);
result = ma_resource_manager_data_buffer_node_decode_next_page(pResourceManager, pDataBufferNode, pJob->data.pageDataBufferNode.pDecoder);
/*
If we have a success code by this point, we want to post another job. We're going to set the
newJob = *pJob; /* Everything is the same as the input job, except the execution order. */
newJob.order = ma_resource_manager_data_buffer_node_next_execution_order(pJob->data.pageDataBufferNode.pDataBufferNode); /* We need a fresh execution order. */
newJob.order = ma_resource_manager_data_buffer_node_next_execution_order(pDataBufferNode); /* We need a fresh execution order. */
result = ma_resource_manager_post_job(pResourceManager, &newJob);
...
...
@@ -65116,7 +65129,7 @@ done:
}
/* Make sure we set the result of node in case some error occurred. */
if (pJob->order != c89atomic_load_32(&pDataBuffer->executionPointer)) {
return ma_resource_manager_post_job(pResourceManager, pJob); /* Attempting to execute out of order. Probably interleaved with a MA_RESOURCE_MANAGER_JOB_FREE_DATA_BUFFER job. */
if (dataSupplyType != ma_resource_manager_data_supply_type_unknown) {
/* We can now initialize the connector. If this fails, we need to abort. It's very rare for this to fail. */
result = ma_resource_manager_data_buffer_init_connector(pJob->data.loadDataBuffer.pDataBuffer, pJob->data.loadDataBuffer.pInitNotification, pJob->data.loadDataBuffer.pInitFence);
result = ma_resource_manager_data_buffer_init_connector(pDataBuffer, pJob->data.loadDataBuffer.pInitNotification, pJob->data.loadDataBuffer.pInitFence);
if (result != MA_SUCCESS) {
ma_log_postf(ma_resource_manager_get_log(pResourceManager), MA_LOG_LEVEL_ERROR, "Failed to initialize connector for data buffer. %s.\n", ma_result_description(result));
if (pJob->order != c89atomic_load_32(&pDataStream->executionPointer)) {
return ma_resource_manager_post_job(pResourceManager, pJob); /* Out of order. */
}
/* For streams the status should be MA_SUCCESS for this to do anything. */
if (ma_resource_manager_data_stream_result(pDataStream) != MA_SUCCESS || pDataStream->isDecoderInitialized == MA_FALSE) {
result = MA_INVALID_OPERATION;
goto done;
}
if (pJob->order != pDataStream->executionPointer) {
return ma_resource_manager_post_job(pResourceManager, pJob); /* Out of order. */
}
/*
With seeking we just assume both pages are invalid and the relative frame cursor at at position 0. This is basically exactly the same as loading, except
instead of initializing the decoder, we seek to a frame.