summaryrefslogtreecommitdiffstats
path: root/player
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2020-03-21 14:01:38 +0100
committerwm4 <wm4@nowhere>2020-03-21 19:32:50 +0100
commit26ac6ead911bedf01b20d52e0696f70459ff0be2 (patch)
treebf5d797785610e8cfbc468a38807dd387a2c3ff5 /player
parent2a85e8a1864ebe1d7749dfd2748931d1f320e337 (diff)
downloadmpv-26ac6ead911bedf01b20d52e0696f70459ff0be2.tar.bz2
mpv-26ac6ead911bedf01b20d52e0696f70459ff0be2.tar.xz
player: fix subtle idle mode differences on early program start
If the user manages to run a "loadfile x append" command before the loop in mp_play_files() is entered, then the player could start playing these. This isn't expected, because appending files to the playlist in idle mode does not normally start playback. It could happen because there is a short time window where commands are processed before the loop is entered (such as running the command when a script is loaded). The idle mode semantics are pretty weird: if files were provided in advance (on the command line), then these should be played immediately. But if idle mode was already entered, and something is appended to the playlist using "append", i.e. without explicitly triggering playback, then it should remain in idle mode. Try to follow this by redefining PT_STOP to strictly mean idle mode. Remove the playlist->current check from idle_loop(), since only the stop_play field counts now (cf. what mp_set_playlist_entry() does). This actually introduces the possibility that playlist->current, and with it playlist-pos, are set to something, even though playback is not active or being started. Previously, this was only possible during state transitions, such as when changing playlist entries. Very annoyingly, this means the current way MPV_EVENT_IDLE was sent doesn't work anymore. Logically, idle mode can be "active" even if idle_loop() was not entered yet (between the time after mp_initialize() and before the loop in mp_play_files()). Instead of worrying about this, redo the "idle-active" property, and deprecate the event. See: #7543
Diffstat (limited to 'player')
-rw-r--r--player/command.c9
-rw-r--r--player/core.h2
-rw-r--r--player/loadfile.c16
-rw-r--r--player/main.c6
-rw-r--r--player/playloop.c4
5 files changed, 18 insertions, 19 deletions
diff --git a/player/command.c b/player/command.c
index 73c6d86712..938d9fa988 100644
--- a/player/command.c
+++ b/player/command.c
@@ -80,8 +80,6 @@ struct command_ctx {
// All properties, terminated with a {0} item.
struct m_property *properties;
- bool is_idle;
-
double last_seek_time;
double last_seek_pts;
double marked_pts;
@@ -1310,8 +1308,7 @@ static int mp_property_idle(void *ctx, struct m_property *prop,
int action, void *arg)
{
MPContext *mpctx = ctx;
- struct command_ctx *cmd = mpctx->command_ctx;
- return m_property_flag_ro(action, arg, cmd->is_idle);
+ return m_property_flag_ro(action, arg, mpctx->stop_play == PT_STOP);
}
static int mp_property_eof_reached(void *ctx, struct m_property *prop,
@@ -6036,10 +6033,6 @@ static void command_event(struct MPContext *mpctx, int event, void *arg)
ctx->marked_pts = MP_NOPTS_VALUE;
}
- if (event == MPV_EVENT_IDLE)
- ctx->is_idle = true;
- if (event == MPV_EVENT_START_FILE)
- ctx->is_idle = false;
if (event == MPV_EVENT_END_FILE || event == MPV_EVENT_FILE_LOADED) {
// Update chapters - does nothing if something else is visible.
set_osd_bar_chapters(mpctx, OSD_BAR_SEEK);
diff --git a/player/core.h b/player/core.h
index 0dbf56d2b1..5161b07799 100644
--- a/player/core.h
+++ b/player/core.h
@@ -43,7 +43,7 @@ enum stop_play_reason {
// also returned on unrecoverable playback errors
PT_NEXT_ENTRY, // prepare to play next entry in playlist
PT_CURRENT_ENTRY, // prepare to play mpctx->playlist->current
- PT_STOP, // stop playback, or transient state when going to next
+ PT_STOP, // stop playback / idle mode
PT_QUIT, // stop playback, quit player
PT_ERROR, // play next playlist entry (due to an error)
};
diff --git a/player/loadfile.c b/player/loadfile.c
index baedfbbcb7..8a8094c3e3 100644
--- a/player/loadfile.c
+++ b/player/loadfile.c
@@ -1378,7 +1378,7 @@ static void play_current_file(struct MPContext *mpctx)
mpctx->stop_play = 0;
process_hooks(mpctx, "on_before_start_file");
- if (mpctx->stop_play)
+ if (mpctx->stop_play || !mpctx->playlist->current)
return;
mp_notify(mpctx, MPV_EVENT_START_FILE, NULL);
@@ -1777,25 +1777,29 @@ void mp_play_files(struct MPContext *mpctx)
prepare_playlist(mpctx, mpctx->playlist);
for (;;) {
- assert(mpctx->stop_play);
idle_loop(mpctx);
+
if (mpctx->stop_play == PT_QUIT)
break;
- play_current_file(mpctx);
+ if (mpctx->playlist->current)
+ play_current_file(mpctx);
+
if (mpctx->stop_play == PT_QUIT)
break;
- struct playlist_entry *new_entry = mpctx->playlist->current;
+ struct playlist_entry *new_entry = NULL;
if (mpctx->stop_play == PT_NEXT_ENTRY || mpctx->stop_play == PT_ERROR ||
- mpctx->stop_play == AT_END_OF_FILE || mpctx->stop_play == PT_STOP)
+ mpctx->stop_play == AT_END_OF_FILE)
{
new_entry = mp_next_file(mpctx, +1, false, true);
+ } else if (mpctx->stop_play == PT_CURRENT_ENTRY) {
+ new_entry = mpctx->playlist->current;
}
mpctx->playlist->current = new_entry;
mpctx->playlist->current_was_replaced = false;
- mpctx->stop_play = PT_STOP;
+ mpctx->stop_play = new_entry ? PT_NEXT_ENTRY : PT_STOP;
if (!mpctx->playlist->current && mpctx->opts->player_idle_mode < 2)
break;
diff --git a/player/main.c b/player/main.c
index f3d591ecae..b0150b2b80 100644
--- a/player/main.c
+++ b/player/main.c
@@ -267,7 +267,7 @@ struct MPContext *mp_create(void)
.dispatch = mp_dispatch_create(mpctx),
.playback_abort = mp_cancel_new(mpctx),
.thread_pool = mp_thread_pool_create(mpctx, 0, 1, 30),
- .stop_play = PT_STOP,
+ .stop_play = PT_NEXT_ENTRY,
.play_dir = 1,
};
@@ -407,6 +407,10 @@ int mp_initialize(struct MPContext *mpctx, char **options)
if (opts->force_vo == 2 && handle_force_window(mpctx, false) < 0)
return -1;
+ // Needed to properly enter _initial_ idle mode if playlist empty.
+ if (mpctx->opts->player_idle_mode && !mpctx->playlist->num_entries)
+ mpctx->stop_play = PT_STOP;
+
MP_STATS(mpctx, "end init");
return 0;
diff --git a/player/playloop.c b/player/playloop.c
index f2ccf94410..f581e92f28 100644
--- a/player/playloop.c
+++ b/player/playloop.c
@@ -1253,9 +1253,7 @@ void idle_loop(struct MPContext *mpctx)
{
// ================= idle loop (STOP state) =========================
bool need_reinit = true;
- while (mpctx->opts->player_idle_mode && !mpctx->playlist->current
- && mpctx->stop_play != PT_QUIT)
- {
+ while (mpctx->opts->player_idle_mode && mpctx->stop_play == PT_STOP) {
if (need_reinit) {
uninit_audio_out(mpctx);
handle_force_window(mpctx, true);