diff options
Diffstat (limited to 'src/modules/alsa/module-alsa-card.c')
-rw-r--r-- | src/modules/alsa/module-alsa-card.c | 79 |
1 files changed, 74 insertions, 5 deletions
diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c index 08e655e..0fe8893 100644 --- a/src/modules/alsa/module-alsa-card.c +++ b/src/modules/alsa/module-alsa-card.c @@ -104,6 +104,15 @@ static const char* const valid_modargs[] = { #define DEFAULT_DEVICE_ID "0" +#define PULSE_MODARGS "PULSE_MODARGS" + +/* dynamic profile priority bonus, for all alsa profiles, the original priority + needs to be less than 0x7fff (32767), then could apply the rule of priority + bonus. So far there are 2 kinds of alsa profiles, one is from alsa ucm, the + other is from mixer profile-sets, their priorities are all far less than 0x7fff +*/ +#define PROFILE_PRIO_BONUS 0x8000 + struct userdata { pa_core *core; pa_module *module; @@ -459,9 +468,19 @@ static int report_jack_state(snd_mixer_elem_t *melem, unsigned int mask) { * as available (well, "unknown" to be precise, but there's little * practical difference). * - * When all output ports are unavailable, we know that all sinks are - * unavailable, and therefore the profile is marked unavailable as well. - * The same applies to input ports as well, of course. + * A profile will be marked unavailable: + * only contains output ports and all ports are unavailable + * only contains input ports and all ports are unavailable + * contains both input and output ports and all ports are unavailable + * + * A profile will be awarded priority bonus: + * only contains output ports and at least one port is available + * only contains input ports and at least one port is available + * contains both output and input ports and at least one output port + * and one input port are available + * + * The rest profiles will not be marked unavailable and will not be + * awarded priority bonus * * If there are no output ports at all, but the profile contains at least * one sink, then the output is considered to be available. */ @@ -476,6 +495,7 @@ static int report_jack_state(snd_mixer_elem_t *melem, unsigned int mask) { bool found_available_output_port = false; pa_available_t available = PA_AVAILABLE_UNKNOWN; + profile->priority &= ~PROFILE_PRIO_BONUS; PA_HASHMAP_FOREACH(port, u->card->ports, state2) { if (!pa_hashmap_get(port->profiles, profile->name)) continue; @@ -493,8 +513,15 @@ static int report_jack_state(snd_mixer_elem_t *melem, unsigned int mask) { } } - if ((has_input_port && !found_available_input_port) || (has_output_port && !found_available_output_port)) - available = PA_AVAILABLE_NO; + if ((has_input_port && found_available_input_port && !has_output_port) || + (has_output_port && found_available_output_port && !has_input_port) || + (has_input_port && found_available_input_port && has_output_port && found_available_output_port)) + profile->priority |= PROFILE_PRIO_BONUS; + + if ((has_input_port && !found_available_input_port && has_output_port && !found_available_output_port) || + (has_input_port && !found_available_input_port && !has_output_port) || + (has_output_port && !found_available_output_port && !has_input_port)) + available = PA_AVAILABLE_NO; /* We want to update the active profile's status last, so logic that * may change the active profile based on profile availability status @@ -822,6 +849,7 @@ int pa__init(pa_module *m) { const char *description; const char *profile_str = NULL; char *fn = NULL; + char *udev_args = NULL; bool namereg_fail = false; int err = -PA_MODULE_ERR_UNSPECIFIED, rval; @@ -851,6 +879,47 @@ int pa__init(pa_module *m) { goto fail; } +#ifdef HAVE_UDEV + udev_args = pa_udev_get_property(u->alsa_card_index, PULSE_MODARGS); +#endif + + if (udev_args) { + bool udev_modargs_success = true; + pa_modargs *temp_ma = pa_modargs_new(udev_args, valid_modargs); + + if (temp_ma) { + /* do not try to replace device_id */ + + if (pa_modargs_remove_key(temp_ma, "device_id") == 0) { + pa_log_warn("Unexpected 'device_id' module argument override ignored from udev " PULSE_MODARGS "='%s'", udev_args); + } + + /* Implement modargs override by copying original module arguments + * over udev entry arguments ignoring duplicates. */ + + if (pa_modargs_merge_missing(temp_ma, u->modargs, valid_modargs) == 0) { + /* swap module arguments */ + pa_modargs *old_ma = u->modargs; + u->modargs = temp_ma; + temp_ma = old_ma; + + pa_log_info("Applied module arguments override from udev " PULSE_MODARGS "='%s'", udev_args); + } else { + pa_log("Failed to apply module arguments override from udev " PULSE_MODARGS "='%s'", udev_args); + udev_modargs_success = false; + } + + pa_modargs_free(temp_ma); + } else { + pa_log("Failed to parse module arguments from udev " PULSE_MODARGS "='%s'", udev_args); + udev_modargs_success = false; + } + pa_xfree(udev_args); + + if (!udev_modargs_success) + goto fail; + } + if (pa_modargs_get_value_boolean(u->modargs, "ignore_dB", &ignore_dB) < 0) { pa_log("Failed to parse ignore_dB argument."); goto fail; |