summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-12-14 19:50:00 +0100
committerwm4 <wm4@nowhere>2013-12-14 19:54:49 +0100
commit683d7e88e46463497033eb4759ced45ee8b8cc49 (patch)
treeaa99cebe436f180c2d3c2e070ec4d3896386153a
parentdcf9f77c58691bde3e4e0ac60e5a5d7e1fc95b42 (diff)
downloadmpv-683d7e88e46463497033eb4759ced45ee8b8cc49.tar.bz2
mpv-683d7e88e46463497033eb4759ced45ee8b8cc49.tar.xz
Allow some options taking filenames to refer to mpv config dir
Add the mp_get_user_path() function, and make it expand special path prefixes. Use it for some things in mpv which take filenames (--input-config, --screenshot-template, opengl icc-profile suboption). This allows accessing files in the mpv config dir without hardcoding the config path by prefixing the path with ~~/. Details see manpage additions.
-rw-r--r--DOCS/man/en/mpv.rst22
-rw-r--r--mpvcore/input/input.c24
-rw-r--r--mpvcore/path.c22
-rw-r--r--mpvcore/path.h5
-rw-r--r--mpvcore/player/screenshot.c5
-rw-r--r--video/out/gl_lcms.c5
6 files changed, 73 insertions, 10 deletions
diff --git a/DOCS/man/en/mpv.rst b/DOCS/man/en/mpv.rst
index 44a0c36f80..003a36ed53 100644
--- a/DOCS/man/en/mpv.rst
+++ b/DOCS/man/en/mpv.rst
@@ -285,6 +285,28 @@ It has the following format::
``mpv --ao=pcm:file=%`expr length "$NAME"`%"$NAME" test.avi``
+Paths
+-----
+
+Some care must be taken when passing arbitrary paths and filenames to mpv. For
+example, paths starting with ``-`` will be interpreted as options. Likewise,
+if a path contains the sequence ``://``, the string before that might be
+interpreted as protocol prefix, even though ``://`` can be part of a legal
+UNIX path. To avoid problems with arbitrary paths, you should be sure that
+absolute paths passed to mpv start with ``/``, and relative paths with ``./``.
+
+The name ``-`` itself is interpreted as stdin, and will cause mpv to disable
+console controls. (Which makes it suitable for playing data piped to stdin.)
+
+For paths passed to suboptions, the situation is further complicated by the
+need to escape special characters. To work this around, the path can be
+additionally wrapped in the ``%n%string_of_length_n`` syntax (see above).
+
+Some mpv options interpret paths starting with ``~``. Currently, the prefix
+``~~/`` expands to the mpv configuration directory (usually ``~/.mpv/``).
+``~/`` expands to the user's home directory. (The trailing ``/`` is always
+required.)
+
Per-File Options
----------------
diff --git a/mpvcore/input/input.c b/mpvcore/input/input.c
index f6553e7ba4..f9c7e0c173 100644
--- a/mpvcore/input/input.c
+++ b/mpvcore/input/input.c
@@ -2156,23 +2156,31 @@ static int parse_config(struct input_ctx *ictx, bool builtin, bstr data,
static int parse_config_file(struct input_ctx *ictx, char *file, bool warn)
{
+ int r = 0;
+ void *tmp = talloc_new(NULL);
+ stream_t *s = NULL;
+
+ file = mp_get_user_path(tmp, file);
if (!mp_path_exists(file)) {
MP_MSG(ictx, warn ? MSGL_ERR : MSGL_V,
"Input config file %s not found.\n", file);
- return 0;
+ goto done;
}
- stream_t *s = stream_open(file, NULL);
+ s = stream_open(file, NULL);
if (!s) {
MP_ERR(ictx, "Can't open input config file %s.\n", file);
- return 0;
+ goto done;
}
- bstr res = stream_read_complete(s, NULL, 1000000);
- free_stream(s);
+ bstr data = stream_read_complete(s, tmp, 1000000);
MP_VERBOSE(ictx, "Parsing input config file %s\n", file);
- int n_binds = parse_config(ictx, false, res, file, NULL);
- talloc_free(res.start);
+ int n_binds = parse_config(ictx, false, data, file, NULL);
MP_VERBOSE(ictx, "Input config file %s parsed: %d binds\n", file, n_binds);
- return 1;
+ r = 1;
+
+done:
+ free_stream(s);
+ talloc_free(tmp);
+ return r;
}
// If name is NULL, return "default".
diff --git a/mpvcore/path.c b/mpvcore/path.c
index df138489d6..9de11b24d1 100644
--- a/mpvcore/path.c
+++ b/mpvcore/path.c
@@ -97,6 +97,28 @@ char *mp_find_global_config_file(const char *filename)
}
}
+char *mp_get_user_path(void *talloc_ctx, const char *path)
+{
+ if (!path)
+ return NULL;
+ bstr bpath = bstr0(path);
+ if (bstr_eatstart0(&bpath, "~")) {
+ // parse to "~" <prefix> "/" <rest>
+ bstr prefix, rest;
+ if (bstr_split_tok(bpath, "/", &prefix, &rest)) {
+ const char *rest0 = rest.start; // ok in this case
+ char *res = NULL;
+ if (bstr_equals0(prefix, "~"))
+ res = talloc_steal(talloc_ctx, mp_find_user_config_file(rest0));
+ if (bstr_equals0(prefix, ""))
+ res = mp_path_join(talloc_ctx, bstr0(getenv("HOME")), rest);
+ if (res)
+ return res;
+ }
+ }
+ return talloc_strdup(talloc_ctx, path);
+}
+
char *mp_basename(const char *path)
{
char *s;
diff --git a/mpvcore/path.h b/mpvcore/path.h
index bae6956ec7..e0c61321d2 100644
--- a/mpvcore/path.h
+++ b/mpvcore/path.h
@@ -36,6 +36,11 @@ char *mp_find_global_config_file(const char *filename);
// Search for the input filename in the user configuration location.
char *mp_find_user_config_file(const char *filename);
+// Normally returns a talloc_strdup'ed copy of the path, except for special
+// paths starting with '~'. Used to allow the user explicitly reference a
+// file from the user's home or mpv config directory.
+char *mp_get_user_path(void *talloc_ctx, const char *path);
+
// Return pointer to filename part of path
char *mp_basename(const char *path);
diff --git a/mpvcore/player/screenshot.c b/mpvcore/player/screenshot.c
index bf7a0ce9ee..d719495f9e 100644
--- a/mpvcore/player/screenshot.c
+++ b/mpvcore/player/screenshot.c
@@ -233,7 +233,10 @@ static char *create_fname(struct MPContext *mpctx, char *template,
}
res = talloc_strdup_append(res, template);
- return talloc_asprintf_append(res, ".%s", file_ext);
+ res = talloc_asprintf_append(res, ".%s", file_ext);
+ char *fname = mp_get_user_path(NULL, res);
+ talloc_free(res);
+ return fname;
error_exit:
talloc_free(res);
diff --git a/video/out/gl_lcms.c b/video/out/gl_lcms.c
index 9999eca233..49a3a0346c 100644
--- a/video/out/gl_lcms.c
+++ b/video/out/gl_lcms.c
@@ -31,6 +31,7 @@
#include "mpvcore/bstr.h"
#include "mpvcore/mp_msg.h"
#include "mpvcore/m_option.h"
+#include "mpvcore/path.h"
#include "gl_video.h"
#include "gl_lcms.h"
@@ -90,11 +91,13 @@ static void lcms2_error_handler(cmsContext ctx, cmsUInt32Number code,
static struct bstr load_file(void *talloc_ctx, const char *filename)
{
struct bstr res = {0};
- stream_t *s = stream_open(filename, NULL);
+ char *fname = mp_get_user_path(NULL, filename);
+ stream_t *s = stream_open(fname, NULL);
if (s) {
res = stream_read_complete(s, talloc_ctx, 1000000000);
free_stream(s);
}
+ talloc_free(fname);
return res;
}