mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-31 22:25:33 -04:00
alsa-mixer: add required-any and required-* for enum options
Now you can add required-any to elements in a path and the path will be valid as long as at least one of the elements are present. Also you can have required, required-any and required-absent in element options, causing a path to be unsupported if an option is (not) present (simplified example: to skip line in path if "Capture source" doesn't have a "Line In" option). Signed-off-by: David Henningsson <david.henningsson@canonical.com>
This commit is contained in:
parent
0ce3017b74
commit
b0f72311cf
3 changed files with 91 additions and 12 deletions
|
|
@ -1121,6 +1121,41 @@ static int check_required(pa_alsa_element *e, snd_mixer_elem_t *me) {
|
|||
if (e->required_absent == PA_ALSA_REQUIRED_ANY && (has_switch || has_volume || has_enumeration))
|
||||
return -1;
|
||||
|
||||
if (e->required_any != PA_ALSA_REQUIRED_IGNORE) {
|
||||
switch (e->required_any) {
|
||||
case PA_ALSA_REQUIRED_VOLUME:
|
||||
e->path->req_any_present |= (e->volume_use != PA_ALSA_VOLUME_IGNORE);
|
||||
break;
|
||||
case PA_ALSA_REQUIRED_SWITCH:
|
||||
e->path->req_any_present |= (e->switch_use != PA_ALSA_SWITCH_IGNORE);
|
||||
break;
|
||||
case PA_ALSA_REQUIRED_ENUMERATION:
|
||||
e->path->req_any_present |= (e->enumeration_use != PA_ALSA_ENUMERATION_IGNORE);
|
||||
break;
|
||||
case PA_ALSA_REQUIRED_ANY:
|
||||
e->path->req_any_present |=
|
||||
(e->volume_use != PA_ALSA_VOLUME_IGNORE) ||
|
||||
(e->switch_use != PA_ALSA_SWITCH_IGNORE) ||
|
||||
(e->enumeration_use != PA_ALSA_ENUMERATION_IGNORE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (e->enumeration_use == PA_ALSA_ENUMERATION_SELECT) {
|
||||
pa_alsa_option *o;
|
||||
PA_LLIST_FOREACH(o, e->options) {
|
||||
e->path->req_any_present |= (o->required_any != PA_ALSA_REQUIRED_IGNORE) &&
|
||||
(o->alsa_idx >= 0);
|
||||
if (o->required != PA_ALSA_REQUIRED_IGNORE && o->alsa_idx < 0)
|
||||
return -1;
|
||||
if (o->required_absent != PA_ALSA_REQUIRED_IGNORE && o->alsa_idx >= 0)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (check_required(e, me) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1293,9 +1328,6 @@ static int element_probe(pa_alsa_element *e, snd_mixer_t *m) {
|
|||
|
||||
}
|
||||
|
||||
if (check_required(e, me) < 0)
|
||||
return -1;
|
||||
|
||||
if (e->switch_use == PA_ALSA_SWITCH_SELECT) {
|
||||
pa_alsa_option *o;
|
||||
|
||||
|
|
@ -1581,20 +1613,23 @@ static int element_parse_required(
|
|||
|
||||
pa_alsa_path *p = userdata;
|
||||
pa_alsa_element *e;
|
||||
pa_alsa_option *o;
|
||||
pa_alsa_required_t req;
|
||||
|
||||
pa_assert(p);
|
||||
|
||||
if (!(e = element_get(p, section, TRUE))) {
|
||||
e = element_get(p, section, TRUE);
|
||||
o = option_get(p, section);
|
||||
if (!e && !o) {
|
||||
pa_log("[%s:%u] Required makes no sense in '%s'", filename, line, section);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pa_streq(rvalue, "ignore"))
|
||||
req = PA_ALSA_REQUIRED_IGNORE;
|
||||
else if (pa_streq(rvalue, "switch"))
|
||||
else if (pa_streq(rvalue, "switch") && e)
|
||||
req = PA_ALSA_REQUIRED_SWITCH;
|
||||
else if (pa_streq(rvalue, "volume"))
|
||||
else if (pa_streq(rvalue, "volume") && e)
|
||||
req = PA_ALSA_REQUIRED_VOLUME;
|
||||
else if (pa_streq(rvalue, "enumeration"))
|
||||
req = PA_ALSA_REQUIRED_ENUMERATION;
|
||||
|
|
@ -1605,10 +1640,28 @@ static int element_parse_required(
|
|||
return -1;
|
||||
}
|
||||
|
||||
if (pa_streq(lvalue, "required-absent"))
|
||||
e->required_absent = req;
|
||||
else
|
||||
e->required = req;
|
||||
if (pa_streq(lvalue, "required-absent")) {
|
||||
if (e)
|
||||
e->required_absent = req;
|
||||
if (o)
|
||||
o->required_absent = req;
|
||||
}
|
||||
else if (pa_streq(lvalue, "required-any")) {
|
||||
if (e) {
|
||||
e->required_any = req;
|
||||
e->path->has_req_any = TRUE;
|
||||
}
|
||||
if (o) {
|
||||
o->required_any = req;
|
||||
o->element->path->has_req_any = TRUE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (e)
|
||||
e->required = req;
|
||||
if (o)
|
||||
o->required = req;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -1860,7 +1913,10 @@ static int element_verify(pa_alsa_element *e) {
|
|||
|
||||
pa_assert(e);
|
||||
|
||||
// pa_log_debug("Element %s, path %s: r=%d, r-any=%d, r-abs=%d", e->alsa_name, e->path->name, e->required, e->required_any, e->required_absent);
|
||||
if ((e->required != PA_ALSA_REQUIRED_IGNORE && e->required == e->required_absent) ||
|
||||
(e->required_any != PA_ALSA_REQUIRED_IGNORE && e->required_any == e->required_absent) ||
|
||||
(e->required_absent == PA_ALSA_REQUIRED_ANY && e->required_any != PA_ALSA_REQUIRED_IGNORE) ||
|
||||
(e->required_absent == PA_ALSA_REQUIRED_ANY && e->required != PA_ALSA_REQUIRED_IGNORE)) {
|
||||
pa_log("Element %s cannot be required and absent at the same time.", e->alsa_name);
|
||||
return -1;
|
||||
|
|
@ -1941,6 +1997,7 @@ pa_alsa_path* pa_alsa_path_new(const char *fname, pa_alsa_direction_t direction)
|
|||
{ "override-map.2", element_parse_override_map, NULL, NULL },
|
||||
/* ... later on we might add override-map.3 and so on here ... */
|
||||
{ "required", element_parse_required, NULL, NULL },
|
||||
{ "required-any", element_parse_required, NULL, NULL },
|
||||
{ "required-absent", element_parse_required, NULL, NULL },
|
||||
{ "direction", element_parse_direction, NULL, NULL },
|
||||
{ "direction-try-other", element_parse_direction_try_other, NULL, NULL },
|
||||
|
|
@ -2185,11 +2242,13 @@ int pa_alsa_path_probe(pa_alsa_path *p, snd_mixer_t *m, pa_bool_t ignore_dB) {
|
|||
min_dB[t] += e->min_dB;
|
||||
max_dB[t] += e->max_dB;
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
/* Hmm, there's another element before us
|
||||
* which cannot do dB volumes, so we we need
|
||||
* to 'neutralize' this slider */
|
||||
e->volume_use = PA_ALSA_VOLUME_ZERO;
|
||||
pa_log_info("Zeroing volume of '%s' on path '%s'", e->alsa_name, p->name);
|
||||
}
|
||||
}
|
||||
} else if (p->has_volume)
|
||||
/* We can't use this volume, so let's ignore it */
|
||||
|
|
@ -2202,6 +2261,12 @@ int pa_alsa_path_probe(pa_alsa_path *p, snd_mixer_t *m, pa_bool_t ignore_dB) {
|
|||
p->has_mute = TRUE;
|
||||
}
|
||||
|
||||
if (p->has_req_any && !p->req_any_present) {
|
||||
p->supported = FALSE;
|
||||
pa_log_debug("Skipping path '%s', none of required-any elements preset.", p->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
path_drop_unsupported(p);
|
||||
path_make_options_unique(p);
|
||||
path_create_settings(p);
|
||||
|
|
@ -2247,13 +2312,14 @@ void pa_alsa_element_dump(pa_alsa_element *e) {
|
|||
pa_alsa_option *o;
|
||||
pa_assert(e);
|
||||
|
||||
pa_log_debug("Element %s, direction=%i, switch=%i, volume=%i, enumeration=%i, required=%i, required_absent=%i, mask=0x%llx, n_channels=%u, override_map=%s",
|
||||
pa_log_debug("Element %s, direction=%i, switch=%i, volume=%i, enumeration=%i, required=%i, required_any=%i, required_absent=%i, mask=0x%llx, n_channels=%u, override_map=%s",
|
||||
e->alsa_name,
|
||||
e->direction,
|
||||
e->switch_use,
|
||||
e->volume_use,
|
||||
e->enumeration_use,
|
||||
e->required,
|
||||
e->required_any,
|
||||
e->required_absent,
|
||||
(long long unsigned) e->merged_mask,
|
||||
e->n_channels,
|
||||
|
|
|
|||
|
|
@ -112,6 +112,10 @@ struct pa_alsa_option {
|
|||
char *name;
|
||||
char *description;
|
||||
unsigned priority;
|
||||
|
||||
pa_alsa_required_t required;
|
||||
pa_alsa_required_t required_any;
|
||||
pa_alsa_required_t required_absent;
|
||||
};
|
||||
|
||||
/* And element wraps one specific ALSA element. A series of elements *
|
||||
|
|
@ -129,6 +133,7 @@ struct pa_alsa_element {
|
|||
pa_alsa_enumeration_use_t enumeration_use;
|
||||
|
||||
pa_alsa_required_t required;
|
||||
pa_alsa_required_t required_any;
|
||||
pa_alsa_required_t required_absent;
|
||||
|
||||
pa_bool_t override_map:1;
|
||||
|
|
@ -164,6 +169,9 @@ struct pa_alsa_path {
|
|||
pa_bool_t has_mute:1;
|
||||
pa_bool_t has_volume:1;
|
||||
pa_bool_t has_dB:1;
|
||||
/* These two are used during probing only */
|
||||
pa_bool_t has_req_any:1;
|
||||
pa_bool_t req_any_present:1;
|
||||
|
||||
long min_volume, max_volume;
|
||||
double min_dB, max_dB;
|
||||
|
|
|
|||
|
|
@ -63,10 +63,15 @@
|
|||
; # by the option name, resp. on/off if the element is a switch.
|
||||
; name = ... # Logical name to use in the path identifier
|
||||
; priority = ... # Priority if this is made into a device port
|
||||
; required = ignore | enumeration | any # In this element, this option must exist or the path will be invalid. ("any" is an alias for "enumeration".)
|
||||
; required-any = ignore | enumeration | any # In this element, either this or another option must exist (or an element)
|
||||
; required-absent = ignore | enumeration | any # In this element, this option must not exist or the path will be invalid
|
||||
;
|
||||
; [Element ...] # For each element that we shall control
|
||||
; required = ignore | switch | volume | enumeration | any # If set, require this element to be of this kind and available,
|
||||
; # otherwise don't consider this path valid for the card
|
||||
; required-any = ignore | switch | volume | enumeration | any # If set, at least one of the elements with required-any in this
|
||||
; # path must be present, otherwise this path is invalid for the card
|
||||
; required-absent = ignore | switch | volume # If set, require this element to not be of this kind and not
|
||||
; # available, otherwise don't consider this path valid for the card
|
||||
;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue