[pulseaudio-discuss] [RFC PATCH 2/3] alsa: Allow "fallback" configuration for mappings and profiles
David Henningsson
david.henningsson at canonical.com
Fri Jul 25 06:31:12 PDT 2014
A fallback mapping or profile will only be considered for probing
if all non-fallback profiles fail.
If auto-profiles are used, a profile made up of one non-fallback
mapping and one fallback mapping will be considered a fallback profile.
Signed-off-by: David Henningsson <david.henningsson at canonical.com>
---
src/modules/alsa/alsa-mixer.c | 45 ++++++++++++++++++++++++
src/modules/alsa/alsa-mixer.h | 2 ++
src/modules/alsa/mixer/profile-sets/default.conf | 2 ++
3 files changed, 49 insertions(+)
diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
index 014499b..57d56c0 100644
--- a/src/modules/alsa/alsa-mixer.c
+++ b/src/modules/alsa/alsa-mixer.c
@@ -3611,6 +3611,36 @@ static int mapping_parse_priority(pa_config_parser_state *state) {
return 0;
}
+static int mapping_parse_fallback(pa_config_parser_state *state) {
+ pa_alsa_profile_set *ps;
+ pa_alsa_profile *p;
+ pa_alsa_mapping *m;
+ int k;
+ bool fallback;
+
+ pa_assert(state);
+
+ ps = state->userdata;
+
+ if ((k = pa_parse_boolean(state->rvalue)) < 0) {
+ pa_log("[%s:%u] Fallback invalid of '%s'", state->filename, state->lineno, state->section);
+ return -1;
+ }
+ fallback = !!k;
+
+ if ((m = pa_alsa_mapping_get(ps, state->section)))
+ m->fallback = fallback;
+ else if ((p = profile_get(ps, state->section)))
+ p->fallback = fallback;
+ else {
+ pa_log("[%s:%u] Section name %s invalid.", state->filename, state->lineno, state->section);
+ return -1;
+ }
+
+ return 0;
+}
+
+
static int profile_parse_mappings(pa_config_parser_state *state) {
pa_alsa_profile_set *ps;
pa_alsa_profile *p;
@@ -3939,12 +3969,14 @@ static void profile_set_add_auto_pair(
p->output_mappings = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
pa_idxset_put(p->output_mappings, m, NULL);
p->priority += m->priority * 100;
+ p->fallback = m->fallback;
}
if (n) {
p->input_mappings = pa_idxset_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
pa_idxset_put(p->input_mappings, n, NULL);
p->priority += n->priority;
+ p->fallback |= n->fallback;
}
pa_hashmap_put(ps->profiles, p->name, p);
@@ -4186,6 +4218,7 @@ pa_alsa_profile_set* pa_alsa_profile_set_new(const char *fname, const pa_channel
/* Shared by [Mapping ...] and [Profile ...] */
{ "description", mapping_parse_description, NULL, NULL },
{ "priority", mapping_parse_priority, NULL, NULL },
+ { "fallback", mapping_parse_fallback, NULL, NULL },
/* [Profile ...] */
{ "input-mappings", profile_parse_mappings, NULL, NULL },
@@ -4337,6 +4370,8 @@ void pa_alsa_profile_set_probe(
unsigned default_fragment_size_msec) {
void *state;
+ bool tryfallback = false;
+ int profilesfound = 0;
pa_alsa_profile *p, *last = NULL;
pa_alsa_mapping *m;
pa_hashmap *broken_inputs, *broken_outputs, *used_paths;
@@ -4352,9 +4387,13 @@ void pa_alsa_profile_set_probe(
broken_outputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
used_paths = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
+again:
PA_HASHMAP_FOREACH(p, ps->profiles, state) {
uint32_t idx;
+ if (p->fallback != tryfallback)
+ continue;
+
/* Skip if this is already marked that it is supported (i.e. from the config file) */
if (!p->supported) {
@@ -4434,6 +4473,7 @@ void pa_alsa_profile_set_probe(
}
pa_log_debug("Profile %s supported.", p->name);
+ profilesfound++;
if (p->output_mappings)
PA_IDXSET_FOREACH(m, p->output_mappings, idx)
@@ -4446,6 +4486,11 @@ void pa_alsa_profile_set_probe(
mapping_paths_probe(m, p, PA_ALSA_DIRECTION_INPUT, used_paths);
}
+ if (!tryfallback && (profilesfound == 0)) {
+ tryfallback = true;
+ goto again;
+ }
+
/* Clean up */
profile_finalize_probing(last, NULL);
diff --git a/src/modules/alsa/alsa-mixer.h b/src/modules/alsa/alsa-mixer.h
index d04c2bb..f394743 100644
--- a/src/modules/alsa/alsa-mixer.h
+++ b/src/modules/alsa/alsa-mixer.h
@@ -265,6 +265,7 @@ struct pa_alsa_mapping {
unsigned supported;
bool exact_channels:1;
+ bool fallback:1;
/* Temporarily used during probing */
snd_pcm_t *input_pcm;
@@ -285,6 +286,7 @@ struct pa_alsa_profile {
unsigned priority;
bool supported:1;
+ bool fallback:1;
char **input_mapping_names;
char **output_mapping_names;
diff --git a/src/modules/alsa/mixer/profile-sets/default.conf b/src/modules/alsa/mixer/profile-sets/default.conf
index 77a4d76..a481efa 100644
--- a/src/modules/alsa/mixer/profile-sets/default.conf
+++ b/src/modules/alsa/mixer/profile-sets/default.conf
@@ -57,6 +57,7 @@
;
; exact-channels = yes | no # If no, and the exact number of channels is not supported,
; # allow device to be opened with another channel count
+; fallback = no | yes # This mapping will only be considered if all non-fallback mappings fail
; [Profile id]
; input-mappings = ... # Lists mappings for sources on this profile, those mapping must be
; # defined in this file too
@@ -68,6 +69,7 @@
; # will be assumed as working without probing. Makes initialization
; # a bit faster but only works if the card is really known well.
;
+; fallback = no | yes # This mapping will only be considered if all non-fallback profiles fail
; [DecibelFix element] # Decibel fixes can be used to work around missing or incorrect dB
; # information from alsa. A decibel fix is a table that maps volume steps
; # to decibel values for one volume element. The "element" part in the
--
1.9.1
More information about the pulseaudio-discuss
mailing list