Commit 1c493d6f authored by David Reid's avatar David Reid

More post-refactoring cleanup.

parent 6c74b309
...@@ -12024,29 +12024,32 @@ static ma_bool32 ma_device_descriptor_is_valid(const ma_device_descriptor* pDevi ...@@ -12024,29 +12024,32 @@ static ma_bool32 ma_device_descriptor_is_valid(const ma_device_descriptor* pDevi
} }
/* TODO: Remove the pCallbacks parameter when we move all backends to the new callbacks system, at which time we can just reference the context directly. */ static ma_result ma_device_audio_thread__default_read_write(ma_device* pDevice)
static ma_result ma_device_audio_thread__default_read_write(ma_device* pDevice, ma_backend_callbacks* pCallbacks)
{ {
ma_result result = MA_SUCCESS; ma_result result = MA_SUCCESS;
ma_bool32 exitLoop = MA_FALSE; ma_bool32 exitLoop = MA_FALSE;
ma_uint8 capturedDeviceData[MA_DATA_CONVERTER_STACK_BUFFER_SIZE]; ma_uint8 capturedDeviceData[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
ma_uint8 playbackDeviceData[MA_DATA_CONVERTER_STACK_BUFFER_SIZE]; ma_uint8 playbackDeviceData[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
ma_uint32 capturedDeviceDataCapInFrames = sizeof(capturedDeviceData) / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels); ma_uint32 capturedDeviceDataCapInFrames = 0;
ma_uint32 playbackDeviceDataCapInFrames = sizeof(playbackDeviceData) / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels); ma_uint32 playbackDeviceDataCapInFrames = 0;
MA_ASSERT(pDevice != NULL); MA_ASSERT(pDevice != NULL);
/* Just some quick validation on the device type and the available callbacks. */ /* Just some quick validation on the device type and the available callbacks. */
if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex || pDevice->type == ma_device_type_loopback) { if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex || pDevice->type == ma_device_type_loopback) {
if (pCallbacks->onDeviceRead == NULL) { if (pDevice->pContext->callbacks.onDeviceRead == NULL) {
return MA_NOT_IMPLEMENTED; return MA_NOT_IMPLEMENTED;
} }
capturedDeviceDataCapInFrames = sizeof(capturedDeviceData) / ma_get_bytes_per_frame(pDevice->capture.internalFormat, pDevice->capture.internalChannels);
} }
if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) { if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
if (pCallbacks->onDeviceWrite == NULL) { if (pDevice->pContext->callbacks.onDeviceWrite == NULL) {
return MA_NOT_IMPLEMENTED; return MA_NOT_IMPLEMENTED;
} }
playbackDeviceDataCapInFrames = sizeof(playbackDeviceData) / ma_get_bytes_per_frame(pDevice->playback.internalFormat, pDevice->playback.internalChannels);
} }
/* NOTE: The device was started outside of this function, in the worker thread. */ /* NOTE: The device was started outside of this function, in the worker thread. */
...@@ -12068,7 +12071,7 @@ static ma_result ma_device_audio_thread__default_read_write(ma_device* pDevice, ...@@ -12068,7 +12071,7 @@ static ma_result ma_device_audio_thread__default_read_write(ma_device* pDevice,
capturedDeviceFramesToTryProcessing = capturedDeviceDataCapInFrames; capturedDeviceFramesToTryProcessing = capturedDeviceDataCapInFrames;
} }
result = pCallbacks->onDeviceRead(pDevice, capturedDeviceData, capturedDeviceFramesToTryProcessing, &capturedDeviceFramesToProcess); result = pDevice->pContext->callbacks.onDeviceRead(pDevice, capturedDeviceData, capturedDeviceFramesToTryProcessing, &capturedDeviceFramesToProcess);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
exitLoop = MA_TRUE; exitLoop = MA_TRUE;
break; break;
...@@ -12115,7 +12118,7 @@ static ma_result ma_device_audio_thread__default_read_write(ma_device* pDevice, ...@@ -12115,7 +12118,7 @@ static ma_result ma_device_audio_thread__default_read_write(ma_device* pDevice,
break; break;
} }
result = pCallbacks->onDeviceWrite(pDevice, playbackDeviceData, (ma_uint32)convertedDeviceFrameCount, NULL); /* Safe cast. */ result = pDevice->pContext->callbacks.onDeviceWrite(pDevice, playbackDeviceData, (ma_uint32)convertedDeviceFrameCount, NULL); /* Safe cast. */
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
exitLoop = MA_TRUE; exitLoop = MA_TRUE;
break; break;
...@@ -12151,7 +12154,7 @@ static ma_result ma_device_audio_thread__default_read_write(ma_device* pDevice, ...@@ -12151,7 +12154,7 @@ static ma_result ma_device_audio_thread__default_read_write(ma_device* pDevice,
framesToReadThisIteration = capturedDeviceDataCapInFrames; framesToReadThisIteration = capturedDeviceDataCapInFrames;
} }
result = pCallbacks->onDeviceRead(pDevice, capturedDeviceData, framesToReadThisIteration, &framesProcessed); result = pDevice->pContext->callbacks.onDeviceRead(pDevice, capturedDeviceData, framesToReadThisIteration, &framesProcessed);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
exitLoop = MA_TRUE; exitLoop = MA_TRUE;
break; break;
...@@ -12178,7 +12181,7 @@ static ma_result ma_device_audio_thread__default_read_write(ma_device* pDevice, ...@@ -12178,7 +12181,7 @@ static ma_result ma_device_audio_thread__default_read_write(ma_device* pDevice,
ma_device__read_frames_from_client(pDevice, framesToWriteThisIteration, playbackDeviceData); ma_device__read_frames_from_client(pDevice, framesToWriteThisIteration, playbackDeviceData);
result = pCallbacks->onDeviceWrite(pDevice, playbackDeviceData, framesToWriteThisIteration, &framesProcessed); result = pDevice->pContext->callbacks.onDeviceWrite(pDevice, playbackDeviceData, framesToWriteThisIteration, &framesProcessed);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
exitLoop = MA_TRUE; exitLoop = MA_TRUE;
break; break;
...@@ -15278,9 +15281,9 @@ static ma_result ma_device_audio_thread__wasapi(ma_device* pDevice) ...@@ -15278,9 +15281,9 @@ static ma_result ma_device_audio_thread__wasapi(ma_device* pDevice)
ma_uint32 bpfCaptureClient = ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels); ma_uint32 bpfCaptureClient = ma_get_bytes_per_frame(pDevice->capture.format, pDevice->capture.channels);
ma_uint32 bpfPlaybackClient = ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels); ma_uint32 bpfPlaybackClient = ma_get_bytes_per_frame(pDevice->playback.format, pDevice->playback.channels);
ma_uint8 inputDataInClientFormat[MA_DATA_CONVERTER_STACK_BUFFER_SIZE]; ma_uint8 inputDataInClientFormat[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
ma_uint32 inputDataInClientFormatCap = sizeof(inputDataInClientFormat) / bpfCaptureClient; ma_uint32 inputDataInClientFormatCap = 0;
ma_uint8 outputDataInClientFormat[MA_DATA_CONVERTER_STACK_BUFFER_SIZE]; ma_uint8 outputDataInClientFormat[MA_DATA_CONVERTER_STACK_BUFFER_SIZE];
ma_uint32 outputDataInClientFormatCap = sizeof(outputDataInClientFormat) / bpfPlaybackClient; ma_uint32 outputDataInClientFormatCap = 0;
ma_uint32 outputDataInClientFormatCount = 0; ma_uint32 outputDataInClientFormatCount = 0;
ma_uint32 outputDataInClientFormatConsumed = 0; ma_uint32 outputDataInClientFormatConsumed = 0;
ma_uint32 periodSizeInFramesCapture = 0; ma_uint32 periodSizeInFramesCapture = 0;
...@@ -15296,6 +15299,12 @@ static ma_result ma_device_audio_thread__wasapi(ma_device* pDevice) ...@@ -15296,6 +15299,12 @@ static ma_result ma_device_audio_thread__wasapi(ma_device* pDevice)
return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to start internal capture device.", ma_result_from_HRESULT(hr)); return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[WASAPI] Failed to start internal capture device.", ma_result_from_HRESULT(hr));
} }
c89atomic_exchange_8(&pDevice->wasapi.isStartedCapture, MA_TRUE); c89atomic_exchange_8(&pDevice->wasapi.isStartedCapture, MA_TRUE);
inputDataInClientFormatCap = sizeof(inputDataInClientFormat) / bpfCaptureClient;
}
if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
outputDataInClientFormatCap = sizeof(outputDataInClientFormat) / bpfPlaybackClient;
} }
while (ma_device_get_state(pDevice) == MA_STATE_STARTED && !exitLoop) { while (ma_device_get_state(pDevice) == MA_STATE_STARTED && !exitLoop) {
...@@ -31886,7 +31895,7 @@ static ma_thread_result MA_THREADCALL ma_worker_thread(void* pData) ...@@ -31886,7 +31895,7 @@ static ma_thread_result MA_THREADCALL ma_worker_thread(void* pData)
pDevice->pContext->callbacks.onDeviceAudioThread(pDevice); pDevice->pContext->callbacks.onDeviceAudioThread(pDevice);
} else { } else {
/* The backend is not using a custom main loop implementation, so now fall back to the blocking read-write implementation. */ /* The backend is not using a custom main loop implementation, so now fall back to the blocking read-write implementation. */
ma_device_audio_thread__default_read_write(pDevice, &pDevice->pContext->callbacks); ma_device_audio_thread__default_read_write(pDevice);
} }
/* /*
...@@ -32587,7 +32596,6 @@ MA_API ma_device_config ma_device_config_init(ma_device_type deviceType) ...@@ -32587,7 +32596,6 @@ MA_API ma_device_config ma_device_config_init(ma_device_type deviceType)
MA_API ma_result ma_device_init(ma_context* pContext, const ma_device_config* pConfig, ma_device* pDevice) MA_API ma_result ma_device_init(ma_context* pContext, const ma_device_config* pConfig, ma_device* pDevice)
{ {
ma_result result; ma_result result;
ma_device_config config;
ma_device_descriptor descriptorPlayback; ma_device_descriptor descriptorPlayback;
ma_device_descriptor descriptorCapture; ma_device_descriptor descriptorCapture;
...@@ -32613,28 +32621,25 @@ MA_API ma_result ma_device_init(ma_context* pContext, const ma_device_config* pC ...@@ -32613,28 +32621,25 @@ MA_API ma_result ma_device_init(ma_context* pContext, const ma_device_config* pC
} }
/* We need to make a copy of the config so we can set default values if they were left unset in the input config. */
config = *pConfig;
/* Basic config validation. */ /* Basic config validation. */
if (config.deviceType != ma_device_type_playback && config.deviceType != ma_device_type_capture && config.deviceType != ma_device_type_duplex && config.deviceType != ma_device_type_loopback) { if (pConfig->deviceType != ma_device_type_playback && pConfig->deviceType != ma_device_type_capture && pConfig->deviceType != ma_device_type_duplex && pConfig->deviceType != ma_device_type_loopback) {
return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "ma_device_init() called with an invalid config. Device type is invalid. Make sure the device type has been set in the config.", MA_INVALID_DEVICE_CONFIG); return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "ma_device_init() called with an invalid config. Device type is invalid. Make sure the device type has been set in the config.", MA_INVALID_DEVICE_CONFIG);
} }
if (config.deviceType == ma_device_type_capture || config.deviceType == ma_device_type_duplex) { if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
if (config.capture.channels > MA_MAX_CHANNELS) { if (pConfig->capture.channels > MA_MAX_CHANNELS) {
return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "ma_device_init() called with an invalid config. Capture channel count cannot exceed 32.", MA_INVALID_DEVICE_CONFIG); return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "ma_device_init() called with an invalid config. Capture channel count cannot exceed 32.", MA_INVALID_DEVICE_CONFIG);
} }
if (!ma__is_channel_map_valid(config.capture.channelMap, config.capture.channels)) { if (!ma__is_channel_map_valid(pConfig->capture.channelMap, pConfig->capture.channels)) {
return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "ma_device_init() called with invalid config. Capture channel map is invalid.", MA_INVALID_DEVICE_CONFIG); return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "ma_device_init() called with invalid config. Capture channel map is invalid.", MA_INVALID_DEVICE_CONFIG);
} }
} }
if (config.deviceType == ma_device_type_playback || config.deviceType == ma_device_type_duplex || config.deviceType == ma_device_type_loopback) { if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex || pConfig->deviceType == ma_device_type_loopback) {
if (config.playback.channels > MA_MAX_CHANNELS) { if (pConfig->playback.channels > MA_MAX_CHANNELS) {
return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "ma_device_init() called with an invalid config. Playback channel count cannot exceed 32.", MA_INVALID_DEVICE_CONFIG); return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "ma_device_init() called with an invalid config. Playback channel count cannot exceed 32.", MA_INVALID_DEVICE_CONFIG);
} }
if (!ma__is_channel_map_valid(config.playback.channelMap, config.playback.channels)) { if (!ma__is_channel_map_valid(pConfig->playback.channelMap, pConfig->playback.channels)) {
return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "ma_device_init() called with invalid config. Playback channel map is invalid.", MA_INVALID_DEVICE_CONFIG); return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "ma_device_init() called with invalid config. Playback channel map is invalid.", MA_INVALID_DEVICE_CONFIG);
} }
} }
...@@ -32642,9 +32647,9 @@ MA_API ma_result ma_device_init(ma_context* pContext, const ma_device_config* pC ...@@ -32642,9 +32647,9 @@ MA_API ma_result ma_device_init(ma_context* pContext, const ma_device_config* pC
pDevice->pContext = pContext; pDevice->pContext = pContext;
/* Set the user data and log callback ASAP to ensure it is available for the entire initialization process. */ /* Set the user data and log callback ASAP to ensure it is available for the entire initialization process. */
pDevice->pUserData = config.pUserData; pDevice->pUserData = pConfig->pUserData;
pDevice->onData = config.dataCallback; pDevice->onData = pConfig->dataCallback;
pDevice->onStop = config.stopCallback; pDevice->onStop = pConfig->stopCallback;
if (((ma_uintptr)pDevice % sizeof(pDevice)) != 0) { if (((ma_uintptr)pDevice % sizeof(pDevice)) != 0) {
if (pContext->logCallback) { if (pContext->logCallback) {
...@@ -32652,106 +32657,76 @@ MA_API ma_result ma_device_init(ma_context* pContext, const ma_device_config* pC ...@@ -32652,106 +32657,76 @@ MA_API ma_result ma_device_init(ma_context* pContext, const ma_device_config* pC
} }
} }
if (config.playback.pDeviceID != NULL) { if (pConfig->playback.pDeviceID != NULL) {
MA_COPY_MEMORY(&pDevice->playback.id, config.playback.pDeviceID, sizeof(pDevice->playback.id)); MA_COPY_MEMORY(&pDevice->playback.id, pConfig->playback.pDeviceID, sizeof(pDevice->playback.id));
} }
if (config.capture.pDeviceID != NULL) { if (pConfig->capture.pDeviceID != NULL) {
MA_COPY_MEMORY(&pDevice->capture.id, config.capture.pDeviceID, sizeof(pDevice->capture.id)); MA_COPY_MEMORY(&pDevice->capture.id, pConfig->capture.pDeviceID, sizeof(pDevice->capture.id));
} }
pDevice->noPreZeroedOutputBuffer = config.noPreZeroedOutputBuffer; pDevice->noPreZeroedOutputBuffer = pConfig->noPreZeroedOutputBuffer;
pDevice->noClip = config.noClip; pDevice->noClip = pConfig->noClip;
pDevice->masterVolumeFactor = 1; pDevice->masterVolumeFactor = 1;
/* /*
When passing in 0 for the format/channels/rate/chmap it means the device will be using whatever is chosen by the backend. If everything is set When passing in 0 for the format/channels/rate/chmap it means the device will be using whatever is chosen by the backend. If everything is set
to defaults it means the format conversion pipeline will run on a fast path where data transfer is just passed straight through to the backend. to defaults it means the format conversion pipeline will run on a fast path where data transfer is just passed straight through to the backend.
*/ */
if (config.sampleRate == 0) { if (pConfig->sampleRate == 0) {
config.sampleRate = MA_DEFAULT_SAMPLE_RATE;
pDevice->usingDefaultSampleRate = MA_TRUE; pDevice->usingDefaultSampleRate = MA_TRUE;
} }
if (config.capture.format == ma_format_unknown) { if (pConfig->capture.format == ma_format_unknown) {
config.capture.format = MA_DEFAULT_FORMAT;
pDevice->capture.usingDefaultFormat = MA_TRUE; pDevice->capture.usingDefaultFormat = MA_TRUE;
} }
if (config.capture.channels == 0) { if (pConfig->capture.channels == 0) {
config.capture.channels = MA_DEFAULT_CHANNELS;
pDevice->capture.usingDefaultChannels = MA_TRUE; pDevice->capture.usingDefaultChannels = MA_TRUE;
} }
if (config.capture.channelMap[0] == MA_CHANNEL_NONE) { if (pConfig->capture.channelMap[0] == MA_CHANNEL_NONE) {
pDevice->capture.usingDefaultChannelMap = MA_TRUE; pDevice->capture.usingDefaultChannelMap = MA_TRUE;
} }
if (config.playback.format == ma_format_unknown) { if (pConfig->playback.format == ma_format_unknown) {
config.playback.format = MA_DEFAULT_FORMAT;
pDevice->playback.usingDefaultFormat = MA_TRUE; pDevice->playback.usingDefaultFormat = MA_TRUE;
} }
if (config.playback.channels == 0) { if (pConfig->playback.channels == 0) {
config.playback.channels = MA_DEFAULT_CHANNELS;
pDevice->playback.usingDefaultChannels = MA_TRUE; pDevice->playback.usingDefaultChannels = MA_TRUE;
} }
if (config.playback.channelMap[0] == MA_CHANNEL_NONE) { if (pConfig->playback.channelMap[0] == MA_CHANNEL_NONE) {
pDevice->playback.usingDefaultChannelMap = MA_TRUE; pDevice->playback.usingDefaultChannelMap = MA_TRUE;
} }
/* Default periods. */ /* Default periods. */
if (config.periods == 0) { if (pConfig->periods == 0) {
config.periods = MA_DEFAULT_PERIODS;
pDevice->usingDefaultPeriods = MA_TRUE; pDevice->usingDefaultPeriods = MA_TRUE;
} }
/*
Must have at least 3 periods for full-duplex mode. The idea is that the playback and capture positions hang out in the middle period, with the surrounding
periods acting as a buffer in case the capture and playback devices get's slightly out of sync.
*/
if (config.deviceType == ma_device_type_duplex && config.periods < 3) {
config.periods = 3;
}
/* Default buffer size. */ /* Default buffer size. */
if (config.periodSizeInMilliseconds == 0 && config.periodSizeInFrames == 0) { if (pConfig->periodSizeInMilliseconds == 0 && pConfig->periodSizeInFrames == 0) {
config.periodSizeInMilliseconds = (config.performanceProfile == ma_performance_profile_low_latency) ? MA_DEFAULT_PERIOD_SIZE_IN_MILLISECONDS_LOW_LATENCY : MA_DEFAULT_PERIOD_SIZE_IN_MILLISECONDS_CONSERVATIVE;
pDevice->usingDefaultBufferSize = MA_TRUE; pDevice->usingDefaultBufferSize = MA_TRUE;
} }
MA_ASSERT(config.capture.channels <= MA_MAX_CHANNELS); pDevice->type = pConfig->deviceType;
MA_ASSERT(config.playback.channels <= MA_MAX_CHANNELS); pDevice->sampleRate = pConfig->sampleRate;
pDevice->resampling.algorithm = pConfig->resampling.algorithm;
pDevice->resampling.linear.lpfOrder = pConfig->resampling.linear.lpfOrder;
pDevice->resampling.speex.quality = pConfig->resampling.speex.quality;
pDevice->type = config.deviceType; pDevice->capture.shareMode = pConfig->capture.shareMode;
pDevice->sampleRate = config.sampleRate; pDevice->capture.format = pConfig->capture.format;
pDevice->resampling.algorithm = config.resampling.algorithm; pDevice->capture.channels = pConfig->capture.channels;
pDevice->resampling.linear.lpfOrder = config.resampling.linear.lpfOrder; ma_channel_map_copy(pDevice->capture.channelMap, pConfig->capture.channelMap, pConfig->capture.channels);
pDevice->resampling.speex.quality = config.resampling.speex.quality; pDevice->capture.channelMixMode = pConfig->capture.channelMixMode;
pDevice->capture.shareMode = config.capture.shareMode;
pDevice->capture.format = config.capture.format;
pDevice->capture.channels = config.capture.channels;
ma_channel_map_copy(pDevice->capture.channelMap, config.capture.channelMap, config.capture.channels);
pDevice->capture.channelMixMode = config.capture.channelMixMode;
pDevice->playback.shareMode = config.playback.shareMode; pDevice->playback.shareMode = pConfig->playback.shareMode;
pDevice->playback.format = config.playback.format; pDevice->playback.format = pConfig->playback.format;
pDevice->playback.channels = config.playback.channels; pDevice->playback.channels = pConfig->playback.channels;
ma_channel_map_copy(pDevice->playback.channelMap, config.playback.channelMap, config.playback.channels); ma_channel_map_copy(pDevice->playback.channelMap, pConfig->playback.channelMap, pConfig->playback.channels);
pDevice->playback.channelMixMode = config.playback.channelMixMode; pDevice->playback.channelMixMode = pConfig->playback.channelMixMode;
/* The internal format, channel count and sample rate can be modified by the backend. */
pDevice->capture.internalFormat = pDevice->capture.format;
pDevice->capture.internalChannels = pDevice->capture.channels;
pDevice->capture.internalSampleRate = pDevice->sampleRate;
ma_channel_map_copy(pDevice->capture.internalChannelMap, pDevice->capture.channelMap, pDevice->capture.channels);
pDevice->playback.internalFormat = pDevice->playback.format;
pDevice->playback.internalChannels = pDevice->playback.channels;
pDevice->playback.internalSampleRate = pDevice->sampleRate;
ma_channel_map_copy(pDevice->playback.internalChannelMap, pDevice->playback.channelMap, pDevice->playback.channels);
result = ma_mutex_init(&pDevice->lock); result = ma_mutex_init(&pDevice->lock);
if (result != MA_SUCCESS) { if (result != MA_SUCCESS) {
return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "Failed to create mutex.", result); return ma_context_post_error(pContext, NULL, MA_LOG_LEVEL_ERROR, "Failed to create mutex.", result);
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