diff --git a/options/options.c b/options/options.c index ebccc5976f82d..76a929a5ce81b 100644 --- a/options/options.c +++ b/options/options.c @@ -405,8 +405,8 @@ const m_option_t mp_opts[] = { OPT_FLAG("rebase-start-time", rebase_start_time, 0), - 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_REL_TIME("ab-loop-a", ab_loop[0], 0), + OPT_REL_TIME("ab-loop-b", ab_loop[1], 0), OPT_CHOICE_OR_INT("playlist-start", playlist_pos, 0, 0, INT_MAX, ({"auto", -1}, {"no", -1})), @@ -918,7 +918,6 @@ const struct MPOpts mp_default_opts = { .cache_pause = 1, .cache_pause_wait = 1.0, .chapterrange = {-1, -1}, - .ab_loop = {MP_NOPTS_VALUE, MP_NOPTS_VALUE}, .edition_id = -1, .default_max_pts_correction = -1, .correct_pts = 1, diff --git a/options/options.h b/options/options.h index 1c58ca14b1536..75a3bb7688ebf 100644 --- a/options/options.h +++ b/options/options.h @@ -239,7 +239,7 @@ typedef struct MPOpts { struct m_rel_time play_length; int rebase_start_time; int play_frames; - double ab_loop[2]; + struct m_rel_time ab_loop[2]; double step_sec; int position_resume; int position_save_on_quit; diff --git a/player/command.c b/player/command.c index 67cc1db250209..10d25aeee9be1 100644 --- a/player/command.c +++ b/player/command.c @@ -3411,18 +3411,20 @@ static int mp_property_ab_loop(void *ctx, struct m_property *prop, struct MPContext *mpctx = ctx; struct MPOpts *opts = mpctx->opts; if (action == M_PROPERTY_KEY_ACTION) { - double val; + struct m_rel_time val; if (mp_property_generic_option(mpctx, prop, M_PROPERTY_GET, &val) < 1) return M_PROPERTY_ERROR; - return property_time(action, arg, val); + double time = rel_time_to_abs(mpctx, val); + return property_time(action, arg, time); } int r = mp_property_generic_option(mpctx, prop, action, arg); if (r > 0 && action == M_PROPERTY_SET) { - mpctx->ab_loop_clip = mpctx->playback_pts < opts->ab_loop[1]; + double ab_loop_end_time = rel_time_to_abs(mpctx, opts->ab_loop[1]); + mpctx->ab_loop_clip = mpctx->playback_pts < ab_loop_end_time; if (strcmp(prop->name, "ab-loop-b") == 0) { - if (opts->ab_loop[1] != MP_NOPTS_VALUE && - mpctx->playback_pts <= opts->ab_loop[1]) + if (ab_loop_end_time != MP_NOPTS_VALUE && + mpctx->playback_pts <= ab_loop_end_time) mpctx->ab_loop_clip = true; } // Update if visible @@ -5429,15 +5431,18 @@ int run_command(struct MPContext *mpctx, struct mp_cmd *cmd, struct mpv_node *re break; case MP_CMD_AB_LOOP: { - double now = get_current_time(mpctx); - if (opts->ab_loop[0] == MP_NOPTS_VALUE) { + struct m_rel_time now = { + .pos = get_current_time(mpctx), + .type = REL_TIME_ABSOLUTE + }; + if (rel_time_to_abs(mpctx, opts->ab_loop[0]) == MP_NOPTS_VALUE) { mp_property_do("ab-loop-a", M_PROPERTY_SET, &now, mpctx); show_property_osd(mpctx, "ab-loop-a", on_osd); - } else if (opts->ab_loop[1] == MP_NOPTS_VALUE) { + } else if (rel_time_to_abs(mpctx, opts->ab_loop[1]) == MP_NOPTS_VALUE) { mp_property_do("ab-loop-b", M_PROPERTY_SET, &now, mpctx); show_property_osd(mpctx, "ab-loop-b", on_osd); } else { - now = MP_NOPTS_VALUE; + now.type = REL_TIME_NONE; mp_property_do("ab-loop-a", M_PROPERTY_SET, &now, mpctx); mp_property_do("ab-loop-b", M_PROPERTY_SET, &now, mpctx); set_osd_msg(mpctx, osdl, osd_duration, "Clear A-B loop"); diff --git a/player/misc.c b/player/misc.c index 88767ce2d0bc6..8e226f106765c 100644 --- a/player/misc.c +++ b/player/misc.c @@ -108,11 +108,13 @@ double get_play_end_pts(struct MPContext *mpctx) // even though MP_NOPTS_VALUE is currently negative // it doesn't necessarily have to remain that way double ab_loop_start_time = get_ab_loop_start_time(mpctx); - if (mpctx->ab_loop_clip && opts->ab_loop[1] != MP_NOPTS_VALUE && - (ab_loop_start_time == MP_NOPTS_VALUE || opts->ab_loop[1] > ab_loop_start_time)) + double ab_loop_end_time = rel_time_to_abs(mpctx, opts->ab_loop[1]); + if (mpctx->ab_loop_clip && ab_loop_end_time != MP_NOPTS_VALUE && + (ab_loop_start_time == MP_NOPTS_VALUE || + ab_loop_end_time > ab_loop_start_time)) { - if (end == MP_NOPTS_VALUE || end > opts->ab_loop[1]) - end = opts->ab_loop[1]; + if (end == MP_NOPTS_VALUE || end > ab_loop_end_time) + end = ab_loop_end_time; } return end; } @@ -161,10 +163,8 @@ double get_play_start_pts(struct MPContext *mpctx) double get_ab_loop_start_time(struct MPContext *mpctx) { struct MPOpts *opts = mpctx->opts; - double ab_loop_start_time; - if (opts->ab_loop[0] != MP_NOPTS_VALUE) { - ab_loop_start_time = opts->ab_loop[0]; - } else { + double ab_loop_start_time = rel_time_to_abs(mpctx, opts->ab_loop[0]); + if (ab_loop_start_time == MP_NOPTS_VALUE) { /* * There is no check for MP_NOPTS_VALUE here * because that's exactly what we want to return diff --git a/player/osd.c b/player/osd.c index fd6b421849966..510bdb064a9c9 100644 --- a/player/osd.c +++ b/player/osd.c @@ -363,16 +363,17 @@ void set_osd_bar_chapters(struct MPContext *mpctx, int type) double len = get_time_length(mpctx); if (len > 0) { double ab_loop_start_time = get_ab_loop_start_time(mpctx); - if (opts->ab_loop[0] != MP_NOPTS_VALUE || + double ab_loop_end_time = rel_time_to_abs(mpctx, opts->ab_loop[1]); + if (rel_time_to_abs(mpctx, opts->ab_loop[0]) != MP_NOPTS_VALUE || (ab_loop_start_time != MP_NOPTS_VALUE && - opts->ab_loop[1] != MP_NOPTS_VALUE)) + ab_loop_end_time != MP_NOPTS_VALUE)) { MP_TARRAY_APPEND(mpctx, mpctx->osd_progbar.stops, mpctx->osd_progbar.num_stops, ab_loop_start_time / len); } - if (opts->ab_loop[1] != MP_NOPTS_VALUE) { + if (ab_loop_end_time != MP_NOPTS_VALUE) { MP_TARRAY_APPEND(mpctx, mpctx->osd_progbar.stops, - mpctx->osd_progbar.num_stops, opts->ab_loop[1] / len); + mpctx->osd_progbar.num_stops, ab_loop_end_time / len); } if (mpctx->osd_progbar.num_stops == 0) { int num = get_chapter_count(mpctx); diff --git a/player/playloop.c b/player/playloop.c index 852fc7c199cbd..0bee34b2144a1 100644 --- a/player/playloop.c +++ b/player/playloop.c @@ -393,7 +393,8 @@ static void mp_seek(MPContext *mpctx, struct seek_params seek) mp_notify(mpctx, MPV_EVENT_SEEK, NULL); mp_notify(mpctx, MPV_EVENT_TICK, NULL); - mpctx->ab_loop_clip = mpctx->last_seek_pts < opts->ab_loop[1]; + mpctx->ab_loop_clip = + mpctx->last_seek_pts < rel_time_to_abs(mpctx, opts->ab_loop[1]); mpctx->current_seek = seek; } @@ -781,7 +782,8 @@ static void handle_loop_file(struct MPContext *mpctx) struct MPOpts *opts = mpctx->opts; if (mpctx->stop_play == AT_END_OF_FILE && - (opts->ab_loop[0] != MP_NOPTS_VALUE || opts->ab_loop[1] != MP_NOPTS_VALUE)) + (rel_time_to_abs(mpctx, opts->ab_loop[0]) != MP_NOPTS_VALUE || + rel_time_to_abs(mpctx, opts->ab_loop[1]) != MP_NOPTS_VALUE)) { // Assumes execute_queued_seek() happens before next audio/video is // attempted to be decoded or filtered. @@ -1043,7 +1045,8 @@ static void handle_playback_restart(struct MPContext *mpctx) } mpctx->playing_msg_shown = true; mp_wakeup_core(mpctx); - mpctx->ab_loop_clip = mpctx->playback_pts < opts->ab_loop[1]; + mpctx->ab_loop_clip = + mpctx->playback_pts < rel_time_to_abs(mpctx, opts->ab_loop[1]); MP_VERBOSE(mpctx, "playback restart complete\n"); } }