summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/en/input.rst4
-rw-r--r--DOCS/man/en/mpv.rst4
-rw-r--r--DOCS/man/en/options.rst13
-rw-r--r--core/cfg-mplayer.h3
-rw-r--r--core/command.c6
-rw-r--r--core/defaultopts.c1
-rw-r--r--core/input/input.c1
-rw-r--r--core/input/input.h1
-rw-r--r--core/mp_core.h1
-rw-r--r--core/mplayer.c125
-rw-r--r--core/options.h2
-rw-r--r--core/path.c14
-rw-r--r--core/path.h2
-rw-r--r--etc/input.conf1
14 files changed, 177 insertions, 1 deletions
diff --git a/DOCS/man/en/input.rst b/DOCS/man/en/input.rst
index 7938502573..6d1072353f 100644
--- a/DOCS/man/en/input.rst
+++ b/DOCS/man/en/input.rst
@@ -169,6 +169,10 @@ run "<command>"
quit [<code>]
Exit the player using the given exit code.
+quit_watch_later
+ Exit player, and store current playback position. Playing that file later
+ will seek to the previous position on start.
+
sub_add "<file>"
Load the given subtitle file. It's not selected as current subtitle after
loading.
diff --git a/DOCS/man/en/mpv.rst b/DOCS/man/en/mpv.rst
index 9a62333983..2ebdcab506 100644
--- a/DOCS/man/en/mpv.rst
+++ b/DOCS/man/en/mpv.rst
@@ -90,6 +90,10 @@ p / SPACE
q / ESC
Stop playing and quit.
+Q
+ Like ``q``, but store the current playback position. Playing the same file
+ later will resume at the old playback position if possible.
+
U
Stop playing (and quit if ``--idle`` is not used).
diff --git a/DOCS/man/en/options.rst b/DOCS/man/en/options.rst
index 766c3ae562..3a98ca9c93 100644
--- a/DOCS/man/en/options.rst
+++ b/DOCS/man/en/options.rst
@@ -1329,6 +1329,10 @@
Do not play sound. With some demuxers this may not work. In those cases
you can try ``--ao=null`` instead.
+--no-resume-playback
+ Do not restore playback position from ``~/.mpv/watch_later/``.
+ See ``quit_watch_later`` input command.
+
--no-sub
Disables display of internal and external subtitles.
@@ -1791,6 +1795,15 @@
grayscale output with this option. Not supported by all video output
drivers.
+--save-position-on-quit
+ Always save the current playback position on quit. When this file is
+ played again later, the player will seek to the old playback position on
+ start. This affects any form of stopping playback (quitting, going to the
+ next file).
+
+ This behavior is disabled by default, but is always available when quitting
+ the player with Shift+Q.
+
--sb=<n>
Seek to byte position. Useful for playback from CD-ROM images or VOB files
with junk at the beginning. See also ``--start``.
diff --git a/core/cfg-mplayer.h b/core/cfg-mplayer.h
index 570c403f9c..f2e90d07d2 100644
--- a/core/cfg-mplayer.h
+++ b/core/cfg-mplayer.h
@@ -650,6 +650,9 @@ const m_option_t mplayer_opts[]={
{"{", NULL, CONF_TYPE_STORE, CONF_NOCFG, 0, 0, NULL},
{"}", NULL, CONF_TYPE_STORE, CONF_NOCFG, 0, 0, NULL},
+ OPT_FLAG("resume-playback", position_resume, 0),
+ OPT_FLAG("save-position-on-quit", position_save_on_quit, 0),
+
OPT_FLAG("ordered-chapters", ordered_chapters, 0),
OPT_INTRANGE("chapter-merge-threshold", chapter_merge_threshold, 0, 0, 10000),
diff --git a/core/command.c b/core/command.c
index 4831c939c0..72d6f34469 100644
--- a/core/command.c
+++ b/core/command.c
@@ -1856,6 +1856,12 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd)
mpctx->quit_player_rc = cmd->args[0].v.i;
break;
+ case MP_CMD_QUIT_WATCH_LATER:
+ mp_write_watch_later_conf(mpctx);
+ mpctx->stop_play = PT_QUIT;
+ mpctx->quit_player_rc = 0;
+ break;
+
case MP_CMD_PLAYLIST_NEXT:
case MP_CMD_PLAYLIST_PREV:
{
diff --git a/core/defaultopts.c b/core/defaultopts.c
index 03d697d732..b80bea5c1e 100644
--- a/core/defaultopts.c
+++ b/core/defaultopts.c
@@ -52,6 +52,7 @@ void set_default_mplayer_options(struct MPOpts *opts)
.ordered_chapters = 1,
.chapter_merge_threshold = 100,
.load_config = 1,
+ .position_resume = 1,
.stream_cache_min_percent = 20.0,
.stream_cache_seek_min_percent = 50.0,
.stream_cache_pause = 10.0,
diff --git a/core/input/input.c b/core/input/input.c
index 31b807d92f..7ba6b64cdc 100644
--- a/core/input/input.c
+++ b/core/input/input.c
@@ -126,6 +126,7 @@ static const mp_cmd_t mp_cmds[] = {
}},
{ MP_CMD_SPEED_MULT, "speed_mult", { ARG_FLOAT } },
{ MP_CMD_QUIT, "quit", { OARG_INT(0) } },
+ { MP_CMD_QUIT_WATCH_LATER, "quit_watch_later", },
{ MP_CMD_STOP, "stop", },
{ MP_CMD_FRAME_STEP, "frame_step", },
{ MP_CMD_FRAME_BACK_STEP, "frame_back_step", },
diff --git a/core/input/input.h b/core/input/input.h
index ff79222c9b..367abedfca 100644
--- a/core/input/input.h
+++ b/core/input/input.h
@@ -28,6 +28,7 @@ enum mp_command_type {
MP_CMD_IGNORE,
MP_CMD_SEEK,
MP_CMD_QUIT,
+ MP_CMD_QUIT_WATCH_LATER,
MP_CMD_PLAYLIST_NEXT,
MP_CMD_PLAYLIST_PREV,
MP_CMD_OSD,
diff --git a/core/mp_core.h b/core/mp_core.h
index 9588a77b24..2590eefb96 100644
--- a/core/mp_core.h
+++ b/core/mp_core.h
@@ -321,6 +321,7 @@ struct track *mp_track_by_tid(struct MPContext *mpctx, enum stream_type type,
bool mp_remove_track(struct MPContext *mpctx, struct track *track);
struct playlist_entry *mp_next_file(struct MPContext *mpctx, int direction);
int mp_get_cache_percent(struct MPContext *mpctx);
+void mp_write_watch_later_conf(struct MPContext *mpctx);
// timeline/tl_matroska.c
void build_ordered_chapter_timeline(struct MPContext *mpctx);
diff --git a/core/mplayer.c b/core/mplayer.c
index 9028cbafce..a6cc189df6 100644
--- a/core/mplayer.c
+++ b/core/mplayer.c
@@ -21,6 +21,7 @@
#include <stdbool.h>
#include <math.h>
#include <assert.h>
+#include <ctype.h>
#ifdef PTW32_STATIC_LIB
#include <pthread.h>
@@ -28,6 +29,7 @@
#include <libavutil/intreadwrite.h>
#include <libavutil/attributes.h>
+#include <libavutil/md5.h>
#include <libavcodec/version.h>
@@ -763,6 +765,121 @@ static void load_per_file_config(m_config_t *conf, const char * const file,
}
}
+static bool might_be_an_url(bstr f)
+{
+ return bstr_find0(f, "://") >= 0;
+}
+
+#define MP_WATCH_LATER_CONF "watch_later"
+
+static char *get_playback_resume_config_filename(const char *fname)
+{
+ char *res = NULL;
+ void *tmp = talloc_new(NULL);
+ const char *realpath = fname;
+ if (!might_be_an_url(bstr0(fname))) {
+ char *cwd = mp_getcwd(tmp);
+ if (!cwd)
+ goto exit;
+ realpath = mp_path_join(tmp, bstr0(cwd), bstr0(fname));
+ }
+ uint8_t md5[16];
+ av_md5_sum(md5, realpath, strlen(realpath));
+ char *conf = talloc_strdup(tmp, "");
+ for (int i = 0; i < 16; i++)
+ conf = talloc_asprintf_append(conf, "%02X", md5[i]);
+
+ conf = talloc_asprintf(tmp, "%s/%s", MP_WATCH_LATER_CONF, conf);
+
+ res = mp_find_user_config_file(conf);
+
+exit:
+ talloc_free(tmp);
+ return res;
+}
+
+static const char *backup_properties[] = {
+ "osd-level",
+ //"loop",
+ "speed",
+ "edition",
+ "pause",
+ //"volume",
+ //"mute",
+ "audio-delay",
+ //"balance",
+ "fullscreen",
+ "colormatrix",
+ "colormatrix-input-range",
+ "colormatrix-output-range",
+ "ontop",
+ "border",
+ "gamma",
+ "brightness",
+ "contrast",
+ "saturation",
+ "hue",
+ "panscan",
+ "aid",
+ "vid",
+ "sid",
+ "sub-delay",
+ "sub-pos",
+ //"sub-visibility",
+ "sub-scale",
+ "ass-use-margins",
+ "ass-vsfilter-aspect-compat",
+ "ass-style-override",
+ 0
+};
+
+void mp_write_watch_later_conf(struct MPContext *mpctx)
+{
+ void *tmp = talloc_new(NULL);
+ char *filename = mpctx->filename;
+ if (!filename)
+ goto exit;
+
+ double pos = get_current_time(mpctx);
+ int percent = get_percent_pos(mpctx);
+ if (percent < 1 || percent > 99 || pos == MP_NOPTS_VALUE)
+ goto exit;
+
+ mk_config_dir(MP_WATCH_LATER_CONF);
+
+ char *conffile = get_playback_resume_config_filename(mpctx->filename);
+ talloc_steal(tmp, conffile);
+ if (!conffile)
+ goto exit;
+
+ FILE *file = fopen(conffile, "wb");
+ if (!file)
+ goto exit;
+ fprintf(file, "start=%f\n", pos);
+ for (int i = 0; backup_properties[i]; i++) {
+ const char *pname = backup_properties[i];
+ char *tmp = NULL;
+ int r = mp_property_do(pname, M_PROPERTY_GET_STRING, &tmp, mpctx);
+ if (r == M_PROPERTY_OK)
+ fprintf(file, "%s=%s\n", pname, tmp);
+ talloc_free(tmp);
+ }
+ fclose(file);
+
+exit:
+ talloc_free(tmp);
+}
+
+static void load_playback_resume(m_config_t *conf, const char *file)
+{
+ char *fname = get_playback_resume_config_filename(file);
+ if (fname) {
+ try_load_config(conf, fname);
+ unlink(fname);
+ }
+ talloc_free(fname);
+}
+
static void load_per_file_options(m_config_t *conf,
struct playlist_param *params,
int params_count)
@@ -3988,7 +4105,9 @@ static void play_current_file(struct MPContext *mpctx)
load_per_output_config(mpctx->mconfig, PROFILE_CFG_AO,
opts->audio_driver_list[0]);
- assert(mpctx->playlist->current);
+ if (opts->position_resume)
+ load_playback_resume(mpctx->mconfig, mpctx->filename);
+
load_per_file_options(mpctx->mconfig, mpctx->playlist->current->params,
mpctx->playlist->current->num_params);
@@ -4283,6 +4402,9 @@ goto_enable_cache: ;
terminate_playback: // don't jump here after ao/vo/getch initialization!
+ if (opts->position_save_on_quit && mpctx->stop_play != PT_RESTART)
+ mp_write_watch_later_conf(mpctx);
+
if (mpctx->step_frames)
opts->pause = 1;
@@ -4566,6 +4688,7 @@ int main(int argc, char *argv[])
init_input(mpctx);
mpctx->playlist->current = mpctx->playlist->first;
+
play_files(mpctx);
exit_player(mpctx, mpctx->stop_play == PT_QUIT ? EXIT_QUIT : EXIT_EOF,
diff --git a/core/options.h b/core/options.h
index 4729d7ca6a..276745492d 100644
--- a/core/options.h
+++ b/core/options.h
@@ -125,6 +125,8 @@ typedef struct MPOpts {
int play_frames;
double step_sec;
int64_t seek_to_byte;
+ int position_resume;
+ int position_save_on_quit;
int pause;
int keep_open;
int audio_id;
diff --git a/core/path.c b/core/path.c
index ed53d5d465..e373df21ab 100644
--- a/core/path.c
+++ b/core/path.c
@@ -31,6 +31,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
+#include <errno.h>
#include "config.h"
#include "core/mp_msg.h"
#include "core/path.h"
@@ -178,6 +179,19 @@ char *mp_path_join(void *talloc_ctx, struct bstr p1, struct bstr p2)
have_separator ? "" : "/", BSTR_P(p2));
}
+char *mp_getcwd(void *talloc_ctx)
+{
+ char *wd = talloc_array(talloc_ctx, char, 20);
+ while (getcwd(wd, talloc_get_size(wd)) == NULL) {
+ if (errno != ERANGE) {
+ talloc_free(wd);
+ return NULL;
+ }
+ wd = talloc_realloc(talloc_ctx, wd, char, talloc_get_size(wd) * 2);
+ }
+ return wd;
+}
+
bool mp_path_exists(const char *path)
{
struct stat st;
diff --git a/core/path.h b/core/path.h
index 3711be44b9..a3033199df 100644
--- a/core/path.h
+++ b/core/path.h
@@ -51,6 +51,8 @@ struct bstr mp_dirname(const char *path);
*/
char *mp_path_join(void *talloc_ctx, struct bstr p1, struct bstr p2);
+char *mp_getcwd(void *talloc_ctx);
+
bool mp_path_exists(const char *path);
bool mp_path_isdir(const char *path);
diff --git a/etc/input.conf b/etc/input.conf
index 300f20c307..5dbb7c8a06 100644
--- a/etc/input.conf
+++ b/etc/input.conf
@@ -56,6 +56,7 @@ PGDWN seek -600
} speed_mult 2.0
BS set speed 1.0 # reset speed to normal
q quit
+Q quit_watch_later
q {encode} quit
ESC quit
p cycle pause # toggle pause/playback mode