mirror of
https://github.com/mpv-player/mpv
synced 2024-12-26 00:42:57 +00:00
path: refactor
Somewhat less ifdeffery, higher flexibility. Now there are 3 separate config file resolvers for 3 platforms (unix, win, osx), and they can still interact with each other somewhat. For example, OSX for now uses most of Unix, but adds the OSX bundle path. This can be extended to resolve very specific platform paths, such as location of the desktop. Most of the Unix specific code moves to path-unix.c. The behavior should be the same - if not, it is likely a bug.
This commit is contained in:
parent
60958ddf9b
commit
d3a3cfe54c
@ -195,6 +195,7 @@ SOURCES = audio/audio.c \
|
||||
options/parse_configfile.c \
|
||||
options/path.c \
|
||||
osdep/io.c \
|
||||
osdep/path-unix.c \
|
||||
osdep/semaphore_osx.c \
|
||||
osdep/subprocess.c \
|
||||
osdep/subprocess-posix.c \
|
||||
|
@ -43,41 +43,36 @@
|
||||
#include "osdep/io.h"
|
||||
#include "osdep/path.h"
|
||||
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
static int mp_add_xdg_config_dirs(struct mpv_global *global, char **dirs, int i)
|
||||
#define MAX_CONFIG_PATHS 32
|
||||
|
||||
static const char *mp_get_forced_home(void *talloc_ctx, const char *type)
|
||||
{
|
||||
void *talloc_ctx = dirs;
|
||||
|
||||
char *home = getenv("HOME");
|
||||
char *tmp = NULL;
|
||||
|
||||
char *xdg_home = NULL;
|
||||
tmp = getenv("XDG_CONFIG_HOME");
|
||||
if (tmp && *tmp)
|
||||
xdg_home = talloc_asprintf(talloc_ctx, "%s/mpv", tmp);
|
||||
else if (home && *home)
|
||||
xdg_home = talloc_asprintf(talloc_ctx, "%s/.config/mpv", home);
|
||||
|
||||
// Maintain compatibility with old ~/.mpv
|
||||
char *old_home = NULL;
|
||||
if (home && *home)
|
||||
old_home = talloc_asprintf(talloc_ctx, "%s/.mpv", home);
|
||||
|
||||
// If the old ~/.mpv exists, and the XDG config dir doesn't, use the old
|
||||
// config dir only.
|
||||
if (mp_path_exists(xdg_home) || !mp_path_exists(old_home))
|
||||
dirs[i++] = xdg_home;
|
||||
dirs[i++] = old_home;
|
||||
|
||||
#if HAVE_COCOA
|
||||
i = mp_add_macosx_bundle_dir(global, dirs, i);
|
||||
#endif
|
||||
|
||||
dirs[i++] = MPV_CONFDIR;
|
||||
|
||||
return i;
|
||||
return strcmp(type, "home") == 0 ? getenv("MPV_HOME") : NULL;
|
||||
}
|
||||
|
||||
// In order of increasing priority: the first hiz has highest priority.
|
||||
static const mp_get_platform_path_cb path_resolvers[] = {
|
||||
mp_get_forced_home,
|
||||
#if HAVE_COCOA
|
||||
mp_get_platform_path_osx,
|
||||
#endif
|
||||
#if !defined(_WIN32) || defined(__CYGWIN__)
|
||||
mp_get_platform_path_unix,
|
||||
#endif
|
||||
#if defined(_WIN32)
|
||||
mp_get_platform_path_win,
|
||||
#endif
|
||||
};
|
||||
|
||||
static const char *mp_get_platform_path(void *talloc_ctx, const char *type)
|
||||
{
|
||||
for (int n = 0; n < MP_ARRAY_SIZE(path_resolvers); n++) {
|
||||
const char *path = path_resolvers[n](talloc_ctx, type);
|
||||
if (path && path[0])
|
||||
return path;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Return NULL-terminated array of config directories, from highest to lowest
|
||||
// priority
|
||||
@ -85,7 +80,8 @@ static char **mp_config_dirs(void *talloc_ctx, struct mpv_global *global)
|
||||
{
|
||||
struct MPOpts *opts = global->opts;
|
||||
|
||||
char **ret = talloc_zero_array(talloc_ctx, char*, MAX_CONFIG_PATHS);
|
||||
char **ret = talloc_zero_array(talloc_ctx, char*, MAX_CONFIG_PATHS + 1);
|
||||
int num_ret = 0;
|
||||
|
||||
if (!opts->load_config)
|
||||
return ret;
|
||||
@ -95,22 +91,23 @@ static char **mp_config_dirs(void *talloc_ctx, struct mpv_global *global)
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char *tmp = NULL;
|
||||
int i = 0;
|
||||
// from highest (most preferred) to lowest priority
|
||||
static const char *const configdirs[] = {
|
||||
"home",
|
||||
"old_home",
|
||||
"osxbundle",
|
||||
"global",
|
||||
};
|
||||
|
||||
tmp = getenv("MPV_HOME");
|
||||
if (tmp && *tmp)
|
||||
ret[i++] = talloc_strdup(ret, tmp);
|
||||
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
i = mp_add_win_config_dirs(global, ret, i);
|
||||
#else
|
||||
i = mp_add_xdg_config_dirs(global, ret, i);
|
||||
#endif
|
||||
for (int n = 0; n < MP_ARRAY_SIZE(configdirs); n++) {
|
||||
const char *path = mp_get_platform_path(ret, configdirs[n]);
|
||||
if (path && path[0] && num_ret < MAX_CONFIG_PATHS)
|
||||
ret[num_ret++] = (char *)path;
|
||||
}
|
||||
|
||||
MP_VERBOSE(global, "search dirs:");
|
||||
for (char **c = ret; *c; c++)
|
||||
MP_VERBOSE(global, " %s", *c);
|
||||
for (int n = 0; n < num_ret; n++)
|
||||
MP_VERBOSE(global, " %s", ret[n]);
|
||||
MP_VERBOSE(global, "\n");
|
||||
|
||||
return ret;
|
||||
|
@ -19,12 +19,14 @@
|
||||
#include "options/path.h"
|
||||
#include "osdep/path.h"
|
||||
|
||||
int mp_add_macosx_bundle_dir(struct mpv_global *global, char **dirs, int i)
|
||||
const char *mp_get_platform_path_osx(void *talloc_ctx, const char *type)
|
||||
{
|
||||
void *talloc_ctx = dirs;
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSString *path = [[NSBundle mainBundle] resourcePath];
|
||||
dirs[i++] = talloc_strdup(talloc_ctx, [path UTF8String]);
|
||||
[pool release];
|
||||
return i;
|
||||
if (strcmp(type, "osxbundle") == 0) {
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
||||
NSString *path = [[NSBundle mainBundle] resourcePath];
|
||||
char *res = talloc_strdup(talloc_ctx, [path UTF8String]);
|
||||
[pool release];
|
||||
return res;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
64
osdep/path-unix.c
Normal file
64
osdep/path-unix.c
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* This file is part of mpv.
|
||||
*
|
||||
* mpv is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* mpv is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with mpv. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "options/path.h"
|
||||
#include "path.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
static pthread_once_t path_init_once = PTHREAD_ONCE_INIT;
|
||||
|
||||
static char mpv_home[512];
|
||||
static char old_home[512];
|
||||
|
||||
static void path_init(void)
|
||||
{
|
||||
char *home = getenv("HOME");
|
||||
char *xdg_dir = getenv("XDG_CONFIG_HOME");
|
||||
|
||||
if (xdg_dir && xdg_dir[0]) {
|
||||
snprintf(mpv_home, sizeof(mpv_home), "%s/mpv", xdg_dir);
|
||||
} else if (home && home[0]) {
|
||||
snprintf(mpv_home, sizeof(mpv_home), "%s/.config/mpv", home);
|
||||
}
|
||||
|
||||
// Maintain compatibility with old ~/.mpv
|
||||
if (home && home[0])
|
||||
snprintf(old_home, sizeof(old_home), "%s/.mpv", home);
|
||||
|
||||
// If the old ~/.mpv exists, and the XDG config dir doesn't, use the old
|
||||
// config dir only.
|
||||
if (mp_path_exists(old_home) && !mp_path_exists(mpv_home)) {
|
||||
snprintf(mpv_home, sizeof(mpv_home), "%s", old_home);
|
||||
old_home[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
const char *mp_get_platform_path_unix(void *talloc_ctx, const char *type)
|
||||
{
|
||||
pthread_once(&path_init_once, path_init);
|
||||
if (strcmp(type, "home") == 0)
|
||||
return mpv_home;
|
||||
if (strcmp(type, "old_home") == 0)
|
||||
return old_home;
|
||||
if (strcmp(type, "global") == 0)
|
||||
return MPV_CONFDIR;
|
||||
return NULL;
|
||||
}
|
@ -58,14 +58,14 @@ static char *mp_get_win_app_dir(void *talloc_ctx)
|
||||
return talloc_asprintf(talloc_ctx, "%s/mpv", mp_to_utf8(talloc_ctx, w_appdir));
|
||||
}
|
||||
|
||||
int mp_add_win_config_dirs(struct mpv_global *global, char **dirs, int i)
|
||||
const char *mp_get_platform_path_win(void *talloc_ctx, const char *type)
|
||||
{
|
||||
void *talloc_ctx = dirs;
|
||||
if ((dirs[i] = mp_get_win_app_dir(talloc_ctx)))
|
||||
i++;
|
||||
if ((dirs[i] = mp_get_win_exe_dir(talloc_ctx)))
|
||||
i++;
|
||||
if ((dirs[i] = mp_get_win_exe_subdir(talloc_ctx)))
|
||||
i++;
|
||||
return i;
|
||||
if (strcmp(type, "home") == 0)
|
||||
return mp_get_win_app_dir(talloc_ctx);
|
||||
if (strcmp(type, "old_home") == 0)
|
||||
return mp_get_win_exe_dir(talloc_ctx);
|
||||
// Not really true, but serves as a way to return a lowest-priority dir.
|
||||
if (strcmp(type, "global") == 0)
|
||||
return mp_get_win_exe_subdir(talloc_ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
25
osdep/path.h
25
osdep/path.h
@ -1,15 +1,22 @@
|
||||
#ifndef OSDEP_PATH_H
|
||||
#define OSDEP_PATH_H
|
||||
|
||||
#define MAX_CONFIG_PATHS 32
|
||||
// Return a platform-specific path, identified by the type parameter. If the
|
||||
// return value is allocated, talloc_ctx is used as talloc parent context.
|
||||
//
|
||||
// The following type values are defined:
|
||||
// "home" the native mpv-specific user config dir
|
||||
// "old_home" same as "home", but lesser priority (compatibility)
|
||||
// "osxbundle" OSX bundle path
|
||||
// "global" the least priority, global config file location
|
||||
//
|
||||
// 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);
|
||||
|
||||
struct mpv_global;
|
||||
|
||||
// Append paths starting at dirs[i]. The dirs array has place only for at most
|
||||
// MAX_CONFIG_PATHS paths, but it's guaranteed that at least 4 paths can be
|
||||
// added without checking for i>=MAX_CONFIG_PATHS.
|
||||
// Return the new value of i.
|
||||
int mp_add_win_config_dirs(struct mpv_global *global, char **dirs, int i);
|
||||
int mp_add_macosx_bundle_dir(struct mpv_global *global, char **dirs, int i);
|
||||
// Conforming to mp_get_platform_path_cb.
|
||||
const char *mp_get_platform_path_win(void *talloc_ctx, const char *type);
|
||||
const char *mp_get_platform_path_osx(void *talloc_ctx, const char *type);
|
||||
const char *mp_get_platform_path_unix(void *talloc_ctx, const char *type);
|
||||
|
||||
#endif
|
||||
|
@ -380,6 +380,7 @@ def build(ctx):
|
||||
( "osdep/subprocess-posix.c", "posix-spawn" ),
|
||||
( "osdep/subprocess-win.c", "os-win32" ),
|
||||
( "osdep/path-macosx.m", "cocoa" ),
|
||||
( "osdep/path-unix.c"),
|
||||
( "osdep/path-win.c", "os-win32" ),
|
||||
( "osdep/path-win.c", "os-cygwin" ),
|
||||
( "osdep/glob-win.c", "glob-win32-replacement" ),
|
||||
|
Loading…
Reference in New Issue
Block a user