diff --git a/old-makefile b/old-makefile index 7adc45d712..d7b1f1f1dc 100644 --- a/old-makefile +++ b/old-makefile @@ -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 \ diff --git a/options/path.c b/options/path.c index 433f5112cd..d19b360b99 100644 --- a/options/path.c +++ b/options/path.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; diff --git a/osdep/path-macosx.m b/osdep/path-macosx.m index ee34f9638b..618f2038c8 100644 --- a/osdep/path-macosx.m +++ b/osdep/path-macosx.m @@ -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; } diff --git a/osdep/path-unix.c b/osdep/path-unix.c new file mode 100644 index 0000000000..c3b70d7e06 --- /dev/null +++ b/osdep/path-unix.c @@ -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 . + */ + +#include +#include + +#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; +} diff --git a/osdep/path-win.c b/osdep/path-win.c index 66d8de96e4..26f7ffa62e 100644 --- a/osdep/path-win.c +++ b/osdep/path-win.c @@ -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; } diff --git a/osdep/path.h b/osdep/path.h index c697453fcc..59a3ba7590 100644 --- a/osdep/path.h +++ b/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 diff --git a/wscript_build.py b/wscript_build.py index 7328be13b8..e2d1562d5b 100644 --- a/wscript_build.py +++ b/wscript_build.py @@ -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" ),