From 3eb0f400e65bd5ea940b7d6c3def4ce934703580 Mon Sep 17 00:00:00 2001 From: David Reid Date: Sun, 17 Jan 2021 21:11:21 +1000 Subject: [PATCH] Add support for wide strings (wchar_t) to the resource manager. --- miniaudio.h | 17 ++- research/miniaudio_engine.h | 208 +++++++++++++++++++++++++++++------- 2 files changed, 183 insertions(+), 42 deletions(-) diff --git a/miniaudio.h b/miniaudio.h index 9a717c0b..48135db2 100644 --- a/miniaudio.h +++ b/miniaudio.h @@ -43995,7 +43995,7 @@ MA_API ma_result ma_vfs_info(ma_vfs* pVFS, ma_vfs_file file, ma_file_info* pInfo } -static ma_result ma_vfs_open_and_read_file_ex(ma_vfs* pVFS, const char* pFilePath, void** ppData, size_t* pSize, const ma_allocation_callbacks* pAllocationCallbacks, ma_uint32 allocationType) +static ma_result ma_vfs_open_and_read_file_ex(ma_vfs* pVFS, const char* pFilePath, const wchar_t* pFilePathW, void** ppData, size_t* pSize, const ma_allocation_callbacks* pAllocationCallbacks, ma_uint32 allocationType) { ma_result result; ma_vfs_file file; @@ -44016,7 +44016,11 @@ static ma_result ma_vfs_open_and_read_file_ex(ma_vfs* pVFS, const char* pFilePat return MA_INVALID_ARGS; } - result = ma_vfs_open(pVFS, pFilePath, MA_OPEN_MODE_READ, &file); + if (pFilePath != NULL) { + result = ma_vfs_open(pVFS, pFilePath, MA_OPEN_MODE_READ, &file); + } else { + result = ma_vfs_open_w(pVFS, pFilePathW, MA_OPEN_MODE_READ, &file); + } if (result != MA_SUCCESS) { return result; } @@ -44056,9 +44060,14 @@ static ma_result ma_vfs_open_and_read_file_ex(ma_vfs* pVFS, const char* pFilePat return MA_SUCCESS; } -ma_result ma_vfs_open_and_read_file(ma_vfs* pVFS, const char* pFilePath, void** ppData, size_t* pSize, const ma_allocation_callbacks* pAllocationCallbacks) +MA_API ma_result ma_vfs_open_and_read_file(ma_vfs* pVFS, const char* pFilePath, void** ppData, size_t* pSize, const ma_allocation_callbacks* pAllocationCallbacks) { - return ma_vfs_open_and_read_file_ex(pVFS, pFilePath, ppData, pSize, pAllocationCallbacks, 0 /*MA_ALLOCATION_TYPE_GENERAL*/); + return ma_vfs_open_and_read_file_ex(pVFS, pFilePath, NULL, ppData, pSize, pAllocationCallbacks, 0 /*MA_ALLOCATION_TYPE_GENERAL*/); +} + +MA_API ma_result ma_vfs_open_and_read_file_w(ma_vfs* pVFS, const wchar_t* pFilePath, void** ppData, size_t* pSize, const ma_allocation_callbacks* pAllocationCallbacks) +{ + return ma_vfs_open_and_read_file_ex(pVFS, NULL, pFilePath, ppData, pSize, pAllocationCallbacks, 0 /*MA_ALLOCATION_TYPE_GENERAL*/); } diff --git a/research/miniaudio_engine.h b/research/miniaudio_engine.h index 86ce476b..73c4d94c 100644 --- a/research/miniaudio_engine.h +++ b/research/miniaudio_engine.h @@ -1120,6 +1120,7 @@ typedef struct { ma_resource_manager_data_buffer* pDataBuffer; char* pFilePath; + wchar_t* pFilePathW; ma_async_notification* pInitNotification; /* Signalled when the data buffer has been initialized and the format/channels/rate can be retrieved. */ ma_async_notification* pCompletedNotification; /* Signalled when the data buffer has been fully decoded. */ } loadDataBuffer; @@ -1143,6 +1144,7 @@ typedef struct { ma_resource_manager_data_stream* pDataStream; char* pFilePath; /* Allocated when the job is posted, freed by the job thread after loading. */ + wchar_t* pFilePathW; /* ^ As above ^. Only used if pFilePath is NULL. */ ma_async_notification* pNotification; /* Signalled after the first two pages have been decoded and frames can be read from the stream. */ } loadDataStream; struct @@ -1337,11 +1339,15 @@ MA_API void ma_resource_manager_uninit(ma_resource_manager* pResourceManager); /* Registration. */ MA_API ma_result ma_resource_manager_register_decoded_data(ma_resource_manager* pResourceManager, const char* pName, const void* pData, ma_uint64 frameCount, ma_format format, ma_uint32 channels, ma_uint32 sampleRate); /* Does not copy. Increments the reference count if already exists and returns MA_SUCCESS. */ +MA_API ma_result ma_resource_manager_register_decoded_data_w(ma_resource_manager* pResourceManager, const wchar_t* pName, const void* pData, ma_uint64 frameCount, ma_format format, ma_uint32 channels, ma_uint32 sampleRate); MA_API ma_result ma_resource_manager_register_encoded_data(ma_resource_manager* pResourceManager, const char* pName, const void* pData, size_t sizeInBytes); /* Does not copy. Increments the reference count if already exists and returns MA_SUCCESS. */ +MA_API ma_result ma_resource_manager_register_encoded_data_w(ma_resource_manager* pResourceManager, const wchar_t* pName, const void* pData, size_t sizeInBytes); 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_w(ma_resource_manager* pResourceManager, const wchar_t* pName); /* Data Buffers. */ 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_init_w(ma_resource_manager* pResourceManager, const wchar_t* 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_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); @@ -1357,6 +1363,7 @@ MA_API ma_result ma_resource_manager_data_buffer_get_available_frames(ma_resourc /* Data Streams. */ 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_init_w(ma_resource_manager* pResourceManager, const wchar_t* 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_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); @@ -1372,6 +1379,7 @@ MA_API ma_result ma_resource_manager_data_stream_get_available_frames(ma_resourc /* Data Sources. */ 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_init_w(ma_resource_manager* pResourceManager, const wchar_t* 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_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); @@ -5006,6 +5014,11 @@ static ma_uint32 ma_hash_string_32(const char* str) return ma_hash_32(str, (int)strlen(str), MA_DEFAULT_HASH_SEED); } +static ma_uint32 ma_hash_string_w_32(const wchar_t* str) +{ + return ma_hash_32(str, (int)wcslen(str) * sizeof(*str), MA_DEFAULT_HASH_SEED); +} + @@ -5614,18 +5627,22 @@ MA_API void ma_resource_manager_uninit(ma_resource_manager* pResourceManager) } -static ma_result ma_resource_manager__init_decoder(ma_resource_manager* pResourceManager, const char* pFilePath, ma_decoder* pDecoder) +static ma_result ma_resource_manager__init_decoder(ma_resource_manager* pResourceManager, const char* pFilePath, const wchar_t* pFilePathW, ma_decoder* pDecoder) { ma_decoder_config config; MA_ASSERT(pResourceManager != NULL); - MA_ASSERT(pFilePath != NULL); + MA_ASSERT(pFilePath != NULL || pFilePathW != NULL); MA_ASSERT(pDecoder != NULL); config = ma_decoder_config_init(pResourceManager->config.decodedFormat, pResourceManager->config.decodedChannels, pResourceManager->config.decodedSampleRate); config.allocationCallbacks = pResourceManager->config.allocationCallbacks; - return ma_decoder_init_vfs(pResourceManager->config.pVFS, pFilePath, &config, pDecoder); + if (pFilePath != NULL) { + return ma_decoder_init_vfs(pResourceManager->config.pVFS, pFilePath, &config, pDecoder); + } else { + return ma_decoder_init_vfs_w(pResourceManager->config.pVFS, pFilePathW, &config, pDecoder); + } } static ma_result ma_resource_manager_data_buffer_init_connector(ma_resource_manager_data_buffer* pDataBuffer, ma_async_notification* pNotification) @@ -5800,16 +5817,17 @@ static ma_result ma_resource_manager_data_buffer_cb__get_length_in_pcm_frames(ma return ma_resource_manager_data_buffer_get_length_in_pcm_frames((ma_resource_manager_data_buffer*)pDataSource, pLength); } -static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager* pResourceManager, const char* pFilePath, ma_uint32 hashedName32, ma_uint32 flags, ma_async_notification* pNotification, ma_resource_manager_data_buffer* pDataBuffer) +static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager* pResourceManager, const char* pFilePath, const wchar_t* pFilePathW, ma_uint32 hashedName32, ma_uint32 flags, ma_async_notification* pNotification, ma_resource_manager_data_buffer* pDataBuffer) { ma_result result; ma_resource_manager_data_buffer_node* pInsertPoint; - char* pFilePathCopy; /* Allocated here, freed in the job thread. */ + char* pFilePathCopy = NULL; /* Allocated here, freed in the job thread. */ + wchar_t* pFilePathWCopy = NULL; ma_resource_manager_data_buffer_encoding dataBufferType; ma_bool32 async; MA_ASSERT(pResourceManager != NULL); - MA_ASSERT(pFilePath != NULL); + MA_ASSERT(pFilePath != NULL || pFilePathW != NULL); MA_ASSERT(pDataBuffer != NULL); MA_ZERO_OBJECT(pDataBuffer); @@ -5910,8 +5928,13 @@ static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager ma_resource_manager_inline_notification initNotification; /* 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*/); - if (pFilePathCopy == NULL) { + if (pFilePath != NULL) { + pFilePathCopy = ma_copy_string(pFilePath, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_TRANSIENT_STRING*/); + } else { + pFilePathWCopy = ma_copy_string_w(pFilePathW, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_TRANSIENT_STRING*/); + } + + if (pFilePathCopy == NULL || pFilePathWCopy == NULL) { if (pNotification != NULL) { ma_async_notification_signal(pNotification, MA_NOTIFICATION_FAILED); } @@ -5931,6 +5954,7 @@ 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.loadDataBuffer.pDataBuffer = pDataBuffer; job.loadDataBuffer.pFilePath = pFilePathCopy; + job.loadDataBuffer.pFilePathW = pFilePathWCopy; job.loadDataBuffer.pInitNotification = (waitInit == MA_TRUE) ? &initNotification : NULL; job.loadDataBuffer.pCompletedNotification = pNotification; result = ma_resource_manager_post_job(pResourceManager, &job); @@ -5947,6 +5971,7 @@ static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager ma_resource_manager_data_buffer_node_remove(pResourceManager, pDataBuffer->pNode); ma__free_from_callbacks(pDataBuffer->pNode, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_RESOURCE_MANAGER_DATA_BUFFER*/); ma__free_from_callbacks(pFilePathCopy, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_TRANSIENT_STRING*/); + ma__free_from_callbacks(pFilePathWCopy, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_TRANSIENT_STRING*/); return result; } @@ -5961,7 +5986,7 @@ static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager /* No decoding. Just store the file contents in memory. */ void* pData; size_t sizeInBytes; - result = ma_vfs_open_and_read_file_ex(pResourceManager->config.pVFS, pFilePath, &pData, &sizeInBytes, &pResourceManager->config.allocationCallbacks, MA_ALLOCATION_TYPE_ENCODED_BUFFER); + result = ma_vfs_open_and_read_file_ex(pResourceManager->config.pVFS, pFilePath, pFilePathW, &pData, &sizeInBytes, &pResourceManager->config.allocationCallbacks, MA_ALLOCATION_TYPE_ENCODED_BUFFER); if (result == MA_SUCCESS) { pDataBuffer->pNode->data.encoded.pData = pData; pDataBuffer->pNode->data.encoded.sizeInBytes = sizeInBytes; @@ -5970,7 +5995,7 @@ static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager /* Decoding. */ ma_decoder decoder; - result = ma_resource_manager__init_decoder(pResourceManager, pFilePath, &decoder); + result = ma_resource_manager__init_decoder(pResourceManager, pFilePath, pFilePathW, &decoder); if (result == MA_SUCCESS) { ma_uint64 totalFrameCount; ma_uint64 dataSizeInBytes; @@ -6100,7 +6125,7 @@ static ma_result ma_resource_manager_data_buffer_init_nolock(ma_resource_manager return MA_SUCCESS; } -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) +static ma_result ma_resource_manager_data_buffer_init_internal(ma_resource_manager* pResourceManager, const char* pFilePath, const wchar_t* pFilePathW, ma_uint32 flags, ma_async_notification* pNotification, ma_resource_manager_data_buffer* pDataBuffer) { ma_result result; ma_uint32 hashedName32; @@ -6109,23 +6134,37 @@ MA_API ma_result ma_resource_manager_data_buffer_init(ma_resource_manager* pReso return MA_INVALID_ARGS; } - if (pResourceManager == NULL || pFilePath == NULL) { + if (pResourceManager == NULL || (pFilePath == NULL && pFilePathW == NULL)) { return MA_INVALID_ARGS; } /* Do as much set up before entering into the critical section to reduce our lock time as much as possible. */ - hashedName32 = ma_hash_string_32(pFilePath); + if (pFilePath != NULL) { + hashedName32 = ma_hash_string_32(pFilePath); + } else { + hashedName32 = ma_hash_string_w_32(pFilePathW); + } /* At this point we can now enter the critical section. */ ma_resource_manager_data_buffer_bst_lock(pResourceManager); { - result = ma_resource_manager_data_buffer_init_nolock(pResourceManager, pFilePath, hashedName32, flags, pNotification, pDataBuffer); + result = ma_resource_manager_data_buffer_init_nolock(pResourceManager, pFilePath, pFilePathW, hashedName32, flags, pNotification, pDataBuffer); } ma_resource_manager_data_buffer_bst_unlock(pResourceManager); return result; } +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) +{ + return ma_resource_manager_data_buffer_init_internal(pResourceManager, pFilePath, NULL, flags, pNotification, pDataBuffer); +} + +MA_API ma_result ma_resource_manager_data_buffer_init_w(ma_resource_manager* pResourceManager, const wchar_t* pFilePath, ma_uint32 flags, ma_async_notification* pNotification, ma_resource_manager_data_buffer* pDataBuffer) +{ + return ma_resource_manager_data_buffer_init_internal(pResourceManager, NULL, pFilePath, flags, pNotification, pDataBuffer); +} + static ma_result ma_resource_manager_data_buffer_uninit_internal(ma_resource_manager_data_buffer* pDataBuffer) { MA_ASSERT(pDataBuffer != NULL); @@ -6519,16 +6558,20 @@ static ma_result ma_resource_manager_register_data_nolock(ma_resource_manager* p return MA_SUCCESS; } -static ma_result ma_resource_manager_register_data(ma_resource_manager* pResourceManager, const char* pName, ma_resource_manager_data_buffer_encoding type, ma_resource_manager_memory_buffer* pExistingData) +static ma_result ma_resource_manager_register_data(ma_resource_manager* pResourceManager, const char* pName, const wchar_t* pNameW, ma_resource_manager_data_buffer_encoding type, ma_resource_manager_memory_buffer* pExistingData) { ma_result result = MA_SUCCESS; ma_uint32 hashedName32; - if (pResourceManager == NULL || pName == NULL) { + if (pResourceManager == NULL || (pName == NULL && pNameW == NULL)) { return MA_INVALID_ARGS; } - hashedName32 = ma_hash_string_32(pName); + if (pName != NULL) { + hashedName32 = ma_hash_string_32(pName); + } else { + hashedName32 = ma_hash_string_w_32(pNameW); + } ma_resource_manager_data_buffer_bst_lock(pResourceManager); { @@ -6539,7 +6582,7 @@ static ma_result ma_resource_manager_register_data(ma_resource_manager* pResourc return result; } -MA_API ma_result ma_resource_manager_register_decoded_data(ma_resource_manager* pResourceManager, const char* pName, const void* pData, ma_uint64 frameCount, ma_format format, ma_uint32 channels, ma_uint32 sampleRate) +static ma_result ma_resource_manager_register_decoded_data_internal(ma_resource_manager* pResourceManager, const char* pName, const wchar_t* pNameW, const void* pData, ma_uint64 frameCount, ma_format format, ma_uint32 channels, ma_uint32 sampleRate) { ma_resource_manager_memory_buffer data; data.type = ma_resource_manager_data_buffer_encoding_decoded; @@ -6549,19 +6592,41 @@ MA_API ma_result ma_resource_manager_register_decoded_data(ma_resource_manager* data.decoded.channels = channels; data.decoded.sampleRate = sampleRate; - return ma_resource_manager_register_data(pResourceManager, pName, data.type, &data); + return ma_resource_manager_register_data(pResourceManager, pName, pNameW, data.type, &data); } -MA_API ma_result ma_resource_manager_register_encoded_data(ma_resource_manager* pResourceManager, const char* pName, const void* pData, size_t sizeInBytes) +MA_API ma_result ma_resource_manager_register_decoded_data(ma_resource_manager* pResourceManager, const char* pName, const void* pData, ma_uint64 frameCount, ma_format format, ma_uint32 channels, ma_uint32 sampleRate) +{ + return ma_resource_manager_register_decoded_data_internal(pResourceManager, pName, NULL, pData, frameCount, format, channels, sampleRate); +} + +MA_API ma_result ma_resource_manager_register_decoded_data_w(ma_resource_manager* pResourceManager, const wchar_t* pName, const void* pData, ma_uint64 frameCount, ma_format format, ma_uint32 channels, ma_uint32 sampleRate) +{ + return ma_resource_manager_register_decoded_data_internal(pResourceManager, NULL, pName, pData, frameCount, format, channels, sampleRate); +} + + +static ma_result ma_resource_manager_register_encoded_data_internal(ma_resource_manager* pResourceManager, const char* pName, const wchar_t* pNameW, const void* pData, size_t sizeInBytes) { ma_resource_manager_memory_buffer data; data.type = ma_resource_manager_data_buffer_encoding_encoded; data.encoded.pData = pData; data.encoded.sizeInBytes = sizeInBytes; - return ma_resource_manager_register_data(pResourceManager, pName, data.type, &data); + return ma_resource_manager_register_data(pResourceManager, pName, pNameW, data.type, &data); } +MA_API ma_result ma_resource_manager_register_encoded_data(ma_resource_manager* pResourceManager, const char* pName, const void* pData, size_t sizeInBytes) +{ + return ma_resource_manager_register_encoded_data_internal(pResourceManager, pName, NULL, pData, sizeInBytes); +} + +MA_API ma_result ma_resource_manager_register_encoded_data_w(ma_resource_manager* pResourceManager, const wchar_t* pName, const void* pData, size_t sizeInBytes) +{ + return ma_resource_manager_register_encoded_data_internal(pResourceManager, NULL, pName, pData, sizeInBytes); +} + + static ma_result ma_resource_manager_unregister_data_nolock(ma_resource_manager* pResourceManager, ma_uint32 hashedName32) { @@ -6593,16 +6658,21 @@ static ma_result ma_resource_manager_unregister_data_nolock(ma_resource_manager* return MA_SUCCESS; } -MA_API ma_result ma_resource_manager_unregister_data(ma_resource_manager* pResourceManager, const char* pName) +static ma_result ma_resource_manager_unregister_data_internal(ma_resource_manager* pResourceManager, const char* pName, const wchar_t* pNameW) { ma_result result; ma_uint32 hashedName32; - if (pResourceManager == NULL || pName == NULL) { + if (pResourceManager == NULL || (pName == NULL && pNameW == NULL)) { return MA_INVALID_ARGS; } - hashedName32 = ma_hash_string_32(pName); + if (pName != NULL) { + hashedName32 = ma_hash_string_32(pName); + } else { + hashedName32 = ma_hash_string_w_32(pNameW); + } + /* It's assumed that the data specified by pName was registered with a prior call to ma_resource_manager_register_encoded/decoded_data(). To unregister it, all @@ -6617,6 +6687,16 @@ MA_API ma_result ma_resource_manager_unregister_data(ma_resource_manager* pResou return result; } +MA_API ma_result ma_resource_manager_unregister_data(ma_resource_manager* pResourceManager, const char* pName) +{ + return ma_resource_manager_unregister_data_internal(pResourceManager, pName, NULL); +} + +MA_API ma_result ma_resource_manager_unregister_data_w(ma_resource_manager* pResourceManager, const wchar_t* pName) +{ + return ma_resource_manager_unregister_data_internal(pResourceManager, NULL, pName); +} + static ma_uint32 ma_resource_manager_data_stream_next_execution_order(ma_resource_manager_data_stream* pDataStream) { @@ -6672,10 +6752,11 @@ static ma_result ma_resource_manager_data_stream_cb__get_length_in_pcm_frames(ma return ma_resource_manager_data_stream_get_length_in_pcm_frames((ma_resource_manager_data_stream*)pDataSource, pLength); } -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) +static ma_result ma_resource_manager_data_stream_init_internal(ma_resource_manager* pResourceManager, const char* pFilePath, const wchar_t* pFilePathW, ma_uint32 flags, ma_async_notification* pNotification, ma_resource_manager_data_stream* pDataStream) { ma_result result; - char* pFilePathCopy; + char* pFilePathCopy = NULL; + wchar_t* pFilePathWCopy = NULL; ma_job job; ma_bool32 waitBeforeReturning = MA_FALSE; ma_resource_manager_inline_notification waitNotification; @@ -6701,7 +6782,7 @@ MA_API ma_result ma_resource_manager_data_stream_init(ma_resource_manager* pReso pDataStream->flags = flags; pDataStream->result = MA_BUSY; - if (pResourceManager == NULL || pFilePath == NULL) { + if (pResourceManager == NULL || (pFilePath == NULL && pFilePathW == NULL)) { if (pNotification != NULL) { ma_async_notification_signal(pNotification, MA_NOTIFICATION_FAILED); } @@ -6712,8 +6793,13 @@ MA_API ma_result ma_resource_manager_data_stream_init(ma_resource_manager* pReso /* We want all access to the VFS and the internal decoder to happen on the job thread just to keep things easier to manage for the VFS. */ /* 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*/); - if (pFilePathCopy == NULL) { + if (pFilePath != NULL) { + pFilePathCopy = ma_copy_string(pFilePath, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_TRANSIENT_STRING*/); + } else { + pFilePathWCopy = ma_copy_string_w(pFilePathW, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_TRANSIENT_STRING*/); + } + + if (pFilePathCopy == NULL && pFilePathWCopy == NULL) { if (pNotification != NULL) { ma_async_notification_signal(pNotification, MA_NOTIFICATION_FAILED); } @@ -6735,6 +6821,7 @@ 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.loadDataStream.pDataStream = pDataStream; job.loadDataStream.pFilePath = pFilePathCopy; + job.loadDataStream.pFilePathW = pFilePathWCopy; job.loadDataStream.pNotification = (waitBeforeReturning == MA_TRUE) ? &waitNotification : pNotification; result = ma_resource_manager_post_job(pResourceManager, &job); if (result != MA_SUCCESS) { @@ -6746,7 +6833,8 @@ MA_API ma_result ma_resource_manager_data_stream_init(ma_resource_manager* pReso ma_resource_manager_inline_notification_uninit(&waitNotification); } - 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*/); + ma__free_from_callbacks(pFilePathWCopy, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_TRANSIENT_STRING*/); return result; } @@ -6763,6 +6851,16 @@ MA_API ma_result ma_resource_manager_data_stream_init(ma_resource_manager* pReso return MA_SUCCESS; } +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) +{ + return ma_resource_manager_data_stream_init_internal(pResourceManager, pFilePath, NULL, flags, pNotification, pDataStream); +} + +MA_API ma_result ma_resource_manager_data_stream_init_w(ma_resource_manager* pResourceManager, const wchar_t* pFilePath, ma_uint32 flags, ma_async_notification* pNotification, ma_resource_manager_data_stream* pDataStream) +{ + return ma_resource_manager_data_stream_init_internal(pResourceManager, NULL, pFilePath, flags, pNotification, pDataStream); +} + MA_API ma_result ma_resource_manager_data_stream_uninit(ma_resource_manager_data_stream* pDataStream) { ma_resource_manager_inline_notification freeEvent; @@ -7254,8 +7352,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_async_notification* pNotification, ma_resource_manager_data_source* pDataSource) +static ma_result ma_resource_manager_data_source_preinit(ma_resource_manager* pResourceManager, ma_uint32 flags, ma_resource_manager_data_source* pDataSource) { if (pDataSource == NULL) { return MA_INVALID_ARGS; @@ -7263,12 +7360,24 @@ MA_API ma_result ma_resource_manager_data_source_init(ma_resource_manager* pReso MA_ZERO_OBJECT(pDataSource); - if (pResourceManager == NULL || pName == NULL) { + if (pResourceManager == NULL) { return MA_INVALID_ARGS; } pDataSource->flags = flags; + return MA_SUCCESS; +} + +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_result result; + + result = ma_resource_manager_data_source_preinit(pResourceManager, flags, pDataSource); + if (result != MA_SUCCESS) { + return result; + } + /* The data source itself is just a data stream or a data buffer. */ if ((flags & MA_DATA_SOURCE_FLAG_STREAM) != 0) { return ma_resource_manager_data_stream_init(pResourceManager, pName, flags, pNotification, &pDataSource->stream); @@ -7277,6 +7386,23 @@ MA_API ma_result ma_resource_manager_data_source_init(ma_resource_manager* pReso } } +MA_API ma_result ma_resource_manager_data_source_init_w(ma_resource_manager* pResourceManager, const wchar_t* pName, ma_uint32 flags, ma_async_notification* pNotification, ma_resource_manager_data_source* pDataSource) +{ + ma_result result; + + result = ma_resource_manager_data_source_preinit(pResourceManager, flags, pDataSource); + if (result != MA_SUCCESS) { + return result; + } + + /* The data source itself is just a data stream or a data buffer. */ + if ((flags & MA_DATA_SOURCE_FLAG_STREAM) != 0) { + return ma_resource_manager_data_stream_init_w(pResourceManager, pName, flags, pNotification, &pDataSource->stream); + } else { + return ma_resource_manager_data_buffer_init_w(pResourceManager, pName, flags, pNotification, &pDataSource->buffer); + } +} + MA_API ma_result ma_resource_manager_data_source_uninit(ma_resource_manager_data_source* pDataSource) { if (pDataSource == NULL) { @@ -7505,7 +7631,7 @@ static ma_result ma_resource_manager_process_job__load_data_buffer(ma_resource_m /* No decoding. Just store the file contents in memory. */ size_t sizeInBytes; - result = ma_vfs_open_and_read_file_ex(pResourceManager->config.pVFS, pJob->loadDataBuffer.pFilePath, &pData, &sizeInBytes, &pResourceManager->config.allocationCallbacks, MA_ALLOCATION_TYPE_ENCODED_BUFFER); + result = ma_vfs_open_and_read_file_ex(pResourceManager->config.pVFS, pJob->loadDataBuffer.pFilePath, pJob->loadDataBuffer.pFilePathW, &pData, &sizeInBytes, &pResourceManager->config.allocationCallbacks, MA_ALLOCATION_TYPE_ENCODED_BUFFER); if (result == MA_SUCCESS) { pDataBuffer->pNode->data.encoded.pData = pData; pDataBuffer->pNode->data.encoded.sizeInBytes = sizeInBytes; @@ -7527,7 +7653,7 @@ static ma_result ma_resource_manager_process_job__load_data_buffer(ma_resource_m goto done; } - result = ma_resource_manager__init_decoder(pResourceManager, pJob->loadDataBuffer.pFilePath, pDecoder); + result = ma_resource_manager__init_decoder(pResourceManager, pJob->loadDataBuffer.pFilePath, pJob->loadDataBuffer.pFilePathW, pDecoder); /* Make sure we never set the result code to MA_BUSY or else we'll get everything confused. */ if (result == MA_BUSY) { @@ -7615,7 +7741,8 @@ static ma_result ma_resource_manager_process_job__load_data_buffer(ma_resource_m } done: - ma__free_from_callbacks(pJob->loadDataBuffer.pFilePath, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_TRANSIENT_STRING*/); + ma__free_from_callbacks(pJob->loadDataBuffer.pFilePath, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_TRANSIENT_STRING*/); + ma__free_from_callbacks(pJob->loadDataBuffer.pFilePathW, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_TRANSIENT_STRING*/); /* We need to set the result to at the very end to ensure no other threads try reading the data before we've fully initialized the object. Other threads @@ -7882,7 +8009,11 @@ static ma_result ma_resource_manager_process_job__load_data_stream(ma_resource_m decoderConfig = ma_decoder_config_init(pResourceManager->config.decodedFormat, pResourceManager->config.decodedChannels, pResourceManager->config.decodedSampleRate); decoderConfig.allocationCallbacks = pResourceManager->config.allocationCallbacks; - result = ma_decoder_init_vfs(pResourceManager->config.pVFS, pJob->loadDataStream.pFilePath, &decoderConfig, &pDataStream->decoder); + if (pJob->loadDataStream.pFilePath != NULL) { + result = ma_decoder_init_vfs(pResourceManager->config.pVFS, pJob->loadDataStream.pFilePath, &decoderConfig, &pDataStream->decoder); + } else { + result = ma_decoder_init_vfs_w(pResourceManager->config.pVFS, pJob->loadDataStream.pFilePathW, &decoderConfig, &pDataStream->decoder); + } if (result != MA_SUCCESS) { goto done; } @@ -7913,7 +8044,8 @@ static ma_result ma_resource_manager_process_job__load_data_stream(ma_resource_m result = MA_SUCCESS; done: - ma__free_from_callbacks(pJob->loadDataStream.pFilePath, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_TRANSIENT_STRING*/); + ma__free_from_callbacks(pJob->loadDataStream.pFilePath, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_TRANSIENT_STRING*/); + ma__free_from_callbacks(pJob->loadDataStream.pFilePathW, &pResourceManager->config.allocationCallbacks/*, MA_ALLOCATION_TYPE_TRANSIENT_STRING*/); /* We can only change the status away from MA_BUSY. If it's set to anything else it means an error has occurred somewhere or the uninitialization process has started (most likely). */ c89atomic_compare_and_swap_32(&pDataStream->result, MA_BUSY, result);