mirror of
				https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
				synced 2025-11-03 09:01:50 -05:00 
			
		
		
		
	unify ALSA mixer initialization
This commit is contained in:
		
							parent
							
								
									023998e3c8
								
							
						
					
					
						commit
						6790c03f91
					
				
					 4 changed files with 83 additions and 74 deletions
				
			
		| 
						 | 
					@ -1386,43 +1386,7 @@ pa_sink *pa_alsa_sink_new(pa_module *m, pa_modargs *ma, const char*driver, pa_ca
 | 
				
			||||||
    /* ALSA might tweak the sample spec, so recalculate the frame size */
 | 
					    /* ALSA might tweak the sample spec, so recalculate the frame size */
 | 
				
			||||||
    frame_size = pa_frame_size(&ss);
 | 
					    frame_size = pa_frame_size(&ss);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((err = snd_mixer_open(&u->mixer_handle, 0)) < 0)
 | 
					    pa_alsa_find_mixer_and_elem(u->pcm_handle, &u->mixer_handle, &u->mixer_elem);
 | 
				
			||||||
        pa_log_warn("Error opening mixer: %s", snd_strerror(err));
 | 
					 | 
				
			||||||
    else {
 | 
					 | 
				
			||||||
        pa_bool_t found = FALSE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (pa_alsa_prepare_mixer(u->mixer_handle, u->device_name) >= 0)
 | 
					 | 
				
			||||||
            found = TRUE;
 | 
					 | 
				
			||||||
        else {
 | 
					 | 
				
			||||||
            snd_pcm_info_t *info;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            snd_pcm_info_alloca(&info);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (snd_pcm_info(u->pcm_handle, info) >= 0) {
 | 
					 | 
				
			||||||
                char *md;
 | 
					 | 
				
			||||||
                int card_idx;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if ((card_idx = snd_pcm_info_get_card(info)) >= 0) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    md = pa_sprintf_malloc("hw:%i", card_idx);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    if (strcmp(u->device_name, md))
 | 
					 | 
				
			||||||
                        if (pa_alsa_prepare_mixer(u->mixer_handle, md) >= 0)
 | 
					 | 
				
			||||||
                            found = TRUE;
 | 
					 | 
				
			||||||
                    pa_xfree(md);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (found)
 | 
					 | 
				
			||||||
            if (!(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "Master", "PCM", TRUE)))
 | 
					 | 
				
			||||||
                found = FALSE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (!found) {
 | 
					 | 
				
			||||||
            snd_mixer_close(u->mixer_handle);
 | 
					 | 
				
			||||||
            u->mixer_handle = NULL;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_sink_new_data_init(&data);
 | 
					    pa_sink_new_data_init(&data);
 | 
				
			||||||
    data.driver = driver;
 | 
					    data.driver = driver;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1211,43 +1211,7 @@ pa_source *pa_alsa_source_new(pa_module *m, pa_modargs *ma, const char*driver, p
 | 
				
			||||||
    /* ALSA might tweak the sample spec, so recalculate the frame size */
 | 
					    /* ALSA might tweak the sample spec, so recalculate the frame size */
 | 
				
			||||||
    frame_size = pa_frame_size(&ss);
 | 
					    frame_size = pa_frame_size(&ss);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if ((err = snd_mixer_open(&u->mixer_handle, 0)) < 0)
 | 
					    pa_alsa_find_mixer_and_elem(u->pcm_handle, &u->mixer_handle, &u->mixer_elem);
 | 
				
			||||||
        pa_log("Error opening mixer: %s", snd_strerror(err));
 | 
					 | 
				
			||||||
    else {
 | 
					 | 
				
			||||||
        pa_bool_t found = FALSE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (pa_alsa_prepare_mixer(u->mixer_handle, u->device_name) >= 0)
 | 
					 | 
				
			||||||
            found = TRUE;
 | 
					 | 
				
			||||||
        else {
 | 
					 | 
				
			||||||
            snd_pcm_info_t* info;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            snd_pcm_info_alloca(&info);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (snd_pcm_info(u->pcm_handle, info) >= 0) {
 | 
					 | 
				
			||||||
                char *md;
 | 
					 | 
				
			||||||
                int card_idx;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if ((card_idx = snd_pcm_info_get_card(info)) >= 0) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    md = pa_sprintf_malloc("hw:%i", card_idx);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    if (strcmp(u->device_name, md))
 | 
					 | 
				
			||||||
                        if (pa_alsa_prepare_mixer(u->mixer_handle, md) >= 0)
 | 
					 | 
				
			||||||
                            found = TRUE;
 | 
					 | 
				
			||||||
                    pa_xfree(md);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (found)
 | 
					 | 
				
			||||||
            if (!(u->mixer_elem = pa_alsa_find_elem(u->mixer_handle, "Capture", "Mic", FALSE)))
 | 
					 | 
				
			||||||
                found = FALSE;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (!found) {
 | 
					 | 
				
			||||||
            snd_mixer_close(u->mixer_handle);
 | 
					 | 
				
			||||||
            u->mixer_handle = NULL;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_source_new_data_init(&data);
 | 
					    pa_source_new_data_init(&data);
 | 
				
			||||||
    data.driver = driver;
 | 
					    data.driver = driver;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1057,6 +1057,86 @@ success:
 | 
				
			||||||
    return elem;
 | 
					    return elem;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int pa_alsa_find_mixer_and_elem(
 | 
				
			||||||
 | 
					        snd_pcm_t *pcm,
 | 
				
			||||||
 | 
					        snd_mixer_t **_m,
 | 
				
			||||||
 | 
					        snd_mixer_elem_t **_e) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int err;
 | 
				
			||||||
 | 
					    snd_mixer_t *m;
 | 
				
			||||||
 | 
					    snd_mixer_elem_t *e;
 | 
				
			||||||
 | 
					    pa_bool_t found = FALSE;
 | 
				
			||||||
 | 
					    const char *dev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pa_assert(pcm);
 | 
				
			||||||
 | 
					    pa_assert(_m);
 | 
				
			||||||
 | 
					    pa_assert(_e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((err = snd_mixer_open(&m, 0)) < 0) {
 | 
				
			||||||
 | 
					        pa_log("Error opening mixer: %s", snd_strerror(err));
 | 
				
			||||||
 | 
					        return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* First, try by name */
 | 
				
			||||||
 | 
					    if ((dev = snd_pcm_name(pcm)))
 | 
				
			||||||
 | 
					        if (pa_alsa_prepare_mixer(m, dev) >= 0)
 | 
				
			||||||
 | 
					            found = TRUE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Then, try by card index */
 | 
				
			||||||
 | 
					    if (!found) {
 | 
				
			||||||
 | 
					        snd_pcm_info_t* info;
 | 
				
			||||||
 | 
					        snd_pcm_info_alloca(&info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (snd_pcm_info(pcm, info) >= 0) {
 | 
				
			||||||
 | 
					            char *md;
 | 
				
			||||||
 | 
					            int card_idx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if ((card_idx = snd_pcm_info_get_card(info)) >= 0) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                md = pa_sprintf_malloc("hw:%i", card_idx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (!dev || !pa_streq(dev, md))
 | 
				
			||||||
 | 
					                    if (pa_alsa_prepare_mixer(m, md) >= 0)
 | 
				
			||||||
 | 
					                        found = TRUE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                pa_xfree(md);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!found) {
 | 
				
			||||||
 | 
					        snd_mixer_close(m);
 | 
				
			||||||
 | 
					        return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    switch (snd_pcm_stream(pcm)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case SND_PCM_STREAM_PLAYBACK:
 | 
				
			||||||
 | 
					            e = pa_alsa_find_elem(m, "Master", "PCM", TRUE);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        case SND_PCM_STREAM_CAPTURE:
 | 
				
			||||||
 | 
					            e = pa_alsa_find_elem(m, "Capture", "Mic", FALSE);
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            pa_assert_not_reached();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!e) {
 | 
				
			||||||
 | 
					        snd_mixer_close(m);
 | 
				
			||||||
 | 
					        return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pa_assert(e && m);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    *_m = m;
 | 
				
			||||||
 | 
					    *_e = e;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const snd_mixer_selem_channel_id_t alsa_channel_ids[PA_CHANNEL_POSITION_MAX] = {
 | 
					static const snd_mixer_selem_channel_id_t alsa_channel_ids[PA_CHANNEL_POSITION_MAX] = {
 | 
				
			||||||
    [PA_CHANNEL_POSITION_MONO] = SND_MIXER_SCHN_MONO, /* The ALSA name is just an alias! */
 | 
					    [PA_CHANNEL_POSITION_MONO] = SND_MIXER_SCHN_MONO, /* The ALSA name is just an alias! */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -54,6 +54,7 @@ int pa_alsa_set_sw_params(snd_pcm_t *pcm, snd_pcm_uframes_t avail_min);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev);
 | 
					int pa_alsa_prepare_mixer(snd_mixer_t *mixer, const char *dev);
 | 
				
			||||||
snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name, const char *fallback, pa_bool_t playback);
 | 
					snd_mixer_elem_t *pa_alsa_find_elem(snd_mixer_t *mixer, const char *name, const char *fallback, pa_bool_t playback);
 | 
				
			||||||
 | 
					int pa_alsa_find_mixer_and_elem(snd_pcm_t *pcm, snd_mixer_t **_m, snd_mixer_elem_t **_e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct pa_alsa_profile_info {
 | 
					typedef struct pa_alsa_profile_info {
 | 
				
			||||||
    pa_channel_map map;
 | 
					    pa_channel_map map;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue