acp: Respect XDG base directory spec when loading configs

Backport from Pulseaudio. Reimplement get_data_path. We'll look for the
override files similarly as we do for other config files
(XDG_CONFIG_HOME then /etc then install location), instead of looking at
the Pulseaudio locations ~/.local/share/pulseaudio etc.

Upstream commits:

From: SimonP <simonp.git@gmail.com>

alsa-mixer: Respect XDG base directory spec when loading profile sets

Try $XDG_DATA_HOME, then $XDG_DATA_DIRS, and finally fall back to old behaviour.

From: SimonP <simonp.git@gmail.com>

alsa-mixer: Respect XDG base directory spec when loading path configs

Try $XDG_DATA_HOME, then $XDG_DATA_DIRS, and finally fall back to old
behaviour (prefix-defined directory).

core-util: Ignore non-absolute XDG base dirs

These are invalid per the spec.
This commit is contained in:
Pauli Virtanen 2023-11-08 21:22:42 +02:00 committed by Wim Taymans
parent 3bbd1e66d2
commit 636a9c611d
4 changed files with 90 additions and 37 deletions

View file

@ -219,8 +219,7 @@ cdata.set_quoted('MODULEDIR', modules_install_dir)
cdata.set_quoted('PIPEWIRE_CONFIG_DIR', pipewire_configdir)
cdata.set_quoted('PLUGINDIR', spa_plugindir)
cdata.set_quoted('SPADATADIR', spa_datadir)
cdata.set_quoted('PA_ALSA_PATHS_DIR', alsadatadir / 'paths')
cdata.set_quoted('PA_ALSA_PROFILE_SETS_DIR', alsadatadir / 'profile-sets')
cdata.set_quoted('PA_ALSA_DATA_DIR', alsadatadir)
if host_machine.endian() == 'big'
cdata.set('WORDS_BIGENDIAN', 1)

View file

@ -2795,20 +2795,6 @@ static int path_verify(pa_alsa_path *p) {
return 0;
}
static const char *get_default_paths_dir(void) {
const char *str;
#ifdef HAVE_RUNNING_FROM_BUILD_TREE
if (pa_run_from_build_tree())
return PA_SRCDIR "mixer/paths";
else
#endif
if (getenv("ACP_BUILDDIR") != NULL)
return "mixer/paths";
if ((str = getenv("ACP_PATHS_DIR")) != NULL)
return str;
return PA_ALSA_PATHS_DIR;
}
pa_alsa_path* pa_alsa_path_new(const char *paths_dir, const char *fname, pa_alsa_direction_t direction) {
pa_alsa_path *p;
char *fn;
@ -2873,10 +2859,9 @@ pa_alsa_path* pa_alsa_path_new(const char *paths_dir, const char *fname, pa_alsa
items[2].data = &p->description;
items[3].data = &mute_during_activation;
if (!paths_dir)
paths_dir = get_default_paths_dir();
fn = get_data_path(paths_dir, "paths", fname);
fn = pa_maybe_prefix_path(fname, paths_dir);
pa_log_info("Loading path config: %s", fn);
r = pa_config_parse(fn, NULL, items, p->proplist, false, p);
pa_xfree(fn);
@ -4827,20 +4812,6 @@ void pa_alsa_decibel_fix_dump(pa_alsa_decibel_fix *db_fix) {
pa_xfree(db_values);
}
static const char *get_default_profile_dir(void) {
const char *str;
#ifdef HAVE_RUNNING_FROM_BUILD_TREE
if (pa_run_from_build_tree())
return PA_SRCDIR "mixer/profile-sets";
else
#endif
if (getenv("ACP_BUILDDIR") != NULL)
return "mixer/profile-sets";
if ((str = getenv("ACP_PROFILES_DIR")) != NULL)
return str;
return PA_ALSA_PROFILE_SETS_DIR;
}
pa_alsa_profile_set* pa_alsa_profile_set_new(const char *fname, const pa_channel_map *bonus) {
pa_alsa_profile_set *ps;
pa_alsa_profile *p;
@ -4890,13 +4861,14 @@ pa_alsa_profile_set* pa_alsa_profile_set_new(const char *fname, const pa_channel
items[0].data = &ps->auto_profiles;
fn = pa_maybe_prefix_path(fname ? fname : "default.conf",
get_default_profile_dir());
fn = get_data_path(NULL, "profile-sets", fname ? fname : "default.conf");
pa_log_info("Loading profile set: %s", fn);
if ((r = access(fn, R_OK)) != 0) {
if (fname != NULL) {
pa_log_warn("profile-set '%s' can't be accessed: %m", fn);
fn = pa_maybe_prefix_path("default.conf",
get_default_profile_dir());
fn = get_data_path(NULL, "profile-sets", "default.conf");
r = access(fn, R_OK);
}
if (r != 0) {

View file

@ -18,9 +18,13 @@
along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
***/
#include <spa/utils/string.h>
#include <spa/utils/cleanup.h>
#include "compat.h"
#include "device-port.h"
#include "alsa-mixer.h"
#include "config.h"
static const char *port_types[] = {
[PA_DEVICE_PORT_TYPE_UNKNOWN] = "unknown",
@ -208,3 +212,77 @@ bool pa_alsa_device_init_description(pa_proplist *p, pa_card *card) {
return true;
}
static char *try_path(const char *fname, const char *path)
{
char *result = pa_maybe_prefix_path(fname, path);
pa_log_trace("Check for file: %s", result);
if (access(result, R_OK) == 0)
return result;
pa_xfree(result);
return NULL;
}
static char *get_xdg_home(const char *key, const char *fallback)
{
const char *e;
e = getenv(key);
if (e && *e) {
return strdup(e);
} else {
e = getenv("HOME");
if (!(e && *e))
e = getenv("USERPROFILE");
if (e && *e)
return spa_aprintf("%s/%s", e, fallback);
}
return NULL;
}
char *get_data_path(const char *data_dir, const char *data_type, const char *fname)
{
static const char * const subpaths[] = {
"alsa-card-profile/mixer",
"alsa-card-profile",
};
const char *e;
spa_autofree char *base = NULL;
spa_autofree char *path = NULL;
char *result;
if (data_dir)
if ((result = try_path(fname, data_dir)) != NULL)
return result;
e = getenv("ACP_PATHS_DIR");
if (e && *e && spa_streq(data_type, "paths"))
if ((result = try_path(fname, e)) != NULL)
return result;
e = getenv("ACP_PROFILES_DIR");
if (e && *e && spa_streq(data_type, "profile-sets"))
if ((result = try_path(fname, e)) != NULL)
return result;
base = get_xdg_home("XDG_CONFIG_HOME", ".config");
if (base) {
SPA_FOR_EACH_ELEMENT_VAR(subpaths, subpath) {
path = spa_aprintf("%s/%s/%s", base, *subpath, data_type);
if ((result = try_path(fname, path)) != NULL)
return result;
}
}
SPA_FOR_EACH_ELEMENT_VAR(subpaths, subpath) {
path = spa_aprintf("/etc/%s/%s", *subpath, data_type);
if ((result = try_path(fname, path)) != NULL)
return result;
}
path = spa_aprintf("%s/%s", PA_ALSA_DATA_DIR, data_type);
return pa_maybe_prefix_path(fname, path);
}

View file

@ -214,6 +214,7 @@ typedef enum pa_log_level {
PA_LOG_NOTICE = 2, /* Notice messages */
PA_LOG_INFO = 3, /* Info messages */
PA_LOG_DEBUG = 4, /* Debug messages */
PA_LOG_TRACE = 5,
PA_LOG_LEVEL_MAX
} pa_log_level_t;
@ -245,6 +246,7 @@ static inline PA_PRINTF_FUNC(5, 6) void pa_log_level_meta(enum pa_log_level leve
#define pa_log_notice(fmt,...) pa_logl(PA_LOG_NOTICE, fmt, ##__VA_ARGS__)
#define pa_log_info(fmt,...) pa_logl(PA_LOG_INFO, fmt, ##__VA_ARGS__)
#define pa_log_debug(fmt,...) pa_logl(PA_LOG_DEBUG, fmt, ##__VA_ARGS__)
#define pa_log_trace(fmt,...) pa_logl(PA_LOG_TRACE, fmt, ##__VA_ARGS__)
#define pa_log pa_log_error
#define pa_assert_se(expr) \
@ -677,6 +679,8 @@ static inline char *pa_readlink(const char *p) {
#endif
}
char *get_data_path(const char *data_dir, const char *data_type, const char *fname);
#include <spa/support/i18n.h>
extern struct spa_i18n *acp_i18n;