diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index 1d18638f2a..f8b38d4911 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -346,6 +346,14 @@ Playback Control The loop-points can be adjusted at runtime with the corresponding properties. See also ``ab-loop`` command. +``--ab-loop-count=`` + Run A-B loops only N times, then ignore the A-B loop points (default: inf). + Every finished loop iteration will decrement this option by 1 (unless it is + set to ``inf`` or 0). ``inf`` means that looping goes on forever. If this + option is set to 0, A-B looping is ignored, and even the ``ab-loop`` command + will not enable looping again (the command will show ``(disabled)`` on the + OSD message if both loop points are set, but ``ab-loop-count`` is 0). + ``--ordered-chapters``, ``--no-ordered-chapters`` Enabled by default. Disable support for Matroska ordered chapters. mpv will not load or diff --git a/options/options.c b/options/options.c index 7eccfa03fb..d2388bcf07 100644 --- a/options/options.c +++ b/options/options.c @@ -427,6 +427,8 @@ static const m_option_t mp_opts[] = { OPT_TIME("ab-loop-a", ab_loop[0], 0, .min = MP_NOPTS_VALUE), OPT_TIME("ab-loop-b", ab_loop[1], 0, .min = MP_NOPTS_VALUE), + OPT_CHOICE_OR_INT("ab-loop-count", ab_loop_count, 0, 0, INT_MAX, + ({"inf", -1})), OPT_CHOICE_OR_INT("playlist-start", playlist_pos, 0, 0, INT_MAX, ({"auto", -1}, {"no", -1})), @@ -940,6 +942,7 @@ static const struct MPOpts mp_default_opts = { .cache_pause = 1, .cache_pause_wait = 1.0, .ab_loop = {MP_NOPTS_VALUE, MP_NOPTS_VALUE}, + .ab_loop_count = -1, .edition_id = -1, .default_max_pts_correction = -1, .correct_pts = 1, diff --git a/options/options.h b/options/options.h index 06321d2fe2..bc0f1b3e89 100644 --- a/options/options.h +++ b/options/options.h @@ -232,6 +232,7 @@ typedef struct MPOpts { int rebase_start_time; int play_frames; double ab_loop[2]; + int ab_loop_count; double step_sec; int position_resume; int position_check_mtime; diff --git a/player/command.c b/player/command.c index 3f13c39a02..21c595ce57 100644 --- a/player/command.c +++ b/player/command.c @@ -3731,7 +3731,8 @@ static const struct property_osd_display { {"vf", "Video filters", .msg = "Video filters:\n${vf}"}, {"af", "Audio filters", .msg = "Audio filters:\n${af}"}, {"ab-loop-a", "A-B loop start"}, - {"ab-loop-b", .msg = "A-B loop: ${ab-loop-a} - ${ab-loop-b}"}, + {"ab-loop-b", .msg = "A-B loop: ${ab-loop-a} - ${ab-loop-b}" + "${?=ab-loop-count==0: (disabled)}"}, {"audio-device", "Audio device"}, {"hwdec", .msg = "Hardware decoding: ${hwdec-current}"}, {"video-aspect-override", "Aspect ratio override"}, diff --git a/player/misc.c b/player/misc.c index c3765e5055..f6a63ec7ef 100644 --- a/player/misc.c +++ b/player/misc.c @@ -123,6 +123,9 @@ bool get_ab_loop_times(struct MPContext *mpctx, double t[2]) t[0] = opts->ab_loop[0]; t[1] = opts->ab_loop[1]; + if (!opts->ab_loop_count) + return false; + if (t[0] == MP_NOPTS_VALUE || t[1] == MP_NOPTS_VALUE || t[0] == t[1]) return false; diff --git a/player/playloop.c b/player/playloop.c index 86f19fd79f..4f0efad275 100644 --- a/player/playloop.c +++ b/player/playloop.c @@ -885,6 +885,10 @@ static void handle_loop_file(struct MPContext *mpctx) double ab[2]; if (get_ab_loop_times(mpctx, ab) && mpctx->ab_loop_clip) { + if (opts->ab_loop_count > 0) { + opts->ab_loop_count--; + m_config_notify_change_opt_ptr(mpctx->mconfig, &opts->ab_loop_count); + } target = ab[0]; prec = MPSEEK_EXACT; } else if (opts->loop_file) {