diff options
Diffstat (limited to 'player/main.c')
-rw-r--r-- | player/main.c | 208 |
1 files changed, 132 insertions, 76 deletions
diff --git a/player/main.c b/player/main.c index e0371cc5ca..c455a0641c 100644 --- a/player/main.c +++ b/player/main.c @@ -31,6 +31,7 @@ #include "osdep/priority.h" #include "osdep/terminal.h" #include "osdep/timer.h" +#include "osdep/threads.h" #include "common/av_log.h" #include "common/codecs.h" @@ -61,6 +62,7 @@ #include "video/out/vo.h" #include "core.h" +#include "client.h" #include "lua.h" #include "command.h" #include "screenshot.h" @@ -89,6 +91,8 @@ #endif #endif +static bool terminal_initialized; + const char mp_help_text[] = "Usage: mpv [options] [url|path/]filename\n" "\n" @@ -113,11 +117,20 @@ void mp_print_version(struct mp_log *log, int always) mp_msg(log, v, "\n"); } -static MP_NORETURN void exit_player(struct MPContext *mpctx, - enum exit_reason how) +static void shutdown_clients(struct MPContext *mpctx) { - int rc; - uninit_player(mpctx, INITIALIZED_ALL); + while (mpctx->clients && mp_clients_num(mpctx)) { + mp_client_broadcast_event(mpctx, MPV_EVENT_SHUTDOWN, NULL); + mp_dispatch_queue_process(mpctx->dispatch, 0); + mp_input_get_cmd(mpctx->input, 100, 1); + } + mp_clients_destroy(mpctx); +} + +void mp_destroy(struct MPContext *mpctx) +{ + if (mpctx->initialized) + uninit_player(mpctx, INITIALIZED_ALL); #if HAVE_ENCODING encode_lavc_finish(mpctx->encode_lavc_ctx); @@ -129,10 +142,7 @@ static MP_NORETURN void exit_player(struct MPContext *mpctx, #if HAVE_LUA mp_lua_uninit(mpctx); #endif - -#if HAVE_COCOA - cocoa_set_input_context(NULL); -#endif + shutdown_clients(mpctx); command_uninit(mpctx); @@ -141,14 +151,27 @@ static MP_NORETURN void exit_player(struct MPContext *mpctx, osd_free(mpctx->osd); #if HAVE_LIBASS - ass_library_done(mpctx->ass_library); - mpctx->ass_library = NULL; + if (mpctx->ass_library) + ass_library_done(mpctx->ass_library); #endif if (mpctx->opts->use_terminal) getch2_disable(); uninit_libav(mpctx->global); + mp_msg_uninit(mpctx->global); + talloc_free(mpctx); +} + +static MP_NORETURN void exit_player(struct MPContext *mpctx, + enum exit_reason how) +{ + int rc; + +#if HAVE_COCOA + cocoa_set_input_context(NULL); +#endif + if (how != EXIT_NONE) { const char *reason; switch (how) { @@ -183,11 +206,7 @@ static MP_NORETURN void exit_player(struct MPContext *mpctx, } } - // must be last since e.g. mp_msg uses option values - // that will be freed by this. - - mp_msg_uninit(mpctx->global); - talloc_free(mpctx); + mp_destroy(mpctx); #if HAVE_COCOA terminate_cocoa_application(); @@ -284,8 +303,6 @@ static void osdep_preinit(int *p_argc, char ***p_argv) if (pSetSearchPathMode) pSetSearchPathMode(BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE); #endif - - mp_time_init(); } static int cfg_include(void *ctx, char *filename, int flags) @@ -294,14 +311,10 @@ static int cfg_include(void *ctx, char *filename, int flags) return m_config_parse_config_file(mpctx->mconfig, filename, flags); } -static int mpv_main(int argc, char *argv[]) +struct MPContext *mp_create(void) { - osdep_preinit(&argc, &argv); - - if (argc >= 1) { - argc--; - argv++; - } + mp_time_init(); + GetCpuCaps(&gCpuCaps); struct MPContext *mpctx = talloc(NULL, MPContext); *mpctx = (struct MPContext){ @@ -309,6 +322,7 @@ static int mpv_main(int argc, char *argv[]) .term_osd_contents = talloc_strdup(mpctx, ""), .osd_progbar = { .type = -1 }, .playlist = talloc_struct(mpctx, struct playlist, {0}), + .dispatch = mp_dispatch_create(mpctx), }; mpctx->global = talloc_zero(mpctx, struct mpv_global); @@ -331,68 +345,35 @@ static int mpv_main(int argc, char *argv[]) mpctx->mconfig->use_profiles = true; mpctx->mconfig->is_toplevel = true; - struct MPOpts *opts = mpctx->opts; - mpctx->global->opts = opts; + mpctx->global->opts = mpctx->opts; - char *verbose_env = getenv("MPV_VERBOSE"); - if (verbose_env) - opts->verbose = atoi(verbose_env); - - // Preparse the command line - m_config_preparse_command_line(mpctx->mconfig, mpctx->global, argc, argv); - - mp_msg_update_msglevels(mpctx->global); - - if (opts->use_terminal) - terminal_init(); - - init_libav(mpctx->global); - GetCpuCaps(&gCpuCaps); screenshot_init(mpctx); mpctx->mixer = mixer_init(mpctx, mpctx->global); command_init(mpctx); + init_libav(mpctx->global); + mp_clients_init(mpctx); - mp_print_version(mpctx->log, false); - - if (!mp_parse_cfgfiles(mpctx)) - exit_player(mpctx, EXIT_ERROR); - - int r = m_config_parse_mp_command_line(mpctx->mconfig, mpctx->playlist, - mpctx->global, argc, argv); - if (r < 0) { - if (r <= M_OPT_EXIT) { - exit_player(mpctx, EXIT_NONE); - } else { - exit_player(mpctx, EXIT_ERROR); - } - } - - mp_msg_update_msglevels(mpctx->global); + return mpctx; +} - if (handle_help_options(mpctx)) - exit_player(mpctx, EXIT_NONE); +// 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 +// Returns: <0 on error, 0 on success. +int mp_initialize(struct MPContext *mpctx) +{ + struct MPOpts *opts = mpctx->opts; - MP_VERBOSE(mpctx, "Configuration: " CONFIGURATION "\n"); - MP_VERBOSE(mpctx, "Command line:"); - for (int i = 0; i < argc; i++) - MP_VERBOSE(mpctx, " '%s'", argv[i]); - MP_VERBOSE(mpctx, "\n"); + assert(!mpctx->initialized); - if (!mpctx->playlist->first && !opts->player_idle_mode) { - mp_print_version(mpctx->log, true); - MP_INFO(mpctx, "%s", mp_help_text); - exit_player(mpctx, EXIT_NONE); + if (mpctx->opts->use_terminal && !terminal_initialized) { + terminal_initialized = true; + terminal_init(); } -#if HAVE_PRIORITY - set_priority(); -#endif - mpctx->input = mp_input_init(mpctx->global); stream_set_interrupt_callback(mp_input_check_interrupt, mpctx->input); -#if HAVE_COCOA - cocoa_set_input_context(mpctx->input); -#endif #if HAVE_ENCODING if (opts->encode_output.file && *opts->encode_output.file) { @@ -400,7 +381,7 @@ static int mpv_main(int argc, char *argv[]) mpctx->global); if(!mpctx->encode_lavc_ctx) { MP_INFO(mpctx, "Encoding initialization failed."); - exit_player(mpctx, EXIT_ERROR); + return -1; } m_config_set_option0(mpctx->mconfig, "vo", "lavc"); m_config_set_option0(mpctx->mconfig, "ao", "lavc"); @@ -431,6 +412,9 @@ static int mpv_main(int argc, char *argv[]) mpctx->osd = osd_create(mpctx->global); + // From this point on, all mpctx members are initialized. + mpctx->initialized = true; + if (opts->force_vo) { opts->fixed_vo = 1; mpctx->video_out = init_best_video_out(mpctx->global, mpctx->input, @@ -438,7 +422,7 @@ static int mpv_main(int argc, char *argv[]) if (!mpctx->video_out) { MP_FATAL(mpctx, "Error opening/initializing " "the selected video_out (-vo) device.\n"); - exit_player(mpctx, EXIT_ERROR); + return -1; } mpctx->mouse_cursor_visible = true; mpctx->initialized_flags |= INITIALIZED_VO; @@ -460,6 +444,78 @@ static int mpv_main(int argc, char *argv[]) if (!mpctx->playlist->current) mpctx->playlist->current = mpctx->playlist->first; + return 0; +} + +static int mpv_main(int argc, char *argv[]) +{ + osdep_preinit(&argc, &argv); + + if (argc >= 1) { + argc--; + argv++; + } + + struct MPContext *mpctx = mp_create(); + struct MPOpts *opts = mpctx->opts; + + char *verbose_env = getenv("MPV_VERBOSE"); + if (verbose_env) + opts->verbose = atoi(verbose_env); + + // Preparse the command line + m_config_preparse_command_line(mpctx->mconfig, mpctx->global, argc, argv); + + if (mpctx->opts->use_terminal && !terminal_initialized) { + terminal_initialized = true; + terminal_init(); + } + + mp_msg_update_msglevels(mpctx->global); + + mp_print_version(mpctx->log, false); + + if (!mp_parse_cfgfiles(mpctx)) + exit_player(mpctx, EXIT_ERROR); + + int r = m_config_parse_mp_command_line(mpctx->mconfig, mpctx->playlist, + mpctx->global, argc, argv); + if (r < 0) { + if (r <= M_OPT_EXIT) { + exit_player(mpctx, EXIT_NONE); + } else { + exit_player(mpctx, EXIT_ERROR); + } + } + + mp_msg_update_msglevels(mpctx->global); + + if (handle_help_options(mpctx)) + exit_player(mpctx, EXIT_NONE); + + MP_VERBOSE(mpctx, "Configuration: " CONFIGURATION "\n"); + MP_VERBOSE(mpctx, "Command line:"); + for (int i = 0; i < argc; i++) + MP_VERBOSE(mpctx, " '%s'", argv[i]); + MP_VERBOSE(mpctx, "\n"); + + if (!mpctx->playlist->first && !opts->player_idle_mode) { + mp_print_version(mpctx->log, true); + MP_INFO(mpctx, "%s", mp_help_text); + exit_player(mpctx, EXIT_NONE); + } + +#if HAVE_PRIORITY + set_priority(); +#endif + + if (mp_initialize(mpctx) < 0) + exit_player(mpctx, EXIT_ERROR); + +#if HAVE_COCOA + cocoa_set_input_context(mpctx->input); +#endif + mp_play_files(mpctx); exit_player(mpctx, mpctx->stop_play == PT_QUIT ? EXIT_QUIT : mpctx->quit_player_rc); |