player, client API: refactor cplayer init, reduce client API differences

Move the command line parsing and some other things to the common init
routine shared between command line player and client API. This means
they're using almost exactly the same code now.

The main intended side effect is that the client API will load mpv.conf;
though still only if config loading is enabled.

(The cplayer still avoids creating an extra thread, passes a command
line, and prints an exit status to the terminal. It also has some
different defaults.)
This commit is contained in:
wm4 2015-03-05 11:17:22 +01:00
parent dcabceb626
commit 2e26639155
5 changed files with 60 additions and 51 deletions

View File

@ -25,6 +25,10 @@ API changes
::
--- mpv 0.9.0 will be released ---
1.15 - mpv_initialize() will now load config files. This requires setting
the "config" and "config-dir" options. In particular, it will load
mpv.conf.
--- mpv 0.8.0 is released ---
1.14 - add mpv_wait_async_requests()
- the --msg-level option changes its native type from a flat string to

View File

@ -195,7 +195,7 @@ extern "C" {
* relational operators (<, >, <=, >=).
*/
#define MPV_MAKE_VERSION(major, minor) (((major) << 16) | (minor) | 0UL)
#define MPV_CLIENT_API_VERSION MPV_MAKE_VERSION(1, 14)
#define MPV_CLIENT_API_VERSION MPV_MAKE_VERSION(1, 15)
/**
* Return the MPV_CLIENT_API_VERSION the mpv source has been compiled with.
@ -360,8 +360,10 @@ const char *mpv_client_name(mpv_handle *ctx);
* equivalent to setting the --no-terminal option.
* (Technically, this also suppresses C signal handling.)
* - No config files will be loaded. This is roughly equivalent to using
* --no-config (but actually the code path for loading config files is
* disabled).
* --no-config. Since libmpv 1.15, you can actually re-enable this option,
* which will make libmpv load config files during mpv_initialize(). If you
* do this, you are strongly encouraged to set the "config-dir" option too.
* (Otherwise it will load the mpv command line player's config.)
* - Idle mode is enabled, which means the playback core will enter idle mode
* if there are no more files to play on the internal playlist, instead of
* exiting. This is equivalent to the --idle option.

View File

@ -516,11 +516,9 @@ static void *playback_thread(void *p)
int mpv_initialize(mpv_handle *ctx)
{
if (mp_initialize(ctx->mpctx) < 0)
if (mp_initialize(ctx->mpctx, NULL) < 0)
return MPV_ERROR_INVALID_PARAMETER;
mp_print_version(ctx->mpctx->log, false);
pthread_t thread;
if (pthread_create(&thread, NULL, playback_thread, ctx->mpctx) != 0)
return MPV_ERROR_NOMEM;

View File

@ -404,7 +404,7 @@ struct track *select_track(struct MPContext *mpctx, enum stream_type type,
// main.c
int mpv_main(int argc, char *argv[]);
int mp_initialize(struct MPContext *mpctx);
int mp_initialize(struct MPContext *mpctx, char **argv);
struct MPContext *mp_create(void);
void mp_destroy(struct MPContext *mpctx);
void mp_print_version(struct mp_log *log, int always);

View File

@ -112,6 +112,13 @@ static bool cas_terminal_owner(struct MPContext *old, struct MPContext *new)
return r;
}
static void update_logging(struct MPContext *mpctx)
{
mp_msg_update_msglevels(mpctx->global);
if (mpctx->opts->use_terminal && cas_terminal_owner(NULL, mpctx))
terminal_init();
}
void mp_print_version(struct mp_log *log, int always)
{
int v = always ? MSGL_INFO : MSGL_V;
@ -361,9 +368,9 @@ void wakeup_playloop(void *ctx)
// Finish mpctx initialization. This must be done after setting up all options.
// Some of the initializations depend on the options, and can't be changed or
// undone later.
// cplayer: true if called by the command line player, false for client API
// If argv is not NULL, apply them as command line player arguments.
// Returns: <0 on error, 0 on success.
int mp_initialize(struct MPContext *mpctx)
int mp_initialize(struct MPContext *mpctx, char **argv)
{
struct MPOpts *opts = mpctx->opts;
@ -375,10 +382,35 @@ int mp_initialize(struct MPContext *mpctx)
}
MP_STATS(mpctx, "start init");
if (mpctx->opts->use_terminal && cas_terminal_owner(NULL, mpctx))
terminal_init();
update_logging(mpctx);
mp_msg_update_msglevels(mpctx->global);
if (argv) {
// Preparse the command line, so we can init the terminal early.
m_config_preparse_command_line(mpctx->mconfig, mpctx->global, argv);
update_logging(mpctx);
MP_VERBOSE(mpctx, "Command line:");
for (int i = 0; argv[i]; i++)
MP_VERBOSE(mpctx, " '%s'", argv[i]);
MP_VERBOSE(mpctx, "\n");
}
mp_print_version(mpctx->log, false);
mp_parse_cfgfiles(mpctx);
update_logging(mpctx);
if (argv) {
int r = m_config_parse_mp_command_line(mpctx->mconfig, mpctx->playlist,
mpctx->global, argv);
if (r < 0)
return r <= M_OPT_EXIT ? -2 : -1;
update_logging(mpctx);
}
if (handle_help_options(mpctx))
return -2;
if (opts->slave_mode) {
MP_WARN(mpctx, "--slave-broken is deprecated (see manpage).\n");
@ -386,6 +418,9 @@ int mp_initialize(struct MPContext *mpctx)
m_config_set_option0(mpctx->mconfig, "input-file", "/dev/stdin");
}
if (!mpctx->playlist->first && !opts->player_idle_mode)
return -3;
mp_input_load(mpctx->input);
mp_input_set_cancel(mpctx->input, mpctx->playback_abort);
@ -457,6 +492,11 @@ int mp_initialize(struct MPContext *mpctx)
mpctx->ipc_ctx = mp_init_ipc(mpctx->clients, mpctx->global);
#endif
#ifdef _WIN32
if (opts->w32_priority > 0)
SetPriorityClass(GetCurrentProcess(), opts->w32_priority);
#endif
prepare_playlist(mpctx, mpctx->playlist);
MP_STATS(mpctx, "end init");
@ -475,50 +515,15 @@ int mpv_main(int argc, char *argv[])
if (verbose_env)
opts->verbose = atoi(verbose_env);
// Preparse the command line
m_config_preparse_command_line(mpctx->mconfig, mpctx->global, argv);
if (mpctx->opts->use_terminal && cas_terminal_owner(NULL, mpctx))
terminal_init();
mp_msg_update_msglevels(mpctx->global);
MP_VERBOSE(mpctx, "Command line:");
for (int i = 0; argv[i]; i++)
MP_VERBOSE(mpctx, " '%s'", argv[i]);
MP_VERBOSE(mpctx, "\n");
mp_print_version(mpctx->log, false);
mp_parse_cfgfiles(mpctx);
int r = m_config_parse_mp_command_line(mpctx->mconfig, mpctx->playlist,
mpctx->global, argv);
if (r < 0) {
if (r <= M_OPT_EXIT) {
return prepare_exit_cplayer(mpctx, EXIT_NONE);
} else {
return prepare_exit_cplayer(mpctx, EXIT_ERROR);
}
}
mp_msg_update_msglevels(mpctx->global);
if (handle_help_options(mpctx))
int r = mp_initialize(mpctx, argv);
if (r == -2) // help
return prepare_exit_cplayer(mpctx, EXIT_NONE);
if (!mpctx->playlist->first && !opts->player_idle_mode) {
if (r == -3) { // nothing to play
mp_print_version(mpctx->log, true);
MP_INFO(mpctx, "%s", mp_help_text);
return prepare_exit_cplayer(mpctx, EXIT_NONE);
}
#ifdef _WIN32
if (opts->w32_priority > 0)
SetPriorityClass(GetCurrentProcess(), opts->w32_priority);
#endif
if (mp_initialize(mpctx) < 0)
if (r < 0) // another error
return prepare_exit_cplayer(mpctx, EXIT_ERROR);
mp_play_files(mpctx);