player: change the role of the "stop_play" and "playing" variable

Before this, mpctx->playing was often used to determine whether certain
new state could be added to the playback state. In particular this
affected external files (which added tracks and demuxers). The variable
was checked to prevent that they were added before the corresponding
uninit code. We want to make a small part of uninit asynchronous, but
mpctx->playing needs to stay in the place where it is. It can't be used
for this purpose anymore.

Use mpctx->stop_play instead. Make it never have the value 0 outside of
loading/playback. On unloading, it obviously has to be non-0.

Change some other code in playloop.c to use this, because it seems
slightly more correct. But mostly this is preparation for the following
commit.
This commit is contained in:
wm4 2018-05-19 18:25:54 +02:00
parent c24520b7f3
commit 8816e1117e
5 changed files with 23 additions and 18 deletions

View File

@ -5522,7 +5522,7 @@ static void cmd_track_add(void *p)
struct MPContext *mpctx = cmd->mpctx;
int type = *(int *)cmd->priv;
if (!mpctx->playing) {
if (mpctx->stop_play) {
cmd->success = false;
return;
}
@ -5623,7 +5623,7 @@ static void cmd_rescan_external_files(void *p)
struct mp_cmd_ctx *cmd = p;
struct MPContext *mpctx = cmd->mpctx;
if (!mpctx->playing) {
if (mpctx->stop_play) {
cmd->success = false;
return;
}

View File

@ -37,12 +37,13 @@
// definitions used internally by the core player code
enum stop_play_reason {
KEEP_PLAYING = 0, // must be 0, numeric values of others do not matter
KEEP_PLAYING = 0, // playback of a file is actually going on
// must be 0, numeric values of others do not matter
AT_END_OF_FILE, // file has ended, prepare to play next
// 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, clear playlist
PT_STOP, // stop playback, or transient state when going to next
PT_QUIT, // stop playback, quit player
PT_ERROR, // play next playlist entry (due to an error)
};

View File

@ -662,7 +662,7 @@ int mp_add_external_file(struct MPContext *mpctx, char *filename,
// The command could have overlapped with playback exiting. (We don't care
// if playback has started again meanwhile - weird, but not a problem.)
if (!mpctx->playing)
if (mpctx->stop_play)
goto err_out;
if (!demuxer)
@ -1248,6 +1248,8 @@ static void play_current_file(struct MPContext *mpctx)
struct MPOpts *opts = mpctx->opts;
double playback_start = -1e100;
assert(mpctx->stop_play);
mp_notify(mpctx, MPV_EVENT_START_FILE, NULL);
mp_cancel_reset(mpctx->playback_abort);
@ -1473,16 +1475,16 @@ static void play_current_file(struct MPContext *mpctx)
terminate_playback:
update_core_idle_state(mpctx);
process_hooks(mpctx, "on_unload");
if (mpctx->stop_play == KEEP_PLAYING)
mpctx->stop_play = AT_END_OF_FILE;
if (!mpctx->stop_play)
mpctx->stop_play = PT_ERROR;
if (mpctx->stop_play != AT_END_OF_FILE)
clear_audio_output_buffers(mpctx);
update_core_idle_state(mpctx);
process_hooks(mpctx, "on_unload");
if (mpctx->step_frames)
opts->pause = 1;
@ -1550,8 +1552,6 @@ terminate_playback:
if (mpctx->playing)
playlist_entry_unref(mpctx->playing);
// Note: a lot of things assume that the core won't be unlocked between
// uninitializing various playback-only resources (such as tracks).
mpctx->playing = NULL;
talloc_free(mpctx->filename);
mpctx->filename = NULL;
@ -1564,6 +1564,8 @@ terminate_playback:
} else {
mpctx->files_played++;
}
assert(mpctx->stop_play);
}
// Determine the next file to play. Note that if this function returns non-NULL,
@ -1629,6 +1631,7 @@ 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;
@ -1639,14 +1642,14 @@ void mp_play_files(struct MPContext *mpctx)
struct playlist_entry *new_entry = mpctx->playlist->current;
if (mpctx->stop_play == PT_NEXT_ENTRY || mpctx->stop_play == PT_ERROR ||
mpctx->stop_play == AT_END_OF_FILE || !mpctx->stop_play)
mpctx->stop_play == AT_END_OF_FILE || mpctx->stop_play == PT_STOP)
{
new_entry = mp_next_file(mpctx, +1, false, true);
}
mpctx->playlist->current = new_entry;
mpctx->playlist->current_was_replaced = false;
mpctx->stop_play = 0;
mpctx->stop_play = PT_STOP;
if (!mpctx->playlist->current && mpctx->opts->player_idle_mode < 2)
break;

View File

@ -283,6 +283,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,
};
pthread_mutex_init(&mpctx->abort_lock, NULL);

View File

@ -127,8 +127,8 @@ void update_core_idle_state(struct MPContext *mpctx)
{
bool eof = mpctx->video_status == STATUS_EOF &&
mpctx->audio_status == STATUS_EOF;
bool active = !mpctx->paused && mpctx->restart_complete && mpctx->playing &&
mpctx->in_playloop && !eof;
bool active = !mpctx->paused && mpctx->restart_complete &&
mpctx->stop_play && mpctx->in_playloop && !eof;
if (mpctx->playback_active != active) {
mpctx->playback_active = active;
@ -873,7 +873,7 @@ int handle_force_window(struct MPContext *mpctx, bool force)
{
// True if we're either in idle mode, or loading of the file has finished.
// It's also set via force in some stages during file loading.
bool act = !mpctx->playing || mpctx->playback_initialized || force;
bool act = mpctx->stop_play || mpctx->playback_initialized || force;
// On the other hand, if a video track is selected, but no video is ever
// decoded on it, then create the window.