diff options
Diffstat (limited to 'mplayer.c')
-rw-r--r-- | mplayer.c | 848 |
1 files changed, 439 insertions, 409 deletions
@@ -5,6 +5,7 @@ #include <stdio.h> #include <stdlib.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()*/ @@ -45,6 +46,8 @@ #include "m_option.h" #include "m_config.h" +#include "mplayer.h" +#include "access_mpcontext.h" #include "m_property.h" #include "cfg-mplayer-def.h" @@ -53,6 +56,7 @@ #include "subreader.h" +#include "mp_osd.h" #include "libvo/video_out.h" #include "libvo/font_load.h" @@ -132,27 +136,15 @@ extern int import_initial_playtree_into_gui(play_tree_t* my_playtree, m_config_t #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: //**************************************************************************// @@ -180,6 +172,8 @@ static int max_framesize=0; #include "mixer.h" #include "mp_core.h" +#include "options.h" +#include "defaultopts.h" //**************************************************************************// //**************************************************************************// @@ -189,24 +183,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; @@ -220,8 +196,6 @@ int benchmark=0; int auto_quality=0; static int output_quality=0; -float playback_speed=1.0; - int use_gui=0; #ifdef CONFIG_GUI @@ -249,10 +223,6 @@ 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 @@ -264,15 +234,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; @@ -307,10 +272,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; @@ -338,9 +299,9 @@ char* current_module=NULL; // for debugging #ifdef CONFIG_MENU #include "m_struct.h" #include "libmenu/menu.h" -extern void vf_menu_pause_update(struct vf_instance_s* vf); +extern 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 }; @@ -362,7 +323,6 @@ 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" @@ -375,7 +335,7 @@ const void *mpctx_get_video_out(MPContext *mpctx) return mpctx->video_out; } -void *mpctx_get_audio_out(MPContext *mpctx) +const void *mpctx_get_audio_out(MPContext *mpctx) { return mpctx->audio_out; } @@ -405,7 +365,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 */ @@ -449,7 +417,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; @@ -463,19 +431,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: @@ -538,25 +507,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; @@ -579,13 +548,13 @@ 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 @@ -596,7 +565,7 @@ void uninit_player(unsigned int mask){ } 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; @@ -606,7 +575,7 @@ 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->demuxer){ mpctx->stream=mpctx->demuxer->stream; @@ -617,16 +586,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); @@ -635,7 +604,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: @@ -643,51 +612,42 @@ 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; + mpctx->audio_out->uninit(mpctx->stop_play != AT_END_OF_FILE); + mpctx->audio_out=NULL; } #ifdef CONFIG_GUI if(mask&INITIALIZED_GUI){ - initialized_flags&=~INITIALIZED_GUI; + mpctx->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 - } - current_module=NULL; } -void exit_player_with_rc(const char* how, int rc){ +void exit_player_with_rc(struct MPContext *mpctx, const char* 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 @@ -695,18 +655,25 @@ void exit_player_with_rc(const char* how, int rc){ #ifdef CONFIG_GUI if ( !use_gui ) #endif - vo_uninit(); // Close the X11 connection (if any is open). + vo_uninit(mpctx->x11_state); // Close the X11 connection (if any is open). +#endif + + 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); @@ -715,12 +682,13 @@ void exit_player_with_rc(const char* 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 if(how) mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_ExitingHow,how); @@ -729,8 +697,9 @@ void exit_player_with_rc(const char* how, int rc){ exit(rc); } -void exit_player(const char* how){ - exit_player_with_rc(how, 1); +static void exit_player(struct MPContext *mpctx, const char* how) +{ + exit_player_with_rc(mpctx, how, 1); } #ifndef __MINGW32__ @@ -751,7 +720,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 :( @@ -816,17 +784,20 @@ static void exit_sighandler(int x){ exit(1); } -extern 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(NULL); + exit_player(mpctx, NULL); if ((conffile = get_path("")) == NULL) { mp_msg(MSGT_CPLAYER,MSGL_WARN,MSGTR_NoHomeDir); } else { @@ -846,7 +817,7 @@ if ((conffile = get_path("")) == NULL) { } if (!disable_user_conf && m_config_parse_config_file(conf, conffile) < 0) - exit_player(NULL); + exit_player(mpctx, NULL); free(conffile); } } @@ -884,7 +855,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; @@ -952,38 +923,39 @@ 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(MSGTR_Exit_quit, (cmd->nargs > 0)? cmd->args[0].v.i : 0); + exit_player_with_rc(mpctx, MSGTR_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); + import_playtree_playlist_into_gui(entry, mpctx->mconfig); play_tree_free_list(entry,1); } } else @@ -1013,7 +985,7 @@ 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 @@ -1058,7 +1030,7 @@ void add_subtitles(char *filename, float fps, int noerr) } // FIXME: if/when the GUI calls this, global sub numbering gets (potentially) broken. -void update_set_of_subtitles(void) +void update_set_of_subtitles(struct MPContext *mpctx) // subdata was changed, set_of_sub... have to be updated. { sub_data ** const set_of_subtitles = mpctx->set_of_subtitles; @@ -1079,10 +1051,11 @@ void update_set_of_subtitles(void) } } -void init_vo_spudec(void) { +void init_vo_spudec(struct MPContext *mpctx) +{ 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; @@ -1135,7 +1108,7 @@ void init_vo_spudec(void) { } if (vo_spudec!=NULL) - initialized_flags|=INITIALIZED_SPUDEC; + mpctx->initialized_flags|=INITIALIZED_SPUDEC; } /* @@ -1196,8 +1169,9 @@ static void sadd_hhmmssf(char *buf, unsigned *pos, int len, float time) { * \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, float a_pos, float a_v, float corr) { + struct MPOpts *opts = &mpctx->opts; sh_video_t * const sh_video = mpctx->sh_video; int width; char *line; @@ -1245,9 +1219,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) { @@ -1269,8 +1243,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) { @@ -1290,8 +1264,9 @@ 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) @@ -1304,17 +1279,17 @@ int build_afilter_chain(sh_audio_t *sh_audio, ao_data_t *ao_data) } 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, @@ -1425,7 +1400,8 @@ 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) +{ mp_osd_msg_t *msg,*prev,*last = NULL; static unsigned last_update = 0; unsigned now = GetTimerMS(); @@ -1484,7 +1460,7 @@ static mp_osd_msg_t* get_osd_msg(void) { * */ -void set_osd_bar(int type,const char* name,double min,double max,double val) { +void set_osd_bar(struct MPContext *mpctx, int type,const char* name,double min,double max,double val) { if(osd_level < 1) return; @@ -1510,18 +1486,16 @@ void set_osd_bar(int type,const char* name,double min,double max,double val) { * */ -static void update_osd_msg(void) { +static void update_osd_msg(struct MPContext *mpctx) +{ mp_osd_msg_t *msg; - static char osd_text[64] = ""; - static char osd_text_timer[64]; - - // we need some mem for vo_osd_text - vo_osd_text = (unsigned char*)osd_text; + struct osd_state *osd = mpctx->osd; + char osd_text_timer[64]; // Look if we have a msg - if((msg = get_osd_msg())) { - if(strcmp(osd_text,msg->msg)) { - strncpy((char*)osd_text, msg->msg, 63); + if((msg = get_osd_msg(mpctx))) { + if (strcmp(osd->osd_text, msg->msg)) { + strncpy(osd->osd_text, msg->msg, 63); if(mpctx->sh_video) vo_osd_changed(OSDTYPE_OSD); else if(term_osd) mp_msg(MSGT_CPLAYER,MSGL_STATUS,"%s%s\n",term_osd_esc,msg->msg); } @@ -1560,16 +1534,16 @@ static void update_osd_msg(void) { if(mpctx->osd_show_percentage) mpctx->osd_show_percentage--; - if(strcmp(osd_text,osd_text_timer)) { - strncpy(osd_text, osd_text_timer, 63); + if (strcmp(osd->osd_text, osd_text_timer)) { + strncpy(osd->osd_text, osd_text_timer, 63); vo_osd_changed(OSDTYPE_OSD); } return; } // Clear the term osd line - if(term_osd && osd_text[0]) { - osd_text[0] = 0; + if (term_osd && osd->osd_text[0]) { + osd->osd_text[0] = 0; printf("%s\n",term_osd_esc); } } @@ -1578,7 +1552,9 @@ static void update_osd_msg(void) { // OSDMsgStack -void reinit_audio_chain(void) { +void reinit_audio_chain(struct MPContext *mpctx) +{ + struct MPOpts *opts = &mpctx->opts; if(mpctx->sh_audio){ current_module="init_audio_codec"; mp_msg(MSGT_CPLAYER,MSGL_INFO,"==========================================================================\n"); @@ -1587,7 +1563,7 @@ if(mpctx->sh_audio){ mpctx->d_audio->id = -2; return; } else - initialized_flags|=INITIALIZED_ACODEC; + mpctx->initialized_flags|=INITIALIZED_ACODEC; mp_msg(MSGT_CPLAYER,MSGL_INFO,"==========================================================================\n"); @@ -1604,24 +1580,24 @@ if(mpctx->sh_audio){ // output: &ao_data.samplerate, &ao_data.channels, &ao_data.format)){ mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_AudioFilterChainPreinitError); - exit_player(MSGTR_Exit_error); + exit_player(mpctx, MSGTR_Exit_error); } #endif current_module="ao2_init"; - if(!(mpctx->audio_out=init_best_audio_out(audio_driver_list, + if(!(mpctx->audio_out=init_best_audio_out(opts->audio_driver_list, 0, // plugin flag ao_data.samplerate, ao_data.channels, ao_data.format,0))){ // FAILED: mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_CannotInitAO); - uninit_player(INITIALIZED_ACODEC); // close codec + uninit_player(mpctx, INITIALIZED_ACODEC); // close codec mpctx->sh_audio=mpctx->d_audio->sh=NULL; // -> nosound mpctx->d_audio->id = -2; return; } else { // SUCCESS: - initialized_flags|=INITIALIZED_AO; + mpctx->initialized_flags|=INITIALIZED_AO; mp_msg(MSGT_CPLAYER,MSGL_INFO,"AO: [%s] %dHz %dch %s (%d bytes per sample)\n", mpctx->audio_out->info->short_name, ao_data.samplerate, ao_data.channels, @@ -1634,10 +1610,10 @@ if(mpctx->sh_audio){ // init audio filters: #if 1 current_module="af_init"; - if(!build_afilter_chain(mpctx->sh_audio, &ao_data)) { + if(!build_afilter_chain(mpctx, mpctx->sh_audio, &ao_data)) { mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_NoMatchingFilter); // mp_msg(MSGT_CPLAYER,MSGL_ERR,"Couldn't find matching filter / ao format! -> NOSOUND\n"); -// uninit_player(INITIALIZED_ACODEC|INITIALIZED_AO); // close codec & ao +// uninit_player(mpctx, INITIALIZED_ACODEC|INITIALIZED_AO); // close codec & ao // sh_audio=mpctx->d_audio->sh=NULL; // -> nosound } #endif @@ -1654,8 +1630,10 @@ if(mpctx->sh_audio){ // Return pts value corresponding to the end point of audio written to the // ao so far. -static double written_audio_pts(sh_audio_t *sh_audio, demux_stream_t *d_audio) +static double written_audio_pts(struct MPContext *mpctx) { + sh_audio_t *sh_audio = mpctx->sh_audio; + demux_stream_t *d_audio = mpctx->d_audio; double buffered_output; // first calculate the end pts of audio that has been output by decoder double a_pts = sh_audio->pts; @@ -1698,25 +1676,25 @@ static double written_audio_pts(sh_audio_t *sh_audio, demux_stream_t *d_audio) // Filters divide audio length by playback_speed, so multiply by it // to get the length in original units without speedup or slowdown - a_pts -= buffered_output * playback_speed / ao_data.bps; + a_pts -= buffered_output * mpctx->opts.playback_speed / ao_data.bps; return a_pts; } // Return pts value corresponding to currently playing audio. -double playing_audio_pts(sh_audio_t *sh_audio, demux_stream_t *d_audio, - const ao_functions_t *audio_out) +double playing_audio_pts(struct MPContext *mpctx) { - return written_audio_pts(sh_audio, d_audio) - playback_speed * - audio_out->get_delay(); + return written_audio_pts(mpctx) - mpctx->opts.playback_speed * + mpctx->audio_out->get_delay(); } -static int check_framedrop(double frame_time) { +static int check_framedrop(struct MPContext *mpctx, double frame_time) { + struct MPOpts *opts = &mpctx->opts; // check for frame-drop: current_module = "check_framedrop"; if (mpctx->sh_audio && !mpctx->d_audio->eof) { static int dropped_frames; - float delay = playback_speed*mpctx->audio_out->get_delay(); + float delay = opts->playback_speed*mpctx->audio_out->get_delay(); float d = delay-mpctx->delay; ++total_frame_cnt; // we should avoid dropping too many frames in sequence unless we @@ -1732,15 +1710,18 @@ static int check_framedrop(double frame_time) { return 0; } -static int generate_video_frame(sh_video_t *sh_video, demux_stream_t *d_video) +static int generate_video_frame(struct MPContext *mpctx) { + sh_video_t * const sh_video = mpctx->sh_video; + demux_stream_t *d_video = mpctx->d_video; + unsigned char *start; int in_size; int hit_eof=0; double pts; while (1) { - int drop_frame = check_framedrop(sh_video->frametime); + int drop_frame = check_framedrop(mpctx, sh_video->frametime); void *decoded_frame; current_module = "decode video"; // XXX Time used in this call is not counted in any performance @@ -1762,9 +1743,10 @@ static int generate_video_frame(sh_video_t *sh_video, demux_stream_t *d_video) if (decoded_frame) { update_subtitles(sh_video, mpctx->d_sub, 0); update_teletext(sh_video, mpctx->demuxer, 0); - update_osd_msg(); + update_osd_msg(mpctx); current_module = "filter video"; - if (filter_video(sh_video, decoded_frame, sh_video->pts)) + if (filter_video(sh_video, decoded_frame, sh_video->pts, + mpctx->osd)) break; } else if (drop_frame) return -1; @@ -1778,7 +1760,7 @@ static int generate_video_frame(sh_video_t *sh_video, demux_stream_t *d_video) int rtc_fd = -1; #endif -static float timing_sleep(float time_frame) +static float timing_sleep(struct MPContext *mpctx, float time_frame) { #ifdef HAVE_RTC if (rtc_fd >= 0){ @@ -1788,7 +1770,7 @@ static float timing_sleep(float time_frame) unsigned long rtc_ts; if (read(rtc_fd, &rtc_ts, sizeof(rtc_ts)) <= 0) mp_msg(MSGT_CPLAYER, MSGL_ERR, MSGTR_LinuxRTCReadError, strerror(errno)); - time_frame -= GetRelativeTime(); + time_frame -= get_relative_time(mpctx); } } else #endif @@ -1799,14 +1781,14 @@ static float timing_sleep(float time_frame) current_module = "sleep_timer"; while (time_frame > margin) { usec_sleep(1000000 * (time_frame - margin)); - time_frame -= GetRelativeTime(); + time_frame -= get_relative_time(mpctx); } if (softsleep){ current_module = "sleep_soft"; if (time_frame < 0) mp_msg(MSGT_AVSYNC, MSGL_WARN, MSGTR_SoftsleepUnderflow); while (time_frame > 0) - time_frame-=GetRelativeTime(); // burn the CPU + time_frame -= get_relative_time(mpctx); // burn the CPU } } return time_frame; @@ -1843,6 +1825,7 @@ static mp_image_t * mp_dvdnav_copy_mpi(mp_image_t *to_mpi, } static void mp_dvdnav_reset_stream (MPContext *ctx) { + struct MPOpts *opts = &ctx->opts; if (ctx->sh_video) { /// clear video pts ctx->d_video->pts = 0.0f; @@ -1867,7 +1850,7 @@ static void mp_dvdnav_reset_stream (MPContext *ctx) { resync_audio_stream(ctx->sh_audio); } - if (ctx->d_sub) dvdsub_id = -2; + if (ctx->d_sub) opts->sub_id = -2; audio_delay = 0.0f; @@ -1876,7 +1859,8 @@ static void mp_dvdnav_reset_stream (MPContext *ctx) { } /// Restore last decoded DVDNAV (still frame) -static mp_image_t *mp_dvdnav_restore_smpi(int *in_size, +static mp_image_t *mp_dvdnav_restore_smpi(struct MPContext *mpctx, + int *in_size, unsigned char **start, mp_image_t *decoded_frame) { @@ -1920,7 +1904,7 @@ static mp_image_t *mp_dvdnav_restore_smpi(int *in_size, } /// Save last decoded DVDNAV (still frame) -static void mp_dvdnav_save_smpi(int in_size, +static void mp_dvdnav_save_smpi(struct MPContext *mpctx, int in_size, unsigned char *start, mp_image_t *decoded_frame) { @@ -1941,8 +1925,11 @@ static void mp_dvdnav_save_smpi(int in_size, } #endif /* CONFIG_DVDNAV */ -static void adjust_sync_and_print_status(int between_frames, float timing_error) +static void adjust_sync_and_print_status(struct MPContext *mpctx, + int between_frames, + float timing_error) { + struct MPOpts *opts = &mpctx->opts; current_module="av_sync"; if(mpctx->sh_audio){ @@ -1960,9 +1947,9 @@ static void adjust_sync_and_print_status(int between_frames, float timing_error) * value here, even a "corrected" one, would be incompatible with * autosync mode.) */ - a_pts = written_audio_pts(mpctx->sh_audio, mpctx->d_audio) - mpctx->delay; + a_pts = written_audio_pts(mpctx) - mpctx->delay; else - a_pts = playing_audio_pts(mpctx->sh_audio, mpctx->d_audio, mpctx->audio_out); + a_pts = playing_audio_pts(mpctx); v_pts = mpctx->sh_video->pts; @@ -1980,7 +1967,7 @@ static void adjust_sync_and_print_status(int between_frames, float timing_error) /* Do not correct target time for the next frame if this frame * was late not because of wrong target time but because the * target time could not be met */ - x = (AV_delay + timing_error * playback_speed) * 0.1f; + x = (AV_delay + timing_error * opts->playback_speed) * 0.1f; if (x < -max_pts_correction) x = -max_pts_correction; else if (x> max_pts_correction) @@ -1994,19 +1981,20 @@ static void adjust_sync_and_print_status(int between_frames, float timing_error) c_total+=x; } if(!quiet) - print_status(a_pts - audio_delay, AV_delay, c_total); + print_status(mpctx, a_pts - audio_delay, AV_delay, c_total); } } else { // No audio: if (!quiet) - print_status(0, 0, 0); + print_status(mpctx, 0, 0, 0); } } -static int fill_audio_out_buffers(void) +static int fill_audio_out_buffers(struct MPContext *mpctx) { + struct MPOpts *opts = &mpctx->opts; unsigned int t; double tt; int playsize; @@ -2070,7 +2058,7 @@ static int fill_audio_out_buffers(void) sh_audio->a_out_buffer_len -= playsize; memmove(sh_audio->a_out_buffer, &sh_audio->a_out_buffer[playsize], sh_audio->a_out_buffer_len); - mpctx->delay += playback_speed*playsize/(double)ao_data.bps; + mpctx->delay += opts->playback_speed*playsize/(double)ao_data.bps; } else if (audio_eof && mpctx->audio_out->get_delay() < .04) { // Sanity check to avoid hanging in case current ao doesn't output @@ -2082,12 +2070,14 @@ static int fill_audio_out_buffers(void) return 1; } -static int sleep_until_update(float *time_frame, float *aq_sleep_time) +static int sleep_until_update(struct MPContext *mpctx, float *time_frame, + float *aq_sleep_time) { + struct MPOpts *opts = &mpctx->opts; int frame_time_remaining = 0; current_module="calc_sleep_time"; - *time_frame -= GetRelativeTime(); // reset timer + *time_frame -= get_relative_time(mpctx); // reset timer if (mpctx->sh_audio && !mpctx->d_audio->eof) { float delay = mpctx->audio_out->get_delay(); @@ -2103,12 +2093,12 @@ static int sleep_until_update(float *time_frame, float *aq_sleep_time) * sync to settle at the right value (but it eventually will.) * This settling time is very short for values below 100. */ - float predicted = mpctx->delay / playback_speed + *time_frame; + float predicted = mpctx->delay / opts->playback_speed + *time_frame; float difference = delay - predicted; delay = predicted + difference / (float)autosync; } - *time_frame = delay - mpctx->delay / playback_speed; + *time_frame = delay - mpctx->delay / opts->playback_speed; // delay = amount of audio buffered in soundcard/driver if (delay > 0.25) delay=0.25; else @@ -2133,26 +2123,27 @@ static int sleep_until_update(float *time_frame, float *aq_sleep_time) //============================== SLEEP: =================================== // flag 256 means: libvo driver does its timing (dvb card) - if (*time_frame > 0.001 && !(vo_flags&256)) - *time_frame = timing_sleep(*time_frame); + if (*time_frame > 0.001 && !(mpctx->sh_video->output_flags&256)) + *time_frame = timing_sleep(mpctx, *time_frame); return frame_time_remaining; } -int reinit_video_chain(void) { +int reinit_video_chain(struct MPContext *mpctx) +{ + struct MPOpts *opts = &mpctx->opts; sh_video_t * const sh_video = mpctx->sh_video; double ar=-1.0; //================== Init VIDEO (codec & libvo) ========================== - if(!fixed_vo || !(initialized_flags&INITIALIZED_VO)){ + if(opts->fixed_vo || !(mpctx->initialized_flags&INITIALIZED_VO)){ current_module="preinit_libvo"; //shouldn't we set dvideo->id=-2 when we fail? - vo_config_count=0; //if((mpctx->video_out->preinit(vo_subdevice))!=0){ - if(!(mpctx->video_out=init_best_video_out(video_driver_list))){ + if(!(mpctx->video_out=init_best_video_out(opts, mpctx->x11_state, mpctx->key_fifo, mpctx->input))){ mp_msg(MSGT_CPLAYER,MSGL_FATAL,MSGTR_ErrorInitializingVODevice); goto err_out; } - initialized_flags|=INITIALIZED_VO; + mpctx->initialized_flags|=INITIALIZED_VO; } if(stream_control(mpctx->demuxer->stream, STREAM_CTRL_GET_ASPECT_RATIO, &ar) != STREAM_UNSUPPORTED) @@ -2160,28 +2151,28 @@ int reinit_video_chain(void) { current_module="init_video_filters"; { char* vf_arg[] = { "_oldargs_", (char*)mpctx->video_out , NULL }; - sh_video->vfilter=(void*)vf_open_filter(NULL,"vo",vf_arg); + sh_video->vfilter = vf_open_filter(opts, NULL,"vo",vf_arg); } #ifdef CONFIG_MENU if(use_menu) { char* vf_arg[] = { "_oldargs_", menu_root, NULL }; - vf_menu = vf_open_plugin(libmenu_vfs,sh_video->vfilter,"menu",vf_arg); + vf_menu = vf_open_plugin(opts,libmenu_vfs,sh_video->vfilter,"menu",vf_arg); if(!vf_menu) { mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_CantOpenLibmenuFilterWithThisRootMenu,menu_root); use_menu = 0; } } if(vf_menu) - sh_video->vfilter=(void*)vf_menu; + sh_video->vfilter = vf_menu; #endif #ifdef CONFIG_ASS if(ass_enabled) { int i; int insert = 1; - if (vf_settings) - for (i = 0; vf_settings[i].name; ++i) - if (strcmp(vf_settings[i].name, "ass") == 0) { + if (opts->vf_settings) + for (i = 0; opts->vf_settings[i].name; ++i) + if (strcmp(opts->vf_settings[i].name, "ass") == 0) { insert = 0; break; } @@ -2189,20 +2180,20 @@ int reinit_video_chain(void) { extern vf_info_t vf_info_ass; const vf_info_t* libass_vfs[] = {&vf_info_ass, NULL}; char* vf_arg[] = {"auto", "1", NULL}; - vf_instance_t* vf_ass = vf_open_plugin(libass_vfs,sh_video->vfilter,"ass",vf_arg); + vf_instance_t* vf_ass = vf_open_plugin(opts, libass_vfs,sh_video->vfilter,"ass",vf_arg); if (vf_ass) - sh_video->vfilter=(void*)vf_ass; + sh_video->vfilter = vf_ass; else mp_msg(MSGT_CPLAYER,MSGL_ERR, "ASS: cannot add video filter\n"); } } #endif - sh_video->vfilter=(void*)append_filters(sh_video->vfilter); + sh_video->vfilter = append_filters(sh_video->vfilter, opts->vf_settings); #ifdef CONFIG_ASS if (ass_enabled) - ((vf_instance_t *)sh_video->vfilter)->control(sh_video->vfilter, VFCTRL_INIT_EOSD, ass_library); + sh_video->vfilter->control(sh_video->vfilter, VFCTRL_INIT_EOSD, ass_library); #endif current_module="init_video_codec"; @@ -2212,11 +2203,11 @@ int reinit_video_chain(void) { mp_msg(MSGT_CPLAYER,MSGL_INFO,"==========================================================================\n"); if(!sh_video->initialized){ - if(!fixed_vo) uninit_player(INITIALIZED_VO); + if(!opts->fixed_vo) uninit_player(mpctx, INITIALIZED_VO); goto err_out; } - initialized_flags|=INITIALIZED_VCODEC; + mpctx->initialized_flags|=INITIALIZED_VCODEC; if (sh_video->codec) mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VIDEO_CODEC=%s\n", sh_video->codec->name); @@ -2245,13 +2236,16 @@ err_out: return 0; } -static double update_video(int *blit_frame) +static double update_video(struct MPContext *mpctx, int *blit_frame) { + struct MPOpts *opts = &mpctx->opts; sh_video_t * const sh_video = mpctx->sh_video; //-------------------- Decode a frame: ----------------------- double frame_time; *blit_frame = 0; // Don't blit if we hit EOF - if (!correct_pts) { + sh_video->vfilter->control(sh_video->vfilter, VFCTRL_SET_OSD_OBJ, + mpctx->osd); // hack for vf_expand + if (!opts->correct_pts) { unsigned char* start=NULL; void *decoded_frame = NULL; int drop_frame=0; @@ -2279,13 +2273,14 @@ static double update_video(int *blit_frame) mpctx->delay -= frame_time; // video_read_frame can change fps (e.g. for ASF video) vo_fps = sh_video->fps; - drop_frame = check_framedrop(frame_time); + drop_frame = check_framedrop(mpctx, frame_time); update_subtitles(sh_video, mpctx->d_sub, 0); update_teletext(sh_video, mpctx->demuxer, 0); - update_osd_msg(); + update_osd_msg(mpctx); current_module = "decode_video"; #ifdef CONFIG_DVDNAV - decoded_frame = mp_dvdnav_restore_smpi(&in_size,&start,decoded_frame); + decoded_frame = mp_dvdnav_restore_smpi(mpctx, &in_size,&start, + decoded_frame); /// still frame has been reached, no need to decode if (in_size > 0 && !decoded_frame) #endif @@ -2293,18 +2288,19 @@ static double update_video(int *blit_frame) sh_video->pts); #ifdef CONFIG_DVDNAV /// save back last still frame for future display - mp_dvdnav_save_smpi(in_size,start,decoded_frame); + mp_dvdnav_save_smpi(mpctx, in_size, start, decoded_frame); #endif current_module = "filter_video"; *blit_frame = (decoded_frame && filter_video(sh_video, decoded_frame, - sh_video->pts)); + sh_video->pts, + mpctx->osd)); } else { - int res = generate_video_frame(sh_video, mpctx->d_video); + int res = generate_video_frame(mpctx); if (!res) return -1; - ((vf_instance_t *)sh_video->vfilter)->control(sh_video->vfilter, - VFCTRL_GET_PTS, &sh_video->pts); + sh_video->vfilter->control(sh_video->vfilter, VFCTRL_GET_PTS, + &sh_video->pts); if (sh_video->pts == MP_NOPTS_VALUE) { mp_msg(MSGT_CPLAYER, MSGL_ERR, "pts after filters MISSING\n"); sh_video->pts = sh_video->last_pts; @@ -2325,7 +2321,7 @@ static double update_video(int *blit_frame) return frame_time; } -static void pause_loop(void) +static void pause_loop(struct MPContext *mpctx) { mp_cmd_t* cmd; if (!quiet) { @@ -2337,7 +2333,7 @@ static void pause_loop(void) int mlen = strlen(msg); msg[mlen-1] = '\0'; set_osd_msg(OSD_MSG_PAUSE, 1, 0, "%s", msg+1); - update_osd_msg(); + update_osd_msg(mpctx); } else mp_msg(MSGT_CPLAYER,MSGL_STATUS,MSGTR_Paused); mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_PAUSED\n"); @@ -2346,27 +2342,27 @@ static void pause_loop(void) if (use_gui) guiGetEvent(guiCEvent, (char *)guiSetPause); #endif - if (mpctx->video_out && mpctx->sh_video && vo_config_count) - mpctx->video_out->control(VOCTRL_PAUSE, NULL); + if (mpctx->video_out && mpctx->sh_video && mpctx->video_out->config_ok) + vo_control(mpctx->video_out, VOCTRL_PAUSE, NULL); if (mpctx->audio_out && mpctx->sh_audio) mpctx->audio_out->pause(); // pause audio, keep data if possible - while ( (cmd = mp_input_get_cmd(20, 1, 1)) == NULL + while ( (cmd = mp_input_get_cmd(mpctx->input, 20, 1, 1)) == NULL || cmd->id == MP_CMD_SET_MOUSE_POS || cmd->pausing == 4) { if (cmd) { - cmd = mp_input_get_cmd(0,1,0); + cmd = mp_input_get_cmd(mpctx->input, 0,1,0); run_command(mpctx, cmd); mp_cmd_free(cmd); continue; } - if (mpctx->sh_video && mpctx->video_out && vo_config_count) - mpctx->video_out->check_events(); + if (mpctx->sh_video && mpctx->video_out) + vo_check_events(mpctx->video_out); #ifdef CONFIG_GUI if (use_gui) { guiEventHandling(); guiGetEvent(guiReDraw, NULL); - if (guiIntfStruct.Playing!=2 || (rel_seek_secs || abs_seek_pos)) + if (guiIntfStruct.Playing!=2 || (mpctx->rel_seek_secs || mpctx->abs_seek_pos)) break; } #endif @@ -2377,15 +2373,15 @@ static void pause_loop(void) usec_sleep(20000); } if (cmd && cmd->id == MP_CMD_PAUSE) { - cmd = mp_input_get_cmd(0,1,0); + cmd = mp_input_get_cmd(mpctx->input, 0,1,0); mp_cmd_free(cmd); } mpctx->osd_function=OSD_PLAY; if (mpctx->audio_out && mpctx->sh_audio) mpctx->audio_out->resume(); // resume audio - if (mpctx->video_out && mpctx->sh_video && vo_config_count) - mpctx->video_out->control(VOCTRL_RESUME, NULL); // resume video - (void)GetRelativeTime(); // ignore time that passed during pause + if (mpctx->video_out && mpctx->sh_video && mpctx->video_out->config_ok) + vo_control(mpctx->video_out, VOCTRL_RESUME, NULL); // resume video + (void)get_relative_time(mpctx); // ignore time that passed during pause #ifdef CONFIG_GUI if (use_gui) { if (guiIntfStruct.Playing == guiSetStop) @@ -2396,7 +2392,7 @@ static void pause_loop(void) #endif } -void print_version(void){ +static void print_version(void){ mp_msg(MSGT_CPLAYER, MSGL_INFO, "%s\n", MP_TITLE); /* Test for CPU capabilities (and corresponding OS support) for optimizing */ @@ -2470,8 +2466,8 @@ static void edl_update(MPContext *mpctx) if (mpctx->sh_video->pts >= next_edl_record->start_sec) { if (next_edl_record->action == EDL_SKIP) { mpctx->osd_function = OSD_FFW; - abs_seek_pos = 0; - rel_seek_secs = next_edl_record->length_sec; + mpctx->abs_seek_pos = 0; + mpctx->rel_seek_secs = next_edl_record->length_sec; mp_msg(MSGT_CPLAYER, MSGL_DBG4, "EDL_SKIP: start [%f], stop " "[%f], length [%f]\n", next_edl_record->start_sec, next_edl_record->stop_sec, next_edl_record->length_sec); @@ -2501,8 +2497,8 @@ static int seek(MPContext *mpctx, double amount, int style) if (mpctx->sh_video) { current_module = "seek_video_reset"; resync_video_stream(mpctx->sh_video); - if (vo_config_count) - mpctx->video_out->control(VOCTRL_RESET, NULL); + if (mpctx->video_out->config_ok) + vo_control(mpctx->video_out, VOCTRL_RESET, NULL); mpctx->sh_video->num_buffered_pts = 0; mpctx->sh_video->last_pts = MP_NOPTS_VALUE; mpctx->num_buffered_frames = 0; @@ -2538,6 +2534,14 @@ static int seek(MPContext *mpctx, double amount, int style) return 0; } + +static int read_keys(void *ctx, int fd) +{ + getch2(ctx); + return mplayer_get_key(ctx, 0); +} + + /* This preprocessor directive is a hack to generate a mplayer-nomain.o object * file for some tools to link against. */ #ifndef DISABLE_MAIN @@ -2557,18 +2561,33 @@ int i; int gui_no_filename=0; + struct MPContext *mpctx = &(struct MPContext){ + .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, + .last_dvb_step = 1, + }; + InitTimer(); srand(GetTimerMS()); mp_msg_init(); +#ifdef CONFIG_X11 + mpctx->x11_state = vo_x11_init_state(); +#endif + struct MPOpts *opts = &mpctx->opts; + set_default_mplayer_options(opts); // Create the config context and register the options - mconfig = m_config_new(); - m_config_register_options(mconfig,mplayer_opts); - mp_input_register_options(mconfig); + mpctx->mconfig = m_config_new(opts, cfg_include); + m_config_register_options(mpctx->mconfig,mplayer_opts); + mp_input_register_options(mpctx->mconfig); // Preparse the command line - m_config_preparse_command_line(mconfig,argc,argv); + m_config_preparse_command_line(mpctx->mconfig,argc,argv); print_version(); #if (defined(__MINGW32__) || defined(__CYGWIN__)) && defined(CONFIG_WIN32DLL) @@ -2594,36 +2613,37 @@ int gui_no_filename=0; use_gui=1; } - parse_cfgfiles(mconfig); + parse_cfgfiles(mpctx, mpctx->mconfig); #ifdef CONFIG_GUI if ( use_gui ) cfg_read(); #endif - mpctx->playtree = m_config_parse_mp_command_line(mconfig, argc, argv); + mpctx->playtree = m_config_parse_mp_command_line(mpctx->mconfig, argc, argv); if(mpctx->playtree == NULL) opt_exit = 1; else { mpctx->playtree = play_tree_cleanup(mpctx->playtree); if(mpctx->playtree) { - mpctx->playtree_iter = play_tree_iter_new(mpctx->playtree,mconfig); + mpctx->playtree_iter = play_tree_iter_new(mpctx->playtree,mpctx->mconfig); if(mpctx->playtree_iter) { if(play_tree_iter_step(mpctx->playtree_iter,0,0) != PLAY_TREE_ITER_ENTRY) { play_tree_iter_free(mpctx->playtree_iter); mpctx->playtree_iter = NULL; } - filename = play_tree_iter_get_file(mpctx->playtree_iter,1); + mpctx->filename = play_tree_iter_get_file(mpctx->playtree_iter,1); } } } + mpctx->key_fifo = mp_fifo_create(opts); #if (defined(__MINGW32__) || defined(__CYGWIN__)) && defined(CONFIG_GUI) void *runningmplayer = FindWindow("MPlayer GUI for Windows", "MPlayer for Windows"); - if(runningmplayer && filename && use_gui){ + if(runningmplayer && mpctx->filename && use_gui){ COPYDATASTRUCT csData; char file[MAX_PATH]; - char *filepart = filename; - if(GetFullPathName(filename, MAX_PATH, file, &filepart)){ + char *filepart = mpctx->filename; + if(GetFullPathName(mpctx->filename, MAX_PATH, file, &filepart)){ csData.dwData = 0; csData.cbData = strlen(file)*2; csData.lpData = file; @@ -2671,16 +2691,16 @@ int gui_no_filename=0; play_tree_add_bpf(mpctx->playtree, cwd); } // Import initital playtree into GUI. - import_initial_playtree_into_gui(mpctx->playtree, mconfig, enqueue); + import_initial_playtree_into_gui(mpctx->playtree, mpctx->mconfig, enqueue); } #endif /* CONFIG_GUI */ - if(video_driver_list && strcmp(video_driver_list[0],"help")==0){ + if(opts->video_driver_list && strcmp(opts->video_driver_list[0],"help")==0){ list_video_out(); opt_exit = 1; } - if(audio_driver_list && strcmp(audio_driver_list[0],"help")==0){ + if(opts->audio_driver_list && strcmp(opts->audio_driver_list[0],"help")==0){ list_audio_out(); opt_exit = 1; } @@ -2690,7 +2710,7 @@ if(!codecs_file || !parse_codec_cfg(codecs_file)){ 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(NULL, 0); + exit_player_with_rc(mpctx, NULL, 0); } mp_msg(MSGT_CPLAYER,MSGL_V,MSGTR_BuiltinCodecsConf); } @@ -2755,18 +2775,18 @@ if(!codecs_file || !parse_codec_cfg(codecs_file)){ } if(opt_exit) - exit_player(NULL); + exit_player(mpctx, NULL); if (player_idle_mode && use_gui) { mp_msg(MSGT_CPLAYER, MSGL_FATAL, MSGTR_NoIdleAndGui); - exit_player_with_rc(NULL, 1); + exit_player_with_rc(mpctx, NULL, 1); } - if(!filename && !player_idle_mode){ + if(!mpctx->filename && !player_idle_mode){ if(!use_gui){ // no file/vcd/dvd -> show HELP: mp_msg(MSGT_CPLAYER, MSGL_INFO, help_text); - exit_player_with_rc(NULL, 0); + exit_player_with_rc(mpctx, NULL, 0); } else gui_no_filename=1; } @@ -2782,6 +2802,8 @@ if(!codecs_file || !parse_codec_cfg(codecs_file)){ //------ load global data first ------ + mpctx->osd = osd_create(); + // check font #ifdef CONFIG_FREETYPE init_freetype(); @@ -2803,16 +2825,14 @@ if(!codecs_file || !parse_codec_cfg(codecs_file)){ vo_font=read_font_desc(MPLAYER_DATADIR "/font/font.desc",font_factor,verbose>1); } if (sub_font_name) - sub_font = read_font_desc(sub_font_name, font_factor, verbose>1); + mpctx->osd->sub_font = read_font_desc(sub_font_name, font_factor, verbose>1); else - sub_font = vo_font; + mpctx->osd->sub_font = vo_font; #endif #ifdef CONFIG_FONTCONFIG } #endif - vo_init_osd(); - #ifdef CONFIG_ASS ass_library = ass_init(); #endif @@ -2859,25 +2879,26 @@ if(!codecs_file || !parse_codec_cfg(codecs_file)){ // Init input system current_module = "init_input"; -mp_input_init(use_gui); - mp_input_add_key_fd(-1,0,mplayer_get_key,NULL); + mpctx->input = mp_input_init(&opts->input, use_gui); + mp_input_add_key_fd(mpctx->input, -1,0,mplayer_get_key,NULL, mpctx->key_fifo); if(slave_mode) - mp_input_add_cmd_fd(0,USE_SELECT,MP_INPUT_SLAVE_CMD_FUNC,NULL); + mp_input_add_cmd_fd(mpctx->input, 0,USE_SELECT,MP_INPUT_SLAVE_CMD_FUNC,NULL); else if(!noconsolecontrols) - mp_input_add_event_fd(0, getch2); + mp_input_add_key_fd(mpctx->input, 0, 1, read_keys, NULL, mpctx->key_fifo); // Set the libstream interrupt callback -stream_set_interrupt_callback(mp_input_check_interrupt); +stream_set_interrupt_callback(mp_input_check_interrupt, mpctx->input); #ifdef CONFIG_MENU if(use_menu) { - if(menu_cfg && menu_init(mpctx, menu_cfg)) + if(menu_cfg && menu_init(mpctx, mpctx->mconfig, mpctx->input, menu_cfg)) mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_MenuInitialized, menu_cfg); else { menu_cfg = get_path("menu.conf"); - if(menu_init(mpctx, menu_cfg)) + if(menu_init(mpctx, mpctx->mconfig, mpctx->input, menu_cfg)) mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_MenuInitialized, menu_cfg); else { - if(menu_init(mpctx, MPLAYER_CONFDIR "/menu.conf")) + if(menu_init(mpctx, mpctx->mconfig, mpctx->input, + MPLAYER_CONFDIR "/menu.conf")) mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_MenuInitialized, MPLAYER_CONFDIR"/menu.conf"); else { mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_MenuInitFailed); @@ -2888,7 +2909,6 @@ stream_set_interrupt_callback(mp_input_check_interrupt); } #endif -initialized_flags|=INITIALIZED_INPUT; current_module = NULL; /// Catch signals @@ -2925,7 +2945,7 @@ current_module = NULL; if(use_gui){ guiInit(); guiGetEvent(guiSetContext, mpctx); - initialized_flags|=INITIALIZED_GUI; + mpctx->initialized_flags|=INITIALIZED_GUI; guiGetEvent( guiCEvent,(char *)((gui_no_filename) ? 0 : 1) ); } #endif @@ -2938,25 +2958,25 @@ play_next_file: mpctx->global_sub_size = 0; { int i; for (i = 0; i < SUB_SOURCES; i++) mpctx->global_sub_indices[i] = -1; } - if (filename) { - load_per_protocol_config (mconfig, filename); - load_per_extension_config (mconfig, filename); - load_per_file_config (mconfig, filename); + if (mpctx->filename) { + load_per_protocol_config (mpctx->mconfig, mpctx->filename); + load_per_extension_config (mpctx->mconfig, mpctx->filename); + load_per_file_config (mpctx->mconfig, mpctx->filename); } - if (video_driver_list) - load_per_output_config (mconfig, PROFILE_CFG_VO, video_driver_list[0]); - if (audio_driver_list) - load_per_output_config (mconfig, PROFILE_CFG_AO, audio_driver_list[0]); + if (opts->video_driver_list) + load_per_output_config (mpctx->mconfig, PROFILE_CFG_VO, opts->video_driver_list[0]); + if (opts->audio_driver_list) + load_per_output_config (mpctx->mconfig, PROFILE_CFG_AO, opts->audio_driver_list[0]); // We must enable getch2 here to be able to interrupt network connection // or cache filling if(!noconsolecontrols && !slave_mode){ - if(initialized_flags&INITIALIZED_GETCH2) + if(mpctx->initialized_flags&INITIALIZED_GETCH2) mp_msg(MSGT_CPLAYER,MSGL_WARN,MSGTR_Getch2InitializedTwice); else getch2_enable(); // prepare stdin for hotkeys... - initialized_flags|=INITIALIZED_GETCH2; + mpctx->initialized_flags|=INITIALIZED_GETCH2; mp_msg(MSGT_CPLAYER,MSGL_DBG2,"\n[[[init getch2]]]\n"); } @@ -2971,7 +2991,7 @@ if(!noconsolecontrols && !slave_mode){ usec_sleep(20000); guiEventHandling(); guiGetEvent( guiReDraw,NULL ); - if ( (cmd = mp_input_get_cmd(0,0,0)) != NULL) { + if ( (cmd = mp_input_get_cmd(mpctx->input, 0,0,0)) != NULL) { guiGetEvent(guiIEvent, (char *)cmd->id); mp_cmd_free(cmd); } @@ -2986,7 +3006,7 @@ if(!noconsolecontrols && !slave_mode){ play_tree_set_child( mpctx->playtree,entry ); if(mpctx->playtree) { - mpctx->playtree_iter = play_tree_iter_new(mpctx->playtree,mconfig); + mpctx->playtree_iter = play_tree_iter_new(mpctx->playtree,mpctx->mconfig); if(mpctx->playtree_iter) { if(play_tree_iter_step(mpctx->playtree_iter,0,0) != PLAY_TREE_ITER_ENTRY) @@ -2994,18 +3014,19 @@ if(!noconsolecontrols && !slave_mode){ play_tree_iter_free(mpctx->playtree_iter); mpctx->playtree_iter = NULL; } - filename = play_tree_iter_get_file(mpctx->playtree_iter,1); + mpctx->filename = play_tree_iter_get_file(mpctx->playtree_iter,1); } } } } #endif /* CONFIG_GUI */ -while (player_idle_mode && !filename) { +while (player_idle_mode && !mpctx->filename) { play_tree_t * entry = NULL; mp_cmd_t * cmd; - while (!(cmd = mp_input_get_cmd(0,1,0))) { // wait for command - if (mpctx->video_out && vo_config_count) mpctx->video_out->check_events(); + while (!(cmd = mp_input_get_cmd(mpctx->input, 0,1,0))) { // wait for command + if (mpctx->video_out) + vo_check_events(mpctx->video_out); usec_sleep(20000); } switch (cmd->id) { @@ -3016,10 +3037,10 @@ while (player_idle_mode && !filename) { // The entry is added to the main playtree after the switch(). break; case MP_CMD_LOADLIST: - entry = parse_playlist_file(cmd->args[0].v.s); + entry = parse_playlist_file(mpctx->mconfig, cmd->args[0].v.s); break; case MP_CMD_QUIT: - exit_player_with_rc(MSGTR_Exit_quit, (cmd->nargs > 0)? cmd->args[0].v.i : 0); + exit_player_with_rc(mpctx, MSGTR_Exit_quit, (cmd->nargs > 0)? cmd->args[0].v.i : 0); break; case MP_CMD_GET_PROPERTY: case MP_CMD_SET_PROPERTY: @@ -3040,7 +3061,7 @@ while (player_idle_mode && !filename) { play_tree_set_child(mpctx->playtree, entry); /* Make iterator start at the top the of tree. */ - mpctx->playtree_iter = play_tree_iter_new(mpctx->playtree, mconfig); + mpctx->playtree_iter = play_tree_iter_new(mpctx->playtree, mpctx->mconfig); if (!mpctx->playtree_iter) continue; // find the first real item in the tree @@ -3050,14 +3071,14 @@ while (player_idle_mode && !filename) { mpctx->playtree_iter = NULL; continue; // wait for next command } - filename = play_tree_iter_get_file(mpctx->playtree_iter, 1); + mpctx->filename = play_tree_iter_get_file(mpctx->playtree_iter, 1); } } //--------------------------------------------------------------------------- - if(filename) + if(mpctx->filename) mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_Playing, - filename_recode(filename)); + filename_recode(mpctx->filename)); if (edl_filename) { if (edl_records) free_edl(edl_records); @@ -3080,9 +3101,9 @@ if (edl_output_filename) { if(vo_vobsub==NULL) mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_CantLoadSub, filename_recode(vobsub_name)); - } else if (sub_auto && filename){ + } else if (sub_auto && mpctx->filename){ /* try to autodetect vobsub from movie filename ::atmos */ - char *buf = strdup(filename), *psub; + char *buf = strdup(mpctx->filename), *psub; char *pdot = strrchr(buf, '.'); char *pslash = strrchr(buf, '/'); #if defined(__MINGW32__) || defined(__CYGWIN__) @@ -3110,7 +3131,7 @@ if (edl_output_filename) { free(buf); } if(vo_vobsub){ - initialized_flags|=INITIALIZED_VOBSUB; + mpctx->initialized_flags|=INITIALIZED_VOBSUB; vobsub_set_from_lang(vo_vobsub, dvdsub_lang); // check if vobsub requested only to display forced subtitles forced_subs_only=vobsub_get_forced_subs_flag(vo_vobsub); @@ -3136,26 +3157,32 @@ if (edl_output_filename) { mpctx->sh_video=NULL; current_module="open_stream"; - mpctx->stream=open_stream(filename,0,&mpctx->file_format); + mpctx->stream = open_stream(mpctx->filename, opts, &mpctx->file_format); if(!mpctx->stream) { // error... - mpctx->eof = libmpdemux_was_interrupted(PT_NEXT_ENTRY); + mpctx->stop_play = libmpdemux_was_interrupted(mpctx, PT_NEXT_ENTRY); goto goto_next_file; } - initialized_flags|=INITIALIZED_STREAM; + mpctx->initialized_flags|=INITIALIZED_STREAM; #ifdef CONFIG_GUI if ( use_gui ) guiGetEvent( guiSetStream,(char *)mpctx->stream ); #endif if(mpctx->file_format == DEMUXER_TYPE_PLAYLIST) { + mp_msg(MSGT_CPLAYER, MSGL_ERR, "\nThis looks like a playlist, but " + "playlist support will not be used automatically.\n" + "MPlayer's playlist code is unsafe and should only be used with " + "trusted sources.\nPlayback will probably fail.\n\n"); +#if 0 play_tree_t* entry; // Handle playlist current_module="handle_playlist"; mp_msg(MSGT_CPLAYER,MSGL_V,"Parsing playlist %s...\n", - filename_recode(filename)); - entry = parse_playtree(mpctx->stream,0); - mpctx->eof=playtree_add_playlist(entry); + filename_recode(mpctx->filename)); + entry = parse_playtree(mpctx->stream, mpctx->mconfig, 0); + mpctx->eof=playtree_add_playlist(mpctx, entry); goto goto_next_file; +#endif } mpctx->stream->start_pos+=seek_to_byte; @@ -3166,14 +3193,14 @@ if(stream_dump_type==5){ current_module="dumpstream"; if(mpctx->stream->type==STREAMTYPE_STREAM && mpctx->stream->fd<0){ mp_msg(MSGT_CPLAYER,MSGL_FATAL,MSGTR_DumpstreamFdUnavailable); - exit_player(MSGTR_Exit_error); + exit_player(mpctx, MSGTR_Exit_error); } stream_reset(mpctx->stream); stream_seek(mpctx->stream,mpctx->stream->start_pos); f=fopen(stream_dump_name,"wb"); if(!f){ mp_msg(MSGT_CPLAYER,MSGL_FATAL,MSGTR_CantOpenDumpfile); - exit_player(MSGTR_Exit_error); + exit_player(mpctx, MSGTR_Exit_error); } if (dvd_chapter > 1) { int chapter = dvd_chapter - 1; @@ -3184,24 +3211,24 @@ if(stream_dump_type==5){ if(len>0) { if(fwrite(buf,len,1,f) != 1) { mp_msg(MSGT_MENCODER,MSGL_FATAL,MSGTR_ErrorWritingFile,stream_dump_name); - exit_player(MSGTR_Exit_error); + exit_player(mpctx, MSGTR_Exit_error); } } } if(fclose(f)) { mp_msg(MSGT_MENCODER,MSGL_FATAL,MSGTR_ErrorWritingFile,stream_dump_name); - exit_player(MSGTR_Exit_error); + exit_player(mpctx, MSGTR_Exit_error); } mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_CoreDumped); - exit_player_with_rc(MSGTR_Exit_eof, 0); + exit_player_with_rc(mpctx, MSGTR_Exit_eof, 0); } #ifdef CONFIG_DVDREAD if(mpctx->stream->type==STREAMTYPE_DVD){ current_module="dvd lang->id"; - if(audio_id==-1) audio_id=dvd_aid_from_lang(mpctx->stream,audio_lang); - if(dvdsub_lang && dvdsub_id==-2) dvdsub_id=-1; - if(dvdsub_lang && dvdsub_id==-1) dvdsub_id=dvd_sid_from_lang(mpctx->stream,dvdsub_lang); + if(opts->audio_id==-1) opts->audio_id=dvd_aid_from_lang(mpctx->stream,audio_lang); + if(dvdsub_lang && opts->sub_id==-2) opts->sub_id=-1; + if(dvdsub_lang && opts->sub_id==-1) opts->sub_id=dvd_sid_from_lang(mpctx->stream,dvdsub_lang); // setup global sub numbering mpctx->global_sub_indices[SUB_SOURCE_DEMUX] = mpctx->global_sub_size; // the global # of the first demux-specific sub. mpctx->global_sub_size += dvd_number_of_subs(mpctx->stream); @@ -3212,9 +3239,9 @@ if(mpctx->stream->type==STREAMTYPE_DVD){ #ifdef CONFIG_DVDNAV if(mpctx->stream->type==STREAMTYPE_DVDNAV){ current_module="dvdnav lang->id"; - if(audio_id==-1) audio_id=mp_dvdnav_aid_from_lang(mpctx->stream,audio_lang); - if(dvdsub_lang && dvdsub_id==-2) dvdsub_id=-1; - if(dvdsub_lang && dvdsub_id==-1) dvdsub_id=mp_dvdnav_sid_from_lang(mpctx->stream,dvdsub_lang); + if(opts->audio_id==-1) opts->audio_id=mp_dvdnav_aid_from_lang(mpctx->stream,audio_lang); + if(dvdsub_lang && opts->sub_id==-2) opts->sub_id=-1; + if(dvdsub_lang && opts->sub_id==-1) opts->sub_id=mp_dvdnav_sid_from_lang(mpctx->stream,dvdsub_lang); // setup global sub numbering mpctx->global_sub_indices[SUB_SOURCE_DEMUX] = mpctx->global_sub_size; // the global # of the first demux-specific sub. mpctx->global_sub_size += mp_dvdnav_number_of_subs(mpctx->stream); @@ -3229,13 +3256,13 @@ if(stream_cache_size>0){ if(!stream_enable_cache(mpctx->stream,stream_cache_size*1024, stream_cache_size*1024*(stream_cache_min_percent / 100.0), stream_cache_size*1024*(stream_cache_seek_min_percent / 100.0))) - if((mpctx->eof = libmpdemux_was_interrupted(PT_NEXT_ENTRY))) goto goto_next_file; + if((mpctx->stop_play = libmpdemux_was_interrupted(mpctx, PT_NEXT_ENTRY))) goto goto_next_file; } //============ Open DEMUXERS --- DETECT file type ======================= current_module="demux_open"; -mpctx->demuxer=demux_open(mpctx->stream,mpctx->file_format,audio_id,video_id,dvdsub_id,filename); +mpctx->demuxer=demux_open(opts, mpctx->stream,mpctx->file_format,opts->audio_id,opts->video_id,opts->sub_id,mpctx->filename); // HACK to get MOV Reference Files working @@ -3256,18 +3283,18 @@ if (mpctx->demuxer && mpctx->demuxer->type==DEMUXER_TYPE_PLAYLIST) if ((strlen(bname)>10) && !strncmp(bname,"qt",2) && !strncmp(bname+3,"gateQT",6)) continue; - if (!strncmp(bname,mp_basename(filename),strlen(bname))) // ignoring self-reference + if (!strncmp(bname,mp_basename(mpctx->filename),strlen(bname))) // ignoring self-reference continue; entry = play_tree_new(); - if (filename && !strcmp(mp_basename(playlist_entry),playlist_entry)) // add reference path of current file + if (mpctx->filename && !strcmp(mp_basename(playlist_entry),playlist_entry)) // add reference path of current file { - temp=malloc((strlen(filename)-strlen(mp_basename(filename))+strlen(playlist_entry)+1)); + temp=malloc((strlen(mpctx->filename)-strlen(mp_basename(mpctx->filename))+strlen(playlist_entry)+1)); if (temp) { - strncpy(temp, filename, strlen(filename)-strlen(mp_basename(filename))); - temp[strlen(filename)-strlen(mp_basename(filename))]='\0'; + strncpy(temp, mpctx->filename, strlen(mpctx->filename)-strlen(mp_basename(mpctx->filename))); + temp[strlen(mpctx->filename)-strlen(mp_basename(mpctx->filename))]='\0'; strcat(temp, playlist_entry); play_tree_add_file(entry,temp); mp_msg(MSGT_CPLAYER,MSGL_V,"Resolving reference to %s.\n",temp); @@ -3289,7 +3316,7 @@ if (mpctx->demuxer && mpctx->demuxer->type==DEMUXER_TYPE_PLAYLIST) { entry = play_tree_new(); play_tree_set_child(entry,list); - mpctx->eof=playtree_add_playlist(entry); + mpctx->stop_play = playtree_add_playlist(mpctx, entry); goto goto_next_file; } } @@ -3302,7 +3329,7 @@ if(dvd_chapter>1) { seek(mpctx, pts, SEEK_ABSOLUTE); } -initialized_flags|=INITIALIZED_DEMUXER; +mpctx->initialized_flags|=INITIALIZED_DEMUXER; if (mpctx->stream->type != STREAMTYPE_DVD && mpctx->stream->type != STREAMTYPE_DVDNAV) { int i; @@ -3311,12 +3338,12 @@ if (mpctx->stream->type != STREAMTYPE_DVD && mpctx->stream->type != STREAMTYPE_D mpctx->global_sub_indices[SUB_SOURCE_DEMUX] = mpctx->global_sub_size; // the global # of the first demux-specific sub. for (i = 0; i < MAX_S_STREAMS; i++) if (mpctx->demuxer->s_streams[i]) - maxid = FFMAX(maxid, ((sh_sub_t *)mpctx->demuxer->s_streams[i])->sid); + maxid = FFMAX(maxid, mpctx->demuxer->s_streams[i]->sid); mpctx->global_sub_size += maxid + 1; } -// Make dvdsub_id always selectable if set. -if (mpctx->global_sub_size <= mpctx->global_sub_indices[SUB_SOURCE_DEMUX] + dvdsub_id) - mpctx->global_sub_size = mpctx->global_sub_indices[SUB_SOURCE_DEMUX] + dvdsub_id + 1; +// Make opts->sub_id always selectable if set. +if (mpctx->global_sub_size <= mpctx->global_sub_indices[SUB_SOURCE_DEMUX] + opts->sub_id) + mpctx->global_sub_size = mpctx->global_sub_indices[SUB_SOURCE_DEMUX] + opts->sub_id + 1; #ifdef CONFIG_ASS if (ass_enabled && ass_library) { @@ -3340,7 +3367,7 @@ mpctx->d_video=mpctx->demuxer->video; mpctx->d_sub=mpctx->demuxer->sub; // select audio stream -select_audio(mpctx->demuxer, audio_id, audio_lang); +select_audio(mpctx->demuxer, opts->audio_id, audio_lang); // DUMP STREAMS: if((stream_dump_type)&&(stream_dump_type<4)){ @@ -3355,7 +3382,7 @@ if((stream_dump_type)&&(stream_dump_type<4)){ } if(!ds){ mp_msg(MSGT_CPLAYER,MSGL_FATAL,MSGTR_DumpSelectedStreamMissing); - exit_player(MSGTR_Exit_error); + exit_player(mpctx, MSGTR_Exit_error); } // disable other streams: if(mpctx->d_audio && mpctx->d_audio!=ds) {ds_free_packs(mpctx->d_audio); mpctx->d_audio->id=-2; } @@ -3365,7 +3392,7 @@ if((stream_dump_type)&&(stream_dump_type<4)){ f=fopen(stream_dump_name,"wb"); if(!f){ mp_msg(MSGT_CPLAYER,MSGL_FATAL,MSGTR_CantOpenDumpfile); - exit_player(MSGTR_Exit_error); + exit_player(mpctx, MSGTR_Exit_error); } while(!ds->eof){ unsigned char* start; @@ -3376,7 +3403,7 @@ if((stream_dump_type)&&(stream_dump_type<4)){ } fclose(f); mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_CoreDumped); - exit_player_with_rc(MSGTR_Exit_eof, 0); + exit_player_with_rc(mpctx, MSGTR_Exit_eof, 0); } mpctx->sh_audio=mpctx->d_audio->sh; @@ -3421,8 +3448,10 @@ if(!mpctx->sh_video && !mpctx->sh_audio){ else dir = DVB_CHANNEL_LOWER; - if(dvb_step_channel(mpctx->stream, dir)) - mpctx->eof = mpctx->dvbin_reopen = 1; + if(dvb_step_channel(mpctx->stream, dir)) { + mpctx->stop_play = PT_NEXT_ENTRY; + mpctx->dvbin_reopen = 1; + } } #endif goto goto_next_file; // exit_player(MSGTR_Exit_error); @@ -3434,7 +3463,7 @@ demux_info_print(mpctx->demuxer); //================== Read SUBTITLES (DVD & TEXT) ========================== if(vo_spudec==NULL && mpctx->sh_video && (mpctx->stream->type==STREAMTYPE_DVD || mpctx->stream->type == STREAMTYPE_DVDNAV || mpctx->d_sub->id >= 0)){ - init_vo_spudec(); + init_vo_spudec(mpctx); } // Apply current settings for forced subs @@ -3448,15 +3477,15 @@ if(mpctx->sh_video) { current_module="read_subtitles_file"; if(sub_name){ for (i = 0; sub_name[i] != NULL; ++i) - add_subtitles (sub_name[i], mpctx->sh_video->fps, 0); + add_subtitles(mpctx, sub_name[i], mpctx->sh_video->fps, 0); } if(sub_auto) { // auto load sub file ... char *psub = get_path( "sub/" ); - char **tmp = sub_filenames((psub ? psub : ""), filename); + char **tmp = sub_filenames((psub ? psub : ""), mpctx->filename); int i = 0; free(psub); // release the buffer created by get_path() above while (tmp[i]) { - add_subtitles (tmp[i], mpctx->sh_video->fps, 1); + add_subtitles(mpctx, tmp[i], mpctx->sh_video->fps, 1); free(tmp[i++]); } free(tmp); @@ -3475,20 +3504,20 @@ if (mpctx->global_sub_size) { if (vobsub_index_id >= 0) { // if user asks for a vobsub id, use that first. mpctx->global_sub_pos = mpctx->global_sub_indices[SUB_SOURCE_VOBSUB] + vobsub_index_id; - } else if (dvdsub_id >= 0 && mpctx->global_sub_indices[SUB_SOURCE_DEMUX] >= 0) { + } else if (opts->sub_id >= 0 && mpctx->global_sub_indices[SUB_SOURCE_DEMUX] >= 0) { // if user asks for a dvd sub id, use that next. - mpctx->global_sub_pos = mpctx->global_sub_indices[SUB_SOURCE_DEMUX] + dvdsub_id; + mpctx->global_sub_pos = mpctx->global_sub_indices[SUB_SOURCE_DEMUX] + opts->sub_id; } else if (mpctx->global_sub_indices[SUB_SOURCE_SUBS] >= 0) { // if there are text subs to use, use those. (autosubs come last here) mpctx->global_sub_pos = mpctx->global_sub_indices[SUB_SOURCE_SUBS]; - } else if (dvdsub_id < 0 && mpctx->global_sub_indices[SUB_SOURCE_DEMUX] >= 0) { + } else if (opts->sub_id < 0 && mpctx->global_sub_indices[SUB_SOURCE_DEMUX] >= 0) { // finally select subs by language and container hints - if (dvdsub_id < 0 && dvdsub_lang) - dvdsub_id = demuxer_sub_track_by_lang(mpctx->demuxer, dvdsub_lang); - if (dvdsub_id < 0) - dvdsub_id = demuxer_default_sub_track(mpctx->demuxer); - if (dvdsub_id >= 0) - mpctx->global_sub_pos = mpctx->global_sub_indices[SUB_SOURCE_DEMUX] + dvdsub_id; + if (opts->sub_id < 0 && dvdsub_lang) + opts->sub_id = demuxer_sub_track_by_lang(mpctx->demuxer, dvdsub_lang); + if (opts->sub_id < 0) + opts->sub_id = demuxer_default_sub_track(mpctx->demuxer); + if (opts->sub_id >= 0) + mpctx->global_sub_pos = mpctx->global_sub_indices[SUB_SOURCE_DEMUX] + opts->sub_id; } // rather than duplicate code, use the SUB_SELECT handler to init the right one. mpctx->global_sub_pos--; @@ -3505,7 +3534,7 @@ if (mpctx->global_sub_size) { } mp_msg(MSGT_IDENTIFY,MSGL_INFO,"ID_FILENAME=%s\n", - filename_recode(filename)); + filename_recode(mpctx->filename)); mp_msg(MSGT_IDENTIFY,MSGL_INFO,"ID_DEMUXER=%s\n", mpctx->demuxer->desc->name); if (mpctx->sh_video) { /* Assume FOURCC if all bytes >= 0x20 (' ') */ @@ -3539,14 +3568,14 @@ if (mpctx->global_sub_size) { if(!mpctx->sh_video) goto main; // audio-only -if(!reinit_video_chain()) { +if(!reinit_video_chain(mpctx)) { if(!mpctx->sh_video){ if(!mpctx->sh_audio) goto goto_next_file; goto main; // exit_player(MSGTR_Exit_error); } } - if(vo_flags & 0x08 && vo_spudec) + if(mpctx->sh_video->output_flags & 0x08 && vo_spudec) spudec_set_hw_spu(vo_spudec,mpctx->video_out); #ifdef CONFIG_FREETYPE @@ -3580,12 +3609,12 @@ mpctx->num_buffered_frames=0; // Make sure old OSD does not stay around, // e.g. with -fixed-vo and same-resolution files clear_osd_msgs(); -update_osd_msg(); +update_osd_msg(mpctx); //================ SETUP AUDIO ========================== if(mpctx->sh_audio){ - reinit_audio_chain(); + reinit_audio_chain(mpctx); if (mpctx->sh_audio && mpctx->sh_audio->codec) mp_msg(MSGT_IDENTIFY,MSGL_INFO, "ID_AUDIO_CODEC=%s\n", mpctx->sh_audio->codec->name); } @@ -3608,14 +3637,14 @@ if(!mpctx->sh_audio){ mp_msg(MSGT_CPLAYER,MSGL_V,"Freeing %d unused audio chunks.\n",mpctx->d_audio->packs); ds_free_packs(mpctx->d_audio); // free buffered chunks //mpctx->d_audio->id=-2; // do not read audio chunks - //uninit_player(INITIALIZED_AO); // close device + //uninit_player(mpctx, INITIALIZED_AO); // close device } if(!mpctx->sh_video){ mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_Video_NoVideo); mp_msg(MSGT_CPLAYER,MSGL_V,"Freeing %d unused video chunks.\n",mpctx->d_video->packs); ds_free_packs(mpctx->d_video); mpctx->d_video->id=-2; - //if(!fixed_vo) uninit_player(INITIALIZED_VO); + //if(!fixed_vo) uninit_player(mpctx, INITIALIZED_VO); } if (!mpctx->sh_video && !mpctx->sh_audio) @@ -3638,15 +3667,15 @@ if ( use_gui ) { } #endif -mp_input_set_section(NULL); + mp_input_set_section(mpctx->input, NULL); //TODO: add desired (stream-based) sections here -if (mpctx->stream->type==STREAMTYPE_TV) mp_input_set_section("tv"); -if (mpctx->stream->type==STREAMTYPE_DVDNAV) mp_input_set_section("dvdnav"); + if (mpctx->stream->type==STREAMTYPE_TV) mp_input_set_section(mpctx->input, "tv"); + if (mpctx->stream->type==STREAMTYPE_DVDNAV) mp_input_set_section(mpctx->input, "dvdnav"); //==================== START PLAYING ======================= -if(mpctx->loop_times>1) mpctx->loop_times--; else -if(mpctx->loop_times==1) mpctx->loop_times = -1; +if(opts->loop_times>1) opts->loop_times--; else +if(opts->loop_times==1) opts->loop_times = -1; mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_StartPlaying); @@ -3656,7 +3685,7 @@ total_frame_cnt=0; drop_frame_cnt=0; // fix for multifile fps benchmark play_n_frames=play_n_frames_mf; if(play_n_frames==0){ - mpctx->eof=PT_NEXT_ENTRY; goto goto_next_file; + mpctx->stop_play=PT_NEXT_ENTRY; goto goto_next_file; } if (seek_to_sec) { @@ -3677,7 +3706,9 @@ if (mpctx->stream->type == STREAMTYPE_DVDNAV) { } #endif -while(!mpctx->eof){ + get_relative_time(mpctx); // reset current delta + +while(!mpctx->stop_play){ float aq_sleep_time=0; if(dvd_last_chapter>0) { @@ -3689,16 +3720,16 @@ if(dvd_last_chapter>0) { if(!mpctx->sh_audio && mpctx->d_audio->sh) { mpctx->sh_audio = mpctx->d_audio->sh; mpctx->sh_audio->ds = mpctx->d_audio; - reinit_audio_chain(); + reinit_audio_chain(mpctx); } /*========================== PLAY AUDIO ============================*/ if (mpctx->sh_audio) - if (!fill_audio_out_buffers()) + if (!fill_audio_out_buffers(mpctx)) // at eof, all audio at least written to ao if (!mpctx->sh_video) - mpctx->eof = PT_NEXT_ENTRY; + mpctx->stop_play = AT_END_OF_FILE; if(!mpctx->sh_video) { @@ -3706,15 +3737,15 @@ if(!mpctx->sh_video) { double a_pos=0; // sh_audio can be NULL due to video stream switching // TODO: handle this better - if((!quiet || end_at.type == END_AT_TIME) && mpctx->sh_audio) - a_pos = playing_audio_pts(mpctx->sh_audio, mpctx->d_audio, mpctx->audio_out); + if(!quiet || end_at.type == END_AT_TIME && mpctx->sh_audio) + a_pos = playing_audio_pts(mpctx); if(!quiet) - print_status(a_pos, 0, 0); + print_status(mpctx, a_pos, 0, 0); if(end_at.type == END_AT_TIME && end_at.pos < a_pos) - mpctx->eof = PT_NEXT_ENTRY; - update_osd_msg(); + mpctx->stop_play = PT_NEXT_ENTRY; + update_osd_msg(mpctx); } else { @@ -3724,18 +3755,19 @@ if(!mpctx->sh_video) { vo_fps=mpctx->sh_video->fps; if (!mpctx->num_buffered_frames) { - double frame_time = update_video(&blit_frame); + double frame_time = update_video(mpctx, &blit_frame); mp_dbg(MSGT_AVSYNC,MSGL_DBG2,"*** ftime=%5.3f ***\n",frame_time); if (mpctx->sh_video->vf_initialized < 0) { mp_msg(MSGT_CPLAYER,MSGL_FATAL, MSGTR_NotInitializeVOPorVO); - mpctx->eof = 1; goto goto_next_file; + mpctx->stop_play = PT_NEXT_ENTRY; + goto goto_next_file; } if (frame_time < 0) - mpctx->eof = 1; + mpctx->stop_play = AT_END_OF_FILE; else { // might return with !eof && !blit_frame if !correct_pts mpctx->num_buffered_frames += blit_frame; - time_frame += frame_time / playback_speed; // for nosound + time_frame += frame_time / opts->playback_speed; // for nosound } } @@ -3749,12 +3781,12 @@ if(!mpctx->sh_video) { #endif current_module="vo_check_events"; - if (vo_config_count) mpctx->video_out->check_events(); + vo_check_events(mpctx->video_out); #ifdef CONFIG_X11 if (stop_xscreensaver) { current_module = "stop_xscreensaver"; - xscreensaver_heartbeat(); + xscreensaver_heartbeat(mpctx->x11_state); } #endif if (heartbeat_cmd) { @@ -3766,7 +3798,7 @@ if(!mpctx->sh_video) { } } - frame_time_remaining = sleep_until_update(&time_frame, &aq_sleep_time); + frame_time_remaining = sleep_until_update(mpctx, &time_frame, &aq_sleep_time); //====================== FLIP PAGE (VIDEO BLT): ========================= @@ -3774,14 +3806,14 @@ if(!mpctx->sh_video) { if (!frame_time_remaining && blit_frame) { unsigned int t2=GetTimer(); - if(vo_config_count) mpctx->video_out->flip_page(); + vo_flip_page(mpctx->video_out); mpctx->num_buffered_frames--; vout_time_usage += (GetTimer() - t2) * 0.000001; } //====================== A-V TIMESTAMP CORRECTION: ========================= - adjust_sync_and_print_status(frame_time_remaining, time_frame); + adjust_sync_and_print_status(mpctx, frame_time_remaining, time_frame); //============================ Auto QUALITY ============================ @@ -3805,14 +3837,14 @@ if(auto_quality>0){ if (play_n_frames >= 0 && !frame_time_remaining && blit_frame) { --play_n_frames; - if (play_n_frames <= 0) mpctx->eof = PT_NEXT_ENTRY; + if (play_n_frames <= 0) mpctx->stop_play = PT_NEXT_ENTRY; } // FIXME: add size based support for -endpos if (end_at.type == END_AT_TIME && !frame_time_remaining && end_at.pos <= mpctx->sh_video->pts) - mpctx->eof = PT_NEXT_ENTRY; + mpctx->stop_play = PT_NEXT_ENTRY; } // end if(mpctx->sh_video) @@ -3839,13 +3871,13 @@ if(auto_quality>0){ if (mpctx->osd_function == OSD_PAUSE) { mpctx->was_paused = 1; - pause_loop(); + pause_loop(mpctx); } // handle -sstep if(step_sec>0) { mpctx->osd_function=OSD_FFW; - rel_seek_secs+=step_sec; + mpctx->rel_seek_secs+=step_sec; } edl_update(mpctx); @@ -3857,7 +3889,7 @@ if(step_sec>0) { { mp_cmd_t* cmd; int brk_cmd = 0; - while( !brk_cmd && (cmd = mp_input_get_cmd(0,0,0)) != NULL) { + while( !brk_cmd && (cmd = mp_input_get_cmd(mpctx->input, 0,0,0)) != NULL) { brk_cmd = run_command(mpctx, cmd); mp_cmd_free(cmd); if (brk_cmd == 2) @@ -3867,28 +3899,28 @@ if(step_sec>0) { mpctx->was_paused = 0; /* Looping. */ - if(mpctx->eof==1 && mpctx->loop_times>=0) { - mp_msg(MSGT_CPLAYER,MSGL_V,"loop_times = %d, eof = %d\n", mpctx->loop_times,mpctx->eof); + if(mpctx->stop_play==AT_END_OF_FILE && opts->loop_times>=0) { + mp_msg(MSGT_CPLAYER,MSGL_V,"loop_times = %d\n", opts->loop_times); - if(mpctx->loop_times>1) mpctx->loop_times--; else - if(mpctx->loop_times==1) mpctx->loop_times=-1; + if(opts->loop_times>1) opts->loop_times--; else + if(opts->loop_times==1) opts->loop_times=-1; play_n_frames=play_n_frames_mf; - mpctx->eof=0; - abs_seek_pos=SEEK_ABSOLUTE; rel_seek_secs=seek_to_sec; + mpctx->stop_play=0; + mpctx->abs_seek_pos=SEEK_ABSOLUTE; mpctx->rel_seek_secs=seek_to_sec; loop_seek = 1; } -if(rel_seek_secs || abs_seek_pos){ - if (seek(mpctx, rel_seek_secs, abs_seek_pos) >= 0) { +if(mpctx->rel_seek_secs || mpctx->abs_seek_pos){ + if (seek(mpctx, mpctx->rel_seek_secs, mpctx->abs_seek_pos) >= 0) { // Set OSD: if(!loop_seek){ if( !edl_decision ) - set_osd_bar(0,"Position",0,100,demuxer_get_percent_pos(mpctx->demuxer)); + set_osd_bar(mpctx, 0,"Position",0,100,demuxer_get_percent_pos(mpctx->demuxer)); } } - rel_seek_secs=0; - abs_seek_pos=0; + mpctx->rel_seek_secs=0; + mpctx->abs_seek_pos=0; loop_seek=0; edl_decision = 0; } @@ -3903,7 +3935,7 @@ if(rel_seek_secs || abs_seek_pos){ guiIntfStruct.Position=demuxer_get_percent_pos(mpctx->demuxer); } if ( mpctx->sh_video ) guiIntfStruct.TimeSec=mpctx->sh_video->pts; - else if ( mpctx->sh_audio ) guiIntfStruct.TimeSec=playing_audio_pts(mpctx->sh_audio, mpctx->d_audio, mpctx->audio_out); + else if ( mpctx->sh_audio ) guiIntfStruct.TimeSec=playing_audio_pts(mpctx); guiIntfStruct.LengthInSec=demuxer_get_time_length(mpctx->demuxer); guiGetEvent( guiReDraw,NULL ); guiGetEvent( guiSetVolume,NULL ); @@ -3920,15 +3952,15 @@ if(rel_seek_secs || abs_seek_pos){ } #endif /* CONFIG_GUI */ -} // while(!mpctx->eof) +} // while(!mpctx->stop_play) -mp_msg(MSGT_GLOBAL,MSGL_V,"EOF code: %d \n",mpctx->eof); +mp_msg(MSGT_GLOBAL,MSGL_V,"EOF code: %d \n",mpctx->stop_play); #ifdef CONFIG_DVBIN if(mpctx->dvbin_reopen) { - mpctx->eof = 0; - uninit_player(INITIALIZED_ALL-(INITIALIZED_GUI|INITIALIZED_STREAM|INITIALIZED_INPUT|INITIALIZED_GETCH2|(fixed_vo?INITIALIZED_VO:0))); + mpctx->stop_play = 0; + uninit_player(mpctx, INITIALIZED_ALL-(INITIALIZED_GUI|INITIALIZED_STREAM|INITIALIZED_GETCH2|(opts->fixed_vo?INITIALIZED_VO:0))); cache_uninit(mpctx->stream); mpctx->dvbin_reopen = 0; goto goto_enable_cache; @@ -3966,7 +3998,7 @@ if(benchmark){ } // time to uninit all, except global stuff: -uninit_player(INITIALIZED_ALL-(INITIALIZED_GUI+INITIALIZED_INPUT+(fixed_vo?INITIALIZED_VO:0))); +uninit_player(mpctx, INITIALIZED_ALL-(INITIALIZED_GUI+(opts->fixed_vo?INITIALIZED_VO:0))); if(mpctx->set_of_sub_size > 0) { current_module="sub_free"; @@ -3987,38 +4019,36 @@ if(ass_library) ass_clear_fonts(ass_library); #endif -if(mpctx->eof == PT_NEXT_ENTRY || mpctx->eof == PT_PREV_ENTRY) { - mpctx->eof = mpctx->eof == PT_NEXT_ENTRY ? 1 : -1; - if(play_tree_iter_step(mpctx->playtree_iter,mpctx->play_tree_step,0) == PLAY_TREE_ITER_ENTRY) { - mpctx->eof = 1; - } else { + if (!mpctx->stop_play) // In case some goto jumped here... + mpctx->stop_play = PT_NEXT_ENTRY; + +int playtree_direction = 1; + +if(mpctx->stop_play == PT_NEXT_ENTRY || mpctx->stop_play == PT_PREV_ENTRY) { + if(play_tree_iter_step(mpctx->playtree_iter,mpctx->play_tree_step,0) != PLAY_TREE_ITER_ENTRY) { play_tree_iter_free(mpctx->playtree_iter); mpctx->playtree_iter = NULL; } mpctx->play_tree_step = 1; -} else if(mpctx->eof == PT_UP_NEXT || mpctx->eof == PT_UP_PREV) { - mpctx->eof = mpctx->eof == PT_UP_NEXT ? 1 : -1; +} else if(mpctx->stop_play == PT_UP_NEXT || mpctx->stop_play == PT_UP_PREV) { + int direction = mpctx->stop_play == PT_UP_NEXT ? 1 : -1; if(mpctx->playtree_iter) { - if(play_tree_iter_up_step(mpctx->playtree_iter,mpctx->eof,0) == PLAY_TREE_ITER_ENTRY) { - mpctx->eof = 1; - } else { + if(play_tree_iter_up_step(mpctx->playtree_iter,direction,0) != PLAY_TREE_ITER_ENTRY) { play_tree_iter_free(mpctx->playtree_iter); mpctx->playtree_iter = NULL; } } -} else if (mpctx->eof == PT_STOP) { +} else if (mpctx->stop_play == PT_STOP) { play_tree_iter_free(mpctx->playtree_iter); mpctx->playtree_iter = NULL; } else { // NEXT PREV SRC - mpctx->eof = mpctx->eof == PT_PREV_SRC ? -1 : 1; + playtree_direction = mpctx->stop_play == PT_PREV_SRC ? -1 : 1; } -if(mpctx->eof == 0) mpctx->eof = 1; - while(mpctx->playtree_iter != NULL) { - filename = play_tree_iter_get_file(mpctx->playtree_iter,mpctx->eof); - if(filename == NULL) { - if(play_tree_iter_step(mpctx->playtree_iter,mpctx->eof,0) != PLAY_TREE_ITER_ENTRY) { + mpctx->filename = play_tree_iter_get_file(mpctx->playtree_iter, playtree_direction); + if(mpctx->filename == NULL) { + if(play_tree_iter_step(mpctx->playtree_iter, playtree_direction, 0) != PLAY_TREE_ITER_ENTRY) { play_tree_iter_free(mpctx->playtree_iter); mpctx->playtree_iter = NULL; }; @@ -4036,13 +4066,13 @@ if(use_gui && !mpctx->playtree_iter) { #endif if(use_gui || mpctx->playtree_iter != NULL || player_idle_mode){ - if(!mpctx->playtree_iter) filename = NULL; - mpctx->eof = 0; + if(!mpctx->playtree_iter) mpctx->filename = NULL; + mpctx->stop_play = 0; goto play_next_file; } -exit_player_with_rc(MSGTR_Exit_eof, 0); +exit_player_with_rc(mpctx, MSGTR_Exit_eof, 0); return 1; } |