diff options
Diffstat (limited to 'mplayer.c')
-rw-r--r-- | mplayer.c | 2170 |
1 files changed, 1196 insertions, 974 deletions
@@ -4,7 +4,9 @@ #include <stdio.h> #include <stdlib.h> +#include <stdbool.h> #include "config.h" +#include "talloc.h" #if defined(__MINGW32__) || defined(__CYGWIN__) #define _UWIN 1 /*disable Non-underscored versions of non-ANSI functions as otherwise int eof would conflict with eof()*/ @@ -43,15 +45,18 @@ #include "m_option.h" #include "m_config.h" +#include "mplayer.h" +#include "access_mpcontext.h" #include "m_property.h" #include "cfg-mplayer-def.h" -#include "libavutil/intreadwrite.h" +#include "ffmpeg_files/intreadwrite.h" #include "libavutil/avstring.h" #include "subreader.h" +#include "mp_osd.h" #include "libvo/video_out.h" #include "libvo/font_load.h" @@ -72,11 +77,11 @@ #include "osdep/getch2.h" #include "osdep/timer.h" - -#include "gui/interface.h" +#include "osdep/findfiles.h" #include "input/input.h" +const int under_mencoder = 0; int slave_mode=0; int player_idle_mode=0; int quiet=0; @@ -112,36 +117,21 @@ char *heartbeat_cmd; #include "playtree.h" #include "playtreeparser.h" -int import_playtree_playlist_into_gui(play_tree_t* my_playtree, m_config_t* config); -int import_initial_playtree_into_gui(play_tree_t* my_playtree, m_config_t* config, int enqueue); - //**************************************************************************// // Config //**************************************************************************// #include "parser-cfg.h" #include "parser-mpcmd.h" -m_config_t* mconfig; - //**************************************************************************// // Config file //**************************************************************************// static int cfg_inc_verbose(m_option_t *conf){ ++verbose; return 0;} -static int cfg_include(m_option_t *conf, char *filename){ - return m_config_parse_config_file(mconfig, filename); -} - #include "get_path.h" //**************************************************************************// -// XScreensaver -//**************************************************************************// - -void xscreensaver_heartbeat(void); - -//**************************************************************************// //**************************************************************************// // Input media streaming & demultiplexer: //**************************************************************************// @@ -166,6 +156,54 @@ static int max_framesize=0; #include "mixer.h" #include "mp_core.h" +#include "options.h" +#include "defaultopts.h" + +#define Exit_SIGILL_RTCpuSel _(\ +"- MPlayer crashed by an 'Illegal Instruction'.\n"\ +" It may be a bug in our new runtime CPU-detection code...\n"\ +" Please read DOCS/HTML/en/bugreports.html.\n") + +#define Exit_SIGILL _(\ +"- MPlayer crashed by an 'Illegal Instruction'.\n"\ +" It usually happens when you run it on a CPU different than the one it was\n"\ +" compiled/optimized for.\n"\ +" Verify this!\n") + +#define Exit_SIGSEGV_SIGFPE _(\ +"- MPlayer crashed by bad usage of CPU/FPU/RAM.\n"\ +" Recompile MPlayer with --enable-debug and make a 'gdb' backtrace and\n"\ +" disassembly. Details in DOCS/HTML/en/bugreports_what.html#bugreports_crash.\n") + +#define Exit_SIGCRASH _(\ +"- MPlayer crashed. This shouldn't happen.\n"\ +" It can be a bug in the MPlayer code _or_ in your drivers _or_ in your\n"\ +" gcc version. If you think it's MPlayer's fault, please read\n"\ +" DOCS/HTML/en/bugreports.html and follow the instructions there. We can't and\n"\ +" won't help unless you provide this information when reporting a possible bug.\n") + +#define SystemTooSlow _("\n\n"\ +" ************************************************\n"\ +" **** Your system is too SLOW to play this! ****\n"\ +" ************************************************\n\n"\ +"Possible reasons, problems, workarounds:\n"\ +"- Most common: broken/buggy _audio_ driver\n"\ +" - Try -ao sdl or use the OSS emulation of ALSA.\n"\ +" - Experiment with different values for -autosync, 30 is a good start.\n"\ +"- Slow video output\n"\ +" - Try a different -vo driver (-vo help for a list) or try -framedrop!\n"\ +"- Slow CPU\n"\ +" - Don't try to play a big DVD/DivX on a slow CPU! Try some of the lavdopts,\n"\ +" e.g. -vfm ffmpeg -lavdopts lowres=1:fast:skiploopfilter=all.\n"\ +"- Broken file\n"\ +" - Try various combinations of -nobps -ni -forceidx -mc 0.\n"\ +"- Slow media (NFS/SMB mounts, DVD, VCD etc)\n"\ +" - Try -cache 8192.\n"\ +"- Are you using -cache to play a non-interleaved AVI file?\n"\ +" - Try -nocache.\n"\ +"Read DOCS/HTML/en/video.html for tuning/speedup tips.\n"\ +"If none of this helps you, read DOCS/HTML/en/bugreports.html.\n\n") + //**************************************************************************// //**************************************************************************// @@ -175,24 +213,6 @@ static int max_framesize=0; int noconsolecontrols=0; //**************************************************************************// -// Not all functions in mplayer.c take the context as an argument yet -static MPContext mpctx_s = { - .osd_function = OSD_PLAY, - .begin_skip = MP_NOPTS_VALUE, - .play_tree_step = 1, - .global_sub_pos = -1, - .set_of_sub_pos = -1, - .file_format = DEMUXER_TYPE_UNKNOWN, - .loop_times = -1, -#ifdef CONFIG_DVBIN - .last_dvb_step = 1, -#endif -}; - -static MPContext *mpctx = &mpctx_s; - -int fixed_vo=0; - // benchmark: double video_time_usage=0; double vout_time_usage=0; @@ -206,21 +226,8 @@ int benchmark=0; int auto_quality=0; static int output_quality=0; -float playback_speed=1.0; - -int use_gui=0; - -#ifdef CONFIG_GUI -int enqueue=0; -#endif - static int list_properties = 0; -int osd_level=1; -// if nonzero, hide current OSD contents when GetTimerMS() reaches this -unsigned int osd_visible; -int osd_duration = 1000; - int term_osd = 1; static char* term_osd_esc = "\x1b[A\r\x1b[K"; static char* playing_msg = NULL; @@ -228,17 +235,12 @@ static char* playing_msg = NULL; static double seek_to_sec; static off_t seek_to_byte=0; static off_t step_sec=0; -static int loop_seek=0; static m_time_size_t end_at = { .type = END_AT_NONE, .pos = 0 }; // A/V sync: int autosync=0; // 30 might be a good default value. -// may be changed by GUI: (FIXME!) -float rel_seek_secs=0; -int abs_seek_pos=0; - // codecs: char **audio_codec_list=NULL; // override audio codec char **video_codec_list=NULL; // override video codec @@ -250,15 +252,10 @@ extern char *demuxer_name; // override demuxer extern char *audio_demuxer_name; // override audio demuxer extern char *sub_demuxer_name; // override sub demuxer -// streaming: -int audio_id=-1; -int video_id=-1; -int dvdsub_id=-2; int vobsub_id=-1; char* audio_lang=NULL; char* dvdsub_lang=NULL; static char* spudec_ifo=NULL; -char* filename=NULL; //"MI2-Trailer.avi"; int forced_subs_only=0; int file_filter=1; @@ -279,8 +276,6 @@ static char *stream_dump_name="stream.dump"; // A-V sync: static float default_max_pts_correction=-1;//0.01f; -static float max_pts_correction=0;//default_max_pts_correction; -static float c_total=0; float audio_delay=0; static int ignore_start=0; @@ -293,10 +288,6 @@ static int audio_output_format=-1; // AF_FORMAT_UNKNOWN static int play_n_frames=-1; static int play_n_frames_mf=-1; -// screen info: -char** video_driver_list=NULL; -char** audio_driver_list=NULL; - // sub: char *font_name=NULL; char *sub_font_name=NULL; @@ -311,8 +302,7 @@ char *vobsub_name=NULL; int subcc_enabled=0; int suboverlap_enabled = 1; -#include "libass/ass.h" -#include "libass/ass_mp.h" +#include "ass_mp.h" char* current_module=NULL; // for debugging @@ -322,9 +312,9 @@ char* current_module=NULL; // for debugging #ifdef CONFIG_MENU #include "m_struct.h" #include "libmenu/menu.h" -void vf_menu_pause_update(struct vf_instance_s* vf); +void vf_menu_pause_update(struct vf_instance* vf); extern vf_info_t vf_info_menu; -static vf_info_t* libmenu_vfs[] = { +static const vf_info_t* const libmenu_vfs[] = { &vf_info_menu, NULL }; @@ -342,11 +332,9 @@ static char* rtc_device; edl_record_ptr edl_records = NULL; ///< EDL entries memory area edl_record_ptr next_edl_record = NULL; ///< only for traversing edl_records -short edl_decision = 0; ///< 1 when an EDL operation has been made. FILE* edl_fd = NULL; ///< fd to write to when in -edlout mode. int use_filedir_conf; -static unsigned int initialized_flags=0; #include "mpcommon.h" #include "command.h" @@ -389,7 +377,15 @@ int mpctx_get_osd_function(MPContext *mpctx) return mpctx->osd_function; } -static int is_valid_metadata_type (metadata_t type) { +static float get_relative_time(struct MPContext *mpctx) +{ + unsigned int new_time = GetTimer(); + unsigned int delta = new_time - mpctx->last_time; + mpctx->last_time = new_time; + return delta * 0.000001; +} + +static int is_valid_metadata_type(struct MPContext *mpctx, metadata_t type) { switch (type) { /* check for valid video stream */ @@ -433,7 +429,7 @@ static int is_valid_metadata_type (metadata_t type) { return 1; } -static char *get_demuxer_info (char *tag) { +static char *get_demuxer_info(struct MPContext *mpctx, char *tag) { char **info = mpctx->demuxer->info; int n; @@ -447,19 +443,20 @@ static char *get_demuxer_info (char *tag) { return info[2*n+1] ? strdup (info[2*n+1]) : NULL; } -char *get_metadata (metadata_t type) { +char *get_metadata(struct MPContext *mpctx, metadata_t type) +{ char *meta = NULL; sh_audio_t * const sh_audio = mpctx->sh_audio; sh_video_t * const sh_video = mpctx->sh_video; - if (!is_valid_metadata_type (type)) + if (!is_valid_metadata_type(mpctx, type)) return NULL; switch (type) { case META_NAME: { - return strdup (mp_basename2 (filename)); + return strdup (mp_basename2 (mpctx->filename)); } case META_VIDEO_CODEC: @@ -522,25 +519,25 @@ char *get_metadata (metadata_t type) { /* check for valid demuxer */ case META_INFO_TITLE: - return get_demuxer_info ("Title"); + return get_demuxer_info(mpctx, "Title"); case META_INFO_ARTIST: - return get_demuxer_info ("Artist"); + return get_demuxer_info(mpctx, "Artist"); case META_INFO_ALBUM: - return get_demuxer_info ("Album"); + return get_demuxer_info(mpctx, "Album"); case META_INFO_YEAR: - return get_demuxer_info ("Year"); + return get_demuxer_info(mpctx, "Year"); case META_INFO_COMMENT: - return get_demuxer_info ("Comment"); + return get_demuxer_info(mpctx, "Comment"); case META_INFO_TRACK: - return get_demuxer_info ("Track"); + return get_demuxer_info(mpctx, "Track"); case META_INFO_GENRE: - return get_demuxer_info ("Genre"); + return get_demuxer_info(mpctx, "Genre"); default: break; @@ -563,24 +560,21 @@ static void mp_dvdnav_context_free(MPContext *ctx){ } #endif -void uninit_player(unsigned int mask){ - mask=initialized_flags&mask; +void uninit_player(struct MPContext *mpctx, unsigned int mask){ + mask=mpctx->initialized_flags&mask; mp_msg(MSGT_CPLAYER,MSGL_DBG2,"\n*** uninit(0x%X)\n",mask); if(mask&INITIALIZED_ACODEC){ - initialized_flags&=~INITIALIZED_ACODEC; + mpctx->initialized_flags&=~INITIALIZED_ACODEC; current_module="uninit_acodec"; if(mpctx->sh_audio) uninit_audio(mpctx->sh_audio); -#ifdef CONFIG_GUI - if (use_gui) guiGetEvent(guiSetAfilter, (char *)NULL); -#endif mpctx->sh_audio=NULL; mpctx->mixer.afilter = NULL; } if(mask&INITIALIZED_VCODEC){ - initialized_flags&=~INITIALIZED_VCODEC; + mpctx->initialized_flags&=~INITIALIZED_VCODEC; current_module="uninit_vcodec"; if(mpctx->sh_video) uninit_video(mpctx->sh_video); mpctx->sh_video=NULL; @@ -590,8 +584,25 @@ void uninit_player(unsigned int mask){ } if(mask&INITIALIZED_DEMUXER){ - initialized_flags&=~INITIALIZED_DEMUXER; + mpctx->initialized_flags&=~INITIALIZED_DEMUXER; current_module="free_demuxer"; + if (mpctx->num_sources) { + mpctx->demuxer = mpctx->sources[0].demuxer; + for (int i = 1; i < mpctx->num_sources; i++) { + free_stream(mpctx->sources[i].stream); + free_demuxer(mpctx->sources[i].demuxer); + } + } + talloc_free(mpctx->sources); + mpctx->sources = NULL; + mpctx->num_sources = 0; + talloc_free(mpctx->timeline); + mpctx->timeline = NULL; + mpctx->num_timeline_parts = 0; + talloc_free(mpctx->chapters); + mpctx->chapters = NULL; + mpctx->num_chapters = 0; + mpctx->video_offset = 0; if(mpctx->demuxer){ mpctx->stream=mpctx->demuxer->stream; free_demuxer(mpctx->demuxer); @@ -601,16 +612,16 @@ void uninit_player(unsigned int mask){ // kill the cache process: if(mask&INITIALIZED_STREAM){ - initialized_flags&=~INITIALIZED_STREAM; + mpctx->initialized_flags&=~INITIALIZED_STREAM; current_module="uninit_stream"; if(mpctx->stream) free_stream(mpctx->stream); mpctx->stream=NULL; } if(mask&INITIALIZED_VO){ - initialized_flags&=~INITIALIZED_VO; + mpctx->initialized_flags&=~INITIALIZED_VO; current_module="uninit_vo"; - mpctx->video_out->uninit(); + vo_destroy(mpctx->video_out); mpctx->video_out=NULL; #ifdef CONFIG_DVDNAV mp_dvdnav_context_free(mpctx); @@ -619,7 +630,7 @@ void uninit_player(unsigned int mask){ // Must be after libvo uninit, as few vo drivers (svgalib) have tty code. if(mask&INITIALIZED_GETCH2){ - initialized_flags&=~INITIALIZED_GETCH2; + mpctx->initialized_flags&=~INITIALIZED_GETCH2; current_module="uninit_getch2"; mp_msg(MSGT_CPLAYER,MSGL_DBG2,"\n[[[uninit getch2]]]\n"); // restore terminal: @@ -627,70 +638,57 @@ void uninit_player(unsigned int mask){ } if(mask&INITIALIZED_VOBSUB){ - initialized_flags&=~INITIALIZED_VOBSUB; + mpctx->initialized_flags&=~INITIALIZED_VOBSUB; current_module="uninit_vobsub"; if(vo_vobsub) vobsub_close(vo_vobsub); vo_vobsub=NULL; } if (mask&INITIALIZED_SPUDEC){ - initialized_flags&=~INITIALIZED_SPUDEC; + mpctx->initialized_flags&=~INITIALIZED_SPUDEC; current_module="uninit_spudec"; spudec_free(vo_spudec); vo_spudec=NULL; } if(mask&INITIALIZED_AO){ - initialized_flags&=~INITIALIZED_AO; + mpctx->initialized_flags&=~INITIALIZED_AO; current_module="uninit_ao"; if (mpctx->edl_muted) mixer_mute(&mpctx->mixer); - mpctx->audio_out->uninit(mpctx->eof?0:1); mpctx->audio_out=NULL; - } - -#ifdef CONFIG_GUI - if(mask&INITIALIZED_GUI){ - initialized_flags&=~INITIALIZED_GUI; - current_module="uninit_gui"; - guiDone(); - } -#endif - - if(mask&INITIALIZED_INPUT){ - initialized_flags&=~INITIALIZED_INPUT; - current_module="uninit_input"; - mp_input_uninit(); -#ifdef CONFIG_MENU - if (use_menu) - menu_uninit(); -#endif + mpctx->audio_out->uninit(mpctx->stop_play != AT_END_OF_FILE); + mpctx->audio_out=NULL; } current_module=NULL; } -void exit_player_with_rc(exit_reason_t how, int rc){ - +void exit_player_with_rc(struct MPContext *mpctx, exit_reason_t how, int rc) +{ if (mpctx->user_muted && !mpctx->edl_muted) mixer_mute(&mpctx->mixer); - uninit_player(INITIALIZED_ALL); + uninit_player(mpctx, INITIALIZED_ALL); #if defined(__MINGW32__) || defined(__CYGWIN__) timeEndPeriod(1); #endif #ifdef CONFIG_X11 -#ifdef CONFIG_GUI - if ( !use_gui ) + vo_uninit(mpctx->x11_state); // Close the X11 connection (if any is open). #endif - vo_uninit(); // Close the X11 connection (if any is open). + + current_module="uninit_input"; + mp_input_uninit(mpctx->input); +#ifdef CONFIG_MENU + if (use_menu) + menu_uninit(); #endif #ifdef CONFIG_FREETYPE current_module="uninit_font"; - if (sub_font && sub_font != vo_font) free_font_desc(sub_font); - sub_font = NULL; - if (vo_font) free_font_desc(vo_font); + if (mpctx->osd && mpctx->osd->sub_font != vo_font) + free_font_desc(mpctx->osd->sub_font); + free_font_desc(vo_font); vo_font = NULL; done_freetype(); #endif - free_osd_list(); + osd_free(mpctx->osd); #ifdef CONFIG_ASS ass_library_done(ass_library); @@ -699,25 +697,26 @@ void exit_player_with_rc(exit_reason_t how, int rc){ current_module="exit_player"; // free mplayer config - if(mconfig) - m_config_free(mconfig); + if(mpctx->mconfig) + m_config_free(mpctx->mconfig); if(mpctx->playtree) play_tree_free(mpctx->playtree, 1); + talloc_free(mpctx->key_fifo); if(edl_records != NULL) free(edl_records); // free mem allocated for EDL switch(how) { case EXIT_QUIT: - mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_ExitingHow,MSGTR_Exit_quit); + mp_tmsg(MSGT_CPLAYER,MSGL_INFO,"\nExiting... (%s)\n","Quit"); mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_EXIT=QUIT\n"); break; case EXIT_EOF: - mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_ExitingHow,MSGTR_Exit_eof); + mp_tmsg(MSGT_CPLAYER,MSGL_INFO,"\nExiting... (%s)\n","End of file"); mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_EXIT=EOF\n"); break; case EXIT_ERROR: - mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_ExitingHow,MSGTR_Exit_error); + mp_tmsg(MSGT_CPLAYER,MSGL_INFO,"\nExiting... (%s)\n","Fatal error"); mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_EXIT=ERROR\n"); break; default: @@ -728,8 +727,9 @@ void exit_player_with_rc(exit_reason_t how, int rc){ exit(rc); } -void exit_player(exit_reason_t how){ - exit_player_with_rc(how, 1); +static void exit_player(struct MPContext *mpctx, exit_reason_t how) +{ + exit_player_with_rc(mpctx, how, 1); } #ifndef __MINGW32__ @@ -750,7 +750,6 @@ static void exit_sighandler(int x){ if (!crash_debug || x != SIGTRAP) #endif ++sig_count; - if(initialized_flags==0 && sig_count>1) exit(1); if(sig_count==5) { /* We're crashing bad and can't uninit cleanly :( @@ -767,7 +766,7 @@ static void exit_sighandler(int x){ kill(getpid(),SIGKILL); #endif } - mp_msg(MSGT_CPLAYER,MSGL_FATAL,"\n" MSGTR_IntBySignal,x, + mp_tmsg(MSGT_CPLAYER,MSGL_FATAL,"\n" "\nMPlayer interrupted by signal %d in module: %s\n",x, current_module?current_module:"unknown" ); mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_SIGNAL=%d\n", x); @@ -781,15 +780,15 @@ static void exit_sighandler(int x){ return; // killed from keyboard (^C) or killed [-9] case SIGILL: #if CONFIG_RUNTIME_CPUDETECT - mp_msg(MSGT_CPLAYER,MSGL_FATAL,MSGTR_Exit_SIGILL_RTCpuSel); + mp_tmsg(MSGT_CPLAYER,MSGL_FATAL,Exit_SIGILL_RTCpuSel); #else - mp_msg(MSGT_CPLAYER,MSGL_FATAL,MSGTR_Exit_SIGILL); + mp_tmsg(MSGT_CPLAYER,MSGL_FATAL,Exit_SIGILL); #endif case SIGFPE: case SIGSEGV: - mp_msg(MSGT_CPLAYER,MSGL_FATAL,MSGTR_Exit_SIGSEGV_SIGFPE); + mp_tmsg(MSGT_CPLAYER,MSGL_FATAL,Exit_SIGSEGV_SIGFPE); default: - mp_msg(MSGT_CPLAYER,MSGL_FATAL,MSGTR_Exit_SIGCRASH); + mp_tmsg(MSGT_CPLAYER,MSGL_FATAL,Exit_SIGCRASH); #ifdef CONFIG_CRASH_DEBUG if (crash_debug) { int gdb_pid; @@ -815,19 +814,22 @@ static void exit_sighandler(int x){ exit(1); } -void mp_input_register_options(m_config_t* cfg); - #include "cfg-mplayer.h" -static void parse_cfgfiles( m_config_t* conf ) +static int cfg_include(m_option_t *conf, char *filename) +{ + return m_config_parse_config_file(conf->priv, filename); +} + +static void parse_cfgfiles(struct MPContext *mpctx, m_config_t* conf) { char *conffile; int conffile_fd; if (!disable_system_conf && m_config_parse_config_file(conf, MPLAYER_CONFDIR "/mplayer.conf") < 0) - exit_player(EXIT_NONE); + exit_player(mpctx, EXIT_NONE); if ((conffile = get_path("")) == NULL) { - mp_msg(MSGT_CPLAYER,MSGL_WARN,MSGTR_NoHomeDir); + mp_tmsg(MSGT_CPLAYER,MSGL_WARN,"Cannot find HOME directory.\n"); } else { #ifdef __MINGW32__ mkdir(conffile); @@ -836,16 +838,16 @@ if ((conffile = get_path("")) == NULL) { #endif free(conffile); if ((conffile = get_path("config")) == NULL) { - mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_GetpathProblem); + mp_tmsg(MSGT_CPLAYER,MSGL_ERR,"get_path(\"config\") problem\n"); } else { if ((conffile_fd = open(conffile, O_CREAT | O_EXCL | O_WRONLY, 0666)) != -1) { - mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_CreatingCfgFile, conffile); + mp_tmsg(MSGT_CPLAYER,MSGL_INFO,"Creating config file: %s\n", conffile); write(conffile_fd, default_config, strlen(default_config)); close(conffile_fd); } if (!disable_user_conf && m_config_parse_config_file(conf, conffile) < 0) - exit_player(EXIT_NONE); + exit_player(mpctx, EXIT_NONE); free(conffile); } } @@ -869,7 +871,7 @@ static void load_per_protocol_config (m_config_t* conf, const char *const file) p = m_config_get_profile (conf, protocol); if (p) { - mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_LoadingProtocolProfile, protocol); + mp_tmsg(MSGT_CPLAYER,MSGL_INFO,"Loading protocol-related profile '%s'\n", protocol); m_config_set_profile(conf,p); } } @@ -883,7 +885,7 @@ static void load_per_extension_config (m_config_t* conf, const char *const file) m_profile_t *p; /* does filename actually have an extension ? */ - str = strrchr (filename, '.'); + str = strrchr (file, '.'); if (!str) return; @@ -892,7 +894,7 @@ static void load_per_extension_config (m_config_t* conf, const char *const file) p = m_config_get_profile (conf, extension); if (p) { - mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_LoadingExtensionProfile, extension); + mp_tmsg(MSGT_CPLAYER,MSGL_INFO,"Loading extension-related profile '%s'\n", extension); m_config_set_profile(conf,p); } } @@ -909,7 +911,7 @@ static void load_per_output_config (m_config_t* conf, char *cfg, char *out) p = m_config_get_profile (conf, profile); if (p) { - mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_LoadingExtensionProfile, profile); + mp_tmsg(MSGT_CPLAYER,MSGL_INFO,"Loading extension-related profile '%s'\n", profile); m_config_set_profile(conf,p); } } @@ -923,7 +925,7 @@ static int try_load_config(m_config_t *conf, const char *file) struct stat st; if (stat(file, &st)) return 0; - mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_LoadingConfig, file); + mp_tmsg(MSGT_CPLAYER, MSGL_INFO, "Loading config '%s'\n", file); m_config_parse_config_file (conf, file); return 1; } @@ -976,42 +978,35 @@ static void load_per_file_config (m_config_t* conf, const char *const file) * cache filling) if the operation fails we use this function to check * if it was interrupted by the user. * The function returns a new value for eof. */ -static int libmpdemux_was_interrupted(int eof) { +static int libmpdemux_was_interrupted(struct MPContext *mpctx, int stop_play) +{ mp_cmd_t* cmd; - if((cmd = mp_input_get_cmd(0,0,0)) != NULL) { + if((cmd = mp_input_get_cmd(mpctx->input, 0,0,0)) != NULL) { switch(cmd->id) { case MP_CMD_QUIT: - exit_player_with_rc(EXIT_QUIT, (cmd->nargs > 0)? cmd->args[0].v.i : 0); + exit_player_with_rc(mpctx, EXIT_QUIT, (cmd->nargs > 0)? cmd->args[0].v.i : 0); case MP_CMD_PLAY_TREE_STEP: { - eof = (cmd->args[0].v.i > 0) ? PT_NEXT_ENTRY : PT_PREV_ENTRY; + stop_play = (cmd->args[0].v.i > 0) ? PT_NEXT_ENTRY : PT_PREV_ENTRY; mpctx->play_tree_step = (cmd->args[0].v.i == 0) ? 1 : cmd->args[0].v.i; } break; case MP_CMD_PLAY_TREE_UP_STEP: { - eof = (cmd->args[0].v.i > 0) ? PT_UP_NEXT : PT_UP_PREV; + stop_play = (cmd->args[0].v.i > 0) ? PT_UP_NEXT : PT_UP_PREV; } break; case MP_CMD_PLAY_ALT_SRC_STEP: { - eof = (cmd->args[0].v.i > 0) ? PT_NEXT_SRC : PT_PREV_SRC; + stop_play = (cmd->args[0].v.i > 0) ? PT_NEXT_SRC : PT_PREV_SRC; } break; } mp_cmd_free(cmd); } - return eof; + return stop_play; } #define mp_basename(s) (strrchr(s,'\\')==NULL?(mp_basename2(s)):(strrchr(s,'\\')+1)) -static int playtree_add_playlist(play_tree_t* entry) +static int playtree_add_playlist(struct MPContext *mpctx, play_tree_t* entry) { - play_tree_add_bpf(entry,filename); + play_tree_add_bpf(entry,mpctx->filename); -#ifdef CONFIG_GUI - if (use_gui) { - if (entry) { - import_playtree_playlist_into_gui(entry, mconfig); - play_tree_free_list(entry,1); - } - } else -#endif { if(!entry) { entry = mpctx->playtree_iter->tree; @@ -1037,11 +1032,11 @@ static int playtree_add_playlist(play_tree_t* entry) return PT_NEXT_SRC; } -void add_subtitles(char *filename, float fps, int noerr) +void add_subtitles(struct MPContext *mpctx, char *filename, float fps, int noerr) { sub_data *subd; #ifdef CONFIG_ASS - ass_track_t *asst = 0; + ASS_Track *asst = 0; #endif if (filename == NULL || mpctx->set_of_sub_size >= MAX_SUBTITLE_FILES) { @@ -1063,7 +1058,7 @@ void add_subtitles(char *filename, float fps, int noerr) #else if(!subd) #endif - mp_msg(MSGT_CPLAYER, noerr ? MSGL_WARN : MSGL_ERR, MSGTR_CantLoadSub, + mp_tmsg(MSGT_CPLAYER, noerr ? MSGL_WARN : MSGL_ERR, "Cannot load subtitles: %s\n", filename_recode(filename)); #ifdef CONFIG_ASS @@ -1077,36 +1072,15 @@ void add_subtitles(char *filename, float fps, int noerr) mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_FILE_SUB_FILENAME=%s\n", filename_recode(filename)); ++mpctx->set_of_sub_size; - mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_AddedSubtitleFile, mpctx->set_of_sub_size, + mp_tmsg(MSGT_CPLAYER, MSGL_INFO, "SUB: Added subtitle file (%d): %s\n", mpctx->set_of_sub_size, filename_recode(filename)); } -// FIXME: if/when the GUI calls this, global sub numbering gets (potentially) broken. -void update_set_of_subtitles(void) - // subdata was changed, set_of_sub... have to be updated. +void init_vo_spudec(struct MPContext *mpctx) { - sub_data ** const set_of_subtitles = mpctx->set_of_subtitles; - int i; - if (mpctx->set_of_sub_size > 0 && subdata == NULL) { // *subdata was deleted - for (i = mpctx->set_of_sub_pos + 1; i < mpctx->set_of_sub_size; ++i) - set_of_subtitles[i-1] = set_of_subtitles[i]; - set_of_subtitles[mpctx->set_of_sub_size-1] = NULL; - --mpctx->set_of_sub_size; - if (mpctx->set_of_sub_size > 0) subdata = set_of_subtitles[mpctx->set_of_sub_pos=0]; - } - else if (mpctx->set_of_sub_size > 0 && subdata != NULL) { // *subdata was changed - set_of_subtitles[mpctx->set_of_sub_pos] = subdata; - } - else if (mpctx->set_of_sub_size <= 0 && subdata != NULL) { // *subdata was added - set_of_subtitles[mpctx->set_of_sub_pos=mpctx->set_of_sub_size] = subdata; - ++mpctx->set_of_sub_size; - } -} - -void init_vo_spudec(void) { if (vo_spudec) spudec_free(vo_spudec); - initialized_flags &= ~INITIALIZED_SPUDEC; + mpctx->initialized_flags &= ~INITIALIZED_SPUDEC; vo_spudec = NULL; if (spudec_ifo) { unsigned int palette[16], width, height; @@ -1140,7 +1114,7 @@ void init_vo_spudec(void) { } if (vo_spudec!=NULL) { - initialized_flags|=INITIALIZED_SPUDEC; + mpctx->initialized_flags|=INITIALIZED_SPUDEC; mp_property_do("sub_forced_only", M_PROPERTY_SET, &forced_subs_only, mpctx); } } @@ -1197,15 +1171,25 @@ static void sadd_hhmmssf(char *buf, unsigned *pos, int len, float time) { saddf(buf, pos, len, "%02d.%1d", ss, f1); } -/** - * \brief print the status line - * \param a_pos audio position - * \param a_v A-V desynchronization - * \param corr amount out A-V synchronization - */ -static void print_status(float a_pos, float a_v, float corr) +static void print_status(struct MPContext *mpctx, double a_pos, bool at_frame) { + struct MPOpts *opts = &mpctx->opts; sh_video_t * const sh_video = mpctx->sh_video; + + if (mpctx->sh_audio && a_pos == MP_NOPTS_VALUE) + a_pos = playing_audio_pts(mpctx); + if (mpctx->sh_audio && sh_video && at_frame) { + mpctx->last_av_difference = a_pos - sh_video->pts - audio_delay; + if (mpctx->last_av_difference > 0.5 && drop_frame_cnt > 50 + && !mpctx->drop_message_shown) { + mp_tmsg(MSGT_AVSYNC,MSGL_WARN,SystemTooSlow); + mpctx->drop_message_shown = true; + } + } + if (quiet) + return; + + int width; char *line; unsigned pos = 0; @@ -1240,7 +1224,8 @@ static void print_status(float a_pos, float a_v, float corr) // A-V sync if (mpctx->sh_audio && sh_video) - saddf(line, &pos, width, "A-V:%7.3f ct:%7.3f ", a_v, corr); + saddf(line, &pos, width, "A-V:%7.3f ct:%7.3f ", + mpctx->last_av_difference, mpctx->total_avsync_change); // Video stats if (sh_video) @@ -1252,9 +1237,9 @@ static void print_status(float a_pos, float a_v, float corr) if (sh_video) { if (sh_video->timer > 0.5) saddf(line, &pos, width, "%2d%% %2d%% %4.1f%% ", - (int)(100.0*video_time_usage*playback_speed/(double)sh_video->timer), - (int)(100.0*vout_time_usage*playback_speed/(double)sh_video->timer), - (100.0*audio_time_usage*playback_speed/(double)sh_video->timer)); + (int)(100.0*video_time_usage*opts->playback_speed/(double)sh_video->timer), + (int)(100.0*vout_time_usage*opts->playback_speed/(double)sh_video->timer), + (100.0*audio_time_usage*opts->playback_speed/(double)sh_video->timer)); else saddf(line, &pos, width, "??%% ??%% ??,?%% "); } else if (mpctx->sh_audio) { @@ -1276,8 +1261,8 @@ static void print_status(float a_pos, float a_v, float corr) #endif // other - if (playback_speed != 1) - saddf(line, &pos, width, "%4.2fx ", playback_speed); + if (opts->playback_speed != 1) + saddf(line, &pos, width, "%4.2fx ", opts->playback_speed); // end if (erase_to_end_of_line) { @@ -1297,39 +1282,34 @@ static void print_status(float a_pos, float a_v, float corr) * \param sh_audio describes the requested input format of the chain. * \param ao_data describes the requested output format of the chain. */ -int build_afilter_chain(sh_audio_t *sh_audio, ao_data_t *ao_data) +int build_afilter_chain(struct MPContext *mpctx, sh_audio_t *sh_audio, ao_data_t *ao_data) { + struct MPOpts *opts = &mpctx->opts; int new_srate; int result; if (!sh_audio) { -#ifdef CONFIG_GUI - if (use_gui) guiGetEvent(guiSetAfilter, (char *)NULL); -#endif mpctx->mixer.afilter = NULL; return 0; } if(af_control_any_rev(sh_audio->afilter, AF_CONTROL_PLAYBACK_SPEED | AF_CONTROL_SET, - &playback_speed)) { + &opts->playback_speed)) { new_srate = sh_audio->samplerate; } else { - new_srate = sh_audio->samplerate * playback_speed; + new_srate = sh_audio->samplerate * opts->playback_speed; if (new_srate != ao_data->samplerate) { // limits are taken from libaf/af_resample.c if (new_srate < 8000) new_srate = 8000; if (new_srate > 192000) new_srate = 192000; - playback_speed = (float)new_srate / (float)sh_audio->samplerate; + opts->playback_speed = (float)new_srate / (float)sh_audio->samplerate; } } result = init_audio_filters(sh_audio, new_srate, &ao_data->samplerate, &ao_data->channels, &ao_data->format); mpctx->mixer.afilter = sh_audio->afilter; -#ifdef CONFIG_GUI - if (use_gui) guiGetEvent(guiSetAfilter, (char *)sh_audio->afilter); -#endif return result; } @@ -1432,24 +1412,27 @@ static void clear_osd_msgs(void) { * */ -static mp_osd_msg_t* get_osd_msg(void) { +static mp_osd_msg_t* get_osd_msg(struct MPContext *mpctx) +{ + struct MPOpts *opts = &mpctx->opts; mp_osd_msg_t *msg,*prev,*last = NULL; static unsigned last_update = 0; unsigned now = GetTimerMS(); unsigned diff; char hidden_dec_done = 0; - if (osd_visible) { + if (mpctx->osd_visible) { // 36000000 means max timed visibility is 1 hour into the future, if // the difference is greater assume it's wrapped around from below 0 - if (osd_visible - now > 36000000) { - osd_visible = 0; + if (mpctx->osd_visible - now > 36000000) { + mpctx->osd_visible = 0; vo_osd_progbar_type = -1; // disable vo_osd_changed(OSDTYPE_PROGBAR); - if (mpctx->osd_function != OSD_PAUSE) - mpctx->osd_function = OSD_PLAY; + mpctx->osd_function = mpctx->paused ? OSD_PAUSE : OSD_PLAY; } } + if (mpctx->osd_show_percentage_until - now > 36000000) + mpctx->osd_show_percentage_until = 0; if(!last_update) last_update = now; diff = now >= last_update ? now - last_update : 0; @@ -1459,14 +1442,16 @@ static mp_osd_msg_t* get_osd_msg(void) { // Look for the first message in the stack with high enough level. for(msg = osd_msg_stack ; msg ; last = msg, msg = prev) { prev = msg->prev; - if(msg->level > osd_level && hidden_dec_done) continue; + if (msg->level > opts->osd_level && hidden_dec_done) + continue; // The message has a high enough level or it is the first hidden one // in both cases we decrement the timer or kill it. if(!msg->started || msg->time > diff) { if(msg->started) msg->time -= diff; else msg->started = 1; // display it - if(msg->level <= osd_level) return msg; + if (msg->level <= opts->osd_level) + return msg; hidden_dec_done = 1; continue; } @@ -1491,20 +1476,21 @@ static mp_osd_msg_t* get_osd_msg(void) { * */ -void set_osd_bar(int type,const char* name,double min,double max,double val) { - - if(osd_level < 1) return; +void set_osd_bar(struct MPContext *mpctx, int type,const char* name,double min,double max,double val) { + struct MPOpts *opts = &mpctx->opts; + if (opts->osd_level < 1) + return; if(mpctx->sh_video) { - osd_visible = (GetTimerMS() + 1000) | 1; + mpctx->osd_visible = (GetTimerMS() + 1000) | 1; vo_osd_progbar_type = type; vo_osd_progbar_value = 256*(val-min)/(max-min); vo_osd_changed(OSDTYPE_PROGBAR); return; } - set_osd_msg(OSD_MSG_BAR,1,osd_duration,"%s: %d %%", - |