mirror of https://github.com/mpv-player/mpv
mplayer: never exit mplayer from within the play loop
The only place exit_player() should be called is the main() function. exit_player() should be the only function allowed to call exit(). This makes it easier to guarantee proper deinitialization, and allows using the --leak-report flag without showing false positives. The quit slave command now sets a flag only. It uses the same mechanism that's normally used to advance to the next file on the playlist, so the rest of the playback path should be able to react to the quit command quickly enough. That is, the player should react just as fast to quit requests in practice as before this commit. In reinit_audio_chain(), the player was actually exited if init_audio_filters() failed. Reuse the normal error handling path to handle this condition.
This commit is contained in:
parent
c7be71ae71
commit
9a2f4e10e7
|
@ -2872,8 +2872,9 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd)
|
|||
break;
|
||||
|
||||
case MP_CMD_QUIT:
|
||||
exit_player_with_rc(mpctx, EXIT_QUIT,
|
||||
(cmd->nargs > 0) ? cmd->args[0].v.i : 0);
|
||||
mpctx->stop_play = PT_QUIT;
|
||||
mpctx->quit_player_rc = (cmd->nargs > 0) ? cmd->args[0].v.i : 0;
|
||||
break;
|
||||
|
||||
case MP_CMD_PLAYLIST_NEXT:
|
||||
case MP_CMD_PLAYLIST_PREV:
|
||||
|
|
|
@ -193,7 +193,6 @@ static int x11_errorhandler(Display * display, XErrorEvent * event)
|
|||
event->error_code, event->request_code, event->minor_code);
|
||||
|
||||
// abort();
|
||||
//exit_player("X11 error");
|
||||
return 0;
|
||||
#undef MSGLEN
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ enum stop_play_reason {
|
|||
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_QUIT, // stop playback, quit player
|
||||
};
|
||||
|
||||
enum exit_reason {
|
||||
|
@ -99,6 +100,9 @@ typedef struct MPContext {
|
|||
enum stop_play_reason stop_play;
|
||||
unsigned int initialized_flags; // which subsystems have been initialized
|
||||
|
||||
// Return code to use with PT_QUIT
|
||||
int quit_player_rc;
|
||||
|
||||
struct content_source *sources;
|
||||
int num_sources;
|
||||
struct timeline_part *timeline;
|
||||
|
@ -227,7 +231,6 @@ void uninit_player(struct MPContext *mpctx, unsigned int mask);
|
|||
void reinit_audio_chain(struct MPContext *mpctx);
|
||||
void init_vo_spudec(struct MPContext *mpctx);
|
||||
double playing_audio_pts(struct MPContext *mpctx);
|
||||
void exit_player_with_rc(struct MPContext *mpctx, enum exit_reason how, int rc);
|
||||
void add_subtitles(struct MPContext *mpctx, char *filename, float fps, int noerr);
|
||||
int reinit_video_chain(struct MPContext *mpctx);
|
||||
void pause_player(struct MPContext *mpctx);
|
||||
|
|
46
mplayer.c
46
mplayer.c
|
@ -652,7 +652,7 @@ void uninit_player(struct MPContext *mpctx, unsigned int mask)
|
|||
}
|
||||
}
|
||||
|
||||
void exit_player_with_rc(struct MPContext *mpctx, enum exit_reason how, int rc)
|
||||
static void exit_player(struct MPContext *mpctx, enum exit_reason how, int rc)
|
||||
{
|
||||
uninit_player(mpctx, INITIALIZED_ALL);
|
||||
#if defined(__MINGW32__) || defined(__CYGWIN__)
|
||||
|
@ -700,11 +700,6 @@ void exit_player_with_rc(struct MPContext *mpctx, enum exit_reason how, int rc)
|
|||
exit(rc);
|
||||
}
|
||||
|
||||
static void exit_player(struct MPContext *mpctx, enum exit_reason how)
|
||||
{
|
||||
exit_player_with_rc(mpctx, how, 1);
|
||||
}
|
||||
|
||||
#include "cfg-mplayer.h"
|
||||
|
||||
static int cfg_include(struct m_config *conf, char *filename)
|
||||
|
@ -714,14 +709,14 @@ static int cfg_include(struct m_config *conf, char *filename)
|
|||
|
||||
#define DEF_CONFIG "# Write your default config options here!\n\n\n"
|
||||
|
||||
static void parse_cfgfiles(struct MPContext *mpctx, m_config_t *conf)
|
||||
static bool parse_cfgfiles(struct MPContext *mpctx, m_config_t *conf)
|
||||
{
|
||||
struct MPOpts *opts = &mpctx->opts;
|
||||
char *conffile;
|
||||
int conffile_fd;
|
||||
if (!(opts->noconfig & 2) &&
|
||||
m_config_parse_config_file(conf, MPLAYER_CONFDIR "/mplayer.conf") < 0)
|
||||
exit_player(mpctx, EXIT_NONE);
|
||||
return false;
|
||||
if ((conffile = get_path("")) == NULL)
|
||||
mp_tmsg(MSGT_CPLAYER, MSGL_WARN, "Cannot find HOME directory.\n");
|
||||
else {
|
||||
|
@ -739,10 +734,11 @@ static void parse_cfgfiles(struct MPContext *mpctx, m_config_t *conf)
|
|||
}
|
||||
if (!(opts->noconfig & 1) &&
|
||||
m_config_parse_config_file(conf, conffile) < 0)
|
||||
exit_player(mpctx, EXIT_NONE);
|
||||
return false;
|
||||
free(conffile);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#define PROFILE_CFG_PROTOCOL "protocol."
|
||||
|
@ -1509,7 +1505,7 @@ void reinit_audio_chain(struct MPContext *mpctx)
|
|||
&ao->samplerate, &ao->channels, &ao->format)) {
|
||||
mp_tmsg(MSGT_CPLAYER, MSGL_ERR, "Error at audio filter chain "
|
||||
"pre-init!\n");
|
||||
exit_player(mpctx, EXIT_ERROR);
|
||||
goto init_error;
|
||||
}
|
||||
if (!ao->initialized) {
|
||||
ao->buffersize = opts->ao_buffersize;
|
||||
|
@ -3564,7 +3560,9 @@ static bool process_playlist_demuxer(struct MPContext *mpctx)
|
|||
static void idle_loop(struct MPContext *mpctx)
|
||||
{
|
||||
// ================= idle loop (STOP state) =========================
|
||||
while (mpctx->opts.player_idle_mode && !mpctx->playlist->current) {
|
||||
while (mpctx->opts.player_idle_mode && !mpctx->playlist->current
|
||||
&& mpctx->stop_play != PT_QUIT)
|
||||
{
|
||||
uninit_player(mpctx, INITIALIZED_AO | INITIALIZED_VO);
|
||||
mp_cmd_t *cmd;
|
||||
while (!(cmd = mp_input_get_cmd(mpctx->input, WAKEUP_PERIOD * 1000,
|
||||
|
@ -3818,7 +3816,7 @@ goto_enable_cache:
|
|||
}
|
||||
}
|
||||
#endif
|
||||
goto terminate_playback; // exit_player(_("Fatal error"));
|
||||
goto terminate_playback;
|
||||
}
|
||||
|
||||
/* display clip info */
|
||||
|
@ -4033,7 +4031,12 @@ static void play_files(struct MPContext *mpctx)
|
|||
{
|
||||
for (;;) {
|
||||
idle_loop(mpctx);
|
||||
if (mpctx->stop_play == PT_QUIT)
|
||||
break;
|
||||
|
||||
play_current_file(mpctx);
|
||||
if (mpctx->stop_play == PT_QUIT)
|
||||
break;
|
||||
|
||||
if (!mpctx->stop_play || mpctx->stop_play == AT_END_OF_FILE)
|
||||
mpctx->stop_play = PT_NEXT_ENTRY;
|
||||
|
@ -4127,7 +4130,7 @@ static bool handle_help_options(struct MPContext *mpctx)
|
|||
return opt_exit;
|
||||
}
|
||||
|
||||
static void load_codecs_conf(struct MPContext *mpctx)
|
||||
static bool load_codecs_conf(struct MPContext *mpctx)
|
||||
{
|
||||
/* Check codecs.conf. */
|
||||
if (!codecs_file || !parse_codec_cfg(codecs_file)) {
|
||||
|
@ -4135,13 +4138,14 @@ static void load_codecs_conf(struct MPContext *mpctx)
|
|||
if (!parse_codec_cfg(mem_ptr = get_path("codecs.conf"))) {
|
||||
if (!parse_codec_cfg(MPLAYER_CONFDIR "/codecs.conf")) {
|
||||
if (!parse_codec_cfg(NULL))
|
||||
exit_player_with_rc(mpctx, EXIT_NONE, 0);
|
||||
return false;
|
||||
mp_tmsg(MSGT_CPLAYER, MSGL_V,
|
||||
"Using built-in default codecs.conf.\n");
|
||||
}
|
||||
}
|
||||
free(mem_ptr); // release the buffer created by get_path()
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef PTW32_STATIC_LIB
|
||||
|
@ -4238,7 +4242,8 @@ int main(int argc, char *argv[])
|
|||
print_version(false);
|
||||
print_libav_versions();
|
||||
|
||||
parse_cfgfiles(mpctx, mpctx->mconfig);
|
||||
if (!parse_cfgfiles(mpctx, mpctx->mconfig))
|
||||
exit_player(mpctx, EXIT_NONE, 1);
|
||||
|
||||
mpctx->playlist = talloc_struct(mpctx, struct playlist, {0});
|
||||
if (m_config_parse_mp_command_line(mpctx->mconfig, mpctx->playlist,
|
||||
|
@ -4246,13 +4251,14 @@ int main(int argc, char *argv[])
|
|||
{
|
||||
mpctx->playlist->current = mpctx->playlist->first;
|
||||
} else {
|
||||
exit_player(mpctx, EXIT_ERROR);
|
||||
exit_player(mpctx, EXIT_ERROR, 1);
|
||||
}
|
||||
|
||||
load_codecs_conf(mpctx);
|
||||
if (!load_codecs_conf(mpctx))
|
||||
exit_player(mpctx, EXIT_ERROR, 1);
|
||||
|
||||
if (handle_help_options(mpctx))
|
||||
exit_player(mpctx, EXIT_NONE);
|
||||
exit_player(mpctx, EXIT_NONE, 1);
|
||||
|
||||
mp_msg(MSGT_CPLAYER, MSGL_V, "Configuration: " CONFIGURATION "\n");
|
||||
mp_tmsg(MSGT_CPLAYER, MSGL_V, "Command line:");
|
||||
|
@ -4264,7 +4270,7 @@ int main(int argc, char *argv[])
|
|||
// no file/vcd/dvd -> show HELP:
|
||||
print_version(true);
|
||||
mp_msg(MSGT_CPLAYER, MSGL_INFO, "%s", mp_gtext(help_text));
|
||||
exit_player_with_rc(mpctx, EXIT_NONE, 0);
|
||||
exit_player(mpctx, EXIT_NONE, 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PRIORITY
|
||||
|
@ -4281,7 +4287,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
play_files(mpctx);
|
||||
|
||||
exit_player_with_rc(mpctx, EXIT_EOF, 0);
|
||||
exit_player(mpctx, EXIT_EOF, mpctx->quit_player_rc);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ static int recursion_depth = 0;
|
|||
/// Setup the \ref Config from a config file.
|
||||
/** \param config The config object.
|
||||
* \param conffile Path to the config file.
|
||||
* \return 1 on sucess, -1 on error.
|
||||
* \return 1 on sucess, -1 on error, 0 if file not accessible.
|
||||
*/
|
||||
int m_config_parse_config_file(m_config_t *config, const char *conffile)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue