diff --git a/mini_al.h b/mini_al.h index 2a050c2c..563b994e 100644 --- a/mini_al.h +++ b/mini_al.h @@ -7352,12 +7352,12 @@ static mal_result mal_device_init__alsa(mal_context* pContext, mal_device_type t // 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) { 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); } - 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 @@ -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. ((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) { 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); } - pDevice->internalSampleRate = sampleRate; + pDevice->internalSampleRate = (mal_uint32)sampleRate; // 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) { 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; } } +#endif 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) { 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; } } +#endif 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) { 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; - 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) { 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; - 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 (pDevice->usingDefaultChannelMap) { + cmap = deviceCMap; + } 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) { - ((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. + 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. + } } +#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; @@ -8817,10 +8905,7 @@ static mal_result mal_device_init__pulse(mal_context* pContext, mal_device_type goto on_error3; } - const char* dev = NULL; - if (pDeviceID != NULL) { - dev = pDeviceID->pulse; - } + 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);