diff options
author | Martin Herkt <lachs0r@srsfckn.biz> | 2016-10-19 19:09:00 +0200 |
---|---|---|
committer | Martin Herkt <lachs0r@srsfckn.biz> | 2016-10-19 19:09:00 +0200 |
commit | 5d74fa7dc0fa1617d1d11b69769423b1387ec785 (patch) | |
tree | 882752015b3500c91b8ab3a4d669696f23feb817 /player/playloop.c | |
parent | c226bc7616ab2ae9de6172660e9cf727f07dc374 (diff) | |
parent | a2fa0d0b68ce200598122145254f56ae1adff91e (diff) | |
download | mpv-5d74fa7dc0fa1617d1d11b69769423b1387ec785.tar.bz2 mpv-5d74fa7dc0fa1617d1d11b69769423b1387ec785.tar.xz |
Merge branch 'master' into release/current
Diffstat (limited to 'player/playloop.c')
-rw-r--r-- | player/playloop.c | 121 |
1 files changed, 92 insertions, 29 deletions
diff --git a/player/playloop.c b/player/playloop.c index ed4f57dd5c..18a51f33d0 100644 --- a/player/playloop.c +++ b/player/playloop.c @@ -28,6 +28,7 @@ #include "options/options.h" #include "common/common.h" #include "common/encode.h" +#include "options/m_config.h" #include "options/m_property.h" #include "common/playlist.h" #include "input/input.h" @@ -50,26 +51,66 @@ #include "client.h" #include "command.h" -// Wait until mp_input_wakeup(mpctx->input) is called, since the last time -// mp_wait_events() was called. (But see mp_process_input().) -void mp_wait_events(struct MPContext *mpctx, double sleeptime) +// Wait until mp_wakeup_core() is called, since the last time +// mp_wait_events() was called. +void mp_wait_events(struct MPContext *mpctx) { - mp_input_wait(mpctx->input, sleeptime); + if (mpctx->sleeptime > 0) + MP_STATS(mpctx, "start sleep"); + + mpctx->in_dispatch = true; + + mp_dispatch_queue_process(mpctx->dispatch, mpctx->sleeptime); + + while (mpctx->suspend_count) + mp_dispatch_queue_process(mpctx->dispatch, 100); + + mpctx->in_dispatch = false; + mpctx->sleeptime = INFINITY; + + if (mpctx->sleeptime > 0) + MP_STATS(mpctx, "end sleep"); +} + +// Set the timeout used when the playloop goes to sleep. This means the +// playloop will re-run as soon as the timeout elapses (or earlier). +// mp_set_timeout(c, 0) is essentially equivalent to mp_wakeup_core(c). +void mp_set_timeout(struct MPContext *mpctx, double sleeptime) +{ + mpctx->sleeptime = MPMIN(mpctx->sleeptime, sleeptime); + + // Can't adjust timeout if called from mp_dispatch_queue_process(). + if (mpctx->in_dispatch && isfinite(sleeptime)) + mp_wakeup_core(mpctx); +} + +// Cause the playloop to run. This can be called from any thread. If called +// from within the playloop itself, it will be run immediately again, instead +// of going to sleep in the next mp_wait_events(). +void mp_wakeup_core(struct MPContext *mpctx) +{ + mp_dispatch_interrupt(mpctx->dispatch); +} + +// Opaque callback variant of mp_wakeup_core(). +void mp_wakeup_core_cb(void *ctx) +{ + struct MPContext *mpctx = ctx; + mp_wakeup_core(mpctx); } // Process any queued input, whether it's user input, or requests from client // API threads. This also resets the "wakeup" flag used with mp_wait_events(). void mp_process_input(struct MPContext *mpctx) { - mp_dispatch_queue_process(mpctx->dispatch, 0); for (;;) { mp_cmd_t *cmd = mp_input_read_cmd(mpctx->input); if (!cmd) break; run_command(mpctx, cmd, NULL); mp_cmd_free(cmd); - mp_dispatch_queue_process(mpctx->dispatch, 0); } + mp_set_timeout(mpctx, mp_input_get_delay(mpctx->input)); } double get_relative_time(struct MPContext *mpctx) @@ -84,8 +125,7 @@ void pause_player(struct MPContext *mpctx) { mpctx->opts->pause = 1; - if (mpctx->video_out) - vo_control(mpctx->video_out, VOCTRL_RESTORE_SCREENSAVER, NULL); + update_screensaver_state(mpctx); if (mpctx->paused) goto end; @@ -101,6 +141,8 @@ void pause_player(struct MPContext *mpctx) if (mpctx->video_out) vo_set_paused(mpctx->video_out, true); + mp_wakeup_core(mpctx); + end: mp_notify(mpctx, mpctx->opts->pause ? MPV_EVENT_PAUSE : MPV_EVENT_UNPAUSE, 0); } @@ -109,8 +151,7 @@ void unpause_player(struct MPContext *mpctx) { mpctx->opts->pause = 0; - if (mpctx->video_out && mpctx->opts->stop_screensaver) - vo_control(mpctx->video_out, VOCTRL_KILL_SCREENSAVER, NULL); + update_screensaver_state(mpctx); if (!mpctx->paused) goto end; @@ -126,12 +167,25 @@ void unpause_player(struct MPContext *mpctx) if (mpctx->video_out) vo_set_paused(mpctx->video_out, false); + mp_wakeup_core(mpctx); + (void)get_relative_time(mpctx); // ignore time that passed during pause end: mp_notify(mpctx, mpctx->opts->pause ? MPV_EVENT_PAUSE : MPV_EVENT_UNPAUSE, 0); } +void update_screensaver_state(struct MPContext *mpctx) +{ + if (!mpctx->video_out) + return; + + bool saver_state = mpctx->opts->pause || !mpctx->opts->stop_screensaver || + !mpctx->playback_initialized; + vo_control(mpctx->video_out, saver_state ? VOCTRL_RESTORE_SCREENSAVER + : VOCTRL_KILL_SCREENSAVER, NULL); +} + void add_step_frame(struct MPContext *mpctx, int dir) { if (!mpctx->vo_chain) @@ -297,7 +351,7 @@ static void mp_seek(MPContext *mpctx, struct seek_params seek) mpctx->stop_play = KEEP_PLAYING; mpctx->start_timestamp = mp_time_sec(); - mpctx->sleeptime = 0; + mp_wakeup_core(mpctx); mp_notify(mpctx, MPV_EVENT_SEEK, NULL); mp_notify(mpctx, MPV_EVENT_TICK, NULL); @@ -314,6 +368,8 @@ void queue_seek(struct MPContext *mpctx, enum seek_type type, double amount, { struct seek_params *seek = &mpctx->seek; + mp_wakeup_core(mpctx); + if (mpctx->stop_play == AT_END_OF_FILE) mpctx->stop_play = KEEP_PLAYING; @@ -520,7 +576,7 @@ static void handle_osd_redraw(struct MPContext *mpctx) // Don't redraw immediately during a seek (makes it significantly slower). bool use_video = mpctx->vo_chain && !mpctx->vo_chain->is_coverart; if (use_video && mp_time_sec() - mpctx->start_timestamp < 0.1) { - mpctx->sleeptime = MPMIN(mpctx->sleeptime, 0.1); + mp_set_timeout(mpctx, 0.1); return; } bool want_redraw = osd_query_and_reset_want_redraw(mpctx->osd) || @@ -528,7 +584,7 @@ static void handle_osd_redraw(struct MPContext *mpctx) if (!want_redraw) return; vo_redraw(mpctx->video_out); - mpctx->sleeptime = 0; + mp_wakeup_core(mpctx); } static void handle_pause_on_low_cache(struct MPContext *mpctx) @@ -564,7 +620,7 @@ static void handle_pause_on_low_cache(struct MPContext *mpctx) unpause_player(mpctx); force_update = true; } - mpctx->sleeptime = MPMIN(mpctx->sleeptime, 0.2); + mp_set_timeout(mpctx, 0.2); } else { if (opts->cache_pausing && s.underrun) { bool prev_paused_user = opts->pause; @@ -589,10 +645,8 @@ static void handle_pause_on_low_cache(struct MPContext *mpctx) mpctx->next_cache_update = busy ? now + 0.25 : 0; force_update = true; } - if (mpctx->next_cache_update > 0) { - mpctx->sleeptime = - MPMIN(mpctx->sleeptime, mpctx->next_cache_update - now); - } + if (mpctx->next_cache_update > 0) + mp_set_timeout(mpctx, mpctx->next_cache_update - now); } if (mpctx->cache_buffer != cache_buffer) { @@ -628,7 +682,7 @@ static void handle_heartbeat_cmd(struct MPContext *mpctx) mpctx->next_heartbeat = now + opts->heartbeat_interval; (void)system(opts->heartbeat_cmd); } - mpctx->sleeptime = MPMIN(mpctx->sleeptime, mpctx->next_heartbeat - now); + mp_set_timeout(mpctx, mpctx->next_heartbeat - now); } } @@ -651,7 +705,7 @@ static void handle_cursor_autohide(struct MPContext *mpctx) } if (mpctx->mouse_timer > now) { - mpctx->sleeptime = MPMIN(mpctx->sleeptime, mpctx->mouse_timer - now); + mp_set_timeout(mpctx, mpctx->mouse_timer - now); } else { mouse_cursor_visible = false; } @@ -662,7 +716,7 @@ static void handle_cursor_autohide(struct MPContext *mpctx) if (opts->cursor_autohide_delay == -2) mouse_cursor_visible = false; - if (opts->cursor_autohide_fs && !opts->vo.fullscreen) + if (opts->cursor_autohide_fs && !opts->vo->fullscreen) mouse_cursor_visible = true; if (mouse_cursor_visible != mpctx->mouse_cursor_visible) @@ -678,6 +732,14 @@ static void handle_vo_events(struct MPContext *mpctx) mp_notify(mpctx, MP_EVENT_WIN_RESIZE, NULL); if (events & VO_EVENT_WIN_STATE) mp_notify(mpctx, MP_EVENT_WIN_STATE, NULL); + if (events & VO_EVENT_FULLSCREEN_STATE) { + // The only purpose of this is to update the fullscreen flag on the + // playloop side if it changes "from outside" on the VO. + int fs = mpctx->opts->vo->fullscreen; + vo_control(vo, VOCTRL_GET_FULLSCREEN, &fs); + m_config_set_option_raw_direct(mpctx->mconfig, + m_config_get_co(mpctx->mconfig, bstr0("fullscreen")), &fs, 0); + } } static void handle_sstep(struct MPContext *mpctx) @@ -813,6 +875,9 @@ int handle_force_window(struct MPContext *mpctx, bool force) .input_ctx = mpctx->input, .osd = mpctx->osd, .encode_lavc_ctx = mpctx->encode_lavc_ctx, + .opengl_cb_context = mpctx->gl_cb_ctx, + .wakeup_cb = mp_wakeup_core_cb, + .wakeup_ctx = mpctx, }; mpctx->video_out = init_best_video_out(mpctx->global, &ex); if (!mpctx->video_out) @@ -895,7 +960,7 @@ static void handle_playback_restart(struct MPContext *mpctx) if (mpctx->video_status == STATUS_READY) { mpctx->video_status = STATUS_PLAYING; get_relative_time(mpctx); - mpctx->sleeptime = 0; + mp_wakeup_core(mpctx); } if (mpctx->audio_status == STATUS_READY) { @@ -933,7 +998,7 @@ static void handle_playback_restart(struct MPContext *mpctx) } } mpctx->playing_msg_shown = true; - mpctx->sleeptime = 0; + mp_wakeup_core(mpctx); mpctx->ab_loop_clip = mpctx->playback_pts < opts->ab_loop[1]; MP_VERBOSE(mpctx, "playback restart complete\n"); } @@ -1013,7 +1078,7 @@ void run_playloop(struct MPContext *mpctx) if (mpctx->lavfi) { if (lavfi_process(mpctx->lavfi)) - mpctx->sleeptime = 0; + mp_wakeup_core(mpctx); if (lavfi_has_failed(mpctx->lavfi)) mpctx->stop_play = AT_END_OF_FILE; } @@ -1047,8 +1112,7 @@ void run_playloop(struct MPContext *mpctx) handle_osd_redraw(mpctx); - mp_wait_events(mpctx, mpctx->sleeptime); - mpctx->sleeptime = 1e9; // infinite for all practical purposes + mp_wait_events(mpctx); handle_pause_on_low_cache(mpctx); @@ -1064,8 +1128,7 @@ void run_playloop(struct MPContext *mpctx) void mp_idle(struct MPContext *mpctx) { handle_dummy_ticks(mpctx); - mp_wait_events(mpctx, mpctx->sleeptime); - mpctx->sleeptime = 100.0; + mp_wait_events(mpctx); mp_process_input(mpctx); handle_command_updates(mpctx); handle_cursor_autohide(mpctx); @@ -1085,7 +1148,7 @@ void idle_loop(struct MPContext *mpctx) if (need_reinit) { uninit_audio_out(mpctx); handle_force_window(mpctx, true); - mpctx->sleeptime = 0; + mp_wakeup_core(mpctx); mp_notify(mpctx, MPV_EVENT_IDLE, NULL); need_reinit = false; } |