PA_MODULE_USAGE(
"only_from_unavailable=<boolean, only switch from unavailable ports> "
"ignore_virtual=<boolean, ignore new virtual sinks and sources, defaults to true> "
+ "blacklist=<regex, ignore matching devices> "
);
static const char* const valid_modargs[] = {
"only_from_unavailable",
"ignore_virtual",
+ "blacklist",
NULL,
};
struct userdata {
bool only_from_unavailable;
bool ignore_virtual;
+ char *blacklist;
};
static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, void* userdata) {
}
}
+ /* Ignore sinks matching the blacklist regex */
+ if (u->blacklist && (pa_match(u->blacklist, sink->name) > 0)) {
+ pa_log_info("Refusing to switch to blacklisted sink %s", sink->name);
+ return PA_HOOK_OK;
+ }
+
/* Ignore virtual sinks if not configured otherwise on the command line */
if (u->ignore_virtual && !(sink->flags & PA_SINK_HARDWARE)) {
pa_log_debug("Refusing to switch to virtual sink");
return PA_HOOK_OK;
}
+ /* Ignore sources matching the blacklist regex */
+ if (u->blacklist && (pa_match(u->blacklist, source->name) > 0)) {
+ pa_log_info("Refusing to switch to blacklisted source %s", source->name);
+ return PA_HOOK_OK;
+ }
+
/* Ignore virtual sources if not configured otherwise on the command line */
if (u->ignore_virtual && !(source->flags & PA_SOURCE_HARDWARE)) {
pa_log_debug("Refusing to switch to virtual source");
goto fail;
}
+ u->blacklist = pa_modargs_get_value(ma, "blacklist", NULL);
+ if (u->blacklist != NULL && pa_is_regex_valid(u->blacklist)) {
+ /* String returned above will be freed with modargs, duplicate it */
+ u->blacklist = pa_xstrdup(u->blacklist);
+ } else if (u->blacklist != NULL) {
+ pa_log_error("A blacklist pattern was provided but is not a valid regex.");
+ goto fail;
+ }
+
pa_modargs_free(ma);
return 0;
if (!(u = m->userdata))
return;
+ if (u->blacklist)
+ pa_xfree(u->blacklist);
+
pa_xfree(u);
}
#endif
}
+/* Check whenever any substring in v matches the provided regex. */
int pa_match(const char *expr, const char *v) {
#if defined(HAVE_REGEX_H) || defined(HAVE_PCREPOSIX_H)
int k;
regex_t re;
int r;
+ pa_assert(expr);
+ pa_assert(v);
+
if (regcomp(&re, expr, REG_NOSUB|REG_EXTENDED) != 0) {
errno = EINVAL;
return -1;
#endif
}
+/* Check whenever the provided regex pattern is valid. */
+bool pa_is_regex_valid(const char *expr) {
+#if defined(HAVE_REGEX_H) || defined(HAVE_PCREPOSIX_H)
+ regex_t re;
+
+ if (expr == NULL || regcomp(&re, expr, REG_NOSUB|REG_EXTENDED) != 0) {
+ return false;
+ }
+
+ regfree(&re);
+ return true;
+#else
+ return false;
+#endif
+}
+
/* Try to parse a boolean string value.*/
int pa_parse_boolean(const char *v) {
pa_assert(v);