mirror of
https://github.com/mackron/miniaudio.git
synced 2026-04-23 08:44:04 +02:00
PulseAudio: Properly handle default format/channels/rate.
This commit is contained in:
@@ -7352,12 +7352,12 @@ static mal_result mal_device_init__alsa(mal_context* pContext, mal_device_type t
|
|||||||
|
|
||||||
|
|
||||||
// Channels.
|
// Channels.
|
||||||
mal_uint32 channels = pConfig->channels;
|
unsigned int channels = pConfig->channels;
|
||||||
if (((mal_snd_pcm_hw_params_set_channels_near_proc)pContext->alsa.snd_pcm_hw_params_set_channels_near)((mal_snd_pcm_t*)pDevice->alsa.pPCM, pHWParams, &channels) < 0) {
|
if (((mal_snd_pcm_hw_params_set_channels_near_proc)pContext->alsa.snd_pcm_hw_params_set_channels_near)((mal_snd_pcm_t*)pDevice->alsa.pPCM, pHWParams, &channels) < 0) {
|
||||||
mal_device_uninit__alsa(pDevice);
|
mal_device_uninit__alsa(pDevice);
|
||||||
return mal_post_error(pDevice, "[ALSA] Failed to set channel count. snd_pcm_hw_params_set_channels_near() failed.", MAL_FORMAT_NOT_SUPPORTED);
|
return mal_post_error(pDevice, "[ALSA] Failed to set channel count. snd_pcm_hw_params_set_channels_near() failed.", MAL_FORMAT_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
pDevice->internalChannels = channels;
|
pDevice->internalChannels = (mal_uint32)channels;
|
||||||
|
|
||||||
|
|
||||||
// Sample Rate. It appears there's either a bug in ALSA, a bug in some drivers, or I'm doing something silly; but having resampling
|
// Sample Rate. It appears there's either a bug in ALSA, a bug in some drivers, or I'm doing something silly; but having resampling
|
||||||
@@ -7377,12 +7377,12 @@ static mal_result mal_device_init__alsa(mal_context* pContext, mal_device_type t
|
|||||||
// this error with. In the future, we may want to restrict the disabling of resampling to only known bad plugins.
|
// this error with. In the future, we may want to restrict the disabling of resampling to only known bad plugins.
|
||||||
((mal_snd_pcm_hw_params_set_rate_resample_proc)pContext->alsa.snd_pcm_hw_params_set_rate_resample)((mal_snd_pcm_t*)pDevice->alsa.pPCM, pHWParams, 0);
|
((mal_snd_pcm_hw_params_set_rate_resample_proc)pContext->alsa.snd_pcm_hw_params_set_rate_resample)((mal_snd_pcm_t*)pDevice->alsa.pPCM, pHWParams, 0);
|
||||||
|
|
||||||
mal_uint32 sampleRate = pConfig->sampleRate;
|
unsigned int sampleRate = pConfig->sampleRate;
|
||||||
if (((mal_snd_pcm_hw_params_set_rate_near_proc)pContext->alsa.snd_pcm_hw_params_set_rate_near)((mal_snd_pcm_t*)pDevice->alsa.pPCM, pHWParams, &sampleRate, 0) < 0) {
|
if (((mal_snd_pcm_hw_params_set_rate_near_proc)pContext->alsa.snd_pcm_hw_params_set_rate_near)((mal_snd_pcm_t*)pDevice->alsa.pPCM, pHWParams, &sampleRate, 0) < 0) {
|
||||||
mal_device_uninit__alsa(pDevice);
|
mal_device_uninit__alsa(pDevice);
|
||||||
return mal_post_error(pDevice, "[ALSA] Sample rate not supported. snd_pcm_hw_params_set_rate_near() failed.", MAL_FORMAT_NOT_SUPPORTED);
|
return mal_post_error(pDevice, "[ALSA] Sample rate not supported. snd_pcm_hw_params_set_rate_near() failed.", MAL_FORMAT_NOT_SUPPORTED);
|
||||||
}
|
}
|
||||||
pDevice->internalSampleRate = sampleRate;
|
pDevice->internalSampleRate = (mal_uint32)sampleRate;
|
||||||
|
|
||||||
|
|
||||||
// Periods.
|
// Periods.
|
||||||
@@ -8141,6 +8141,7 @@ static mal_result mal_result_from_pulse(int result)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static mal_pa_sample_format_t mal_format_to_pulse(mal_format format)
|
static mal_pa_sample_format_t mal_format_to_pulse(mal_format format)
|
||||||
{
|
{
|
||||||
switch (format)
|
switch (format)
|
||||||
@@ -8160,6 +8161,7 @@ static mal_pa_sample_format_t mal_format_to_pulse(mal_format format)
|
|||||||
default: return MAL_PA_SAMPLE_INVALID;
|
default: return MAL_PA_SAMPLE_INVALID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static mal_format mal_format_from_pulse(mal_pa_sample_format_t format)
|
static mal_format mal_format_from_pulse(mal_pa_sample_format_t format)
|
||||||
{
|
{
|
||||||
@@ -8241,6 +8243,7 @@ static mal_channel mal_channel_position_from_pulse(mal_pa_channel_position_t pos
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static mal_pa_channel_position_t mal_channel_position_to_pulse(mal_channel position)
|
static mal_pa_channel_position_t mal_channel_position_to_pulse(mal_channel position)
|
||||||
{
|
{
|
||||||
switch (position)
|
switch (position)
|
||||||
@@ -8281,6 +8284,7 @@ static mal_pa_channel_position_t mal_channel_position_to_pulse(mal_channel posit
|
|||||||
default: return (mal_pa_channel_position_t)position;
|
default: return (mal_pa_channel_position_t)position;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static mal_result mal_context_uninit__pulse(mal_context* pContext)
|
static mal_result mal_context_uninit__pulse(mal_context* pContext)
|
||||||
@@ -8672,6 +8676,30 @@ static void mal_pulse_device_read_callback(mal_pa_stream* pStream, size_t sizeIn
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mal_device_sink_info_callback(mal_pa_context* pPulseContext, const mal_pa_sink_info* pInfo, int endOfList, void* pUserData)
|
||||||
|
{
|
||||||
|
if (endOfList > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mal_pa_sink_info* pInfoOut = (mal_pa_sink_info*)pUserData;
|
||||||
|
mal_assert(pInfoOut != NULL);
|
||||||
|
|
||||||
|
*pInfoOut = *pInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mal_device_source_info_callback(mal_pa_context* pPulseContext, const mal_pa_source_info* pInfo, int endOfList, void* pUserData)
|
||||||
|
{
|
||||||
|
if (endOfList > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mal_pa_source_info* pInfoOut = (mal_pa_source_info*)pUserData;
|
||||||
|
mal_assert(pInfoOut != NULL);
|
||||||
|
|
||||||
|
*pInfoOut = *pInfo;
|
||||||
|
}
|
||||||
|
|
||||||
static void mal_device_sink_name_callback(mal_pa_context* pPulseContext, const mal_pa_sink_info* pInfo, int endOfList, void* pUserData)
|
static void mal_device_sink_name_callback(mal_pa_context* pPulseContext, const mal_pa_sink_info* pInfo, int endOfList, void* pUserData)
|
||||||
{
|
{
|
||||||
if (endOfList > 0) {
|
if (endOfList > 0) {
|
||||||
@@ -8773,25 +8801,85 @@ static mal_result mal_device_init__pulse(mal_context* pContext, mal_device_type
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char* dev = NULL;
|
||||||
|
if (pDeviceID != NULL) {
|
||||||
|
dev = pDeviceID->pulse;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
mal_pa_sink_info sinkInfo;
|
||||||
|
mal_pa_source_info sourceInfo;
|
||||||
|
mal_pa_operation* pOP = NULL;
|
||||||
|
if (type == mal_device_type_playback) {
|
||||||
|
pOP = ((mal_pa_context_get_sink_info_by_name_proc)pContext->pulse.pa_context_get_sink_info_by_name)((mal_pa_context*)pDevice->pulse.pPulseContext, dev, mal_device_sink_info_callback, &sinkInfo);
|
||||||
|
} else {
|
||||||
|
pOP = ((mal_pa_context_get_source_info_by_name_proc)pContext->pulse.pa_context_get_source_info_by_name)((mal_pa_context*)pDevice->pulse.pPulseContext, dev, mal_device_source_info_callback, &sourceInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pOP != NULL) {
|
||||||
|
mal_device__wait_for_operation__pulse(pDevice, pOP);
|
||||||
|
((mal_pa_operation_unref_proc)pContext->pulse.pa_operation_unref)(pOP);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
mal_pa_sample_spec deviceSS;
|
||||||
|
mal_pa_channel_map deviceCMap;
|
||||||
|
if (type == mal_device_type_playback) {
|
||||||
|
deviceSS = sinkInfo.sample_spec;
|
||||||
|
deviceCMap = sinkInfo.channel_map;
|
||||||
|
} else {
|
||||||
|
deviceSS = sourceInfo.sample_spec;
|
||||||
|
deviceCMap = sourceInfo.channel_map;
|
||||||
|
}
|
||||||
|
|
||||||
mal_pa_sample_spec ss;
|
mal_pa_sample_spec ss;
|
||||||
ss.format = mal_format_to_pulse(pConfig->format);
|
if (pDevice->usingDefaultFormat) {
|
||||||
|
ss.format = deviceSS.format;
|
||||||
|
} else {
|
||||||
|
ss.format = mal_format_to_pulse(pConfig->format);
|
||||||
|
}
|
||||||
if (ss.format == MAL_PA_SAMPLE_INVALID) {
|
if (ss.format == MAL_PA_SAMPLE_INVALID) {
|
||||||
ss.format = MAL_PA_SAMPLE_S16LE;
|
ss.format = MAL_PA_SAMPLE_S16LE;
|
||||||
}
|
}
|
||||||
ss.channels = pConfig->channels;
|
|
||||||
ss.rate = pConfig->sampleRate;
|
if (pDevice->usingDefaultChannels) {
|
||||||
|
ss.channels = deviceSS.channels;
|
||||||
|
} else {
|
||||||
|
ss.channels = pConfig->channels;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pDevice->usingDefaultSampleRate) {
|
||||||
|
ss.rate = deviceSS.rate;
|
||||||
|
} else {
|
||||||
|
ss.rate = pConfig->sampleRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
mal_pa_channel_map cmap;
|
mal_pa_channel_map cmap;
|
||||||
cmap.channels = pConfig->channels;
|
if (pDevice->usingDefaultChannelMap) {
|
||||||
for (mal_uint32 iChannel = 0; iChannel < pConfig->channels; ++iChannel) {
|
cmap = deviceCMap;
|
||||||
cmap.map[iChannel] = mal_channel_position_to_pulse(pConfig->channelMap[iChannel]);
|
} else {
|
||||||
}
|
cmap.channels = pConfig->channels;
|
||||||
|
for (mal_uint32 iChannel = 0; iChannel < pConfig->channels; ++iChannel) {
|
||||||
|
cmap.map[iChannel] = mal_channel_position_to_pulse(pConfig->channelMap[iChannel]);
|
||||||
|
}
|
||||||
|
|
||||||
if (((mal_pa_channel_map_valid_proc)pContext->pulse.pa_channel_map_valid)(&cmap) == 0 || ((mal_pa_channel_map_compatible_proc)pContext->pulse.pa_channel_map_compatible)(&cmap, &ss) == 0) {
|
if (((mal_pa_channel_map_valid_proc)pContext->pulse.pa_channel_map_valid)(&cmap) == 0 || ((mal_pa_channel_map_compatible_proc)pContext->pulse.pa_channel_map_compatible)(&cmap, &ss) == 0) {
|
||||||
((mal_pa_channel_map_init_extend_proc)pContext->pulse.pa_channel_map_init_extend)(&cmap, ss.channels, MAL_PA_CHANNEL_MAP_DEFAULT); // The channel map is invalid, so just fall back to the default.
|
((mal_pa_channel_map_init_extend_proc)pContext->pulse.pa_channel_map_init_extend)(&cmap, ss.channels, MAL_PA_CHANNEL_MAP_DEFAULT); // The channel map is invalid, so just fall back to the default.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
mal_pa_sample_spec ss;
|
||||||
|
mal_pa_channel_map cmap;
|
||||||
|
if (type == mal_device_type_playback) {
|
||||||
|
ss = sinkInfo.sample_spec;
|
||||||
|
cmap = sinkInfo.channel_map;
|
||||||
|
} else {
|
||||||
|
ss = sourceInfo.sample_spec;
|
||||||
|
cmap = sourceInfo.channel_map;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
mal_pa_buffer_attr attr;
|
mal_pa_buffer_attr attr;
|
||||||
@@ -8817,10 +8905,7 @@ static mal_result mal_device_init__pulse(mal_context* pContext, mal_device_type
|
|||||||
goto on_error3;
|
goto on_error3;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* dev = NULL;
|
|
||||||
if (pDeviceID != NULL) {
|
|
||||||
dev = pDeviceID->pulse;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type == mal_device_type_playback) {
|
if (type == mal_device_type_playback) {
|
||||||
error = ((mal_pa_stream_connect_playback_proc)pContext->pulse.pa_stream_connect_playback)((mal_pa_stream*)pDevice->pulse.pStream, dev, &attr, MAL_PA_STREAM_START_CORKED, NULL, NULL);
|
error = ((mal_pa_stream_connect_playback_proc)pContext->pulse.pa_stream_connect_playback)((mal_pa_stream*)pDevice->pulse.pStream, dev, &attr, MAL_PA_STREAM_START_CORKED, NULL, NULL);
|
||||||
|
|||||||
Reference in New Issue
Block a user