mirror of
				https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
				synced 2025-11-03 09:01:50 -05:00 
			
		
		
		
	alsa: Add "exact-channels" mapping configurability
Allow a mapping to relax the exact channel restriction:
exact-channels = yes | no # If no, and the exact number of channels is not supported,
                          # allow device to be opened with another channel count
Signed-off-by: David Henningsson <david.henningsson@canonical.com>
			
			
This commit is contained in:
		
							parent
							
								
									afbe9605c6
								
							
						
					
					
						commit
						be8311417c
					
				
					 3 changed files with 42 additions and 4 deletions
				
			
		| 
						 | 
					@ -3368,6 +3368,7 @@ pa_alsa_mapping *pa_alsa_mapping_get(pa_alsa_profile_set *ps, const char *name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    m = pa_xnew0(pa_alsa_mapping, 1);
 | 
					    m = pa_xnew0(pa_alsa_mapping, 1);
 | 
				
			||||||
    m->profile_set = ps;
 | 
					    m->profile_set = ps;
 | 
				
			||||||
 | 
					    m->exact_channels = true;
 | 
				
			||||||
    m->name = pa_xstrdup(name);
 | 
					    m->name = pa_xstrdup(name);
 | 
				
			||||||
    pa_sample_spec_init(&m->sample_spec);
 | 
					    pa_sample_spec_init(&m->sample_spec);
 | 
				
			||||||
    pa_channel_map_init(&m->channel_map);
 | 
					    pa_channel_map_init(&m->channel_map);
 | 
				
			||||||
| 
						 | 
					@ -3485,6 +3486,30 @@ static int mapping_parse_paths(pa_config_parser_state *state) {
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int mapping_parse_exact_channels(pa_config_parser_state *state) {
 | 
				
			||||||
 | 
					    pa_alsa_profile_set *ps;
 | 
				
			||||||
 | 
					    pa_alsa_mapping *m;
 | 
				
			||||||
 | 
					    int b;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pa_assert(state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ps = state->userdata;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!(m = pa_alsa_mapping_get(ps, state->section))) {
 | 
				
			||||||
 | 
					        pa_log("[%s:%u] %s invalid in section %s", state->filename, state->lineno, state->lvalue, state->section);
 | 
				
			||||||
 | 
					        return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if ((b = pa_parse_boolean(state->rvalue)) < 0) {
 | 
				
			||||||
 | 
					        pa_log("[%s:%u] %s has invalid value '%s'", state->filename, state->lineno, state->lvalue, state->section);
 | 
				
			||||||
 | 
					        return -1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    m->exact_channels = b;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int mapping_parse_element(pa_config_parser_state *state) {
 | 
					static int mapping_parse_element(pa_config_parser_state *state) {
 | 
				
			||||||
    pa_alsa_profile_set *ps;
 | 
					    pa_alsa_profile_set *ps;
 | 
				
			||||||
    pa_alsa_mapping *m;
 | 
					    pa_alsa_mapping *m;
 | 
				
			||||||
| 
						 | 
					@ -4156,6 +4181,7 @@ pa_alsa_profile_set* pa_alsa_profile_set_new(const char *fname, const pa_channel
 | 
				
			||||||
        { "element-input",          mapping_parse_element,        NULL, NULL },
 | 
					        { "element-input",          mapping_parse_element,        NULL, NULL },
 | 
				
			||||||
        { "element-output",         mapping_parse_element,        NULL, NULL },
 | 
					        { "element-output",         mapping_parse_element,        NULL, NULL },
 | 
				
			||||||
        { "direction",              mapping_parse_direction,      NULL, NULL },
 | 
					        { "direction",              mapping_parse_direction,      NULL, NULL },
 | 
				
			||||||
 | 
					        { "exact-channels",         mapping_parse_exact_channels, NULL, NULL },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Shared by [Mapping ...] and [Profile ...] */
 | 
					        /* Shared by [Mapping ...] and [Profile ...] */
 | 
				
			||||||
        { "description",            mapping_parse_description,    NULL, NULL },
 | 
					        { "description",            mapping_parse_description,    NULL, NULL },
 | 
				
			||||||
| 
						 | 
					@ -4264,10 +4290,12 @@ static void profile_finalize_probing(pa_alsa_profile *to_be_finalized, pa_alsa_p
 | 
				
			||||||
static snd_pcm_t* mapping_open_pcm(pa_alsa_mapping *m,
 | 
					static snd_pcm_t* mapping_open_pcm(pa_alsa_mapping *m,
 | 
				
			||||||
                                   const pa_sample_spec *ss,
 | 
					                                   const pa_sample_spec *ss,
 | 
				
			||||||
                                   const char *dev_id,
 | 
					                                   const char *dev_id,
 | 
				
			||||||
 | 
					                                   bool exact_channels,
 | 
				
			||||||
                                   int mode,
 | 
					                                   int mode,
 | 
				
			||||||
                                   unsigned default_n_fragments,
 | 
					                                   unsigned default_n_fragments,
 | 
				
			||||||
                                   unsigned default_fragment_size_msec) {
 | 
					                                   unsigned default_fragment_size_msec) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    snd_pcm_t* handle;
 | 
				
			||||||
    pa_sample_spec try_ss = *ss;
 | 
					    pa_sample_spec try_ss = *ss;
 | 
				
			||||||
    pa_channel_map try_map = m->channel_map;
 | 
					    pa_channel_map try_map = m->channel_map;
 | 
				
			||||||
    snd_pcm_uframes_t try_period_size, try_buffer_size;
 | 
					    snd_pcm_uframes_t try_period_size, try_buffer_size;
 | 
				
			||||||
| 
						 | 
					@ -4279,10 +4307,17 @@ static snd_pcm_t* mapping_open_pcm(pa_alsa_mapping *m,
 | 
				
			||||||
        pa_frame_size(&try_ss);
 | 
					        pa_frame_size(&try_ss);
 | 
				
			||||||
    try_buffer_size = default_n_fragments * try_period_size;
 | 
					    try_buffer_size = default_n_fragments * try_period_size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return pa_alsa_open_by_template(
 | 
					    handle = pa_alsa_open_by_template(
 | 
				
			||||||
                              m->device_strings, dev_id, NULL, &try_ss,
 | 
					                              m->device_strings, dev_id, NULL, &try_ss,
 | 
				
			||||||
                              &try_map, mode, &try_period_size,
 | 
					                              &try_map, mode, &try_period_size,
 | 
				
			||||||
                              &try_buffer_size, 0, NULL, NULL, true);
 | 
					                              &try_buffer_size, 0, NULL, NULL, exact_channels);
 | 
				
			||||||
 | 
					    if (handle && !exact_channels && m->channel_map.channels != try_map.channels) {
 | 
				
			||||||
 | 
					        char buf[PA_CHANNEL_MAP_SNPRINT_MAX];
 | 
				
			||||||
 | 
					        pa_log_debug("Channel map for mapping '%s' permanently changed to '%s'", m->name,
 | 
				
			||||||
 | 
					                     pa_channel_map_snprint(buf, sizeof(buf), &try_map));
 | 
				
			||||||
 | 
					        m->channel_map = try_map;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return handle;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void paths_drop_unused(pa_hashmap* h, pa_hashmap *keep) {
 | 
					static void paths_drop_unused(pa_hashmap* h, pa_hashmap *keep) {
 | 
				
			||||||
| 
						 | 
					@ -4365,7 +4400,7 @@ void pa_alsa_profile_set_probe(
 | 
				
			||||||
                        continue;
 | 
					                        continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    pa_log_debug("Checking for playback on %s (%s)", m->description, m->name);
 | 
					                    pa_log_debug("Checking for playback on %s (%s)", m->description, m->name);
 | 
				
			||||||
                    if (!(m->output_pcm = mapping_open_pcm(m, ss, dev_id,
 | 
					                    if (!(m->output_pcm = mapping_open_pcm(m, ss, dev_id, m->exact_channels,
 | 
				
			||||||
                                                           SND_PCM_STREAM_PLAYBACK,
 | 
					                                                           SND_PCM_STREAM_PLAYBACK,
 | 
				
			||||||
                                                           default_n_fragments,
 | 
					                                                           default_n_fragments,
 | 
				
			||||||
                                                           default_fragment_size_msec))) {
 | 
					                                                           default_fragment_size_msec))) {
 | 
				
			||||||
| 
						 | 
					@ -4386,7 +4421,7 @@ void pa_alsa_profile_set_probe(
 | 
				
			||||||
                        continue;
 | 
					                        continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    pa_log_debug("Checking for recording on %s (%s)", m->description, m->name);
 | 
					                    pa_log_debug("Checking for recording on %s (%s)", m->description, m->name);
 | 
				
			||||||
                    if (!(m->input_pcm = mapping_open_pcm(m, ss, dev_id,
 | 
					                    if (!(m->input_pcm = mapping_open_pcm(m, ss, dev_id, m->exact_channels,
 | 
				
			||||||
                                                          SND_PCM_STREAM_CAPTURE,
 | 
					                                                          SND_PCM_STREAM_CAPTURE,
 | 
				
			||||||
                                                          default_n_fragments,
 | 
					                                                          default_n_fragments,
 | 
				
			||||||
                                                          default_fragment_size_msec))) {
 | 
					                                                          default_fragment_size_msec))) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -264,6 +264,7 @@ struct pa_alsa_mapping {
 | 
				
			||||||
    pa_alsa_path_set *output_path_set;
 | 
					    pa_alsa_path_set *output_path_set;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    unsigned supported;
 | 
					    unsigned supported;
 | 
				
			||||||
 | 
					    bool exact_channels:1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Temporarily used during probing */
 | 
					    /* Temporarily used during probing */
 | 
				
			||||||
    snd_pcm_t *input_pcm;
 | 
					    snd_pcm_t *input_pcm;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -55,6 +55,8 @@
 | 
				
			||||||
; priority = ...
 | 
					; priority = ...
 | 
				
			||||||
; direction = any | input | output          # Only useful for?
 | 
					; direction = any | input | output          # Only useful for?
 | 
				
			||||||
;
 | 
					;
 | 
				
			||||||
 | 
					; exact-channels = yes | no                 # If no, and the exact number of channels is not supported,
 | 
				
			||||||
 | 
					;                                           # allow device to be opened with another channel count
 | 
				
			||||||
; [Profile id]
 | 
					; [Profile id]
 | 
				
			||||||
; input-mappings = ...                      # Lists mappings for sources on this profile, those mapping must be
 | 
					; input-mappings = ...                      # Lists mappings for sources on this profile, those mapping must be
 | 
				
			||||||
;                                           # defined in this file too
 | 
					;                                           # defined in this file too
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue