MPD
MPD copied to clipboard
Environment Variables in config file
Would you consider adding the expansion of environment variables in mpv.conf? I would like mpd to listen on $XDG_RUNTIME_DIR/mpd-socket but cannot do this without expanding the variable by hand.
Thank you!
MPD listens on $XDG_RUNTIME_DIR/mpd/socket if no bind_to_address is set. So maybe expansion of $XDG_RUNTIME_DIR is no longer needed?
Source: https://www.musicpd.org/doc/html/user.html#listeners
Works with MPD 0.21.5 on Debian buster. Commented out all bind_to_address lines in my ~/.mpdconf, killed and restarted mpd. Now I can connect to it using the socket:
$ MPD_HOST="$XDG_RUNTIME_DIR/mpd/socket" mpc
volume: n/a repeat: off random: off single: off consume: off
However, even when bind_to_address is unset, mpd still listens on "[::]:6600" (world reachable) in addition to the XDG socket. If you do set bind_to_address to e.g. localhost, the XDG socket is gone. Tilde is expanded, so you can set bind_to_address to e.g. ~/.mpd/socket but that kinda defeats the point of this issue. You can still control which port mpd listens on, using the port setting, so at least you can avoid port conflicts.
Another use case is music_directory with $XDG_MUSIC_DIR.
If we want to reach maximum versatility of the config file probably Parameter Expansion with subshell support would be ideal; I have zero knowledge of this codebase but I suspect that this would be not so straightforward to implement.
In my case:
music_directory "${XDG_MUSIC_DIR:-~/Music}"
...
bind_to_address "${XDG_RUNTIME_DIR:-/tmp/$(id -u)-runtime}/mpd/main.sock"
I'm for this as well. I'd like to be able to set the playlist directory or the log file directory using $XDG_CONFIG_HOME or $XDG_CACHE_HOME or $XDG_DATA_HOME, etc.. you get the idea.
quick and dirty patch
--- mpd-0.23.12/src/config/Path.cxx.orig 2023-01-17 19:54:47.000000000 +0200
+++ mpd-0.23.12/src/config/Path.cxx 2023-05-09 10:54:13.543284206 +0300
@@ -26,6 +26,8 @@
#include "util/StringView.hxx"
#include <cassert>
+#include <string>
+#include <regex>
#ifndef _WIN32
#include <pwd.h>
@@ -33,6 +35,21 @@
static const char *configured_user = nullptr;
/**
+ * Replace environment variables in form ${...} by its values
+ */
+static void
+ExpandEnvironmentVariables(std::string & text) {
+ static std::regex env( "\\$\\{([^}]+)\\}" );
+ std::smatch match;
+ while ( std::regex_search( text, match, env ) ) {
+ const char * s = getenv( match[1].str().c_str() );
+ const std::string var( s == NULL ? "" : s );
+ text.replace( match[0].first, match[0].second, var );
+ }
+}
+
+
+/**
* Determine a given user's home directory.
*/
static AllocatedPath
@@ -89,17 +106,21 @@
assert(path != nullptr);
#ifndef _WIN32
- if (path[0] == '~') {
- ++path;
+ std::string epath(path);
+ ExpandEnvironmentVariables(epath);
- if (*path == '\0')
+ const char *str = epath.c_str();
+ if (str[0] == '~') {
+ ++str;
+
+ if (*str == '\0')
return GetConfiguredHome();
- if (*path == '/') {
- ++path;
+ if (*str == '/') {
+ ++str;
- AllocatedPath::FromUTF8Throw(path);
+ AllocatedPath::FromUTF8Throw(str);
} else {
const auto [user, rest] =
StringView{path}.Split('/');
@@ -107,12 +128,12 @@
return GetHome(std::string{user}.c_str())
/ AllocatedPath::FromUTF8Throw(rest);
}
- } else if (!PathTraitsUTF8::IsAbsolute(path)) {
- throw FormatRuntimeError("not an absolute path: %s", path);
+ } else if (!PathTraitsUTF8::IsAbsolute(str)) {
+ throw FormatRuntimeError("not an absolute path: %s", str);
} else {
-#endif
- return AllocatedPath::FromUTF8Throw(path);
-#ifndef _WIN32
+ return AllocatedPath::FromUTF8Throw(str);
}
+#else
+ return AllocatedPath::FromUTF8Throw(path);
#endif
}