Commit c4099c86 authored by David Reid's avatar David Reid

PulseAudio: Add support for detecting default devices.

Public issue https://github.com/mackron/miniaudio/issues/126
parent c8444550
...@@ -20719,12 +20719,144 @@ static ma_bool32 ma_context_is_device_id_equal__pulse(ma_context* pContext, cons ...@@ -20719,12 +20719,144 @@ static ma_bool32 ma_context_is_device_id_equal__pulse(ma_context* pContext, cons
} }
static void ma_device_sink_info_callback(ma_pa_context* pPulseContext, const ma_pa_sink_info* pInfo, int endOfList, void* pUserData)
{
ma_pa_sink_info* pInfoOut;
if (endOfList > 0) {
return;
}
pInfoOut = (ma_pa_sink_info*)pUserData;
MA_ASSERT(pInfoOut != NULL);
*pInfoOut = *pInfo;
(void)pPulseContext; /* Unused. */
}
static void ma_device_source_info_callback(ma_pa_context* pPulseContext, const ma_pa_source_info* pInfo, int endOfList, void* pUserData)
{
ma_pa_source_info* pInfoOut;
if (endOfList > 0) {
return;
}
pInfoOut = (ma_pa_source_info*)pUserData;
MA_ASSERT(pInfoOut != NULL);
*pInfoOut = *pInfo;
(void)pPulseContext; /* Unused. */
}
static void ma_device_sink_name_callback(ma_pa_context* pPulseContext, const ma_pa_sink_info* pInfo, int endOfList, void* pUserData)
{
ma_device* pDevice;
if (endOfList > 0) {
return;
}
pDevice = (ma_device*)pUserData;
MA_ASSERT(pDevice != NULL);
ma_strncpy_s(pDevice->playback.name, sizeof(pDevice->playback.name), pInfo->description, (size_t)-1);
(void)pPulseContext; /* Unused. */
}
static void ma_device_source_name_callback(ma_pa_context* pPulseContext, const ma_pa_source_info* pInfo, int endOfList, void* pUserData)
{
ma_device* pDevice;
if (endOfList > 0) {
return;
}
pDevice = (ma_device*)pUserData;
MA_ASSERT(pDevice != NULL);
ma_strncpy_s(pDevice->capture.name, sizeof(pDevice->capture.name), pInfo->description, (size_t)-1);
(void)pPulseContext; /* Unused. */
}
static ma_result ma_context_get_sink_info__pulse(ma_context* pContext, const char* pDeviceName, ma_pa_sink_info* pSinkInfo)
{
ma_pa_operation* pOP;
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);
if (pOP == NULL) {
return MA_ERROR;
}
ma_wait_for_operation_and_unref__pulse(pContext, pOP);
return MA_SUCCESS;
}
static ma_result ma_context_get_source_info__pulse(ma_context* pContext, const char* pDeviceName, ma_pa_source_info* pSourceInfo)
{
ma_pa_operation* pOP;
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);
if (pOP == NULL) {
return MA_ERROR;
}
ma_wait_for_operation_and_unref__pulse(pContext, pOP);
return MA_SUCCESS;
}
static ma_result ma_context_get_default_device_index__pulse(ma_context* pContext, ma_device_type deviceType, ma_uint32* pIndex)
{
ma_result result;
MA_ASSERT(pContext != NULL);
MA_ASSERT(pIndex != NULL);
if (pIndex != NULL) {
*pIndex = (ma_uint32)-1;
}
if (deviceType == ma_device_type_playback) {
ma_pa_sink_info sinkInfo;
result = ma_context_get_sink_info__pulse(pContext, NULL, &sinkInfo);
if (result != MA_SUCCESS) {
return result;
}
if (pIndex != NULL) {
*pIndex = sinkInfo.index;
}
}
if (deviceType == ma_device_type_capture) {
ma_pa_source_info sourceInfo;
result = ma_context_get_source_info__pulse(pContext, NULL, &sourceInfo);
if (result != MA_SUCCESS) {
return result;
}
if (pIndex != NULL) {
*pIndex = sourceInfo.index;
}
}
return MA_SUCCESS;
}
typedef struct typedef struct
{ {
ma_context* pContext; ma_context* pContext;
ma_enum_devices_callback_proc callback; ma_enum_devices_callback_proc callback;
void* pUserData; void* pUserData;
ma_bool32 isTerminated; ma_bool32 isTerminated;
ma_uint32 defaultDeviceIndexPlayback;
ma_uint32 defaultDeviceIndexCapture;
} ma_context_enumerate_devices_callback_data__pulse; } ma_context_enumerate_devices_callback_data__pulse;
static void ma_context_enumerate_devices_sink_callback__pulse(ma_pa_context* pPulseContext, const ma_pa_sink_info* pSinkInfo, int endOfList, void* pUserData) static void ma_context_enumerate_devices_sink_callback__pulse(ma_pa_context* pPulseContext, const ma_pa_sink_info* pSinkInfo, int endOfList, void* pUserData)
...@@ -20750,12 +20882,16 @@ static void ma_context_enumerate_devices_sink_callback__pulse(ma_pa_context* pPu ...@@ -20750,12 +20882,16 @@ static void ma_context_enumerate_devices_sink_callback__pulse(ma_pa_context* pPu
ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), pSinkInfo->description, (size_t)-1); ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), pSinkInfo->description, (size_t)-1);
} }
if (pSinkInfo->index == pData->defaultDeviceIndexPlayback) {
deviceInfo._private.isDefault = MA_TRUE;
}
pData->isTerminated = !pData->callback(pData->pContext, ma_device_type_playback, &deviceInfo, pData->pUserData); pData->isTerminated = !pData->callback(pData->pContext, ma_device_type_playback, &deviceInfo, pData->pUserData);
(void)pPulseContext; /* Unused. */ (void)pPulseContext; /* Unused. */
} }
static void ma_context_enumerate_devices_source_callback__pulse(ma_pa_context* pPulseContext, const ma_pa_source_info* pSinkInfo, int endOfList, void* pUserData) static void ma_context_enumerate_devices_source_callback__pulse(ma_pa_context* pPulseContext, const ma_pa_source_info* pSourceInfo, int endOfList, void* pUserData)
{ {
ma_context_enumerate_devices_callback_data__pulse* pData = (ma_context_enumerate_devices_callback_data__pulse*)pUserData; ma_context_enumerate_devices_callback_data__pulse* pData = (ma_context_enumerate_devices_callback_data__pulse*)pUserData;
ma_device_info deviceInfo; ma_device_info deviceInfo;
...@@ -20769,13 +20905,17 @@ static void ma_context_enumerate_devices_source_callback__pulse(ma_pa_context* p ...@@ -20769,13 +20905,17 @@ static void ma_context_enumerate_devices_source_callback__pulse(ma_pa_context* p
MA_ZERO_OBJECT(&deviceInfo); MA_ZERO_OBJECT(&deviceInfo);
/* The name from PulseAudio is the ID for miniaudio. */ /* The name from PulseAudio is the ID for miniaudio. */
if (pSinkInfo->name != NULL) { if (pSourceInfo->name != NULL) {
ma_strncpy_s(deviceInfo.id.pulse, sizeof(deviceInfo.id.pulse), pSinkInfo->name, (size_t)-1); ma_strncpy_s(deviceInfo.id.pulse, sizeof(deviceInfo.id.pulse), pSourceInfo->name, (size_t)-1);
} }
/* The description from PulseAudio is the name for miniaudio. */ /* The description from PulseAudio is the name for miniaudio. */
if (pSinkInfo->description != NULL) { if (pSourceInfo->description != NULL) {
ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), pSinkInfo->description, (size_t)-1); ma_strncpy_s(deviceInfo.name, sizeof(deviceInfo.name), pSourceInfo->description, (size_t)-1);
}
if (pSourceInfo->index == pData->defaultDeviceIndexCapture) {
deviceInfo._private.isDefault = MA_TRUE;
} }
pData->isTerminated = !pData->callback(pData->pContext, ma_device_type_capture, &deviceInfo, pData->pUserData); pData->isTerminated = !pData->callback(pData->pContext, ma_device_type_capture, &deviceInfo, pData->pUserData);
...@@ -20796,6 +20936,12 @@ static ma_result ma_context_enumerate_devices__pulse(ma_context* pContext, ma_en ...@@ -20796,6 +20936,12 @@ static ma_result ma_context_enumerate_devices__pulse(ma_context* pContext, ma_en
callbackData.callback = callback; callbackData.callback = callback;
callbackData.pUserData = pUserData; callbackData.pUserData = pUserData;
callbackData.isTerminated = MA_FALSE; callbackData.isTerminated = MA_FALSE;
callbackData.defaultDeviceIndexPlayback = (ma_uint32)-1;
callbackData.defaultDeviceIndexCapture = (ma_uint32)-1;
/* We need to get the index of the default devices. */
ma_context_get_default_device_index__pulse(pContext, ma_device_type_playback, &callbackData.defaultDeviceIndexPlayback);
ma_context_get_default_device_index__pulse(pContext, ma_device_type_capture, &callbackData.defaultDeviceIndexCapture);
/* Playback. */ /* Playback. */
if (!callbackData.isTerminated) { if (!callbackData.isTerminated) {
...@@ -20836,6 +20982,7 @@ done: ...@@ -20836,6 +20982,7 @@ done:
typedef struct typedef struct
{ {
ma_device_info* pDeviceInfo; ma_device_info* pDeviceInfo;
ma_uint32 defaultDeviceIndex;
ma_bool32 foundDevice; ma_bool32 foundDevice;
} ma_context_get_device_info_callback_data__pulse; } ma_context_get_device_info_callback_data__pulse;
...@@ -20865,6 +21012,10 @@ static void ma_context_get_device_info_sink_callback__pulse(ma_pa_context* pPuls ...@@ -20865,6 +21012,10 @@ static void ma_context_get_device_info_sink_callback__pulse(ma_pa_context* pPuls
pData->pDeviceInfo->formatCount = 1; pData->pDeviceInfo->formatCount = 1;
pData->pDeviceInfo->formats[0] = ma_format_from_pulse(pInfo->sample_spec.format); pData->pDeviceInfo->formats[0] = ma_format_from_pulse(pInfo->sample_spec.format);
if (pData->defaultDeviceIndex == pInfo->index) {
pData->pDeviceInfo->_private.isDefault = MA_TRUE;
}
(void)pPulseContext; /* Unused. */ (void)pPulseContext; /* Unused. */
} }
...@@ -20894,6 +21045,10 @@ static void ma_context_get_device_info_source_callback__pulse(ma_pa_context* pPu ...@@ -20894,6 +21045,10 @@ static void ma_context_get_device_info_source_callback__pulse(ma_pa_context* pPu
pData->pDeviceInfo->formatCount = 1; pData->pDeviceInfo->formatCount = 1;
pData->pDeviceInfo->formats[0] = ma_format_from_pulse(pInfo->sample_spec.format); pData->pDeviceInfo->formats[0] = ma_format_from_pulse(pInfo->sample_spec.format);
if (pData->defaultDeviceIndex == pInfo->index) {
pData->pDeviceInfo->_private.isDefault = MA_TRUE;
}
(void)pPulseContext; /* Unused. */ (void)pPulseContext; /* Unused. */
} }
...@@ -20912,6 +21067,8 @@ static ma_result ma_context_get_device_info__pulse(ma_context* pContext, ma_devi ...@@ -20912,6 +21067,8 @@ static ma_result ma_context_get_device_info__pulse(ma_context* pContext, ma_devi
callbackData.pDeviceInfo = pDeviceInfo; callbackData.pDeviceInfo = pDeviceInfo;
callbackData.foundDevice = MA_FALSE; callbackData.foundDevice = MA_FALSE;
result = ma_context_get_default_device_index__pulse(pContext, deviceType, &callbackData.defaultDeviceIndex);
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)(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)(pContext->pulse.pPulseContext, pDeviceID->pulse, ma_context_get_device_info_sink_callback__pulse, &callbackData);
...@@ -20935,71 +21092,6 @@ done: ...@@ -20935,71 +21092,6 @@ done:
return result; return result;
} }
static void ma_device_sink_info_callback(ma_pa_context* pPulseContext, const ma_pa_sink_info* pInfo, int endOfList, void* pUserData)
{
ma_pa_sink_info* pInfoOut;
if (endOfList > 0) {
return;
}
pInfoOut = (ma_pa_sink_info*)pUserData;
MA_ASSERT(pInfoOut != NULL);
*pInfoOut = *pInfo;
(void)pPulseContext; /* Unused. */
}
static void ma_device_source_info_callback(ma_pa_context* pPulseContext, const ma_pa_source_info* pInfo, int endOfList, void* pUserData)
{
ma_pa_source_info* pInfoOut;
if (endOfList > 0) {
return;
}
pInfoOut = (ma_pa_source_info*)pUserData;
MA_ASSERT(pInfoOut != NULL);
*pInfoOut = *pInfo;
(void)pPulseContext; /* Unused. */
}
static void ma_device_sink_name_callback(ma_pa_context* pPulseContext, const ma_pa_sink_info* pInfo, int endOfList, void* pUserData)
{
ma_device* pDevice;
if (endOfList > 0) {
return;
}
pDevice = (ma_device*)pUserData;
MA_ASSERT(pDevice != NULL);
ma_strncpy_s(pDevice->playback.name, sizeof(pDevice->playback.name), pInfo->description, (size_t)-1);
(void)pPulseContext; /* Unused. */
}
static void ma_device_source_name_callback(ma_pa_context* pPulseContext, const ma_pa_source_info* pInfo, int endOfList, void* pUserData)
{
ma_device* pDevice;
if (endOfList > 0) {
return;
}
pDevice = (ma_device*)pUserData;
MA_ASSERT(pDevice != NULL);
ma_strncpy_s(pDevice->capture.name, sizeof(pDevice->capture.name), pInfo->description, (size_t)-1);
(void)pPulseContext; /* Unused. */
}
static void ma_device_uninit__pulse(ma_device* pDevice) static void ma_device_uninit__pulse(ma_device* pDevice)
{ {
ma_context* pContext; ma_context* pContext;
...@@ -21214,7 +21306,6 @@ static ma_result ma_device_init__pulse(ma_context* pContext, const ma_device_con ...@@ -21214,7 +21306,6 @@ static ma_result ma_device_init__pulse(ma_context* pContext, const ma_device_con
ma_uint32 periodSizeInMilliseconds; ma_uint32 periodSizeInMilliseconds;
ma_pa_sink_info sinkInfo; ma_pa_sink_info sinkInfo;
ma_pa_source_info sourceInfo; ma_pa_source_info sourceInfo;
ma_pa_operation* pOP = NULL;
ma_pa_sample_spec ss; ma_pa_sample_spec ss;
ma_pa_channel_map cmap; ma_pa_channel_map cmap;
ma_pa_buffer_attr attr; ma_pa_buffer_attr attr;
...@@ -21250,11 +21341,9 @@ static ma_result ma_device_init__pulse(ma_context* pContext, const ma_device_con ...@@ -21250,11 +21341,9 @@ static ma_result ma_device_init__pulse(ma_context* pContext, const ma_device_con
} }
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) {
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, devCapture, ma_device_source_info_callback, &sourceInfo); result = ma_context_get_source_info__pulse(pContext, devCapture, &sourceInfo);
if (pOP != NULL) { if (result != MA_SUCCESS) {
ma_wait_for_operation_and_unref__pulse(pContext, pOP); ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to retrieve source info for capture device.", result);
} else {
result = ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to retrieve source info for capture device.", ma_result_from_pulse(error));
goto on_error0; goto on_error0;
} }
...@@ -21342,11 +21431,9 @@ static ma_result ma_device_init__pulse(ma_context* pContext, const ma_device_con ...@@ -21342,11 +21431,9 @@ static ma_result ma_device_init__pulse(ma_context* pContext, const ma_device_con
} }
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) {
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, devPlayback, ma_device_sink_info_callback, &sinkInfo); result = ma_context_get_sink_info__pulse(pContext, devPlayback, &sinkInfo);
if (pOP != NULL) { if (result != MA_SUCCESS) {
ma_wait_for_operation_and_unref__pulse(pContext, pOP); ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to retrieve sink info for playback device.", result);
} else {
result = ma_post_error(pDevice, MA_LOG_LEVEL_ERROR, "[PulseAudio] Failed to retrieve sink info for playback device.", ma_result_from_pulse(error));
goto on_error2; goto on_error2;
} }
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