mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-23 16:54:03 +02:00
Fix some data race errors in the PulseAudio backend.
Public issue https://github.com/mackron/miniaudio/issues/235
This commit is contained in:
+68
-11
@@ -21480,9 +21480,7 @@ static ma_result ma_wait_for_operation__pulse(ma_context* pContext, ma_pa_operat
|
|||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
ma_mainloop_lock__pulse(pContext, "ma_wait_for_operation__pulse");
|
ma_mainloop_lock__pulse(pContext, "ma_wait_for_operation__pulse");
|
||||||
{
|
|
||||||
state = ((ma_pa_operation_get_state_proc)pContext->pulse.pa_operation_get_state)(pOP);
|
state = ((ma_pa_operation_get_state_proc)pContext->pulse.pa_operation_get_state)(pOP);
|
||||||
}
|
|
||||||
ma_mainloop_unlock__pulse(pContext, "ma_wait_for_operation__pulse");
|
ma_mainloop_unlock__pulse(pContext, "ma_wait_for_operation__pulse");
|
||||||
|
|
||||||
if (state != MA_PA_OPERATION_RUNNING) {
|
if (state != MA_PA_OPERATION_RUNNING) {
|
||||||
@@ -21515,9 +21513,7 @@ static ma_result ma_context_wait_for_pa_context_to_connect__pulse(ma_context* pC
|
|||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
ma_mainloop_lock__pulse(pContext, "ma_context_wait_for_pa_context_to_connect__pulse");
|
ma_mainloop_lock__pulse(pContext, "ma_context_wait_for_pa_context_to_connect__pulse");
|
||||||
{
|
|
||||||
state = ((ma_pa_context_get_state_proc)pContext->pulse.pa_context_get_state)((ma_pa_context*)pContext->pulse.pPulseContext);
|
state = ((ma_pa_context_get_state_proc)pContext->pulse.pa_context_get_state)((ma_pa_context*)pContext->pulse.pPulseContext);
|
||||||
}
|
|
||||||
ma_mainloop_unlock__pulse(pContext, "ma_context_wait_for_pa_context_to_connect__pulse");
|
ma_mainloop_unlock__pulse(pContext, "ma_context_wait_for_pa_context_to_connect__pulse");
|
||||||
|
|
||||||
if (state == MA_PA_CONTEXT_READY) {
|
if (state == MA_PA_CONTEXT_READY) {
|
||||||
@@ -21541,9 +21537,7 @@ static ma_result ma_context_wait_for_pa_stream_to_connect__pulse(ma_context* pCo
|
|||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
ma_mainloop_lock__pulse(pContext, "ma_context_wait_for_pa_stream_to_connect__pulse");
|
ma_mainloop_lock__pulse(pContext, "ma_context_wait_for_pa_stream_to_connect__pulse");
|
||||||
{
|
|
||||||
state = ((ma_pa_stream_get_state_proc)pContext->pulse.pa_stream_get_state)(pStream);
|
state = ((ma_pa_stream_get_state_proc)pContext->pulse.pa_stream_get_state)(pStream);
|
||||||
}
|
|
||||||
ma_mainloop_unlock__pulse(pContext, "ma_context_wait_for_pa_stream_to_connect__pulse");
|
ma_mainloop_unlock__pulse(pContext, "ma_context_wait_for_pa_stream_to_connect__pulse");
|
||||||
|
|
||||||
if (state == MA_PA_STREAM_READY) {
|
if (state == MA_PA_STREAM_READY) {
|
||||||
@@ -21630,7 +21624,10 @@ static ma_result ma_context_get_sink_info__pulse(ma_context* pContext, const cha
|
|||||||
{
|
{
|
||||||
ma_pa_operation* pOP;
|
ma_pa_operation* pOP;
|
||||||
|
|
||||||
|
ma_mainloop_lock__pulse(pContext, "ma_context_get_sink_info__pulse");
|
||||||
pOP = ((ma_pa_context_get_sink_info_by_name_proc)pContext->pulse.pa_context_get_sink_info_by_name)((ma_pa_context*)pContext->pulse.pPulseContext, pDeviceName, ma_device_sink_info_callback, pSinkInfo);
|
pOP = ((ma_pa_context_get_sink_info_by_name_proc)pContext->pulse.pa_context_get_sink_info_by_name)((ma_pa_context*)pContext->pulse.pPulseContext, pDeviceName, ma_device_sink_info_callback, pSinkInfo);
|
||||||
|
ma_mainloop_unlock__pulse(pContext, "ma_context_get_sink_info__pulse");
|
||||||
|
|
||||||
if (pOP == NULL) {
|
if (pOP == NULL) {
|
||||||
return MA_ERROR;
|
return MA_ERROR;
|
||||||
}
|
}
|
||||||
@@ -21643,7 +21640,10 @@ static ma_result ma_context_get_source_info__pulse(ma_context* pContext, const c
|
|||||||
{
|
{
|
||||||
ma_pa_operation* pOP;
|
ma_pa_operation* pOP;
|
||||||
|
|
||||||
|
ma_mainloop_lock__pulse(pContext, "ma_context_get_source_info__pulse");
|
||||||
pOP = ((ma_pa_context_get_source_info_by_name_proc)pContext->pulse.pa_context_get_source_info_by_name)((ma_pa_context*)pContext->pulse.pPulseContext, pDeviceName, ma_device_source_info_callback, pSourceInfo);
|
pOP = ((ma_pa_context_get_source_info_by_name_proc)pContext->pulse.pa_context_get_source_info_by_name)((ma_pa_context*)pContext->pulse.pPulseContext, pDeviceName, ma_device_source_info_callback, pSourceInfo);
|
||||||
|
ma_mainloop_unlock__pulse(pContext, "ma_context_get_source_info__pulse");
|
||||||
|
|
||||||
if (pOP == NULL) {
|
if (pOP == NULL) {
|
||||||
return MA_ERROR;
|
return MA_ERROR;
|
||||||
}
|
}
|
||||||
@@ -21787,7 +21787,10 @@ static ma_result ma_context_enumerate_devices__pulse(ma_context* pContext, ma_en
|
|||||||
|
|
||||||
/* Playback. */
|
/* Playback. */
|
||||||
if (!callbackData.isTerminated) {
|
if (!callbackData.isTerminated) {
|
||||||
|
ma_mainloop_lock__pulse(pContext, "ma_context_enumerate_devices__pulse");
|
||||||
pOP = ((ma_pa_context_get_sink_info_list_proc)pContext->pulse.pa_context_get_sink_info_list)((ma_pa_context*)(pContext->pulse.pPulseContext), ma_context_enumerate_devices_sink_callback__pulse, &callbackData);
|
pOP = ((ma_pa_context_get_sink_info_list_proc)pContext->pulse.pa_context_get_sink_info_list)((ma_pa_context*)(pContext->pulse.pPulseContext), ma_context_enumerate_devices_sink_callback__pulse, &callbackData);
|
||||||
|
ma_mainloop_unlock__pulse(pContext, "ma_context_enumerate_devices__pulse");
|
||||||
|
|
||||||
if (pOP == NULL) {
|
if (pOP == NULL) {
|
||||||
result = MA_ERROR;
|
result = MA_ERROR;
|
||||||
goto done;
|
goto done;
|
||||||
@@ -21803,7 +21806,10 @@ static ma_result ma_context_enumerate_devices__pulse(ma_context* pContext, ma_en
|
|||||||
|
|
||||||
/* Capture. */
|
/* Capture. */
|
||||||
if (!callbackData.isTerminated) {
|
if (!callbackData.isTerminated) {
|
||||||
|
ma_mainloop_lock__pulse(pContext, "ma_context_enumerate_devices__pulse");
|
||||||
pOP = ((ma_pa_context_get_source_info_list_proc)pContext->pulse.pa_context_get_source_info_list)((ma_pa_context*)(pContext->pulse.pPulseContext), ma_context_enumerate_devices_source_callback__pulse, &callbackData);
|
pOP = ((ma_pa_context_get_source_info_list_proc)pContext->pulse.pa_context_get_source_info_list)((ma_pa_context*)(pContext->pulse.pPulseContext), ma_context_enumerate_devices_source_callback__pulse, &callbackData);
|
||||||
|
ma_mainloop_unlock__pulse(pContext, "ma_context_enumerate_devices__pulse");
|
||||||
|
|
||||||
if (pOP == NULL) {
|
if (pOP == NULL) {
|
||||||
result = MA_ERROR;
|
result = MA_ERROR;
|
||||||
goto done;
|
goto done;
|
||||||
@@ -21912,11 +21918,13 @@ static ma_result ma_context_get_device_info__pulse(ma_context* pContext, ma_devi
|
|||||||
|
|
||||||
result = ma_context_get_default_device_index__pulse(pContext, deviceType, &callbackData.defaultDeviceIndex);
|
result = ma_context_get_default_device_index__pulse(pContext, deviceType, &callbackData.defaultDeviceIndex);
|
||||||
|
|
||||||
|
ma_mainloop_lock__pulse(pContext, "ma_context_get_device_info__pulse");
|
||||||
if (deviceType == ma_device_type_playback) {
|
if (deviceType == ma_device_type_playback) {
|
||||||
pOP = ((ma_pa_context_get_sink_info_by_name_proc)pContext->pulse.pa_context_get_sink_info_by_name)((ma_pa_context*)(pContext->pulse.pPulseContext), pDeviceID->pulse, ma_context_get_device_info_sink_callback__pulse, &callbackData);
|
pOP = ((ma_pa_context_get_sink_info_by_name_proc)pContext->pulse.pa_context_get_sink_info_by_name)((ma_pa_context*)(pContext->pulse.pPulseContext), pDeviceID->pulse, ma_context_get_device_info_sink_callback__pulse, &callbackData);
|
||||||
} else {
|
} else {
|
||||||
pOP = ((ma_pa_context_get_source_info_by_name_proc)pContext->pulse.pa_context_get_source_info_by_name)((ma_pa_context*)(pContext->pulse.pPulseContext), pDeviceID->pulse, ma_context_get_device_info_source_callback__pulse, &callbackData);
|
pOP = ((ma_pa_context_get_source_info_by_name_proc)pContext->pulse.pa_context_get_source_info_by_name)((ma_pa_context*)(pContext->pulse.pPulseContext), pDeviceID->pulse, ma_context_get_device_info_source_callback__pulse, &callbackData);
|
||||||
}
|
}
|
||||||
|
ma_mainloop_unlock__pulse(pContext, "ma_context_get_device_info__pulse");
|
||||||
|
|
||||||
if (pOP != NULL) {
|
if (pOP != NULL) {
|
||||||
ma_wait_for_operation_and_unref__pulse(pContext, pOP);
|
ma_wait_for_operation_and_unref__pulse(pContext, pOP);
|
||||||
@@ -21943,6 +21951,8 @@ static void ma_device_uninit__pulse(ma_device* pDevice)
|
|||||||
pContext = pDevice->pContext;
|
pContext = pDevice->pContext;
|
||||||
MA_ASSERT(pContext != NULL);
|
MA_ASSERT(pContext != NULL);
|
||||||
|
|
||||||
|
ma_mainloop_lock__pulse(pContext, "ma_device_uninit__pulse");
|
||||||
|
{
|
||||||
if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
|
if (pDevice->type == ma_device_type_capture || pDevice->type == ma_device_type_duplex) {
|
||||||
((ma_pa_stream_disconnect_proc)pContext->pulse.pa_stream_disconnect)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
|
((ma_pa_stream_disconnect_proc)pContext->pulse.pa_stream_disconnect)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
|
||||||
((ma_pa_stream_unref_proc)pContext->pulse.pa_stream_unref)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
|
((ma_pa_stream_unref_proc)pContext->pulse.pa_stream_unref)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
|
||||||
@@ -21952,6 +21962,8 @@ static void ma_device_uninit__pulse(ma_device* pDevice)
|
|||||||
((ma_pa_stream_disconnect_proc)pContext->pulse.pa_stream_disconnect)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
|
((ma_pa_stream_disconnect_proc)pContext->pulse.pa_stream_disconnect)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
|
||||||
((ma_pa_stream_unref_proc)pContext->pulse.pa_stream_unref)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
|
((ma_pa_stream_unref_proc)pContext->pulse.pa_stream_unref)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
ma_mainloop_unlock__pulse(pContext, "ma_device_uninit__pulse");
|
||||||
|
|
||||||
if (pDevice->type == ma_device_type_duplex) {
|
if (pDevice->type == ma_device_type_duplex) {
|
||||||
ma_pcm_rb_uninit(&pDevice->pulse.duplexRB);
|
ma_pcm_rb_uninit(&pDevice->pulse.duplexRB);
|
||||||
@@ -21972,6 +21984,7 @@ static ma_pa_buffer_attr ma_device__pa_buffer_attr_new(ma_uint32 periodSizeInFra
|
|||||||
|
|
||||||
static ma_pa_stream* ma_context__pa_stream_new__pulse(ma_context* pContext, const char* pStreamName, const ma_pa_sample_spec* ss, const ma_pa_channel_map* cmap)
|
static ma_pa_stream* ma_context__pa_stream_new__pulse(ma_context* pContext, const char* pStreamName, const ma_pa_sample_spec* ss, const ma_pa_channel_map* cmap)
|
||||||
{
|
{
|
||||||
|
ma_pa_stream* pStream;
|
||||||
static int g_StreamCounter = 0;
|
static int g_StreamCounter = 0;
|
||||||
char actualStreamName[256];
|
char actualStreamName[256];
|
||||||
|
|
||||||
@@ -21983,7 +21996,11 @@ static ma_pa_stream* ma_context__pa_stream_new__pulse(ma_context* pContext, cons
|
|||||||
}
|
}
|
||||||
g_StreamCounter += 1;
|
g_StreamCounter += 1;
|
||||||
|
|
||||||
return ((ma_pa_stream_new_proc)pContext->pulse.pa_stream_new)((ma_pa_context*)pContext->pulse.pPulseContext, actualStreamName, ss, cmap);
|
ma_mainloop_lock__pulse(pContext, "ma_context__pa_stream_new__pulse");
|
||||||
|
pStream = ((ma_pa_stream_new_proc)pContext->pulse.pa_stream_new)((ma_pa_context*)pContext->pulse.pPulseContext, actualStreamName, ss, cmap);
|
||||||
|
ma_mainloop_unlock__pulse(pContext, "ma_context__pa_stream_new__pulse");
|
||||||
|
|
||||||
|
return pStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -22208,7 +22225,9 @@ static ma_result ma_device_init__pulse(ma_context* pContext, const ma_device_con
|
|||||||
|
|
||||||
|
|
||||||
/* The callback needs to be set before connecting the stream. */
|
/* The callback needs to be set before connecting the stream. */
|
||||||
|
ma_mainloop_lock__pulse(pContext, "ma_device_init__pulse");
|
||||||
((ma_pa_stream_set_read_callback_proc)pContext->pulse.pa_stream_set_read_callback)((ma_pa_stream*)pDevice->pulse.pStreamCapture, ma_device_on_read__pulse, pDevice);
|
((ma_pa_stream_set_read_callback_proc)pContext->pulse.pa_stream_set_read_callback)((ma_pa_stream*)pDevice->pulse.pStreamCapture, ma_device_on_read__pulse, pDevice);
|
||||||
|
ma_mainloop_unlock__pulse(pContext, "ma_device_init__pulse");
|
||||||
|
|
||||||
|
|
||||||
/* Connect after we've got all of our internal state set up. */
|
/* Connect after we've got all of our internal state set up. */
|
||||||
@@ -22217,7 +22236,9 @@ static ma_result ma_device_init__pulse(ma_context* pContext, const ma_device_con
|
|||||||
streamFlags |= MA_PA_STREAM_DONT_MOVE;
|
streamFlags |= MA_PA_STREAM_DONT_MOVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ma_mainloop_lock__pulse(pContext, "ma_device_init__pulse");
|
||||||
error = ((ma_pa_stream_connect_record_proc)pContext->pulse.pa_stream_connect_record)((ma_pa_stream*)pDevice->pulse.pStreamCapture, devCapture, &attr, streamFlags);
|
error = ((ma_pa_stream_connect_record_proc)pContext->pulse.pa_stream_connect_record)((ma_pa_stream*)pDevice->pulse.pStreamCapture, devCapture, &attr, streamFlags);
|
||||||
|
ma_mainloop_unlock__pulse(pContext, "ma_device_init__pulse");
|
||||||
if (error != MA_PA_OK) {
|
if (error != MA_PA_OK) {
|
||||||
result = ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to connect PulseAudio capture stream.", ma_result_from_pulse(error));
|
result = ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to connect PulseAudio capture stream.", ma_result_from_pulse(error));
|
||||||
goto on_error1;
|
goto on_error1;
|
||||||
@@ -22229,6 +22250,8 @@ static ma_result ma_device_init__pulse(ma_context* pContext, const ma_device_con
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ma_mainloop_lock__pulse(pContext, "ma_device_init__pulse");
|
||||||
|
{
|
||||||
/* Internal format. */
|
/* Internal format. */
|
||||||
pActualSS = ((ma_pa_stream_get_sample_spec_proc)pContext->pulse.pa_stream_get_sample_spec)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
|
pActualSS = ((ma_pa_stream_get_sample_spec_proc)pContext->pulse.pa_stream_get_sample_spec)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
|
||||||
if (pActualSS != NULL) {
|
if (pActualSS != NULL) {
|
||||||
@@ -22258,9 +22281,13 @@ static ma_result ma_device_init__pulse(ma_context* pContext, const ma_device_con
|
|||||||
#ifdef MA_DEBUG_OUTPUT
|
#ifdef MA_DEBUG_OUTPUT
|
||||||
printf("[PulseAudio] Capture actual attr: maxlength=%d, tlength=%d, prebuf=%d, minreq=%d, fragsize=%d; internalPeriodSizeInFrames=%d\n", attr.maxlength, attr.tlength, attr.prebuf, attr.minreq, attr.fragsize, pDevice->capture.internalPeriodSizeInFrames);
|
printf("[PulseAudio] Capture actual attr: maxlength=%d, tlength=%d, prebuf=%d, minreq=%d, fragsize=%d; internalPeriodSizeInFrames=%d\n", attr.maxlength, attr.tlength, attr.prebuf, attr.minreq, attr.fragsize, pDevice->capture.internalPeriodSizeInFrames);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
ma_mainloop_unlock__pulse(pContext, "ma_device_init__pulse");
|
||||||
|
|
||||||
/* Name. */
|
/* Name. */
|
||||||
|
ma_mainloop_lock__pulse(pContext, "ma_device_init__pulse");
|
||||||
devCapture = ((ma_pa_stream_get_device_name_proc)pContext->pulse.pa_stream_get_device_name)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
|
devCapture = ((ma_pa_stream_get_device_name_proc)pContext->pulse.pa_stream_get_device_name)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
|
||||||
|
ma_mainloop_unlock__pulse(pContext, "ma_device_init__pulse");
|
||||||
if (devCapture != NULL) {
|
if (devCapture != NULL) {
|
||||||
ma_wait_for_operation_and_unref__pulse(pContext, ((ma_pa_context_get_source_info_by_name_proc)pContext->pulse.pa_context_get_source_info_by_name)((ma_pa_context*)pContext->pulse.pPulseContext, devCapture, ma_device_source_name_callback, pDevice));
|
ma_wait_for_operation_and_unref__pulse(pContext, ((ma_pa_context_get_source_info_by_name_proc)pContext->pulse.pa_context_get_source_info_by_name)((ma_pa_context*)pContext->pulse.pPulseContext, devCapture, ma_device_source_name_callback, pDevice));
|
||||||
}
|
}
|
||||||
@@ -22295,7 +22322,9 @@ static ma_result ma_device_init__pulse(ma_context* pContext, const ma_device_con
|
|||||||
Note that this callback will be fired as soon as the stream is connected, even though it's started as corked. The callback needs to handle a
|
Note that this callback will be fired as soon as the stream is connected, even though it's started as corked. The callback needs to handle a
|
||||||
device state of MA_STATE_UNINITIALIZED.
|
device state of MA_STATE_UNINITIALIZED.
|
||||||
*/
|
*/
|
||||||
|
ma_mainloop_lock__pulse(pContext, "ma_device_init__pulse");
|
||||||
((ma_pa_stream_set_write_callback_proc)pContext->pulse.pa_stream_set_write_callback)((ma_pa_stream*)pDevice->pulse.pStreamPlayback, ma_device_on_write__pulse, pDevice);
|
((ma_pa_stream_set_write_callback_proc)pContext->pulse.pa_stream_set_write_callback)((ma_pa_stream*)pDevice->pulse.pStreamPlayback, ma_device_on_write__pulse, pDevice);
|
||||||
|
ma_mainloop_unlock__pulse(pContext, "ma_device_init__pulse");
|
||||||
|
|
||||||
|
|
||||||
/* Connect after we've got all of our internal state set up. */
|
/* Connect after we've got all of our internal state set up. */
|
||||||
@@ -22304,7 +22333,9 @@ static ma_result ma_device_init__pulse(ma_context* pContext, const ma_device_con
|
|||||||
streamFlags |= MA_PA_STREAM_DONT_MOVE;
|
streamFlags |= MA_PA_STREAM_DONT_MOVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ma_mainloop_lock__pulse(pContext, "ma_device_init__pulse");
|
||||||
error = ((ma_pa_stream_connect_playback_proc)pContext->pulse.pa_stream_connect_playback)((ma_pa_stream*)pDevice->pulse.pStreamPlayback, devPlayback, &attr, streamFlags, NULL, NULL);
|
error = ((ma_pa_stream_connect_playback_proc)pContext->pulse.pa_stream_connect_playback)((ma_pa_stream*)pDevice->pulse.pStreamPlayback, devPlayback, &attr, streamFlags, NULL, NULL);
|
||||||
|
ma_mainloop_unlock__pulse(pContext, "ma_device_init__pulse");
|
||||||
if (error != MA_PA_OK) {
|
if (error != MA_PA_OK) {
|
||||||
result = ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to connect PulseAudio playback stream.", ma_result_from_pulse(error));
|
result = ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to connect PulseAudio playback stream.", ma_result_from_pulse(error));
|
||||||
goto on_error3;
|
goto on_error3;
|
||||||
@@ -22316,6 +22347,8 @@ static ma_result ma_device_init__pulse(ma_context* pContext, const ma_device_con
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ma_mainloop_lock__pulse(pContext, "ma_device_init__pulse");
|
||||||
|
{
|
||||||
/* Internal format. */
|
/* Internal format. */
|
||||||
pActualSS = ((ma_pa_stream_get_sample_spec_proc)pContext->pulse.pa_stream_get_sample_spec)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
|
pActualSS = ((ma_pa_stream_get_sample_spec_proc)pContext->pulse.pa_stream_get_sample_spec)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
|
||||||
if (pActualSS != NULL) {
|
if (pActualSS != NULL) {
|
||||||
@@ -22345,9 +22378,13 @@ static ma_result ma_device_init__pulse(ma_context* pContext, const ma_device_con
|
|||||||
#ifdef MA_DEBUG_OUTPUT
|
#ifdef MA_DEBUG_OUTPUT
|
||||||
printf("[PulseAudio] Playback actual attr: maxlength=%d, tlength=%d, prebuf=%d, minreq=%d, fragsize=%d; internalPeriodSizeInFrames=%d\n", attr.maxlength, attr.tlength, attr.prebuf, attr.minreq, attr.fragsize, pDevice->playback.internalPeriodSizeInFrames);
|
printf("[PulseAudio] Playback actual attr: maxlength=%d, tlength=%d, prebuf=%d, minreq=%d, fragsize=%d; internalPeriodSizeInFrames=%d\n", attr.maxlength, attr.tlength, attr.prebuf, attr.minreq, attr.fragsize, pDevice->playback.internalPeriodSizeInFrames);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
ma_mainloop_unlock__pulse(pContext, "ma_device_init__pulse");
|
||||||
|
|
||||||
/* Name. */
|
/* Name. */
|
||||||
|
ma_mainloop_lock__pulse(pContext, "ma_device_init__pulse");
|
||||||
devPlayback = ((ma_pa_stream_get_device_name_proc)pContext->pulse.pa_stream_get_device_name)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
|
devPlayback = ((ma_pa_stream_get_device_name_proc)pContext->pulse.pa_stream_get_device_name)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
|
||||||
|
ma_mainloop_unlock__pulse(pContext, "ma_device_init__pulse");
|
||||||
if (devPlayback != NULL) {
|
if (devPlayback != NULL) {
|
||||||
ma_wait_for_operation_and_unref__pulse(pContext, ((ma_pa_context_get_sink_info_by_name_proc)pContext->pulse.pa_context_get_sink_info_by_name)((ma_pa_context*)pContext->pulse.pPulseContext, devPlayback, ma_device_sink_name_callback, pDevice));
|
ma_wait_for_operation_and_unref__pulse(pContext, ((ma_pa_context_get_sink_info_by_name_proc)pContext->pulse.pa_context_get_sink_info_by_name)((ma_pa_context*)pContext->pulse.pPulseContext, devPlayback, ma_device_sink_name_callback, pDevice));
|
||||||
}
|
}
|
||||||
@@ -22380,19 +22417,27 @@ static ma_result ma_device_init__pulse(ma_context* pContext, const ma_device_con
|
|||||||
|
|
||||||
on_error4:
|
on_error4:
|
||||||
if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
|
if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
|
||||||
|
ma_mainloop_lock__pulse(pContext, "ma_device_init__pulse");
|
||||||
((ma_pa_stream_disconnect_proc)pContext->pulse.pa_stream_disconnect)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
|
((ma_pa_stream_disconnect_proc)pContext->pulse.pa_stream_disconnect)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
|
||||||
|
ma_mainloop_unlock__pulse(pContext, "ma_device_init__pulse");
|
||||||
}
|
}
|
||||||
on_error3:
|
on_error3:
|
||||||
if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
|
if (pConfig->deviceType == ma_device_type_playback || pConfig->deviceType == ma_device_type_duplex) {
|
||||||
|
ma_mainloop_lock__pulse(pContext, "ma_device_init__pulse");
|
||||||
((ma_pa_stream_unref_proc)pContext->pulse.pa_stream_unref)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
|
((ma_pa_stream_unref_proc)pContext->pulse.pa_stream_unref)((ma_pa_stream*)pDevice->pulse.pStreamPlayback);
|
||||||
|
ma_mainloop_unlock__pulse(pContext, "ma_device_init__pulse");
|
||||||
}
|
}
|
||||||
on_error2:
|
on_error2:
|
||||||
if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
|
if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
|
||||||
|
ma_mainloop_lock__pulse(pContext, "ma_device_init__pulse");
|
||||||
((ma_pa_stream_disconnect_proc)pContext->pulse.pa_stream_disconnect)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
|
((ma_pa_stream_disconnect_proc)pContext->pulse.pa_stream_disconnect)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
|
||||||
|
ma_mainloop_unlock__pulse(pContext, "ma_device_init__pulse");
|
||||||
}
|
}
|
||||||
on_error1:
|
on_error1:
|
||||||
if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
|
if (pConfig->deviceType == ma_device_type_capture || pConfig->deviceType == ma_device_type_duplex) {
|
||||||
|
ma_mainloop_lock__pulse(pContext, "ma_device_init__pulse");
|
||||||
((ma_pa_stream_unref_proc)pContext->pulse.pa_stream_unref)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
|
((ma_pa_stream_unref_proc)pContext->pulse.pa_stream_unref)((ma_pa_stream*)pDevice->pulse.pStreamCapture);
|
||||||
|
ma_mainloop_unlock__pulse(pContext, "ma_device_init__pulse");
|
||||||
}
|
}
|
||||||
on_error0:
|
on_error0:
|
||||||
return result;
|
return result;
|
||||||
@@ -22427,7 +22472,10 @@ static ma_result ma_device__cork_stream__pulse(ma_device* pDevice, ma_device_typ
|
|||||||
pStream = (ma_pa_stream*)((deviceType == ma_device_type_capture) ? pDevice->pulse.pStreamCapture : pDevice->pulse.pStreamPlayback);
|
pStream = (ma_pa_stream*)((deviceType == ma_device_type_capture) ? pDevice->pulse.pStreamCapture : pDevice->pulse.pStreamPlayback);
|
||||||
MA_ASSERT(pStream != NULL);
|
MA_ASSERT(pStream != NULL);
|
||||||
|
|
||||||
|
ma_mainloop_lock__pulse(pContext, "ma_device__cork_stream__pulse");
|
||||||
pOP = ((ma_pa_stream_cork_proc)pContext->pulse.pa_stream_cork)(pStream, cork, ma_pulse_operation_complete_callback, &wasSuccessful);
|
pOP = ((ma_pa_stream_cork_proc)pContext->pulse.pa_stream_cork)(pStream, cork, ma_pulse_operation_complete_callback, &wasSuccessful);
|
||||||
|
ma_mainloop_unlock__pulse(pContext, "ma_device__cork_stream__pulse");
|
||||||
|
|
||||||
if (pOP == NULL) {
|
if (pOP == NULL) {
|
||||||
return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to cork PulseAudio stream.", (cork == 0) ? MA_FAILED_TO_START_BACKEND_DEVICE : MA_FAILED_TO_STOP_BACKEND_DEVICE);
|
return ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to cork PulseAudio stream.", (cork == 0) ? MA_FAILED_TO_START_BACKEND_DEVICE : MA_FAILED_TO_STOP_BACKEND_DEVICE);
|
||||||
}
|
}
|
||||||
@@ -22464,9 +22512,7 @@ static ma_result ma_device_start__pulse(ma_device* pDevice)
|
|||||||
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) {
|
||||||
/* We need to fill some data before uncorking. Not doing this will result in the write callback never getting fired. */
|
/* We need to fill some data before uncorking. Not doing this will result in the write callback never getting fired. */
|
||||||
ma_mainloop_lock__pulse(pDevice->pContext, "ma_device_start__pulse");
|
ma_mainloop_lock__pulse(pDevice->pContext, "ma_device_start__pulse");
|
||||||
{
|
|
||||||
result = ma_device_write_to_stream__pulse(pDevice, (ma_pa_stream*)(pDevice->pulse.pStreamPlayback), NULL);
|
result = ma_device_write_to_stream__pulse(pDevice, (ma_pa_stream*)(pDevice->pulse.pStreamPlayback), NULL);
|
||||||
}
|
|
||||||
ma_mainloop_unlock__pulse(pDevice->pContext, "ma_device_start__pulse");
|
ma_mainloop_unlock__pulse(pDevice->pContext, "ma_device_start__pulse");
|
||||||
|
|
||||||
if (result != MA_SUCCESS) {
|
if (result != MA_SUCCESS) {
|
||||||
@@ -22498,7 +22544,13 @@ static ma_result ma_device_stop__pulse(ma_device* pDevice)
|
|||||||
|
|
||||||
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) {
|
||||||
/* The stream needs to be drained if it's a playback device. */
|
/* The stream needs to be drained if it's a playback device. */
|
||||||
ma_wait_for_operation_and_unref__pulse(pDevice->pContext, ((ma_pa_stream_drain_proc)pDevice->pContext->pulse.pa_stream_drain)((ma_pa_stream*)pDevice->pulse.pStreamPlayback, ma_pulse_operation_complete_callback, &wasSuccessful));
|
ma_pa_operation* pOP;
|
||||||
|
|
||||||
|
ma_mainloop_lock__pulse(pDevice->pContext, "ma_device_stop__pulse");
|
||||||
|
pOP = ((ma_pa_stream_drain_proc)pDevice->pContext->pulse.pa_stream_drain)((ma_pa_stream*)pDevice->pulse.pStreamPlayback, ma_pulse_operation_complete_callback, &wasSuccessful);
|
||||||
|
ma_mainloop_unlock__pulse(pDevice->pContext, "ma_device_stop__pulse");
|
||||||
|
|
||||||
|
ma_wait_for_operation_and_unref__pulse(pDevice->pContext, pOP);
|
||||||
|
|
||||||
result = ma_device__cork_stream__pulse(pDevice, ma_device_type_playback, 1);
|
result = ma_device__cork_stream__pulse(pDevice, ma_device_type_playback, 1);
|
||||||
if (result != MA_SUCCESS) {
|
if (result != MA_SUCCESS) {
|
||||||
@@ -22518,8 +22570,12 @@ static ma_result ma_context_uninit__pulse(ma_context* pContext)
|
|||||||
MA_ASSERT(pContext != NULL);
|
MA_ASSERT(pContext != NULL);
|
||||||
MA_ASSERT(pContext->backend == ma_backend_pulseaudio);
|
MA_ASSERT(pContext->backend == ma_backend_pulseaudio);
|
||||||
|
|
||||||
|
ma_mainloop_lock__pulse(pContext, "ma_context_uninit__pulse");
|
||||||
|
{
|
||||||
((ma_pa_context_disconnect_proc)pContext->pulse.pa_context_disconnect)((ma_pa_context*)pContext->pulse.pPulseContext);
|
((ma_pa_context_disconnect_proc)pContext->pulse.pa_context_disconnect)((ma_pa_context*)pContext->pulse.pPulseContext);
|
||||||
((ma_pa_context_unref_proc)pContext->pulse.pa_context_unref)((ma_pa_context*)pContext->pulse.pPulseContext);
|
((ma_pa_context_unref_proc)pContext->pulse.pa_context_unref)((ma_pa_context*)pContext->pulse.pPulseContext);
|
||||||
|
}
|
||||||
|
ma_mainloop_unlock__pulse(pContext, "ma_context_uninit__pulse");
|
||||||
|
|
||||||
/* The mainloop needs to be stopped before freeing. */
|
/* The mainloop needs to be stopped before freeing. */
|
||||||
((ma_pa_threaded_mainloop_stop_proc)pContext->pulse.pa_threaded_mainloop_stop)((ma_pa_threaded_mainloop*)pContext->pulse.pMainLoop);
|
((ma_pa_threaded_mainloop_stop_proc)pContext->pulse.pa_threaded_mainloop_stop)((ma_pa_threaded_mainloop*)pContext->pulse.pMainLoop);
|
||||||
@@ -33519,7 +33575,7 @@ MA_API ma_uint32 ma_device_get_state(const ma_device* pDevice)
|
|||||||
return MA_STATE_UNINITIALIZED;
|
return MA_STATE_UNINITIALIZED;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pDevice->state;
|
return c89atomic_load_32((ma_uint32*)&pDevice->state); /* Naughty cast to get rid of a const warning. */
|
||||||
}
|
}
|
||||||
|
|
||||||
MA_API ma_result ma_device_set_master_volume(ma_device* pDevice, float volume)
|
MA_API ma_result ma_device_set_master_volume(ma_device* pDevice, float volume)
|
||||||
@@ -64456,6 +64512,7 @@ v0.10.27 - TBD
|
|||||||
- Add support for configuring the channel mixing mode in the device config.
|
- Add support for configuring the channel mixing mode in the device config.
|
||||||
- Fix a bug with simple channel mixing mode (drop or silence excess channels).
|
- Fix a bug with simple channel mixing mode (drop or silence excess channels).
|
||||||
- Fix some bugs with trying to access uninitialized variables.
|
- Fix some bugs with trying to access uninitialized variables.
|
||||||
|
- PulseAudio: Fix some data race errors.
|
||||||
|
|
||||||
|
|
||||||
v0.10.26 - 2020-11-24
|
v0.10.26 - 2020-11-24
|
||||||
|
|||||||
Reference in New Issue
Block a user