diff --git a/src/pipewire/conf.c b/src/pipewire/conf.c index 0e30fde97..3d602370c 100644 --- a/src/pipewire/conf.c +++ b/src/pipewire/conf.c @@ -625,6 +625,7 @@ static int load_module(struct pw_context *context, const char *key, const char * * { * # all keys must match the value. ~ in value starts regex. * # ! as the first char of the value negates the match + * # @ checks if the value is an element in a JSON array property * = * ... * } @@ -636,6 +637,8 @@ static int load_module(struct pw_context *context, const char *key, const char * * !null -> matches when the property is found (any value) * "!null" -> same as !null * !"null" and "!\"null\"" matches anything that is not the string "null" + * @138 -> matches when the property is a JSON array containing "138" + * !@138 -> matches when the property is a JSON array not containing "138" */ SPA_EXPORT bool pw_conf_find_match(struct spa_json *arr, const struct spa_dict *props, bool condition) @@ -651,7 +654,7 @@ bool pw_conf_find_match(struct spa_json *arr, const struct spa_dict *props, bool int len; while ((len = spa_json_object_next(&it[0], key, sizeof(key), &value)) > 0) { - bool success = false, is_null, reg = false, parse_string = true; + bool success = false, is_null, reg = false, in_array = false, parse_string = true; int skip = 0; /* first decode a string, when there was a string, we assume it @@ -680,6 +683,16 @@ bool pw_conf_find_match(struct spa_json *arr, const struct spa_dict *props, bool skip++; parse_string = true; } + if (len > skip && value[skip] == '@') { + in_array = true; + skip++; + parse_string = true; + } + if (SPA_UNLIKELY(in_array && reg)) { + pw_log_warn("@ and ~ modifiers cannot be combined in '%.*s'", + az, as); + continue; + } str = spa_dict_lookup(props, key); @@ -701,7 +714,18 @@ bool pw_conf_find_match(struct spa_json *arr, const struct spa_dict *props, bool continue; } - if (reg) { + if (in_array) { + struct spa_json arr_iter; + char elem[256]; + if (spa_json_begin_array_relax(&arr_iter, str, strlen(str)) > 0) { + while (spa_json_get_string(&arr_iter, elem, sizeof(elem)) > 0) { + if (strcmp(elem, val) == 0) { + success = !success; + break; + } + } + } + } else if (reg) { regex_t preg; int res; if ((res = regcomp(&preg, val, REG_EXTENDED | REG_NOSUB)) != 0) {