mirror of https://github.com/mpv-player/mpv
player: use XDG_STATE_HOME for watch_later
A pain point for some users is the fact that watch_later is stored in
the ~/.config directory when it's really not configuration data. Roughly
2 years ago, XDG_STATE_DIR was added to the XDG Base Directory
Specification[0] and its description, user-specific state data, actually
perfectly matches what watch_later data is for. Let's go ahead and use
this directory as the default for watch_later. This change only affects
non-darwin unix-like systems (i.e. Linux, BSDs, etc.). The directory
doesn't move for anyone else.
Internally, quite a few things change with regards to the path
selection. If the platform in question does not have a statedir concept,
then the path selection will simply return "home" instead (old
behavior). Fixes #9147.
[0]: 4f2884e16d
This commit is contained in:
parent
5158b85b21
commit
7c4c9bc86f
|
@ -61,6 +61,9 @@ Interface changes
|
|||
`--gamma` to float.
|
||||
- add `platform` property
|
||||
- add `--auto-window-resize`
|
||||
- `--save-position-on-quit` and its associated commands now store state files in
|
||||
the XDG_STATE_HOME directory by default. This only has an effect on linux/bsd
|
||||
systems.
|
||||
--- mpv 0.35.0 ---
|
||||
- add the `--vo=gpu-next` video output driver, as well as the options
|
||||
`--allow-delayed-peak-detect`, `--builtin-scalers`,
|
||||
|
|
|
@ -461,6 +461,8 @@ Name Meaning
|
|||
``~~desktop/`` the path to the desktop (win32, macOS)
|
||||
``~~exe_dir/`` win32 only: the path to the directory containing the exe (for
|
||||
config file purposes; ``$MPV_HOME`` overrides it)
|
||||
``~~state/`` the path to application state data (``~/.local/state/mpv/``)
|
||||
On some platforms, this will be the same as ``~~home/``.
|
||||
``~~old_home/`` do not use
|
||||
================ ===============================================================
|
||||
|
||||
|
@ -1584,7 +1586,7 @@ For Windows-specifics, see `FILES ON WINDOWS`_ section.
|
|||
|
||||
See `Script location`_ for details.
|
||||
|
||||
``~/.config/mpv/watch_later/``
|
||||
``~/.local/state/mpv/watch_later/``
|
||||
Contains temporary config files needed for resuming playback of files with
|
||||
the watch later feature. See for example the ``Q`` key binding, or the
|
||||
``quit-watch-later`` input command.
|
||||
|
|
|
@ -1015,8 +1015,9 @@ Watch Later
|
|||
``--watch-later-directory=<path>``
|
||||
The directory in which to store the "watch later" temporary files.
|
||||
|
||||
The default is a subdirectory named "watch_later" underneath the
|
||||
config directory (usually ``~/.config/mpv/``).
|
||||
If this option is unset, the files will be stored in a subdirectory
|
||||
named "watch_later" underneath the local state directory
|
||||
(usually ``~/.local/state/mpv/``).
|
||||
|
||||
``--no-resume-playback``
|
||||
Do not restore playback position from the ``watch_later`` configuration
|
||||
|
|
|
@ -10,6 +10,7 @@ struct mpv_global {
|
|||
struct mp_client_api *client_api;
|
||||
char *configdir;
|
||||
struct stats_base *stats;
|
||||
bool no_statedir;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -65,19 +65,6 @@ static const char *const config_dirs[] = {
|
|||
"global",
|
||||
};
|
||||
|
||||
void mp_init_paths(struct mpv_global *global, struct MPOpts *opts)
|
||||
{
|
||||
TA_FREEP(&global->configdir);
|
||||
|
||||
const char *force_configdir = getenv("MPV_HOME");
|
||||
if (opts->force_configdir && opts->force_configdir[0])
|
||||
force_configdir = opts->force_configdir;
|
||||
if (!opts->load_config)
|
||||
force_configdir = "";
|
||||
|
||||
global->configdir = talloc_strdup(global, force_configdir);
|
||||
}
|
||||
|
||||
// Return a platform specific path using a path type as defined in osdep/path.h.
|
||||
// Keep in mind that the only way to free the return value is freeing talloc_ctx
|
||||
// (or its children), as this function can return a statically allocated string.
|
||||
|
@ -87,13 +74,19 @@ static const char *mp_get_platform_path(void *talloc_ctx,
|
|||
{
|
||||
assert(talloc_ctx);
|
||||
|
||||
if (global->configdir) {
|
||||
bool config_dir = strcmp(type, "state") != 0;
|
||||
if (global->configdir && config_dir) {
|
||||
for (int n = 0; n < MP_ARRAY_SIZE(config_dirs); n++) {
|
||||
if (strcmp(config_dirs[n], type) == 0)
|
||||
return (n == 0 && global->configdir[0]) ? global->configdir : NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the native config path if the platform doesn't support the
|
||||
// type we are trying to fetch.
|
||||
if (strcmp(type, "state") == 0 && global->no_statedir)
|
||||
type = "home";
|
||||
|
||||
for (int n = 0; n < MP_ARRAY_SIZE(path_resolvers); n++) {
|
||||
const char *path = path_resolvers[n](talloc_ctx, type);
|
||||
if (path && path[0])
|
||||
|
@ -102,6 +95,27 @@ static const char *mp_get_platform_path(void *talloc_ctx,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void mp_init_paths(struct mpv_global *global, struct MPOpts *opts)
|
||||
{
|
||||
TA_FREEP(&global->configdir);
|
||||
|
||||
// Check if the platform has unique directories that differ from
|
||||
// the standard config directory.
|
||||
void *tmp = talloc_new(NULL);
|
||||
const char *state = mp_get_platform_path(tmp, global, "state");
|
||||
if (!state)
|
||||
global->no_statedir = true;
|
||||
talloc_free(tmp);
|
||||
|
||||
const char *force_configdir = getenv("MPV_HOME");
|
||||
if (opts->force_configdir && opts->force_configdir[0])
|
||||
force_configdir = opts->force_configdir;
|
||||
if (!opts->load_config)
|
||||
force_configdir = "";
|
||||
|
||||
global->configdir = talloc_strdup(global, force_configdir);
|
||||
}
|
||||
|
||||
char *mp_find_user_file(void *talloc_ctx, struct mpv_global *global,
|
||||
const char *type, const char *filename)
|
||||
{
|
||||
|
|
|
@ -27,14 +27,16 @@ static pthread_once_t path_init_once = PTHREAD_ONCE_INIT;
|
|||
|
||||
static char mpv_home[512];
|
||||
static char old_home[512];
|
||||
static char mpv_state[512];
|
||||
|
||||
static void path_init(void)
|
||||
{
|
||||
char *home = getenv("HOME");
|
||||
char *xdg_dir = getenv("XDG_CONFIG_HOME");
|
||||
char *xdg_config = getenv("XDG_CONFIG_HOME");
|
||||
char *xdg_state = getenv("XDG_STATE_HOME");
|
||||
|
||||
if (xdg_dir && xdg_dir[0]) {
|
||||
snprintf(mpv_home, sizeof(mpv_home), "%s/mpv", xdg_dir);
|
||||
if (xdg_config && xdg_config[0]) {
|
||||
snprintf(mpv_home, sizeof(mpv_home), "%s/mpv", xdg_config);
|
||||
} else if (home && home[0]) {
|
||||
snprintf(mpv_home, sizeof(mpv_home), "%s/.config/mpv", home);
|
||||
}
|
||||
|
@ -43,10 +45,17 @@ static void path_init(void)
|
|||
if (home && home[0])
|
||||
snprintf(old_home, sizeof(old_home), "%s/.mpv", home);
|
||||
|
||||
if (xdg_state && xdg_state[0]) {
|
||||
snprintf(mpv_state, sizeof(mpv_state), "%s/mpv", xdg_state);
|
||||
} else if (home && home[0]) {
|
||||
snprintf(mpv_state, sizeof(mpv_state), "%s/.local/state/mpv", home);
|
||||
}
|
||||
|
||||
// If the old ~/.mpv exists, and the XDG config dir doesn't, use the old
|
||||
// config dir only.
|
||||
// config dir only. Also do not use any other XDG directories.
|
||||
if (mp_path_exists(old_home) && !mp_path_exists(mpv_home)) {
|
||||
snprintf(mpv_home, sizeof(mpv_home), "%s", old_home);
|
||||
snprintf(mpv_state, sizeof(mpv_state), "%s", old_home);
|
||||
old_home[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
@ -58,6 +67,8 @@ const char *mp_get_platform_path_unix(void *talloc_ctx, const char *type)
|
|||
return mpv_home;
|
||||
if (strcmp(type, "old_home") == 0)
|
||||
return old_home;
|
||||
if (strcmp(type, "state") == 0)
|
||||
return mpv_state;
|
||||
if (strcmp(type, "global") == 0)
|
||||
return MPV_CONFDIR;
|
||||
if (strcmp(type, "desktop") == 0)
|
||||
|
|
|
@ -11,6 +11,12 @@
|
|||
// "global" the least priority, global config file location
|
||||
// "desktop" path to desktop contents
|
||||
//
|
||||
// These additional types are also defined. However, they are not necessarily
|
||||
// implemented on every platform. Unlike some other type values that are
|
||||
// platform specific (like "osxbundle"), the value of "home" is returned
|
||||
// instead if these types are not explicitly defined.
|
||||
// "state" the native mpv-specific user state dir
|
||||
//
|
||||
// It is allowed to return a static string, so the caller must set talloc_ctx
|
||||
// to something other than NULL to avoid memory leaks.
|
||||
typedef const char *(*mp_get_platform_path_cb)(void *talloc_ctx, const char *type);
|
||||
|
|
|
@ -192,6 +192,17 @@ static bool copy_mtime(const char *f1, const char *f2)
|
|||
return true;
|
||||
}
|
||||
|
||||
static char *mp_get_playback_resume_dir(struct MPContext *mpctx)
|
||||
{
|
||||
char *wl_dir = mpctx->opts->watch_later_directory;
|
||||
if (wl_dir && wl_dir[0]) {
|
||||
wl_dir = mp_get_user_path(mpctx, mpctx->global, wl_dir);
|
||||
} else {
|
||||
wl_dir = mp_find_user_file(mpctx, mpctx->global, "state", MP_WATCH_LATER_CONF);
|
||||
}
|
||||
return wl_dir;
|
||||
}
|
||||
|
||||
static char *mp_get_playback_resume_config_filename(struct MPContext *mpctx,
|
||||
const char *fname)
|
||||
{
|
||||
|
@ -216,21 +227,9 @@ static char *mp_get_playback_resume_config_filename(struct MPContext *mpctx,
|
|||
for (int i = 0; i < 16; i++)
|
||||
conf = talloc_asprintf_append(conf, "%02X", md5[i]);
|
||||
|
||||
if (!mpctx->cached_watch_later_configdir) {
|
||||
char *wl_dir = mpctx->opts->watch_later_directory;
|
||||
if (wl_dir && wl_dir[0]) {
|
||||
mpctx->cached_watch_later_configdir =
|
||||
mp_get_user_path(mpctx, mpctx->global, wl_dir);
|
||||
}
|
||||
}
|
||||
|
||||
if (!mpctx->cached_watch_later_configdir) {
|
||||
mpctx->cached_watch_later_configdir =
|
||||
mp_find_user_file(mpctx, mpctx->global, "home", MP_WATCH_LATER_CONF);
|
||||
}
|
||||
|
||||
if (mpctx->cached_watch_later_configdir)
|
||||
res = mp_path_join(NULL, mpctx->cached_watch_later_configdir, conf);
|
||||
char *wl_dir = mp_get_playback_resume_dir(mpctx);
|
||||
if (wl_dir && wl_dir[0])
|
||||
res = mp_path_join(NULL, wl_dir, conf);
|
||||
|
||||
exit:
|
||||
talloc_free(tmp);
|
||||
|
@ -292,7 +291,8 @@ void mp_write_watch_later_conf(struct MPContext *mpctx)
|
|||
if (!conffile)
|
||||
goto exit;
|
||||
|
||||
mp_mk_user_dir(mpctx->global, "home", mpctx->cached_watch_later_configdir);
|
||||
char *wl_dir = mp_get_playback_resume_dir(mpctx);
|
||||
mp_mk_user_dir(mpctx->global, "state", wl_dir);
|
||||
|
||||
MP_INFO(mpctx, "Saving state.\n");
|
||||
|
||||
|
|
|
@ -424,8 +424,6 @@ typedef struct MPContext {
|
|||
|
||||
struct mp_recorder *recorder;
|
||||
|
||||
char *cached_watch_later_configdir;
|
||||
|
||||
struct screenshot_ctx *screenshot_ctx;
|
||||
struct command_ctx *command_ctx;
|
||||
struct encode_lavc_context *encode_lavc_ctx;
|
||||
|
|
Loading…
Reference in New Issue