diff --git a/player/audio.c b/player/audio.c index 7bcd5c87bb..7990a4b77b 100644 --- a/player/audio.c +++ b/player/audio.c @@ -334,7 +334,7 @@ static void reinit_audio_filters_and_output(struct MPContext *mpctx) if (!mp_audio_config_valid(&in_format)) { // We don't know the audio format yet - so configure it later as we're // resyncing. fill_audio_buffers() will call this function again. - mpctx->sleeptime = 0; + mp_wakeup_core(mpctx); return; } @@ -427,7 +427,7 @@ static void reinit_audio_filters_and_output(struct MPContext *mpctx) goto init_error; reset_audio_state(mpctx); ao_c->input_format = (struct mp_audio){0}; - mpctx->sleeptime = 0; // reinit with new format next time + mp_wakeup_core(mpctx); // reinit with new format next time return; } @@ -550,7 +550,7 @@ void reinit_audio_chain_src(struct MPContext *mpctx, struct lavfi_pad *src) mp_audio_buffer_reinit(ao_c->ao_buffer, &fmt); } - mpctx->sleeptime = 0; + mp_wakeup_core(mpctx); return; init_error: @@ -901,20 +901,20 @@ void fill_audio_out_buffers(struct MPContext *mpctx) return; } reinit_audio_filters_and_output(mpctx); - mpctx->sleeptime = 0; + mp_wakeup_core(mpctx); return; // try again next iteration } if (ao_c->ao_resume_time > mp_time_sec()) { double remaining = ao_c->ao_resume_time - mp_time_sec(); - mpctx->sleeptime = MPMIN(mpctx->sleeptime, remaining); + mp_set_timeout(mpctx, remaining); return; } if (mpctx->vo_chain && ao_c->pts_reset) { MP_VERBOSE(mpctx, "Reset playback due to audio timestamp reset.\n"); reset_playback_state(mpctx); - mpctx->sleeptime = 0; + mp_wakeup_core(mpctx); return; } @@ -965,7 +965,7 @@ void fill_audio_out_buffers(struct MPContext *mpctx) if (status == AD_WAIT) return; if (status == AD_NO_PROGRESS) { - mpctx->sleeptime = 0; + mp_wakeup_core(mpctx); return; } if (status == AD_NEW_FMT) { @@ -976,11 +976,11 @@ void fill_audio_out_buffers(struct MPContext *mpctx) if (mpctx->opts->gapless_audio < 1) uninit_audio_out(mpctx); reinit_audio_filters_and_output(mpctx); - mpctx->sleeptime = 0; + mp_wakeup_core(mpctx); return; // retry on next iteration } if (status == AD_ERR) - mpctx->sleeptime = 0; + mp_wakeup_core(mpctx); working = true; } @@ -1031,7 +1031,7 @@ void fill_audio_out_buffers(struct MPContext *mpctx) if (status != AD_OK && !mp_audio_buffer_samples(ao_c->ao_buffer)) mpctx->audio_status = STATUS_EOF; if (working || end_sync) - mpctx->sleeptime = 0; + mp_wakeup_core(mpctx); return; // continue on next iteration } @@ -1089,7 +1089,7 @@ void fill_audio_out_buffers(struct MPContext *mpctx) if (ao_eof_reached(mpctx->ao) || opts->gapless_audio) { mpctx->audio_status = STATUS_EOF; if (!was_eof) - mpctx->sleeptime = 0; + mp_wakeup_core(mpctx); } } } diff --git a/player/command.c b/player/command.c index bc103d0c6b..e0fbc23d06 100644 --- a/player/command.c +++ b/player/command.c @@ -316,6 +316,7 @@ static int mp_property_playback_speed(void *ctx, struct m_property *prop, case M_PROPERTY_SET: { mpctx->opts->playback_speed = *(double *)arg; update_playback_speed(mpctx); + mp_wakeup_core(mpctx); return M_PROPERTY_OK; } case M_PROPERTY_PRINT: @@ -864,6 +865,7 @@ static int mp_property_chapter(void *ctx, struct m_property *prop, return M_PROPERTY_UNAVAILABLE; if (!mpctx->stop_play) mpctx->stop_play = PT_NEXT_ENTRY; + mp_wakeup_core(mpctx); } } else { double pts = chapter_start_time(mpctx, chapter); @@ -949,6 +951,7 @@ static int mp_property_edition(void *ctx, struct m_property *prop, mpctx->opts->edition_id = edition; if (!mpctx->stop_play) mpctx->stop_play = PT_RELOAD_FILE; + mp_wakeup_core(mpctx);; } return M_PROPERTY_OK; } @@ -1135,6 +1138,7 @@ static int mp_property_angle(void *ctx, struct m_property *prop, reset_audio_state(mpctx); reset_video_state(mpctx); + mp_wakeup_core(mpctx); return ris == STREAM_OK ? M_PROPERTY_OK : M_PROPERTY_ERROR; case M_PROPERTY_GET_TYPE: { @@ -1819,6 +1823,7 @@ static int mp_property_audio_delay(void *ctx, struct m_property *prop, mpctx->opts->audio_delay = *(float *)arg; if (mpctx->ao_chain && mpctx->vo_chain) mpctx->delay += mpctx->opts->audio_delay - delay; + mp_wakeup_core(mpctx); return M_PROPERTY_OK; } return mp_property_generic_option(mpctx, prop, action, arg); @@ -1981,6 +1986,7 @@ static int property_switch_track(struct m_property *prop, int action, void *arg, track = mp_track_by_tid(mpctx, type, *(int *)arg); mp_switch_track_n(mpctx, order, type, track, FLAG_MARK_SELECTION); print_track_list(mpctx, "Track switched:"); + mp_wakeup_core(mpctx); } else { mpctx->opts->stream_id[order][type] = *(int *)arg; } @@ -2918,8 +2924,10 @@ static int property_osd_helper(void *ctx, struct m_property *prop, int action, void *arg) { MPContext *mpctx = ctx; - if (action == M_PROPERTY_SET) + if (action == M_PROPERTY_SET) { osd_changed(mpctx->osd); + mp_wakeup_core(mpctx); + } return mp_property_generic_option(mpctx, prop, action, arg); } @@ -3360,6 +3368,7 @@ static int mp_property_ab_loop(void *ctx, struct m_property *prop, } // Update if visible set_osd_bar_chapters(mpctx, OSD_BAR_SEEK); + mp_wakeup_core(mpctx); } return r; } @@ -3548,6 +3557,7 @@ static int access_options(struct m_property_action_arg *ka, bool local, return M_PROPERTY_ERROR; int flags = M_SETOPT_RUNTIME | (local ? M_SETOPT_BACKUP : 0); int r = m_config_set_option_raw(mpctx->mconfig, opt, ka->arg, flags); + mp_wakeup_core(mpctx); return r < 0 ? M_PROPERTY_ERROR : M_PROPERTY_OK; } case M_PROPERTY_GET_TYPE: @@ -4886,6 +4896,7 @@ int run_command(struct MPContext *mpctx, struct mp_cmd *cmd, struct mpv_node *re mpctx->stop_play = PT_QUIT; mpctx->quit_custom_rc = cmd->args[0].v.i; mpctx->has_quit_custom_rc = true; + mp_wakeup_core(mpctx); break; case MP_CMD_PLAYLIST_NEXT: @@ -4951,6 +4962,7 @@ int run_command(struct MPContext *mpctx, struct mp_cmd *cmd, struct mpv_node *re set_osd_msg(mpctx, osdl, osd_duration, "OSD level: %d", opts->osd_level); if (opts->osd_level == 0) set_osd_msg(mpctx, 0, 0, ""); + mp_wakeup_core(mpctx); break; } @@ -4990,6 +5002,7 @@ int run_command(struct MPContext *mpctx, struct mp_cmd *cmd, struct mpv_node *re mp_set_playlist_entry(mpctx, entry); } mp_notify(mpctx, MP_EVENT_CHANGE_PLAYLIST, NULL); + mp_wakeup_core(mpctx); break; } @@ -5009,6 +5022,7 @@ int run_command(struct MPContext *mpctx, struct mp_cmd *cmd, struct mpv_node *re mp_set_playlist_entry(mpctx, new ? new : mpctx->playlist->first); mp_notify(mpctx, MP_EVENT_CHANGE_PLAYLIST, NULL); + mp_wakeup_core(mpctx); } else { MP_ERR(mpctx, "Unable to load playlist %s.\n", filename); return -1; @@ -5030,6 +5044,7 @@ int run_command(struct MPContext *mpctx, struct mp_cmd *cmd, struct mpv_node *re playlist_remove(mpctx->playlist, e); } mp_notify(mpctx, MP_EVENT_CHANGE_PLAYLIST, NULL); + mp_wakeup_core(mpctx); break; } @@ -5045,6 +5060,7 @@ int run_command(struct MPContext *mpctx, struct mp_cmd *cmd, struct mpv_node *re mpctx->stop_play = PT_CURRENT_ENTRY; playlist_remove(mpctx->playlist, e); mp_notify(mpctx, MP_EVENT_CHANGE_PLAYLIST, NULL); + mp_wakeup_core(mpctx); break; } @@ -5069,6 +5085,7 @@ int run_command(struct MPContext *mpctx, struct mp_cmd *cmd, struct mpv_node *re playlist_clear(mpctx->playlist); if (mpctx->stop_play != PT_QUIT) mpctx->stop_play = PT_STOP; + mp_wakeup_core(mpctx); break; case MP_CMD_SHOW_PROGRESS: @@ -5076,6 +5093,7 @@ int run_command(struct MPContext *mpctx, struct mp_cmd *cmd, struct mpv_node *re (msg_osd ? OSD_SEEK_INFO_TEXT : 0) | (bar_osd ? OSD_SEEK_INFO_BAR : 0); mpctx->osd_force_update = true; + mp_wakeup_core(mpctx); break; case MP_CMD_TV_LAST_CHANNEL: { diff --git a/player/core.h b/player/core.h index 3fa2c102b4..c39f316276 100644 --- a/player/core.h +++ b/player/core.h @@ -511,6 +511,7 @@ void set_osd_bar_chapters(struct MPContext *mpctx, int type); // playloop.c void mp_wait_events(struct MPContext *mpctx, double sleeptime); +void mp_set_timeout(struct MPContext *mpctx, double sleeptime); void mp_wakeup_core(struct MPContext *mpctx); void mp_wakeup_core_cb(void *ctx); void mp_process_input(struct MPContext *mpctx); diff --git a/player/loadfile.c b/player/loadfile.c index e89047f0aa..abce5b3168 100644 --- a/player/loadfile.c +++ b/player/loadfile.c @@ -473,6 +473,7 @@ void mp_switch_track_n(struct MPContext *mpctx, int order, enum stream_type type } mp_notify(mpctx, MPV_EVENT_TRACK_SWITCHED, NULL); + mp_wakeup_core(mpctx); talloc_free(mpctx->track_layout_hash); mpctx->track_layout_hash = talloc_steal(mpctx, track_layout_hash(mpctx)); @@ -1329,4 +1330,5 @@ void mp_set_playlist_entry(struct MPContext *mpctx, struct playlist_entry *e) mpctx->playlist->current_was_replaced = false; if (!mpctx->stop_play) mpctx->stop_play = PT_CURRENT_ENTRY; + mp_wakeup_core(mpctx); } diff --git a/player/misc.c b/player/misc.c index 65aad50de7..eb4c1c031e 100644 --- a/player/misc.c +++ b/player/misc.c @@ -201,7 +201,7 @@ void error_on_track(struct MPContext *mpctx, struct track *track) if (mpctx->error_playing >= 0) mpctx->error_playing = MPV_ERROR_NOTHING_TO_PLAY; } - mpctx->sleeptime = 0; + mp_wakeup_core(mpctx); } int stream_dump(struct MPContext *mpctx, const char *source_filename) @@ -222,7 +222,8 @@ int stream_dump(struct MPContext *mpctx, const char *source_filename) (long long int)pos, (long long int)size); } stream_fill_buffer(stream); - mp_process_input(mpctx); + mp_wakeup_core(mpctx); // don't actually sleep + mp_idle(mpctx); // but process input } free_stream(stream); @@ -295,5 +296,6 @@ int mpctx_run_reentrant(struct MPContext *mpctx, void (*thread_fn)(void *arg), pthread_join(thread, NULL); done: pthread_mutex_destroy(&args.mutex); + mp_wakeup_core(mpctx); // avoid lost wakeups during waiting return success ? 0 : -1; } diff --git a/player/osd.c b/player/osd.c index 6f26e9361c..4dbdfe4024 100644 --- a/player/osd.c +++ b/player/osd.c @@ -304,7 +304,7 @@ static bool set_osd_msg_va(struct MPContext *mpctx, int level, int time, mpctx->osd_show_pos = false; mpctx->osd_msg_next_duration = time / 1000.0; mpctx->osd_force_update = true; - mpctx->sleeptime = 0; + mp_wakeup_core(mpctx); if (mpctx->osd_msg_next_duration <= 0) mpctx->osd_msg_visible = mp_time_sec(); return true; @@ -330,7 +330,6 @@ void set_osd_bar(struct MPContext *mpctx, int type, return; mpctx->osd_visible = mp_time_sec() + opts->osd_duration / 1000.0; - mpctx->sleeptime = 0; mpctx->osd_progbar.type = type; mpctx->osd_progbar.value = (val - min) / (max - min); mpctx->osd_progbar.num_stops = 0; @@ -340,6 +339,7 @@ void set_osd_bar(struct MPContext *mpctx, int type, mpctx->osd_progbar.num_stops, pos); } osd_set_progbar(mpctx->osd, &mpctx->osd_progbar); + mp_wakeup_core(mpctx); } // Update a currently displayed bar of the same type, without resetting the @@ -387,6 +387,7 @@ void set_osd_bar_chapters(struct MPContext *mpctx, int type) } } osd_set_progbar(mpctx->osd, &mpctx->osd_progbar); + mp_wakeup_core(mpctx); } // osd_function is the symbol appearing in the video status, such as OSD_PLAY @@ -397,7 +398,7 @@ void set_osd_function(struct MPContext *mpctx, int osd_function) mpctx->osd_function = osd_function; mpctx->osd_function_visible = mp_time_sec() + opts->osd_duration / 1000.0; mpctx->osd_force_update = true; - mpctx->sleeptime = 0; + mp_wakeup_core(mpctx); } void get_current_osd_sym(struct MPContext *mpctx, char *buf, size_t buf_size) @@ -504,7 +505,7 @@ void update_osd_msg(struct MPContext *mpctx) double delay = 0.050; // update the OSD at most this often double diff = now - mpctx->osd_last_update; if (diff < delay) { - mpctx->sleeptime = MPMIN(mpctx->sleeptime, delay - diff); + mp_set_timeout(mpctx, delay - diff); return; } } @@ -515,7 +516,7 @@ void update_osd_msg(struct MPContext *mpctx) if (mpctx->osd_visible) { double sleep = mpctx->osd_visible - now; if (sleep > 0) { - mpctx->sleeptime = MPMIN(mpctx->sleeptime, sleep); + mp_set_timeout(mpctx, sleep); mpctx->osd_idle_update = true; } else { mpctx->osd_visible = 0; @@ -527,7 +528,7 @@ void update_osd_msg(struct MPContext *mpctx) if (mpctx->osd_function_visible) { double sleep = mpctx->osd_function_visible - now; if (sleep > 0) { - mpctx->sleeptime = MPMIN(mpctx->sleeptime, sleep); + mp_set_timeout(mpctx, sleep); mpctx->osd_idle_update = true; } else { mpctx->osd_function_visible = 0; @@ -545,7 +546,7 @@ void update_osd_msg(struct MPContext *mpctx) if (mpctx->osd_msg_visible) { double sleep = mpctx->osd_msg_visible - now; if (sleep > 0) { - mpctx->sleeptime = MPMIN(mpctx->sleeptime, sleep); + mp_set_timeout(mpctx, sleep); mpctx->osd_idle_update = true; } else { talloc_free(mpctx->osd_msg_text); diff --git a/player/playloop.c b/player/playloop.c index f2f421021d..a8d2d1a695 100644 --- a/player/playloop.c +++ b/player/playloop.c @@ -57,6 +57,14 @@ void mp_wait_events(struct MPContext *mpctx, double sleeptime) mp_input_wait(mpctx->input, sleeptime); } +// 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); +} + // 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(). @@ -118,6 +126,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); } @@ -143,6 +153,8 @@ 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: @@ -314,7 +326,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); @@ -331,6 +343,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; @@ -537,7 +551,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) || @@ -545,7 +559,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) @@ -581,7 +595,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; @@ -606,10 +620,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) { @@ -645,7 +657,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); } } @@ -668,7 +680,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; } @@ -915,7 +927,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) { @@ -953,7 +965,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"); } @@ -1105,7 +1117,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; } diff --git a/player/scripting.c b/player/scripting.c index cb35b1bfd7..afa567ca6a 100644 --- a/player/scripting.c +++ b/player/scripting.c @@ -97,6 +97,7 @@ static void wait_loaded(struct MPContext *mpctx) { while (!mp_clients_all_initialized(mpctx)) mp_idle(mpctx); + mp_wakeup_core(mpctx); // avoid lost wakeups during waiting } static void mp_load_script(struct MPContext *mpctx, const char *fname) diff --git a/player/video.c b/player/video.c index e66426f24d..4c56ca1a00 100644 --- a/player/video.c +++ b/player/video.c @@ -706,7 +706,7 @@ static int video_feed_async_filter(struct MPContext *mpctx) if (vf_needs_input(vf) < 1) return 0; - mpctx->sleeptime = 0; // retry until done + mp_wakeup_core(mpctx); // retry until done return video_decode_and_filter(mpctx); } @@ -1376,7 +1376,7 @@ void write_video(struct MPContext *mpctx) if (mpctx->video_status == STATUS_DRAINING) { mpctx->time_frame -= get_relative_time(mpctx); - mpctx->sleeptime = MPMIN(mpctx->sleeptime, mpctx->time_frame); + mp_set_timeout(mpctx, mpctx->time_frame); if (mpctx->time_frame <= 0) { MP_VERBOSE(mpctx, "video EOF reached\n"); mpctx->video_status = STATUS_EOF; @@ -1391,7 +1391,7 @@ void write_video(struct MPContext *mpctx) mpctx->video_status = STATUS_PLAYING; if (r != VD_NEW_FRAME) { - mpctx->sleeptime = 0; // Decode more in next iteration. + mp_wakeup_core(mpctx); // Decode more in next iteration. return; } @@ -1519,7 +1519,7 @@ void write_video(struct MPContext *mpctx) mpctx->max_frames--; } - mpctx->sleeptime = 0; + mp_wakeup_core(mpctx); return; error: @@ -1527,5 +1527,5 @@ error: uninit_video_chain(mpctx); error_on_track(mpctx, track); handle_force_window(mpctx, true); - mpctx->sleeptime = 0; + mp_wakeup_core(mpctx); }