mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-11-01 22:58:47 -04:00
switch-on-connect: Add blacklisting
Add a new module argument, blacklist, which is a regular expression. If the sink/source name matches the provided blacklist regex, don't automatically switch to it. By default, no devices are blacklisted. Add a new function to check whenever a regex pattern is valid, plus extra NULL asserts in pa_match.
This commit is contained in:
parent
c90894b4d5
commit
ad16d77dfe
3 changed files with 48 additions and 0 deletions
|
|
@ -40,17 +40,20 @@ PA_MODULE_LOAD_ONCE(true);
|
||||||
PA_MODULE_USAGE(
|
PA_MODULE_USAGE(
|
||||||
"only_from_unavailable=<boolean, only switch from unavailable ports> "
|
"only_from_unavailable=<boolean, only switch from unavailable ports> "
|
||||||
"ignore_virtual=<boolean, ignore new virtual sinks and sources, defaults to true> "
|
"ignore_virtual=<boolean, ignore new virtual sinks and sources, defaults to true> "
|
||||||
|
"blacklist=<regex, ignore matching devices> "
|
||||||
);
|
);
|
||||||
|
|
||||||
static const char* const valid_modargs[] = {
|
static const char* const valid_modargs[] = {
|
||||||
"only_from_unavailable",
|
"only_from_unavailable",
|
||||||
"ignore_virtual",
|
"ignore_virtual",
|
||||||
|
"blacklist",
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct userdata {
|
struct userdata {
|
||||||
bool only_from_unavailable;
|
bool only_from_unavailable;
|
||||||
bool ignore_virtual;
|
bool ignore_virtual;
|
||||||
|
char *blacklist;
|
||||||
};
|
};
|
||||||
|
|
||||||
static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, void* userdata) {
|
static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, void* userdata) {
|
||||||
|
|
@ -80,6 +83,12 @@ static pa_hook_result_t sink_put_hook_callback(pa_core *c, pa_sink *sink, void*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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 */
|
/* Ignore virtual sinks if not configured otherwise on the command line */
|
||||||
if (u->ignore_virtual && !(sink->flags & PA_SINK_HARDWARE)) {
|
if (u->ignore_virtual && !(sink->flags & PA_SINK_HARDWARE)) {
|
||||||
pa_log_debug("Refusing to switch to virtual sink");
|
pa_log_debug("Refusing to switch to virtual sink");
|
||||||
|
|
@ -157,6 +166,12 @@ static pa_hook_result_t source_put_hook_callback(pa_core *c, pa_source *source,
|
||||||
return PA_HOOK_OK;
|
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 */
|
/* Ignore virtual sources if not configured otherwise on the command line */
|
||||||
if (u->ignore_virtual && !(source->flags & PA_SOURCE_HARDWARE)) {
|
if (u->ignore_virtual && !(source->flags & PA_SOURCE_HARDWARE)) {
|
||||||
pa_log_debug("Refusing to switch to virtual source");
|
pa_log_debug("Refusing to switch to virtual source");
|
||||||
|
|
@ -234,6 +249,15 @@ int pa__init(pa_module*m) {
|
||||||
goto fail;
|
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);
|
pa_modargs_free(ma);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
@ -254,5 +278,8 @@ void pa__done(pa_module*m) {
|
||||||
if (!(u = m->userdata))
|
if (!(u = m->userdata))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (u->blacklist)
|
||||||
|
pa_xfree(u->blacklist);
|
||||||
|
|
||||||
pa_xfree(u);
|
pa_xfree(u);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -784,12 +784,16 @@ void pa_reset_priority(void) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check whenever any substring in v matches the provided regex. */
|
||||||
int pa_match(const char *expr, const char *v) {
|
int pa_match(const char *expr, const char *v) {
|
||||||
#if defined(HAVE_REGEX_H) || defined(HAVE_PCREPOSIX_H)
|
#if defined(HAVE_REGEX_H) || defined(HAVE_PCREPOSIX_H)
|
||||||
int k;
|
int k;
|
||||||
regex_t re;
|
regex_t re;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
pa_assert(expr);
|
||||||
|
pa_assert(v);
|
||||||
|
|
||||||
if (regcomp(&re, expr, REG_NOSUB|REG_EXTENDED) != 0) {
|
if (regcomp(&re, expr, REG_NOSUB|REG_EXTENDED) != 0) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -814,6 +818,22 @@ int pa_match(const char *expr, const char *v) {
|
||||||
#endif
|
#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.*/
|
/* Try to parse a boolean string value.*/
|
||||||
int pa_parse_boolean(const char *v) {
|
int pa_parse_boolean(const char *v) {
|
||||||
pa_assert(v);
|
pa_assert(v);
|
||||||
|
|
|
||||||
|
|
@ -158,6 +158,7 @@ size_t pa_vsnprintf(char *str, size_t size, const char *format, va_list ap);
|
||||||
char *pa_truncate_utf8(char *c, size_t l);
|
char *pa_truncate_utf8(char *c, size_t l);
|
||||||
|
|
||||||
int pa_match(const char *expr, const char *v);
|
int pa_match(const char *expr, const char *v);
|
||||||
|
bool pa_is_regex_valid(const char *expr);
|
||||||
|
|
||||||
char *pa_getcwd(void);
|
char *pa_getcwd(void);
|
||||||
char *pa_make_path_absolute(const char *p);
|
char *pa_make_path_absolute(const char *p);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue