|
|
|
@@ -8097,7 +8097,7 @@ struct ma_device
|
|
|
|
|
{
|
|
|
|
|
/*AAudioStream**/ ma_ptr pStreamPlayback;
|
|
|
|
|
/*AAudioStream**/ ma_ptr pStreamCapture;
|
|
|
|
|
ma_mutex closeLock;
|
|
|
|
|
ma_mutex rerouteLock;
|
|
|
|
|
ma_aaudio_usage usage;
|
|
|
|
|
ma_aaudio_content_type contentType;
|
|
|
|
|
ma_aaudio_input_preset inputPreset;
|
|
|
|
@@ -8534,6 +8534,10 @@ Retrieves basic information about every active playback and/or capture device.
|
|
|
|
|
This function will allocate memory internally for the device lists and return a pointer to them through the `ppPlaybackDeviceInfos` and `ppCaptureDeviceInfos`
|
|
|
|
|
parameters. If you do not want to incur the overhead of these allocations consider using `ma_context_enumerate_devices()` which will instead use a callback.
|
|
|
|
|
|
|
|
|
|
Note that this only retrieves the ID and name/description of the device. The reason for only retrieving basic information is that it would otherwise require
|
|
|
|
|
opening the backend device in order to probe it for more detailed information which can be inefficient. Consider using `ma_context_get_device_info()` for this,
|
|
|
|
|
but don't call it from within the enumeration callback.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Parameters
|
|
|
|
|
----------
|
|
|
|
@@ -10096,7 +10100,7 @@ typedef struct
|
|
|
|
|
ma_allocation_callbacks allocationCallbacks;
|
|
|
|
|
ma_encoding_format encodingFormat;
|
|
|
|
|
ma_uint32 seekPointCount; /* When set to > 0, specifies the number of seek points to use for the generation of a seek table. Not all decoding backends support this. */
|
|
|
|
|
const ma_decoding_backend_vtable* const* ppBackendVTables;
|
|
|
|
|
ma_decoding_backend_vtable** ppBackendVTables;
|
|
|
|
|
void** ppBackendUserData;
|
|
|
|
|
ma_uint32 backendCount;
|
|
|
|
|
} ma_decoder_config;
|
|
|
|
@@ -10615,7 +10619,7 @@ typedef struct
|
|
|
|
|
ma_uint32 jobQueueCapacity; /* The maximum number of jobs that can fit in the queue at a time. Defaults to MA_JOB_TYPE_RESOURCE_MANAGER_QUEUE_CAPACITY. Cannot be zero. */
|
|
|
|
|
ma_uint32 flags;
|
|
|
|
|
ma_vfs* pVFS; /* Can be NULL in which case defaults will be used. */
|
|
|
|
|
const ma_decoding_backend_vtable* const* ppDecodingBackendVTables;
|
|
|
|
|
ma_decoding_backend_vtable** ppDecodingBackendVTables;
|
|
|
|
|
ma_uint32 decodingBackendCount;
|
|
|
|
|
void** ppDecodingBackendUserData;
|
|
|
|
|
} ma_resource_manager_config;
|
|
|
|
@@ -14018,7 +14022,7 @@ static ma_uint32 ma_ffs_32(ma_uint32 x)
|
|
|
|
|
|
|
|
|
|
/* Just a naive implementation just to get things working for now. Will optimize this later. */
|
|
|
|
|
for (i = 0; i < 32; i += 1) {
|
|
|
|
|
if ((x & (1 << i)) != 0) {
|
|
|
|
|
if ((x & (1U << i)) != 0) {
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -17587,7 +17591,7 @@ static ma_job_proc g_jobVTable[MA_JOB_TYPE_COUNT] =
|
|
|
|
|
|
|
|
|
|
/* Device. */
|
|
|
|
|
#if !defined(MA_NO_DEVICE_IO)
|
|
|
|
|
ma_job_process__device__aaudio_reroute /*MA_JOB_TYPE_DEVICE_AAUDIO_REROUTE*/
|
|
|
|
|
ma_job_process__device__aaudio_reroute /* MA_JOB_TYPE_DEVICE_AAUDIO_REROUTE */
|
|
|
|
|
#endif
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@@ -19334,9 +19338,7 @@ static void ma_device__read_frames_from_client(ma_device* pDevice, ma_uint32 fra
|
|
|
|
|
framesToReadThisIterationIn = requiredInputFrameCount;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (framesToReadThisIterationIn > 0) {
|
|
|
|
|
ma_device__handle_data_callback(pDevice, pIntermediaryBuffer, NULL, (ma_uint32)framesToReadThisIterationIn);
|
|
|
|
|
}
|
|
|
|
|
ma_device__handle_data_callback(pDevice, pIntermediaryBuffer, NULL, (ma_uint32)framesToReadThisIterationIn);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
At this point we have our decoded data in input format and now we need to convert to output format. Note that even if we didn't read any
|
|
|
|
@@ -29067,7 +29069,7 @@ static ma_result ma_context_init__alsa(ma_context* pContext, const ma_context_co
|
|
|
|
|
|
|
|
|
|
return MA_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
#endif /* ALSA */
|
|
|
|
|
#endif /* MA_HAS_ALSA */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -32229,7 +32231,7 @@ static ma_result ma_context_init__jack(ma_context* pContext, const ma_context_co
|
|
|
|
|
|
|
|
|
|
return MA_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
#endif /* JACK */
|
|
|
|
|
#endif /* MA_HAS_JACK */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -35474,7 +35476,7 @@ static ma_result ma_context_init__coreaudio(ma_context* pContext, const ma_conte
|
|
|
|
|
|
|
|
|
|
return MA_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
#endif /* Core Audio */
|
|
|
|
|
#endif /* MA_HAS_COREAUDIO */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -36321,7 +36323,7 @@ static ma_result ma_context_init__sndio(ma_context* pContext, const ma_context_c
|
|
|
|
|
(void)pConfig;
|
|
|
|
|
return MA_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
#endif /* sndio */
|
|
|
|
|
#endif /* MA_HAS_SNDIO */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -37219,7 +37221,7 @@ static ma_result ma_context_init__audio4(ma_context* pContext, const ma_context_
|
|
|
|
|
|
|
|
|
|
return MA_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
#endif /* audio4 */
|
|
|
|
|
#endif /* MA_HAS_AUDIO4 */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
|
|
@@ -37850,7 +37852,7 @@ static ma_result ma_context_init__oss(ma_context* pContext, const ma_context_con
|
|
|
|
|
|
|
|
|
|
return MA_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
#endif /* OSS */
|
|
|
|
|
#endif /* MA_HAS_OSS */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -38422,19 +38424,15 @@ static ma_result ma_close_streams__aaudio(ma_device* pDevice)
|
|
|
|
|
{
|
|
|
|
|
MA_ASSERT(pDevice != NULL);
|
|
|
|
|
|
|
|
|
|
ma_mutex_lock(&pDevice->aaudio.closeLock);
|
|
|
|
|
{
|
|
|
|
|
/* When re-routing, streams may have been closed and never re-opened. Hence the extra checks below. */
|
|
|
|
|
if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
|
|
|
|
|
ma_close_stream__aaudio(pDevice->pContext, (ma_AAudioStream*)pDevice->aaudio.pStreamCapture);
|
|
|
|
|
pDevice->aaudio.pStreamCapture = NULL;
|
|
|
|
|
}
|
|
|
|
|
if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
|
|
|
|
|
ma_close_stream__aaudio(pDevice->pContext, (ma_AAudioStream*)pDevice->aaudio.pStreamPlayback);
|
|
|
|
|
pDevice->aaudio.pStreamPlayback = NULL;
|
|
|
|
|
}
|
|
|
|
|
/* When re-routing, streams may have been closed and never re-opened. Hence the extra checks below. */
|
|
|
|
|
if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
|
|
|
|
|
ma_close_stream__aaudio(pDevice->pContext, (ma_AAudioStream*)pDevice->aaudio.pStreamCapture);
|
|
|
|
|
pDevice->aaudio.pStreamCapture = NULL;
|
|
|
|
|
}
|
|
|
|
|
if (pDevice->type == ma_device_type_playback || pDevice->type == ma_device_type_duplex) {
|
|
|
|
|
ma_close_stream__aaudio(pDevice->pContext, (ma_AAudioStream*)pDevice->aaudio.pStreamPlayback);
|
|
|
|
|
pDevice->aaudio.pStreamPlayback = NULL;
|
|
|
|
|
}
|
|
|
|
|
ma_mutex_unlock(&pDevice->aaudio.closeLock);
|
|
|
|
|
|
|
|
|
|
return MA_SUCCESS;
|
|
|
|
|
}
|
|
|
|
@@ -38443,8 +38441,15 @@ static ma_result ma_device_uninit__aaudio(ma_device* pDevice)
|
|
|
|
|
{
|
|
|
|
|
MA_ASSERT(pDevice != NULL);
|
|
|
|
|
|
|
|
|
|
ma_close_streams__aaudio(pDevice);
|
|
|
|
|
ma_mutex_uninit(&pDevice->aaudio.closeLock);
|
|
|
|
|
/* Wait for any rerouting to finish before attempting to close the streams. */
|
|
|
|
|
ma_mutex_lock(&pDevice->aaudio.rerouteLock);
|
|
|
|
|
{
|
|
|
|
|
ma_close_streams__aaudio(pDevice);
|
|
|
|
|
}
|
|
|
|
|
ma_mutex_unlock(&pDevice->aaudio.rerouteLock);
|
|
|
|
|
|
|
|
|
|
/* Destroy re-routing lock. */
|
|
|
|
|
ma_mutex_uninit(&pDevice->aaudio.rerouteLock);
|
|
|
|
|
|
|
|
|
|
return MA_SUCCESS;
|
|
|
|
|
}
|
|
|
|
@@ -38496,7 +38501,7 @@ static ma_result ma_device_init_by_type__aaudio(ma_device* pDevice, const ma_dev
|
|
|
|
|
return MA_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static ma_result ma_device_init__aaudio(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
|
|
|
|
|
static ma_result ma_device_init_streams__aaudio(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
|
|
|
|
|
{
|
|
|
|
|
ma_result result;
|
|
|
|
|
|
|
|
|
@@ -38526,7 +38531,21 @@ static ma_result ma_device_init__aaudio(ma_device* pDevice, const ma_device_conf
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result = ma_mutex_init(&pDevice->aaudio.closeLock);
|
|
|
|
|
return MA_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static ma_result ma_device_init__aaudio(ma_device* pDevice, const ma_device_config* pConfig, ma_device_descriptor* pDescriptorPlayback, ma_device_descriptor* pDescriptorCapture)
|
|
|
|
|
{
|
|
|
|
|
ma_result result;
|
|
|
|
|
|
|
|
|
|
MA_ASSERT(pDevice != NULL);
|
|
|
|
|
|
|
|
|
|
result = ma_device_init_streams__aaudio(pDevice, pConfig, pDescriptorPlayback, pDescriptorCapture);
|
|
|
|
|
if (result != MA_SUCCESS) {
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result = ma_mutex_init(&pDevice->aaudio.rerouteLock);
|
|
|
|
|
if (result != MA_SUCCESS) {
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
@@ -38670,12 +38689,16 @@ static ma_result ma_device_reinit__aaudio(ma_device* pDevice, ma_device_type dev
|
|
|
|
|
|
|
|
|
|
MA_ASSERT(pDevice != NULL);
|
|
|
|
|
|
|
|
|
|
error_disconnected:
|
|
|
|
|
/* The first thing to do is close the streams. */
|
|
|
|
|
ma_close_streams__aaudio(pDevice);
|
|
|
|
|
|
|
|
|
|
/* Now we need to reinitialize each streams. The hardest part with this is just filling output the config and descriptors. */
|
|
|
|
|
/*
|
|
|
|
|
TODO: Stop retrying if main thread is about to uninit device.
|
|
|
|
|
*/
|
|
|
|
|
ma_mutex_lock(&pDevice->aaudio.rerouteLock);
|
|
|
|
|
{
|
|
|
|
|
error_disconnected:
|
|
|
|
|
/* The first thing to do is close the streams. */
|
|
|
|
|
ma_close_streams__aaudio(pDevice);
|
|
|
|
|
|
|
|
|
|
/* Now we need to reinitialize each streams. The hardest part with this is just filling output the config and descriptors. */
|
|
|
|
|
ma_device_config deviceConfig;
|
|
|
|
|
ma_device_descriptor descriptorPlayback;
|
|
|
|
|
ma_device_descriptor descriptorCapture;
|
|
|
|
@@ -38724,17 +38747,17 @@ error_disconnected:
|
|
|
|
|
descriptorPlayback.periodCount = deviceConfig.periods;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result = ma_device_init__aaudio(pDevice, &deviceConfig, &descriptorPlayback, &descriptorCapture);
|
|
|
|
|
result = ma_device_init_streams__aaudio(pDevice, &deviceConfig, &descriptorPlayback, &descriptorCapture);
|
|
|
|
|
if (result != MA_SUCCESS) {
|
|
|
|
|
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_WARNING, "[AAudio] Failed to create stream after route change.");
|
|
|
|
|
return result;
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result = ma_device_post_init(pDevice, deviceType, &descriptorPlayback, &descriptorCapture);
|
|
|
|
|
if (result != MA_SUCCESS) {
|
|
|
|
|
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_WARNING, "[AAudio] Failed to initialize device after route change.");
|
|
|
|
|
ma_close_streams__aaudio(pDevice);
|
|
|
|
|
return result;
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* We'll only ever do this in response to a reroute. */
|
|
|
|
@@ -38752,15 +38775,20 @@ error_disconnected:
|
|
|
|
|
goto error_disconnected;
|
|
|
|
|
}
|
|
|
|
|
ma_log_post(ma_device_get_log(pDevice), MA_LOG_LEVEL_INFO, "[AAudio] Failed to start stream after route change.");
|
|
|
|
|
return result;
|
|
|
|
|
goto done;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
ma_device_stop(pDevice); /* Do a full device stop so we set internal state correctly. */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return MA_SUCCESS;
|
|
|
|
|
|
|
|
|
|
result = MA_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
done:
|
|
|
|
|
/* Re-routing done */
|
|
|
|
|
ma_mutex_unlock(&pDevice->aaudio.rerouteLock);
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static ma_result ma_device_get_info__aaudio(ma_device* pDevice, ma_device_type type, ma_device_info* pDeviceInfo)
|
|
|
|
@@ -41148,7 +41176,7 @@ static ma_result ma_context_init__webaudio(ma_context* pContext, const ma_contex
|
|
|
|
|
|
|
|
|
|
return MA_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
#endif /* Web Audio */
|
|
|
|
|
#endif /* MA_HAS_WEBAUDIO */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -56893,7 +56921,7 @@ MA_API ma_result ma_rb_commit_read(ma_rb* pRB, size_t sizeInBytes)
|
|
|
|
|
newReadOffsetLoopFlag ^= 0x80000000;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ma_atomic_exchange_32(&pRB->encodedReadOffset, ma_rb__construct_offset(newReadOffsetLoopFlag, newReadOffsetInBytes));
|
|
|
|
|
ma_atomic_exchange_32(&pRB->encodedReadOffset, ma_rb__construct_offset(newReadOffsetInBytes, newReadOffsetLoopFlag));
|
|
|
|
|
|
|
|
|
|
return MA_SUCCESS;
|
|
|
|
|
}
|
|
|
|
@@ -56975,7 +57003,7 @@ MA_API ma_result ma_rb_commit_write(ma_rb* pRB, size_t sizeInBytes)
|
|
|
|
|
newWriteOffsetLoopFlag ^= 0x80000000;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ma_atomic_exchange_32(&pRB->encodedWriteOffset, ma_rb__construct_offset(newWriteOffsetLoopFlag, newWriteOffsetInBytes));
|
|
|
|
|
ma_atomic_exchange_32(&pRB->encodedWriteOffset, ma_rb__construct_offset(newWriteOffsetInBytes, newWriteOffsetLoopFlag));
|
|
|
|
|
|
|
|
|
|
return MA_SUCCESS;
|
|
|
|
|
}
|
|
|
|
@@ -65391,6 +65419,7 @@ MA_API ma_result ma_decoder_read_pcm_frames(ma_decoder* pDecoder, void* pFramesO
|
|
|
|
|
result = ma_data_source_read_pcm_frames(pDecoder->pBackend, pIntermediaryBuffer, framesToReadThisIterationIn, &framesReadThisIterationIn);
|
|
|
|
|
} else {
|
|
|
|
|
framesReadThisIterationIn = 0;
|
|
|
|
|
pIntermediaryBuffer[0] = 0; /* <-- This is just to silence a static analysis warning. */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|