From 4bd6c91d9b4c4d35d0d71793933947861e45daad Mon Sep 17 00:00:00 2001 From: wm4 Date: Tue, 18 Nov 2014 00:09:42 +0100 Subject: command: implement A-B loops Probably needs to be polished a bit more. Also, might require a key binding that can set/clear the loop points in a more intuitive way. For now, something like this can be put into input.conf to use it: ctrl+y set ab-loop-a ${time-pos} # set A ctrl+x set ab-loop-b ${time-pos} # set B ctrl+c set ab-loop-a no # clear (mostly) Fixes #1241. --- player/command.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) (limited to 'player/command.c') diff --git a/player/command.c b/player/command.c index f6c20a6cb1..803558f7d9 100644 --- a/player/command.c +++ b/player/command.c @@ -74,6 +74,8 @@ struct command_ctx { double last_seek_time; double last_seek_pts; + double prev_pts; + struct cycle_counter *cycle_counters; int num_cycle_counters; @@ -2930,8 +2932,22 @@ static int mp_property_af(void *ctx, struct m_property *prop, return property_filter(prop, action, arg, ctx, STREAM_AUDIO); } +static int mp_property_ab_loop(void *ctx, struct m_property *prop, + int action, void *arg) +{ + MPContext *mpctx = ctx; + if (action == M_PROPERTY_KEY_ACTION) { + double val; + if (mp_property_generic_option(mpctx, prop, M_PROPERTY_GET, &val) < 1) + return M_PROPERTY_ERROR; + + return property_time(action, arg, val); + } + return mp_property_generic_option(mpctx, prop, action, arg); +} + static int mp_property_version(void *ctx, struct m_property *prop, - int action, void *arg) + int action, void *arg) { return m_property_strdup_ro(action, arg, mpv_version); } @@ -3257,6 +3273,9 @@ static const struct m_property mp_properties[] = { {"video-rotate", video_simple_refresh_property}, + {"ab-loop-a", mp_property_ab_loop}, + {"ab-loop-b", mp_property_ab_loop}, + #define PROPERTY_TV_COLOR(name, type) \ {name, mp_property_tv_color, (void *)(intptr_t)type} PROPERTY_TV_COLOR("tv-brightness", TV_COLOR_BRIGHTNESS), @@ -4515,15 +4534,42 @@ void command_init(struct MPContext *mpctx) mpctx->command_ctx = talloc(NULL, struct command_ctx); *mpctx->command_ctx = (struct command_ctx){ .last_seek_pts = MP_NOPTS_VALUE, + .prev_pts = MP_NOPTS_VALUE, }; } -void mp_notify(struct MPContext *mpctx, int event, void *arg) +static void command_event(struct MPContext *mpctx, int event, void *arg) { struct command_ctx *ctx = mpctx->command_ctx; + struct MPOpts *opts = mpctx->opts; + if (event == MPV_EVENT_START_FILE) ctx->last_seek_pts = MP_NOPTS_VALUE; + if (event == MPV_EVENT_TICK) { + double now = + mpctx->restart_complete ? mpctx->playback_pts : MP_NOPTS_VALUE; + if (now != MP_NOPTS_VALUE && opts->ab_loop[0] != MP_NOPTS_VALUE && + opts->ab_loop[1] != MP_NOPTS_VALUE) + { + if (ctx->prev_pts >= opts->ab_loop[0] && + ctx->prev_pts < opts->ab_loop[1] && + now >= opts->ab_loop[1]) + { + queue_seek(mpctx, MPSEEK_ABSOLUTE, opts->ab_loop[0], 1, false); + } + } + ctx->prev_pts = now; + } + if (event == MPV_EVENT_SEEK) { + ctx->prev_pts = MP_NOPTS_VALUE; + } +} + +void mp_notify(struct MPContext *mpctx, int event, void *arg) +{ + command_event(mpctx, event, arg); + mp_client_broadcast_event(mpctx, event, arg); } -- cgit v1.2.3