From d15b31d751d90274fee303a87a4c8493f1a118eb Mon Sep 17 00:00:00 2001 From: "Igor V. Kovalenko" Date: Sun, 13 Dec 2020 13:09:19 +0300 Subject: [PATCH] module-alsa-card: handle udev PULSE_MODARGS Allow adding module arguments using udev PULSE_MODARGS environment variable and fail module loading if there is a problem with PULSE_MODARGS This helps setting e.g. 'tsched=0' for specific devices without a need to create full load module entry in default.pa. Part-of: --- src/modules/alsa/module-alsa-card.c | 44 +++++++++++++++++++++++++++++ src/pulsecore/modargs.c | 26 +++++++++++++++++ src/pulsecore/modargs.h | 7 +++++ 3 files changed, 77 insertions(+) diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c index de2fe9cc4..f2f50382a 100644 --- a/src/modules/alsa/module-alsa-card.c +++ b/src/modules/alsa/module-alsa-card.c @@ -104,6 +104,8 @@ static const char* const valid_modargs[] = { #define DEFAULT_DEVICE_ID "0" +#define PULSE_MODARGS "PULSE_MODARGS" + struct userdata { pa_core *core; pa_module *module; @@ -820,6 +822,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; @@ -849,6 +852,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; diff --git a/src/pulsecore/modargs.c b/src/pulsecore/modargs.c index bce5891db..a707f6c8d 100644 --- a/src/pulsecore/modargs.c +++ b/src/pulsecore/modargs.c @@ -272,6 +272,15 @@ int pa_modargs_append(pa_modargs *ma, const char *args, const char* const* valid return parse(ma, args, valid_keys, true); } +int pa_modargs_remove_key(pa_modargs *ma, const char *key) { + if (pa_hashmap_remove_and_free(ma->unescaped, key) == 0) { + pa_hashmap_remove_and_free(ma->raw, key); + return 0; + } + + return -1; +} + void pa_modargs_free(pa_modargs*ma) { pa_assert(ma); @@ -544,3 +553,20 @@ const char *pa_modargs_iterate(pa_modargs *ma, void **state) { return e->key; } + +int pa_modargs_merge_missing(pa_modargs *dst, pa_modargs *src, const char* const valid_keys[]) { + void *state; + const char *key, *value; + int ret = 0; + + for (state = NULL, key = pa_modargs_iterate(src, &state); key; key = pa_modargs_iterate(src, &state)) { + value = pa_modargs_get_value(src, key, NULL); + if (value && add_key_value(dst, pa_xstrdup(key), pa_xstrdup(value), valid_keys, true) < 0) { + pa_log_warn("Failed to add module argument '%s=%s'", key, value); + ret = -1; + /* continue to gather all errors */ + } + } + + return ret; +} diff --git a/src/pulsecore/modargs.h b/src/pulsecore/modargs.h index 96132a3aa..abb16747d 100644 --- a/src/pulsecore/modargs.h +++ b/src/pulsecore/modargs.h @@ -95,4 +95,11 @@ int pa_modargs_get_proplist(pa_modargs *ma, const char *name, pa_proplist *p, pa * have any particular order. */ const char *pa_modargs_iterate(pa_modargs *ma, void **state); +/* Remove entry by key. Returns 0 if successful, -1 otherwise */ +int pa_modargs_remove_key(pa_modargs *ma, const char *key); + +/* Add all key/value pairs from src that are is not already present in dst, to dst. + * Returns 0 if there were no errors, -1 otherwise. */ +int pa_modargs_merge_missing(pa_modargs *dst, pa_modargs *src, const char* const valid_keys[]); + #endif