diff --git a/doc/mpd.conf.5.rst b/doc/mpd.conf.5.rst index 3bc1ce2aa..8d70aa3bb 100644 --- a/doc/mpd.conf.5.rst +++ b/doc/mpd.conf.5.rst @@ -17,10 +17,19 @@ Each line in the configuration file contains a setting name and its value, e.g.: Lines starting with ``#`` are treated as comments and ignored. -For settings which specify a filesystem path, the tilde is expanded: +For settings that specify a file system path, the tilde ('~') is expanded to $HOME. +In addition, the following path expansions are supported: + +- `$HOME` +- `$XDG_CONFIG_HOME` +- `$XDG_MUSIC_DIR` +- `$XDG_CACHE_HOME` +- `$XDG_RUNTIME_DIR` :code:`music_directory "~/Music"` +:code:`db_file "$XDG_CONFIG_HOME/mpd/database"` + Some of the settings are grouped in blocks with curly braces, e.g. per-plugin settings: .. code-block:: none diff --git a/doc/mpdconf.example b/doc/mpdconf.example index 7f7ad01be..a6976dc24 100644 --- a/doc/mpdconf.example +++ b/doc/mpdconf.example @@ -10,6 +10,7 @@ # be disabled and audio files will only be accepted over ipc socket (using # file:// protocol) or streaming files over an accepted protocol. # +#music_directory "$XDG_MUSIC_DIR" #music_directory "~/music" # # This setting sets the MPD internal playlist directory. The purpose of this @@ -17,6 +18,7 @@ # playlist files not created by the server but only if they are in the MPD # format. This setting defaults to playlist saving being disabled. # +#playlist_directory "$XDG_CONFIG_HOME/mpd/playlists" #playlist_directory "~/.mpd/playlists" # # This setting sets the location of the MPD database. This file is used to @@ -25,6 +27,7 @@ # MPD to accept files over ipc socket (using file:// protocol) or streaming # files over an accepted protocol. # +#db_file "$XDG_CACHE_HOME/mpd/database" #db_file "~/.mpd/database" # These settings are the locations for the daemon log files for the daemon. @@ -35,6 +38,7 @@ # If you use systemd, do not configure a log_file. With systemd, MPD # defaults to the systemd journal, which is fine. # +#log_file "$XDG_CACHE_HOME/mpd/log" #log_file "~/.mpd/log" # This setting sets the location of the file which stores the process ID @@ -43,6 +47,7 @@ # # If you use systemd, do not configure a pid_file. # +#pid_file "$XDG_RUNTIME_DIR/mpd/mpd.pid" #pid_file "~/.mpd/pid" # This setting sets the location of the file which contains information about @@ -50,11 +55,13 @@ # it was brought down. This setting is disabled by default and the server # state will be reset on server start up. # +#state_file "$XDG_RUNTIME_DIR/mpd/state" #state_file "~/.mpd/state" # # The location of the sticker database. This is a database which # manages dynamic information attached to songs. # +#sticker_file "$XDG_CACHE_HOME/sticker.sql" #sticker_file "~/.mpd/sticker.sql" # ############################################################################### @@ -85,6 +92,7 @@ #bind_to_address "any" # # And for Unix Socket +#bind_to_address "$XDG_RUNTIME_DIR/mpd/socket" #bind_to_address "~/.mpd/socket" # # This setting is the TCP port that is desired for the daemon to get assigned diff --git a/doc/user.rst b/doc/user.rst index 3249c8cb0..e3ba68d7b 100644 --- a/doc/user.rst +++ b/doc/user.rst @@ -250,10 +250,18 @@ Each line in the configuration file contains a setting name and its value, e.g.: Lines starting with ``#`` are treated as comments and ignored. -For settings which specify a filesystem path, the tilde is expanded: +For settings that specify a file system path, the tilde ('~') is expanded to $HOME. In addition, the following path expansions are supported: + +- `$HOME` +- `$XDG_CONFIG_HOME` +- `$XDG_MUSIC_DIR` +- `$XDG_CACHE_HOME` +- `$XDG_RUNTIME_DIR` :code:`music_directory "~/Music"` +:code:`db_file "$XDG_CONFIG_HOME/mpd/database"` + Some of the settings are grouped in blocks with curly braces, e.g. per-plugin settings: .. code-block:: none @@ -1210,8 +1218,11 @@ Mounting is only possible with the simple database plugin and a :code:`cache_dir database { plugin "simple" - path "~/.mpd/db" - cache_directory "~/.mpd/cache" + path "$XDG_CACHE_HOME/mpd/database" + cache_directory "$XDG_CACHE_HOME/mpd/" + # or you can also use relative or absolute paths + # path "~/.mpd/db" + # cache_directory "~/.mpd/cache" } This requires migrating from the old :code:`db_file` setting to a database section. The cache directory must exist, and :program:`MPD` will put one file per mount there, which will be reused when the same storage is used again later. diff --git a/src/config/Net.cxx b/src/config/Net.cxx index f1df3db3f..4a2a0303c 100644 --- a/src/config/Net.cxx +++ b/src/config/Net.cxx @@ -5,13 +5,18 @@ #include "event/ServerSocket.hxx" #include "Path.hxx" #include "fs/AllocatedPath.hxx" +#include "fs/XDG.hxx" void ServerSocketAddGeneric(ServerSocket &server_socket, const char *address, unsigned int port) { if (address == nullptr || 0 == strcmp(address, "any")) { server_socket.AddPort(port); +#ifdef USE_XDG + } else if (address[0] == '/' || address[0] == '~' || address[0] == '$') { +#else } else if (address[0] == '/' || address[0] == '~') { +#endif server_socket.AddPath(ParsePath(address)); } else if (address[0] == '@') { server_socket.AddAbstract(address); diff --git a/src/config/Path.cxx b/src/config/Path.cxx index b1377dc44..8e760361d 100644 --- a/src/config/Path.cxx +++ b/src/config/Path.cxx @@ -5,6 +5,7 @@ #include "Data.hxx" #include "fs/AllocatedPath.hxx" #include "fs/Traits.hxx" +#include "fs/XDG.hxx" #include "fs/glue/StandardDirectory.hxx" #include "lib/fmt/RuntimeError.hxx" #include "util/StringSplit.hxx" @@ -90,6 +91,29 @@ ParsePath(const char *path) return GetHome(std::string{user}.c_str()) / AllocatedPath::FromUTF8Throw(rest); } +#ifdef USE_XDG + } else if (path[0] == '$') { + ++path; + + const auto [env_var, rest] = Split(std::string_view{path}, '/'); + + AllocatedPath xdg_path(nullptr); + if (env_var == "HOME") { + xdg_path = GetConfiguredHome(); + } else if (env_var == "XDG_CONFIG_HOME") { + xdg_path = GetUserConfigDir(); + } else if (env_var == "XDG_MUSIC_DIR") { + xdg_path = GetUserMusicDir(); + } else if (env_var == "XDG_CACHE_HOME") { + xdg_path = GetUserCacheDir(); + } else if (env_var == "XDG_RUNTIME_DIR") { + xdg_path = GetUserRuntimeDir(); + } else { + throw FmtRuntimeError("environment variable not supported: {:?}", env_var); + } + + return xdg_path / AllocatedPath::FromUTF8Throw(rest); +#endif } else if (!PathTraitsUTF8::IsAbsolute(path)) { throw FmtRuntimeError("not an absolute path: {:?}", path); } else {