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" ),