From be15be3a832cedf612c5b319ee3e381d2323cfee Mon Sep 17 00:00:00 2001 From: Dudemanguy Date: Fri, 24 Jan 2025 19:14:01 -0600 Subject: [PATCH] various: expand paths for all file/directory related options There's several path-related options that do not handle common shortcuts (like ~/). Fix this by using mp_get_user_path where appropriate which expands the path so users get more intuitive behavior. Fixes #15598. --- DOCS/interface-changes/option-paths.txt | 1 + audio/out/ao_pcm.c | 3 ++- common/encode_lavc.c | 5 ++++- common/playlist.c | 13 +++++++------ options/path.c | 2 +- player/loadfile.c | 7 +++++-- player/misc.c | 5 ++++- stream/stream_bluray.c | 4 +++- stream/stream_cdda.c | 8 ++++---- stream/stream_dvb.c | 5 ++--- stream/stream_dvdnav.c | 6 +++--- sub/sd_ass.c | 18 +++++++++++------- video/out/drm_common.c | 3 ++- video/out/vo_image.c | 11 +++++++---- 14 files changed, 56 insertions(+), 35 deletions(-) create mode 100644 DOCS/interface-changes/option-paths.txt diff --git a/DOCS/interface-changes/option-paths.txt b/DOCS/interface-changes/option-paths.txt new file mode 100644 index 0000000000..2292c7feae --- /dev/null +++ b/DOCS/interface-changes/option-paths.txt @@ -0,0 +1 @@ +all options that take filepaths as values are now properly expanded (i.e. ~/ -> /home/$USER) diff --git a/audio/out/ao_pcm.c b/audio/out/ao_pcm.c index cf13c478ac..ce55e70f03 100644 --- a/audio/out/ao_pcm.c +++ b/audio/out/ao_pcm.c @@ -28,6 +28,7 @@ #include "mpv_talloc.h" #include "options/m_option.h" +#include "options/path.h" #include "audio/format.h" #include "ao.h" #include "internal.h" @@ -109,7 +110,7 @@ static int init(struct ao *ao) { struct priv *priv = ao->priv; - char *outputfilename = priv->outputfilename; + char *outputfilename = mp_get_user_path(priv, ao->global, priv->outputfilename); if (!outputfilename) { outputfilename = talloc_strdup(priv, priv->waveheader ? "audiodump.wav" : "audiodump.pcm"); diff --git a/common/encode_lavc.c b/common/encode_lavc.c index 4835bd9918..2eb7a63314 100644 --- a/common/encode_lavc.c +++ b/common/encode_lavc.c @@ -31,6 +31,7 @@ #include "options/m_config.h" #include "options/m_option.h" #include "options/options.h" +#include "options/path.h" #include "osdep/timer.h" #include "video/out/vo.h" #include "mpv_talloc.h" @@ -135,7 +136,9 @@ struct encode_lavc_context *encode_lavc_init(struct mpv_global *global) p->muxer->oformat = ctx->oformat; - p->muxer->url = av_strdup(filename); + char *path = mp_get_user_path(NULL, global, filename); + p->muxer->url = av_strdup(path); + talloc_free(path); MP_HANDLE_OOM(p->muxer->url); return ctx; diff --git a/common/playlist.c b/common/playlist.c index 3f4c1b887a..ad2870c022 100644 --- a/common/playlist.c +++ b/common/playlist.c @@ -403,17 +403,16 @@ struct playlist *playlist_parse_file(const char *file, struct mp_cancel *cancel, struct mp_log *log = mp_log_new(NULL, global->log, "!playlist_parser"); mp_verbose(log, "Parsing playlist file %s...\n", file); + char *path = mp_get_user_path(NULL, global, file); struct demuxer_params p = { .force_format = "playlist", .stream_flags = STREAM_ORIGIN_DIRECT, }; - struct demuxer *d = demux_open_url(file, &p, cancel, global); - if (!d) { - talloc_free(log); - return NULL; - } - + struct demuxer *d = demux_open_url(path, &p, cancel, global); struct playlist *ret = NULL; + if (!d) + goto done; + if (d && d->playlist) { ret = talloc_zero(NULL, struct playlist); playlist_populate_playlist_path(d->playlist, file); @@ -434,7 +433,9 @@ struct playlist *playlist_parse_file(const char *file, struct mp_cancel *cancel, if (ret && !ret->num_entries) mp_warn(log, "Warning: empty playlist\n"); +done: talloc_free(log); + talloc_free(path); return ret; } diff --git a/options/path.c b/options/path.c index ab6f30f51c..54dfadc07e 100644 --- a/options/path.c +++ b/options/path.c @@ -115,7 +115,7 @@ void mp_init_paths(struct mpv_global *global, struct MPOpts *opts) if (!opts->load_config) force_configdir = ""; - global->configdir = talloc_strdup(global, force_configdir); + global->configdir = mp_get_user_path(global, global, force_configdir); } char *mp_find_user_file(void *talloc_ctx, struct mpv_global *global, diff --git a/player/loadfile.c b/player/loadfile.c index bf707ae56a..57d9290986 100644 --- a/player/loadfile.c +++ b/player/loadfile.c @@ -854,8 +854,11 @@ int mp_add_external_file(struct MPContext *mpctx, char *filename, mp_core_unlock(mpctx); + char *path = mp_get_user_path(NULL, mpctx->global, filename); struct demuxer *demuxer = - demux_open_url(filename, ¶ms, cancel, mpctx->global); + demux_open_url(path, ¶ms, cancel, mpctx->global); + talloc_free(path); + if (demuxer) enable_demux_thread(mpctx, demuxer); @@ -1059,7 +1062,7 @@ static void load_chapters(struct MPContext *mpctx) bool free_src = false; char *chapter_file = mpctx->opts->chapter_file; if (chapter_file && chapter_file[0]) { - chapter_file = talloc_strdup(NULL, chapter_file); + chapter_file = mp_get_user_path(NULL, mpctx->global, chapter_file); mp_core_unlock(mpctx); struct demuxer_params p = {.stream_flags = STREAM_ORIGIN_DIRECT}; struct demuxer *demux = demux_open_url(chapter_file, &p, diff --git a/player/misc.c b/player/misc.c index cbc65b5510..325f06eb52 100644 --- a/player/misc.c +++ b/player/misc.c @@ -31,6 +31,7 @@ #include "options/options.h" #include "options/m_property.h" #include "options/m_config.h" +#include "options/path.h" #include "common/common.h" #include "common/encode.h" #include "common/playlist.h" @@ -269,6 +270,7 @@ int stream_dump(struct MPContext *mpctx, const char *source_filename) struct MPOpts *opts = mpctx->opts; bool ok = false; + char *filename = mp_get_user_path(NULL, mpctx->global, opts->stream_dump); stream_t *stream = stream_create(source_filename, STREAM_ORIGIN_DIRECT | STREAM_READ, mpctx->playback_abort, mpctx->global); @@ -277,7 +279,7 @@ int stream_dump(struct MPContext *mpctx, const char *source_filename) int64_t size = stream_get_size(stream); - FILE *dest = fopen(opts->stream_dump, "wb"); + FILE *dest = fopen(filename, "wb"); if (!dest) { MP_ERR(mpctx, "Error opening dump file: %s\n", mp_strerror(errno)); goto done; @@ -305,6 +307,7 @@ int stream_dump(struct MPContext *mpctx, const char *source_filename) ok &= fclose(dest) == 0; done: free_stream(stream); + talloc_free(filename); return ok ? 0 : -1; } diff --git a/stream/stream_bluray.c b/stream/stream_bluray.c index 737f0e63ff..7cccc1a538 100644 --- a/stream/stream_bluray.c +++ b/stream/stream_bluray.c @@ -425,7 +425,9 @@ static int bluray_stream_open_internal(stream_t *s) bd_set_debug_mask(0); /* open device */ - BLURAY *bd = bd_open(device, NULL); + char *device_tmp = mp_get_user_path(NULL, s->global, device); + BLURAY *bd = bd_open(device_tmp, NULL); + talloc_free(device_tmp); if (!bd) { MP_ERR(s, "Couldn't open Blu-ray device: %s\n", device); return STREAM_UNSUPPORTED; diff --git a/stream/stream_cdda.c b/stream/stream_cdda.c index a14b1ff0d3..96e505be9a 100644 --- a/stream/stream_cdda.c +++ b/stream/stream_cdda.c @@ -38,6 +38,7 @@ #include "options/m_option.h" #include "options/m_config.h" #include "options/options.h" +#include "options/path.h" #if !HAVE_GPL #error GPL only @@ -251,11 +252,11 @@ static int open_cdda(stream_t *st) int last_track; if (st->path[0]) { - p->device = st->path; + p->device = talloc_strdup(priv, st->path); } else if (p->cdda_device && p->cdda_device[0]) { - p->device = p->cdda_device; + p->device = mp_get_user_path(priv, st->global, p->cdda_device); } else { - p->device = DEFAULT_CDROM_DEVICE; + p->device = talloc_strdup(priv, DEFAULT_CDROM_DEVICE); } #if defined(__NetBSD__) @@ -311,7 +312,6 @@ static int open_cdda(stream_t *st) priv->cdp = paranoia_init(cdd); if (priv->cdp == NULL) { cdda_close(cdd); - free(priv); return STREAM_ERROR; } diff --git a/stream/stream_dvb.c b/stream/stream_dvb.c index b33ffbb913..891c05c8b9 100644 --- a/stream/stream_dvb.c +++ b/stream/stream_dvb.c @@ -1112,12 +1112,11 @@ dvb_state_t *dvb_get_state(stream_t *stream) continue; } - void *talloc_ctx = NULL; + void *talloc_ctx = talloc_new(NULL); char *conf_file; if (priv->opts->cfg_file && priv->opts->cfg_file[0]) { - conf_file = priv->opts->cfg_file; + conf_file = mp_get_user_path(talloc_ctx, global, priv->opts->cfg_file); } else { - talloc_ctx = talloc_new(NULL); conf_file = mp_find_config_file(talloc_ctx, global, conf_file_name); if (conf_file) { mp_verbose(log, "Ignoring other channels.conf files.\n"); diff --git a/stream/stream_dvdnav.c b/stream/stream_dvdnav.c index a27324d164..4f4bce1cf2 100644 --- a/stream/stream_dvdnav.c +++ b/stream/stream_dvdnav.c @@ -542,7 +542,7 @@ static void stream_dvdnav_close(stream_t *s) if (priv->dvd_speed) dvd_set_speed(s, priv->filename, -1); if (priv->filename) - free(priv->filename); + talloc_free(priv->filename); } static struct priv *new_dvdnav_stream(stream_t *stream, char *filename) @@ -553,14 +553,14 @@ static struct priv *new_dvdnav_stream(stream_t *stream, char *filename) if (!filename) return NULL; - if (!(priv->filename = strdup(filename))) + if (!(priv->filename = mp_get_user_path(NULL, stream->global, filename))) return NULL; priv->dvd_speed = priv->opts->speed; dvd_set_speed(stream, priv->filename, priv->dvd_speed); if (dvdnav_open(&(priv->dvdnav), priv->filename) != DVDNAV_STATUS_OK) { - free(priv->filename); + talloc_free(priv->filename); priv->filename = NULL; return NULL; } diff --git a/sub/sd_ass.c b/sub/sd_ass.c index 2ba2af5312..dc8884a4c0 100644 --- a/sub/sd_ass.c +++ b/sub/sd_ass.c @@ -29,6 +29,7 @@ #include "config.h" #include "options/m_config.h" #include "options/options.h" +#include "options/path.h" #include "common/common.h" #include "common/msg.h" #include "demux/demux.h" @@ -107,11 +108,14 @@ static const struct sd_filter_functions *const filters[] = { // Add default styles, if the track does not have any styles yet. // Apply style overrides if the user provides any. -static void mp_ass_add_default_styles(ASS_Track *track, struct mp_subtitle_opts *opts, - struct mp_subtitle_shared_opts *shared_opts, int order) +static void mp_ass_add_default_styles(struct sd *sd, ASS_Track *track, struct mp_subtitle_opts *opts, + struct mp_subtitle_shared_opts *shared_opts) { - if (opts->ass_styles_file && shared_opts->ass_style_override[order]) - ass_read_styles(track, opts->ass_styles_file, NULL); + if (opts->ass_styles_file && shared_opts->ass_style_override[sd->order]) { + char *file = mp_get_user_path(NULL, sd->global, opts->ass_styles_file); + ass_read_styles(track, file, NULL); + talloc_free(file); + } if (track->n_styles == 0) { if (!track->PlayResY) { @@ -126,7 +130,7 @@ static void mp_ass_add_default_styles(ASS_Track *track, struct mp_subtitle_opts mp_ass_set_style(style, track->PlayResY, opts->sub_style); } - if (shared_opts->ass_style_override[order]) + if (shared_opts->ass_style_override[sd->order]) ass_process_force_style(track); } @@ -254,7 +258,7 @@ static void assobjects_init(struct sd *sd) ctx->shadow_track = ass_new_track(ctx->ass_library); ctx->shadow_track->PlayResX = MP_ASS_FONT_PLAYRESX; ctx->shadow_track->PlayResY = MP_ASS_FONT_PLAYRESY; - mp_ass_add_default_styles(ctx->shadow_track, opts, shared_opts, sd->order); + mp_ass_add_default_styles(sd, ctx->shadow_track, opts, shared_opts); char *extradata = sd->codec->extradata; int extradata_size = sd->codec->extradata_size; @@ -265,7 +269,7 @@ static void assobjects_init(struct sd *sd) if (extradata) ass_process_codec_private(ctx->ass_track, extradata, extradata_size); - mp_ass_add_default_styles(ctx->ass_track, opts, shared_opts, sd->order); + mp_ass_add_default_styles(sd, ctx->ass_track, opts, shared_opts); #if LIBASS_VERSION >= 0x01302000 ass_set_check_readorder(ctx->ass_track, sd->opts->sub_clear_on_seek ? 0 : 1); diff --git a/video/out/drm_common.c b/video/out/drm_common.c index 9a30008e37..cd8818a585 100644 --- a/video/out/drm_common.c +++ b/video/out/drm_common.c @@ -44,6 +44,7 @@ #include "common/msg.h" #include "misc/ctype.h" #include "options/m_config.h" +#include "options/path.h" #include "osdep/io.h" #include "osdep/poll_wrapper.h" #include "osdep/timer.h" @@ -943,7 +944,7 @@ static bool card_has_connection(const char *path) static void get_primary_device_path(struct vo_drm_state *drm) { if (drm->opts->device_path) { - drm->card_path = talloc_strdup(drm, drm->opts->device_path); + drm->card_path = mp_get_user_path(drm, drm->vo->global, drm->opts->device_path); return; } diff --git a/video/out/vo_image.c b/video/out/vo_image.c index ea289dcea6..88c966057f 100644 --- a/video/out/vo_image.c +++ b/video/out/vo_image.c @@ -66,13 +66,16 @@ struct priv { struct vo_image_opts *opts; struct mp_image *current; + char *dir; int frame; }; static bool checked_mkdir(struct vo *vo, const char *buf) { - MP_INFO(vo, "Creating output directory '%s'...\n", buf); - if (mkdir(buf, 0755) < 0) { + struct priv *p = vo->priv; + p->dir = mp_get_user_path(vo, vo->global, buf); + MP_INFO(vo, "Creating output directory '%s'...\n", p->dir); + if (mkdir(p->dir, 0755) < 0) { char *errstr = mp_strerror(errno); if (errno == EEXIST) { struct stat stat_p; @@ -117,8 +120,8 @@ static void flip_page(struct vo *vo) char *filename = talloc_asprintf(t, "%08d.%s", p->frame, image_writer_file_ext(p->opts->opts)); - if (p->opts->outdir && strlen(p->opts->outdir)) - filename = mp_path_join(t, p->opts->outdir, filename); + if (p->dir && strlen(p->dir)) + filename = mp_path_join(t, p->dir, filename); MP_INFO(vo, "Saving %s\n", filename); write_image(p->current, p->opts->opts, filename, vo->global, vo->log, true);