mirror of
				https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
				synced 2025-11-03 09:01:50 -05:00 
			
		
		
		
	alsa-util/sink/source: Add infrastructure for supported sample formats
There has been a function to get supported sample rates from alsa and an array for it in userdata of each module-alsa-sink/source. Similarly, this patch adds a function to get supported sample formats(bit depth) from alsa and an array for it to each userdata of the modules. Signed-off-by: Sangchul Lee <sc11.lee@samsung.com>
This commit is contained in:
		
							parent
							
								
									7c066fd886
								
							
						
					
					
						commit
						9d7055004e
					
				
					 4 changed files with 99 additions and 0 deletions
				
			
		| 
						 | 
					@ -111,6 +111,7 @@ struct userdata {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_cvolume hardware_volume;
 | 
					    pa_cvolume hardware_volume;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pa_sample_format_t *supported_formats;
 | 
				
			||||||
    unsigned int *rates;
 | 
					    unsigned int *rates;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    size_t
 | 
					    size_t
 | 
				
			||||||
| 
						 | 
					@ -2349,6 +2350,12 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
 | 
				
			||||||
    if ((is_iec958(u) || is_hdmi(u)) && ss.channels == 2)
 | 
					    if ((is_iec958(u) || is_hdmi(u)) && ss.channels == 2)
 | 
				
			||||||
        set_formats = true;
 | 
					        set_formats = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    u->supported_formats = pa_alsa_get_supported_formats(u->pcm_handle, ss.format);
 | 
				
			||||||
 | 
					    if (!u->supported_formats) {
 | 
				
			||||||
 | 
					        pa_log_error("Failed to find any supported sample formats.");
 | 
				
			||||||
 | 
					        goto fail;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    u->rates = pa_alsa_get_supported_rates(u->pcm_handle, ss.rate);
 | 
					    u->rates = pa_alsa_get_supported_rates(u->pcm_handle, ss.rate);
 | 
				
			||||||
    if (!u->rates) {
 | 
					    if (!u->rates) {
 | 
				
			||||||
        pa_log_error("Failed to find any supported sample rates.");
 | 
					        pa_log_error("Failed to find any supported sample rates.");
 | 
				
			||||||
| 
						 | 
					@ -2629,6 +2636,9 @@ static void userdata_free(struct userdata *u) {
 | 
				
			||||||
    if (u->formats)
 | 
					    if (u->formats)
 | 
				
			||||||
        pa_idxset_free(u->formats, (pa_free_cb_t) pa_format_info_free);
 | 
					        pa_idxset_free(u->formats, (pa_free_cb_t) pa_format_info_free);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (u->supported_formats)
 | 
				
			||||||
 | 
					        pa_xfree(u->supported_formats);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (u->rates)
 | 
					    if (u->rates)
 | 
				
			||||||
        pa_xfree(u->rates);
 | 
					        pa_xfree(u->rates);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -99,6 +99,7 @@ struct userdata {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_cvolume hardware_volume;
 | 
					    pa_cvolume hardware_volume;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pa_sample_format_t *supported_formats;
 | 
				
			||||||
    unsigned int *rates;
 | 
					    unsigned int *rates;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    size_t
 | 
					    size_t
 | 
				
			||||||
| 
						 | 
					@ -2025,6 +2026,12 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
 | 
				
			||||||
            pa_log_info("Disabling latency range changes on overrun");
 | 
					            pa_log_info("Disabling latency range changes on overrun");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    u->supported_formats = pa_alsa_get_supported_formats(u->pcm_handle, ss.format);
 | 
				
			||||||
 | 
					    if (!u->supported_formats) {
 | 
				
			||||||
 | 
					        pa_log_error("Failed to find any supported sample formats.");
 | 
				
			||||||
 | 
					        goto fail;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    u->rates = pa_alsa_get_supported_rates(u->pcm_handle, ss.rate);
 | 
					    u->rates = pa_alsa_get_supported_rates(u->pcm_handle, ss.rate);
 | 
				
			||||||
    if (!u->rates) {
 | 
					    if (!u->rates) {
 | 
				
			||||||
        pa_log_error("Failed to find any supported sample rates.");
 | 
					        pa_log_error("Failed to find any supported sample rates.");
 | 
				
			||||||
| 
						 | 
					@ -2259,6 +2266,9 @@ static void userdata_free(struct userdata *u) {
 | 
				
			||||||
    if (u->smoother)
 | 
					    if (u->smoother)
 | 
				
			||||||
        pa_smoother_free(u->smoother);
 | 
					        pa_smoother_free(u->smoother);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (u->supported_formats)
 | 
				
			||||||
 | 
					        pa_xfree(u->supported_formats);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (u->rates)
 | 
					    if (u->rates)
 | 
				
			||||||
        pa_xfree(u->rates);
 | 
					        pa_xfree(u->rates);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1430,6 +1430,84 @@ unsigned int *pa_alsa_get_supported_rates(snd_pcm_t *pcm, unsigned int fallback_
 | 
				
			||||||
    return rates;
 | 
					    return rates;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pa_sample_format_t *pa_alsa_get_supported_formats(snd_pcm_t *pcm, pa_sample_format_t fallback_format) {
 | 
				
			||||||
 | 
					    static const snd_pcm_format_t format_trans_to_pa[] = {
 | 
				
			||||||
 | 
					        [SND_PCM_FORMAT_U8] = PA_SAMPLE_U8,
 | 
				
			||||||
 | 
					        [SND_PCM_FORMAT_A_LAW] = PA_SAMPLE_ALAW,
 | 
				
			||||||
 | 
					        [SND_PCM_FORMAT_MU_LAW] = PA_SAMPLE_ULAW,
 | 
				
			||||||
 | 
					        [SND_PCM_FORMAT_S16_LE] = PA_SAMPLE_S16LE,
 | 
				
			||||||
 | 
					        [SND_PCM_FORMAT_S16_BE] = PA_SAMPLE_S16BE,
 | 
				
			||||||
 | 
					        [SND_PCM_FORMAT_FLOAT_LE] = PA_SAMPLE_FLOAT32LE,
 | 
				
			||||||
 | 
					        [SND_PCM_FORMAT_FLOAT_BE] = PA_SAMPLE_FLOAT32BE,
 | 
				
			||||||
 | 
					        [SND_PCM_FORMAT_S32_LE] = PA_SAMPLE_S32LE,
 | 
				
			||||||
 | 
					        [SND_PCM_FORMAT_S32_BE] = PA_SAMPLE_S32BE,
 | 
				
			||||||
 | 
					        [SND_PCM_FORMAT_S24_3LE] = PA_SAMPLE_S24LE,
 | 
				
			||||||
 | 
					        [SND_PCM_FORMAT_S24_3BE] = PA_SAMPLE_S24BE,
 | 
				
			||||||
 | 
					        [SND_PCM_FORMAT_S24_LE] = PA_SAMPLE_S24_32LE,
 | 
				
			||||||
 | 
					        [SND_PCM_FORMAT_S24_BE] = PA_SAMPLE_S24_32BE,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    static const snd_pcm_format_t all_formats[] = {
 | 
				
			||||||
 | 
					        SND_PCM_FORMAT_U8,
 | 
				
			||||||
 | 
					        SND_PCM_FORMAT_A_LAW,
 | 
				
			||||||
 | 
					        SND_PCM_FORMAT_MU_LAW,
 | 
				
			||||||
 | 
					        SND_PCM_FORMAT_S16_LE,
 | 
				
			||||||
 | 
					        SND_PCM_FORMAT_S16_BE,
 | 
				
			||||||
 | 
					        SND_PCM_FORMAT_FLOAT_LE,
 | 
				
			||||||
 | 
					        SND_PCM_FORMAT_FLOAT_BE,
 | 
				
			||||||
 | 
					        SND_PCM_FORMAT_S32_LE,
 | 
				
			||||||
 | 
					        SND_PCM_FORMAT_S32_BE,
 | 
				
			||||||
 | 
					        SND_PCM_FORMAT_S24_3LE,
 | 
				
			||||||
 | 
					        SND_PCM_FORMAT_S24_3BE,
 | 
				
			||||||
 | 
					        SND_PCM_FORMAT_S24_LE,
 | 
				
			||||||
 | 
					        SND_PCM_FORMAT_S24_BE,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    bool supported[PA_ELEMENTSOF(all_formats)] = {
 | 
				
			||||||
 | 
					        false,
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    snd_pcm_hw_params_t *hwparams;
 | 
				
			||||||
 | 
					    unsigned int i, j, n;
 | 
				
			||||||
 | 
					    pa_sample_format_t *formats = NULL;
 | 
				
			||||||
 | 
					    int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    snd_pcm_hw_params_alloca(&hwparams);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((ret = snd_pcm_hw_params_any(pcm, hwparams)) < 0) {
 | 
				
			||||||
 | 
					        pa_log_debug("snd_pcm_hw_params_any() failed: %s", pa_alsa_strerror(ret));
 | 
				
			||||||
 | 
					        return NULL;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (i = 0, n = 0; i < PA_ELEMENTSOF(all_formats); i++) {
 | 
				
			||||||
 | 
					        if (snd_pcm_hw_params_test_format(pcm, hwparams, all_formats[i]) == 0) {
 | 
				
			||||||
 | 
					            supported[i] = true;
 | 
				
			||||||
 | 
					            n++;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (n > 0) {
 | 
				
			||||||
 | 
					        formats = pa_xnew(pa_sample_format_t, n + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (i = 0, j = 0; i < PA_ELEMENTSOF(all_formats); i++) {
 | 
				
			||||||
 | 
					            if (supported[i])
 | 
				
			||||||
 | 
					                formats[j++] = format_trans_to_pa[all_formats[i]];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        formats[j] = PA_SAMPLE_MAX;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        formats = pa_xnew(pa_sample_format_t, 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        formats[0] = fallback_format;
 | 
				
			||||||
 | 
					        if ((ret = snd_pcm_hw_params_set_format(pcm, hwparams, format_trans_to_pa[formats[0]])) < 0) {
 | 
				
			||||||
 | 
					            pa_log_debug("snd_pcm_hw_params_set_format() failed: %s", pa_alsa_strerror(ret));
 | 
				
			||||||
 | 
					            pa_xfree(formats);
 | 
				
			||||||
 | 
					            return NULL;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        formats[1] = PA_SAMPLE_MAX;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return formats;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool pa_alsa_pcm_is_hw(snd_pcm_t *pcm) {
 | 
					bool pa_alsa_pcm_is_hw(snd_pcm_t *pcm) {
 | 
				
			||||||
    snd_pcm_info_t* info;
 | 
					    snd_pcm_info_t* info;
 | 
				
			||||||
    snd_pcm_info_alloca(&info);
 | 
					    snd_pcm_info_alloca(&info);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -132,6 +132,7 @@ char *pa_alsa_get_driver_name_by_pcm(snd_pcm_t *pcm);
 | 
				
			||||||
char *pa_alsa_get_reserve_name(const char *device);
 | 
					char *pa_alsa_get_reserve_name(const char *device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
unsigned int *pa_alsa_get_supported_rates(snd_pcm_t *pcm, unsigned int fallback_rate);
 | 
					unsigned int *pa_alsa_get_supported_rates(snd_pcm_t *pcm, unsigned int fallback_rate);
 | 
				
			||||||
 | 
					pa_sample_format_t *pa_alsa_get_supported_formats(snd_pcm_t *pcm, pa_sample_format_t fallback_format);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool pa_alsa_pcm_is_hw(snd_pcm_t *pcm);
 | 
					bool pa_alsa_pcm_is_hw(snd_pcm_t *pcm);
 | 
				
			||||||
bool pa_alsa_pcm_is_modem(snd_pcm_t *pcm);
 | 
					bool pa_alsa_pcm_is_modem(snd_pcm_t *pcm);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue