r22298 - in trunk: Makefile command.c command.h m_property.c m_property.h mp_core.h mplayer.c
Author: uau Date: Wed Feb 21 01:49:24 2007 New Revision: 22298 Added: trunk/command.c trunk/command.h trunk/mp_core.h Modified: trunk/Makefile trunk/m_property.c trunk/m_property.h trunk/mplayer.c Log: Split command/property handling from mplayer.c to a new file command.c. Move some global and static variables under a struct that can be given as a parameter. Add a context argument to the property functions so that they do not have to depend on global/static variables. Modified: trunk/Makefile ============================================================================== --- trunk/Makefile (original) +++ trunk/Makefile Wed Feb 21 01:49:24 2007 @@ -45,6 +45,7 @@ mixer.c \ parser-mpcmd.c \ subopt-helper.c \ + command.c \ SRCS_MENCODER = mencoder.c \ mp_msg-mencoder.c \ Added: trunk/command.c ============================================================================== --- (empty file) +++ trunk/command.c Wed Feb 21 01:49:24 2007 @@ -0,0 +1,2389 @@ +#include <stdlib.h> +#include <inttypes.h> +#include <unistd.h> + +#include "config.h" +#include "input/input.h" +#include "stream/stream.h" +#include "libmpdemux/demuxer.h" +#include "libmpdemux/stheader.h" +#include "mplayer.h" +#include "libvo/sub.h" +#include "m_option.h" +#include "m_property.h" +#include "help_mp.h" +#include "metadata.h" +#include "libmpcodecs/mp_image.h" +#include "libmpcodecs/vf.h" +#include "libmpcodecs/vd.h" +#include "libvo/video_out.h" +#include "playtree.h" +#include "libao2/audio_out.h" +#include "mpcommon.h" +#include "mixer.h" +#include "libmpdemux/matroska.h" +#include "libmpcodecs/dec_video.h" +#include "vobsub.h" +#include "spudec.h" +#ifdef USE_TV +#include "stream/tv.h" +#endif +#ifdef USE_RADIO +#include "stream/stream_radio.h" +#endif +#ifdef HAS_DVBIN_SUPPORT +#include "stream/dvbin.h" +#endif +#ifdef USE_DVDREAD +#include "stream/stream_dvd.h" +#endif +#ifdef USE_DVDNAV +#include "stream/stream_dvdnav.h" +#endif +#ifdef USE_ASS +#include "libass/ass.h" +#include "libass/ass_mp.h" +#endif +#ifdef HAVE_NEW_GUI +#include "Gui/interface.h" +#endif + +#include "mp_core.h" + +#define ROUND(x) ((int)((x)<0 ? (x)-0.5 : (x)+0.5)) + +static void rescale_input_coordinates(int ix, int iy, double *dx, double *dy) +{ + //remove the borders, if any, and rescale to the range [0,1],[0,1] + if (vo_fs) { //we are in full-screen mode + if (vo_screenwidth > vo_dwidth) //there are borders along the x axis + ix -= (vo_screenwidth - vo_dwidth) / 2; + if (vo_screenheight > vo_dheight) //there are borders along the y axis (usual way) + iy -= (vo_screenheight - vo_dheight) / 2; + + if (ix < 0 || ix > vo_dwidth) { + *dx = *dy = -1.0; + return; + } //we are on one of the borders + if (iy < 0 || iy > vo_dheight) { + *dx = *dy = -1.0; + return; + } //we are on one of the borders + } + + *dx = (double) ix / (double) vo_dwidth; + *dy = (double) iy / (double) vo_dheight; + + mp_msg(MSGT_CPLAYER, MSGL_V, + "\r\nrescaled coordinates: %.3lf, %.3lf, screen (%d x %d), vodisplay: (%d, %d), fullscreen: %d\r\n", + *dx, *dy, vo_screenwidth, vo_screenheight, vo_dwidth, + vo_dheight, vo_fs); +} + +static int sub_source(MPContext * mpctx) +{ + int source = -1; + int top = -1; + int i; + for (i = 0; i < SUB_SOURCES; i++) { + int j = mpctx->global_sub_indices[i]; + if ((j >= 0) && (j > top) && (mpctx->global_sub_pos >= j)) { + source = i; + top = j; + } + } + return source; +} + +/** + * \brief Log the currently displayed subtitle to a file + * + * Logs the current or last displayed subtitle together with filename + * and time information to ~/.mplayer/subtitle_log + * + * Intended purpose is to allow convenient marking of bogus subtitles + * which need to be fixed while watching the movie. + */ + +static void log_sub(void) +{ + char *fname; + FILE *f; + int i; + + if (subdata == NULL || vo_sub_last == NULL) + return; + fname = get_path("subtitle_log"); + f = fopen(fname, "a"); + if (!f) + return; + fprintf(f, "----------------------------------------------------------\n"); + if (subdata->sub_uses_time) { + fprintf(f, + "N: %s S: %02ld:%02ld:%02ld.%02ld E: %02ld:%02ld:%02ld.%02ld\n", + filename, vo_sub_last->start / 360000, + (vo_sub_last->start / 6000) % 60, + (vo_sub_last->start / 100) % 60, vo_sub_last->start % 100, + vo_sub_last->end / 360000, (vo_sub_last->end / 6000) % 60, + (vo_sub_last->end / 100) % 60, vo_sub_last->end % 100); + } else { + fprintf(f, "N: %s S: %ld E: %ld\n", filename, vo_sub_last->start, + vo_sub_last->end); + } + for (i = 0; i < vo_sub_last->lines; i++) { + fprintf(f, "%s\n", vo_sub_last->text[i]); + } + fclose(f); +} + + +/// \defgroup Properties +///@{ + +/// \defgroup GeneralProperties General properties +/// \ingroup Properties +///@{ + +/// OSD level (RW) +static int mp_property_osdlevel(m_option_t * prop, int action, void *arg, + MPContext * mpctx) +{ + return m_property_choice(prop, action, arg, &osd_level); +} + +/// Playback speed (RW) +static int mp_property_playback_speed(m_option_t * prop, int action, + void *arg, MPContext * mpctx) +{ + switch (action) { + case M_PROPERTY_SET: + if (!arg) + return M_PROPERTY_ERROR; + M_PROPERTY_CLAMP(prop, *(float *) arg); + playback_speed = *(float *) arg; + build_afilter_chain(mpctx->sh_audio, &ao_data); + return M_PROPERTY_OK; + case M_PROPERTY_STEP_UP: + case M_PROPERTY_STEP_DOWN: + playback_speed += (arg ? *(float *) arg : 0.1) * + (action == M_PROPERTY_STEP_DOWN ? -1 : 1); + M_PROPERTY_CLAMP(prop, playback_speed); + build_afilter_chain(mpctx->sh_audio, &ao_data); + return M_PROPERTY_OK; + } + return m_property_float_range(prop, action, arg, &playback_speed); +} + +/// filename with path (RO) +static int mp_property_path(m_option_t * prop, int action, void *arg, + MPContext * mpctx) +{ + return m_property_string_ro(prop, action, arg, filename); +} + +/// filename without path (RO) +static int mp_property_filename(m_option_t * prop, int action, void *arg, + MPContext * mpctx) +{ + char *f; + if (!filename) + return M_PROPERTY_UNAVAILABLE; + if (((f = strrchr(filename, '/')) || (f = strrchr(filename, '\\'))) && f[1]) + f++; + else + f = filename; + return m_property_string_ro(prop, action, arg, f); +} + +/// Demuxer name (RO) +static int mp_property_demuxer(m_option_t * prop, int action, void *arg, + MPContext * mpctx) +{ + if (!mpctx->demuxer) + return M_PROPERTY_UNAVAILABLE; + return m_property_string_ro(prop, action, arg, + (char *) mpctx->demuxer->desc->name); +} + +/// Position in the stream (RW) +static int mp_property_stream_pos(m_option_t * prop, int action, void *arg, + MPContext * mpctx) +{ + if (!mpctx->demuxer || !mpctx->demuxer->stream) + return M_PROPERTY_UNAVAILABLE; + if (!arg) + return M_PROPERTY_ERROR; + switch (action) { + case M_PROPERTY_GET: + *(off_t *) arg = stream_tell(mpctx->demuxer->stream); + return M_PROPERTY_OK; + case M_PROPERTY_SET: + M_PROPERTY_CLAMP(prop, *(off_t *) arg); + stream_seek(mpctx->demuxer->stream, *(off_t *) arg); + return M_PROPERTY_OK; + } + return M_PROPERTY_NOT_IMPLEMENTED; +} + +/// Stream start offset (RO) +static int mp_property_stream_start(m_option_t * prop, int action, + void *arg, MPContext * mpctx) +{ + if (!mpctx->demuxer || !mpctx->demuxer->stream) + return M_PROPERTY_UNAVAILABLE; + switch (action) { + case M_PROPERTY_GET: + *(off_t *) arg = mpctx->demuxer->stream->start_pos; + return M_PROPERTY_OK; + } + return M_PROPERTY_NOT_IMPLEMENTED; +} + +/// Stream end offset (RO) +static int mp_property_stream_end(m_option_t * prop, int action, void *arg, + MPContext * mpctx) +{ + if (!mpctx->demuxer || !mpctx->demuxer->stream) + return M_PROPERTY_UNAVAILABLE; + switch (action) { + case M_PROPERTY_GET: + *(off_t *) arg = mpctx->demuxer->stream->end_pos; + return M_PROPERTY_OK; + } + return M_PROPERTY_NOT_IMPLEMENTED; +} + +/// Stream length (RO) +static int mp_property_stream_length(m_option_t * prop, int action, + void *arg, MPContext * mpctx) +{ + if (!mpctx->demuxer || !mpctx->demuxer->stream) + return M_PROPERTY_UNAVAILABLE; + switch (action) { + case M_PROPERTY_GET: + *(off_t *) arg = + mpctx->demuxer->stream->end_pos - mpctx->demuxer->stream->start_pos; + return M_PROPERTY_OK; + } + return M_PROPERTY_NOT_IMPLEMENTED; +} + +/// Media length in seconds (RO) +static int mp_property_length(m_option_t * prop, int action, void *arg, + MPContext * mpctx) +{ + double len; + + if (!mpctx->demuxer || + !(int) (len = demuxer_get_time_length(mpctx->demuxer))) + return M_PROPERTY_UNAVAILABLE; + + switch (action) { + case M_PROPERTY_PRINT: + if (!arg) + return M_PROPERTY_ERROR; + else { + int h, m, s = len; + h = s / 3600; + s -= h * 3600; + m = s / 60; + s -= m * 60; + *(char **) arg = malloc(20); + if (h > 0) + sprintf(*(char **) arg, "%d:%02d:%02d", h, m, s); + else if (m > 0) + sprintf(*(char **) arg, "%d:%02d", m, s); + else + sprintf(*(char **) arg, "%d", s); + return M_PROPERTY_OK; + } + break; + } + return m_property_double_ro(prop, action, arg, len); +} + +///@} + +/// \defgroup AudioProperties Audio properties +/// \ingroup Properties +///@{ + +/// Volume (RW) +static int mp_property_volume(m_option_t * prop, int action, void *arg, + MPContext * mpctx) +{ + + if (!mpctx->sh_audio) + return M_PROPERTY_UNAVAILABLE; + + switch (action) { + case M_PROPERTY_GET: + if (!arg) + return M_PROPERTY_ERROR; + mixer_getbothvolume(&mpctx->mixer, arg); + return M_PROPERTY_OK; + case M_PROPERTY_PRINT:{ + float vol; + if (!arg) + return M_PROPERTY_ERROR; + mixer_getbothvolume(&mpctx->mixer, &vol); + return m_property_float_range(prop, action, arg, &vol); + } + case M_PROPERTY_STEP_UP: + case M_PROPERTY_STEP_DOWN: + case M_PROPERTY_SET: + break; + default: + return M_PROPERTY_NOT_IMPLEMENTED; + } + + if (mpctx->edl_muted) + return M_PROPERTY_DISABLED; + mpctx->user_muted = 0; + + switch (action) { + case M_PROPERTY_SET: + if (!arg) + return M_PROPERTY_ERROR; + M_PROPERTY_CLAMP(prop, *(float *) arg); + mixer_setvolume(&mpctx->mixer, *(float *) arg, *(float *) arg); + return M_PROPERTY_OK; + case M_PROPERTY_STEP_UP: + if (arg && *(float *) arg <= 0) + mixer_decvolume(&mpctx->mixer); + else + mixer_incvolume(&mpctx->mixer); + return M_PROPERTY_OK; + case M_PROPERTY_STEP_DOWN: + if (arg && *(float *) arg <= 0) + mixer_incvolume(&mpctx->mixer); + else + mixer_decvolume(&mpctx->mixer); + return M_PROPERTY_OK; + } + return M_PROPERTY_NOT_IMPLEMENTED; +} + +/// Mute (RW) +static int mp_property_mute(m_option_t * prop, int action, void *arg, + MPContext * mpctx) +{ + + if (!mpctx->sh_audio) + return M_PROPERTY_UNAVAILABLE; + + switch (action) { + case M_PROPERTY_SET: + if (mpctx->edl_muted) + return M_PROPERTY_DISABLED; + if (!arg) + return M_PROPERTY_ERROR; + if ((!!*(int *) arg) != mpctx->mixer.muted) + mixer_mute(&mpctx->mixer); + mpctx->user_muted = mpctx->mixer.muted; + return M_PROPERTY_OK; + case M_PROPERTY_STEP_UP: + case M_PROPERTY_STEP_DOWN: + if (mpctx->edl_muted) + return M_PROPERTY_DISABLED; + mixer_mute(&mpctx->mixer); + mpctx->user_muted = mpctx->mixer.muted; + return M_PROPERTY_OK; + case M_PROPERTY_PRINT: + if (!arg) + return M_PROPERTY_ERROR; + if (mpctx->edl_muted) { + *(char **) arg = strdup(MSGTR_EnabledEdl); + return M_PROPERTY_OK; + } + default: + return m_property_flag(prop, action, arg, &mpctx->mixer.muted); + + } +} + +/// Audio delay (RW) +static int mp_property_audio_delay(m_option_t * prop, int action, + void *arg, MPContext * mpctx) +{ + if (!(mpctx->sh_audio && mpctx->sh_video)) + return M_PROPERTY_UNAVAILABLE; + switch (action) { + case M_PROPERTY_SET: + case M_PROPERTY_STEP_UP: + case M_PROPERTY_STEP_DOWN: + if (!arg) + return M_PROPERTY_ERROR; + else { + float delay = audio_delay; + m_property_delay(prop, action, arg, &audio_delay); + if (mpctx->sh_audio) + mpctx->sh_audio->delay -= audio_delay - delay; + } + return M_PROPERTY_OK; + default: + return m_property_delay(prop, action, arg, &audio_delay); + } +} + +/// Audio codec tag (RO) +static int mp_property_audio_format(m_option_t * prop, int action, + void *arg, MPContext * mpctx) +{ + if (!mpctx->sh_audio) + return M_PROPERTY_UNAVAILABLE; + return m_property_int_ro(prop, action, arg, mpctx->sh_audio->format); +} + +/// Audio bitrate (RO) +static int mp_property_audio_bitrate(m_option_t * prop, int action, + void *arg, MPContext * mpctx) +{ + if (!mpctx->sh_audio) + return M_PROPERTY_UNAVAILABLE; + return m_property_int_ro(prop, action, arg, mpctx->sh_audio->i_bps); +} + +/// Samplerate (RO) +static int mp_property_samplerate(m_option_t * prop, int action, void *arg, + MPContext * mpctx) +{ + if (!mpctx->sh_audio) + return M_PROPERTY_UNAVAILABLE; + return m_property_int_ro(prop, action, arg, mpctx->sh_audio->samplerate); +} + +/// Number of channels (RO) +static int mp_property_channels(m_option_t * prop, int action, void *arg, + MPContext * mpctx) +{ + if (!mpctx->sh_audio) + return M_PROPERTY_UNAVAILABLE; + switch (action) { + case M_PROPERTY_PRINT: + if (!arg) + return M_PROPERTY_ERROR; + switch (mpctx->sh_audio->channels) { + case 1: + *(char **) arg = strdup("mono"); + break; + case 2: + *(char **) arg = strdup("stereo"); + break; + default: + *(char **) arg = malloc(32); + sprintf(*(char **) arg, "%d channels", mpctx->sh_audio->channels); + } + return M_PROPERTY_OK; + } + return m_property_int_ro(prop, action, arg, mpctx->sh_audio->channels); +} + +/// Selected audio id (RW) +static int mp_property_audio(m_option_t * prop, int action, void *arg, + MPContext * mpctx) +{ + int current_id = -1, tmp; + + switch (action) { + case M_PROPERTY_GET: + if (!mpctx->sh_audio) + return M_PROPERTY_UNAVAILABLE; + if (!arg) + return M_PROPERTY_ERROR; + *(int *) arg = audio_id; + return M_PROPERTY_OK; + case M_PROPERTY_PRINT: + if (!mpctx->sh_audio) + return M_PROPERTY_UNAVAILABLE; + if (!arg) + return M_PROPERTY_ERROR; + + if (audio_id < 0) + *(char **) arg = strdup(MSGTR_Disabled); + else { + char lang[40] = MSGTR_Unknown; + if (mpctx->demuxer->type == DEMUXER_TYPE_MATROSKA) + demux_mkv_get_audio_lang(mpctx->demuxer, audio_id, lang, 9); +#ifdef USE_DVDREAD + else if (mpctx->stream->type == STREAMTYPE_DVD) { + int code = dvd_lang_from_aid(mpctx->stream, audio_id); + if (code) { + lang[0] = code >> 8; + lang[1] = code; + lang[2] = 0; + } + } +#endif + +#ifdef USE_DVDNAV + else if (mpctx->stream->type == STREAMTYPE_DVDNAV) + dvdnav_lang_from_aid(mpctx->stream, audio_id, lang); +#endif + *(char **) arg = malloc(64); + snprintf(*(char **) arg, 64, "(%d) %s", audio_id, lang); + } + return M_PROPERTY_OK; + + case M_PROPERTY_STEP_UP: + case M_PROPERTY_SET: + if (action == M_PROPERTY_SET && arg) + tmp = *((int *) arg); + else + tmp = -1; + current_id = mpctx->demuxer->audio->id; + audio_id = demuxer_switch_audio(mpctx->demuxer, tmp); + if (audio_id == -2 + || (audio_id > -1 + && mpctx->demuxer->audio->id != current_id && current_id != -2)) + uninit_player(INITED_AO | INITED_ACODEC); + if (audio_id > -1 && mpctx->demuxer->audio->id != current_id) { + sh_audio_t *sh2; + sh2 = mpctx->demuxer->a_streams[mpctx->demuxer->audio->id]; + if (sh2) { + sh2->ds = mpctx->demuxer->audio; + mpctx->sh_audio = sh2; + reinit_audio_chain(); + } + } + mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AUDIO_TRACK=%d\n", audio_id); + return M_PROPERTY_OK; + default: + return M_PROPERTY_NOT_IMPLEMENTED; + } + +} + +/// Selected video id (RW) +static int mp_property_video(m_option_t * prop, int action, void *arg, + MPContext * mpctx) +{ + int current_id = -1, tmp; + + switch (action) { + case M_PROPERTY_GET: + if (!mpctx->sh_video) + return M_PROPERTY_UNAVAILABLE; + if (!arg) + return M_PROPERTY_ERROR; + *(int *) arg = video_id; + return M_PROPERTY_OK; + case M_PROPERTY_PRINT: + if (!mpctx->sh_video) + return M_PROPERTY_UNAVAILABLE; + if (!arg) + return M_PROPERTY_ERROR; + + if (video_id < 0) + *(char **) arg = strdup(MSGTR_Disabled); + else { + char lang[40] = MSGTR_Unknown; + *(char **) arg = malloc(64); + snprintf(*(char **) arg, 64, "(%d) %s", video_id, lang); + } + return M_PROPERTY_OK; + + case M_PROPERTY_STEP_UP: + case M_PROPERTY_SET: + current_id = mpctx->demuxer->video->id; + if (action == M_PROPERTY_SET && arg) + tmp = *((int *) arg); + else + tmp = -1; + video_id = demuxer_switch_video(mpctx->demuxer, tmp); + if (video_id == -2 + || (video_id > -1 && mpctx->demuxer->video->id != current_id + && current_id != -2)) + uninit_player(INITED_VCODEC | + (fixed_vo && video_id != -2 ? 0 : INITED_VO)); + if (video_id > -1 && mpctx->demuxer->video->id != current_id) { + sh_video_t *sh2; + sh2 = mpctx->demuxer->v_streams[mpctx->demuxer->video->id]; + if (sh2) { + sh2->ds = mpctx->demuxer->video; + mpctx->sh_video = sh2; + reinit_video_chain(); + } + } + mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VIDEO_TRACK=%d\n", video_id); + return M_PROPERTY_OK; + + default: + return M_PROPERTY_NOT_IMPLEMENTED; + } +} + +static int mp_property_program(m_option_t * prop, int action, void *arg, + MPContext * mpctx) +{ + demux_program_t prog; + + switch (action) { + case M_PROPERTY_STEP_UP: + case M_PROPERTY_SET: + if (action == M_PROPERTY_SET && arg) + prog.progid = *((int *) arg); + else + prog.progid = -1; + if (demux_control + (mpctx->demuxer, DEMUXER_CTRL_IDENTIFY_PROGRAM, + &prog) == DEMUXER_CTRL_NOTIMPL) + return M_PROPERTY_ERROR; + + mp_property_do("switch_audio", M_PROPERTY_SET, &prog.aid, mpctx); + mp_property_do("switch_video", M_PROPERTY_SET, &prog.vid, mpctx); + return M_PROPERTY_OK; + + default: + return M_PROPERTY_NOT_IMPLEMENTED; + } +} + +///@} + +/// \defgroup VideoProperties Video properties +/// \ingroup Properties +///@{ + +/// Fullscreen state (RW) +static int mp_property_fullscreen(m_option_t * prop, int action, void *arg, + MPContext * mpctx) +{ + + if (!mpctx->video_out) + return M_PROPERTY_UNAVAILABLE; + + switch (action) { + case M_PROPERTY_SET: + if (!arg) + return M_PROPERTY_ERROR; + M_PROPERTY_CLAMP(prop, *(int *) arg); + if (vo_fs == !!*(int *) arg) + return M_PROPERTY_OK; + case M_PROPERTY_STEP_UP: + case M_PROPERTY_STEP_DOWN: +#ifdef HAVE_NEW_GUI + if (use_gui) + guiGetEvent(guiIEvent, (char *) MP_CMD_GUI_FULLSCREEN); + else +#endif + if (vo_config_count) + mpctx->video_out->control(VOCTRL_FULLSCREEN, 0); + return M_PROPERTY_OK; + default: + return m_property_flag(prop, action, arg, &vo_fs); + } +} + +static int mp_property_deinterlace(m_option_t * prop, int action, + void *arg, MPContext * mpctx) +{ + int deinterlace; + vf_instance_t *vf; + if (!mpctx->sh_video || !mpctx->sh_video->vfilter) + return M_PROPERTY_UNAVAILABLE; + vf = mpctx->sh_video->vfilter; + switch (action) { + case M_PROPERTY_GET: + if (!arg) + return M_PROPERTY_ERROR; + vf->control(vf, VFCTRL_GET_DEINTERLACE, arg); + return M_PROPERTY_OK; + case M_PROPERTY_SET: + if (!arg) + return M_PROPERTY_ERROR; + M_PROPERTY_CLAMP(prop, *(int *) arg); + vf->control(vf, VFCTRL_SET_DEINTERLACE, arg); + return M_PROPERTY_OK; + case M_PROPERTY_STEP_UP: + case M_PROPERTY_STEP_DOWN: + vf->control(vf, VFCTRL_GET_DEINTERLACE, &deinterlace); + deinterlace = !deinterlace; + vf->control(vf, VFCTRL_SET_DEINTERLACE, &deinterlace); + return M_PROPERTY_OK; + } + return M_PROPERTY_NOT_IMPLEMENTED; +} + +/// Panscan (RW) +static int mp_property_panscan(m_option_t * prop, int action, void *arg, + MPContext * mpctx) +{ + + if (!mpctx->video_out + || mpctx->video_out->control(VOCTRL_GET_PANSCAN, NULL) != VO_TRUE) + return M_PROPERTY_UNAVAILABLE; + + switch (action) { + case M_PROPERTY_SET: + if (!arg) + return M_PROPERTY_ERROR; + M_PROPERTY_CLAMP(prop, *(float *) arg); + vo_panscan = *(float *) arg; + mpctx->video_out->control(VOCTRL_SET_PANSCAN, NULL); + return M_PROPERTY_OK; + case M_PROPERTY_STEP_UP: + case M_PROPERTY_STEP_DOWN: + vo_panscan += (arg ? *(float *) arg : 0.1) * + (action == M_PROPERTY_STEP_DOWN ? -1 : 1); + if (vo_panscan > 1) + vo_panscan = 1; + else if (vo_panscan < 0) + vo_panscan = 0; + mpctx->video_out->control(VOCTRL_SET_PANSCAN, NULL); + return M_PROPERTY_OK; + default: + return m_property_float_range(prop, action, arg, &vo_panscan); + } +} + +/// Helper to set vo flags. +/** \ingroup PropertyImplHelper + */ +static int mp_property_vo_flag(m_option_t * prop, int action, void *arg, + int vo_ctrl, int *vo_var, MPContext * mpctx) +{ + + if (!mpctx->video_out) + return M_PROPERTY_UNAVAILABLE; + + switch (action) { + case M_PROPERTY_SET: + if (!arg) + return M_PROPERTY_ERROR; + M_PROPERTY_CLAMP(prop, *(int *) arg); + if (*vo_var == !!*(int *) arg) + return M_PROPERTY_OK; + case M_PROPERTY_STEP_UP: + case M_PROPERTY_STEP_DOWN: + if (vo_config_count) + mpctx->video_out->control(vo_ctrl, 0); + return M_PROPERTY_OK; + default: + return m_property_flag(prop, action, arg, vo_var); + } +} + +/// Window always on top (RW) +static int mp_property_ontop(m_option_t * prop, int action, void *arg, + MPContext * mpctx) +{ + return mp_property_vo_flag(prop, action, arg, VOCTRL_ONTOP, &vo_ontop, + mpctx); +} + +/// Display in the root window (RW) +static int mp_property_rootwin(m_option_t * prop, int action, void *arg, + MPContext * mpctx) +{ + return mp_property_vo_flag(prop, action, arg, VOCTRL_ROOTWIN, + &vo_rootwin, mpctx); +} + +/// Show window borders (RW) +static int mp_property_border(m_option_t * prop, int action, void *arg, + MPContext * mpctx) +{ + return mp_property_vo_flag(prop, action, arg, VOCTRL_BORDER, + &vo_border, mpctx); +} + +/// Framedropping state (RW) +static int mp_property_framedropping(m_option_t * prop, int action, + void *arg, MPContext * mpctx) +{ + + if (!mpctx->sh_video) + return M_PROPERTY_UNAVAILABLE; + + switch (action) { + case M_PROPERTY_PRINT: + if (!arg) + return M_PROPERTY_ERROR; + *(char **) arg = strdup(frame_dropping == 1 ? MSGTR_Enabled : + (frame_dropping == 2 ? MSGTR_HardFrameDrop : + MSGTR_Disabled)); + return M_PROPERTY_OK; + default: + return m_property_choice(prop, action, arg, &frame_dropping); + } +} + +/// Color settings, try to use vf/vo then fall back on TV. (RW) +static int mp_property_gamma(m_option_t * prop, int action, void *arg, + MPContext * mpctx) +{ + int *gamma = prop->priv, r; + + if (!mpctx->sh_video) + return M_PROPERTY_UNAVAILABLE; + + if (gamma[0] == 1000) { + gamma[0] = 0; + get_video_colors(mpctx->sh_video, prop->name, gamma); + } + + switch (action) { + case M_PROPERTY_SET: + if (!arg) + return M_PROPERTY_ERROR; + M_PROPERTY_CLAMP(prop, *(int *) arg); + *gamma = *(int *) arg; + r = set_video_colors(mpctx->sh_video, prop->name, *gamma); + if (r <= 0) + break; + return r; + case M_PROPERTY_GET: + if (!arg) + return M_PROPERTY_ERROR; + r = get_video_colors(mpctx->sh_video, prop->name, arg); + if (r <= 0) + break; + return r; + case M_PROPERTY_STEP_UP: + case M_PROPERTY_STEP_DOWN: + *gamma += (arg ? *(int *) arg : 1) * + (action == M_PROPERTY_STEP_DOWN ? -1 : 1); + M_PROPERTY_CLAMP(prop, *gamma); + r = set_video_colors(mpctx->sh_video, prop->name, *gamma); + if (r <= 0) + break; + return r; + default: + return M_PROPERTY_NOT_IMPLEMENTED; + } + +#ifdef USE_TV + if (mpctx->demuxer->type == DEMUXER_TYPE_TV) { + int l = strlen(prop->name); + char tv_prop[3 + l + 1]; + sprintf(tv_prop, "tv_%s", prop->name); + return mp_property_do(tv_prop, action, arg, mpctx); + } +#endif + + return M_PROPERTY_UNAVAILABLE; +} + +/// VSync (RW) +static int mp_property_vsync(m_option_t * prop, int action, void *arg, + MPContext * mpctx) +{ + return m_property_flag(prop, action, arg, &vo_vsync); +} + +/// Video codec tag (RO) +static int mp_property_video_format(m_option_t * prop, int action, + void *arg, MPContext * mpctx) +{ + if (!mpctx->sh_video) + return M_PROPERTY_UNAVAILABLE; + return m_property_int_ro(prop, action, arg, mpctx->sh_video->format); +} + +/// Video bitrate (RO) +static int mp_property_video_bitrate(m_option_t * prop, int action, + void *arg, MPContext * mpctx) +{ + if (!mpctx->sh_video) + return M_PROPERTY_UNAVAILABLE; + return m_property_int_ro(prop, action, arg, mpctx->sh_video->i_bps); +} + +/// Video display width (RO) +static int mp_property_width(m_option_t * prop, int action, void *arg, + MPContext * mpctx) +{ + if (!mpctx->sh_video) + return M_PROPERTY_UNAVAILABLE; + return m_property_int_ro(prop, action, arg, mpctx->sh_video->disp_w); +} + +/// Video display height (RO) +static int mp_property_height(m_option_t * prop, int action, void *arg, + MPContext * mpctx) +{ + if (!mpctx->sh_video) + return M_PROPERTY_UNAVAILABLE; + return m_property_int_ro(prop, action, arg, mpctx->sh_video->disp_h); +} + +/// Video fps (RO) +static int mp_property_fps(m_option_t * prop, int action, void *arg, + MPContext * mpctx) +{ + if (!mpctx->sh_video) + return M_PROPERTY_UNAVAILABLE; + return m_property_float_ro(prop, action, arg, mpctx->sh_video->fps); +} + +/// Video aspect (RO) +static int mp_property_aspect(m_option_t * prop, int action, void *arg, + MPContext * mpctx) +{ + if (!mpctx->sh_video) + return M_PROPERTY_UNAVAILABLE; + return m_property_float_ro(prop, action, arg, mpctx->sh_video->aspect); +} + +///@} + +/// \defgroup SubProprties Subtitles properties +/// \ingroup Properties +///@{ + +/// Text subtitle position (RW) +static int mp_property_sub_pos(m_option_t * prop, int action, void *arg, + MPContext * mpctx) +{ + if (!mpctx->sh_video) + return M_PROPERTY_UNAVAILABLE; + + switch (action) { + case M_PROPERTY_SET: + if (!arg) + return M_PROPERTY_ERROR; + case M_PROPERTY_STEP_UP: + case M_PROPERTY_STEP_DOWN: + vo_osd_changed(OSDTYPE_SUBTITLE); + default: + return m_property_int_range(prop, action, arg, &sub_pos); + } +} + +/// Selected subtitles (RW) +static int mp_property_sub(m_option_t * prop, int action, void *arg, + MPContext * mpctx) +{ + demux_stream_t *const d_sub = mpctx->d_sub; + const int global_sub_size = mpctx->global_sub_size; + int source = -1, reset_spu = 0; + char *sub_name; + + if (global_sub_size <= 0) + return M_PROPERTY_UNAVAILABLE; + + switch (action) { + case M_PROPERTY_GET: + if (!arg) + return M_PROPERTY_ERROR; + *(int *) arg = mpctx->global_sub_pos; + return M_PROPERTY_OK; + case M_PROPERTY_PRINT: + if (!arg) + return M_PROPERTY_ERROR; + *(char **) arg = malloc(64); + (*(char **) arg)[63] = 0; + sub_name = 0; + if (subdata) + sub_name = subdata->filename; +#ifdef USE_ASS + if (ass_track && ass_track->name) + sub_name = ass_track->name; +#endif + if (sub_name) { + char *tmp, *tmp2; + tmp = sub_name; + if ((tmp2 = strrchr(tmp, '/'))) + tmp = tmp2 + 1; + + snprintf(*(char **) arg, 63, "(%d) %s%s", + mpctx->set_of_sub_pos + 1, + strlen(tmp) < 20 ? "" : "...", + strlen(tmp) < 20 ? tmp : tmp + strlen(tmp) - 19); + return M_PROPERTY_OK; + } +#ifdef USE_DVDNAV + if (mpctx->stream->type == STREAMTYPE_DVDNAV) { + if (vo_spudec && dvdsub_id >= 0) { + unsigned char lang[3]; + if (dvdnav_lang_from_sid(mpctx->stream, dvdsub_id, lang)) { + snprintf(*(char **) arg, 63, "(%d) %s", dvdsub_id, lang); + return M_PROPERTY_OK; + } + } + } +#endif + + if (mpctx->demuxer->type == DEMUXER_TYPE_MATROSKA && dvdsub_id >= 0) { + char lang[40] = MSGTR_Unknown; + demux_mkv_get_sub_lang(mpctx->demuxer, dvdsub_id, lang, 9); + snprintf(*(char **) arg, 63, "(%d) %s", dvdsub_id, lang); + return M_PROPERTY_OK; + } +#ifdef HAVE_OGGVORBIS + if (mpctx->demuxer->type == DEMUXER_TYPE_OGG && d_sub && dvdsub_id >= 0) { + char *lang = demux_ogg_sub_lang(mpctx->demuxer, dvdsub_id); + if (!lang) + lang = MSGTR_Unknown; + snprintf(*(char **) arg, 63, "(%d) %s", dvdsub_id, lang); + return M_PROPERTY_OK; + } +#endif + if (vo_vobsub && vobsub_id >= 0) { + const char *language = MSGTR_Unknown; + language = vobsub_get_id(vo_vobsub, (unsigned int) vobsub_id); + snprintf(*(char **) arg, 63, "(%d) %s", + vobsub_id, language ? language : MSGTR_Unknown); + return M_PROPERTY_OK; + } +#ifdef USE_DVDREAD + if (vo_spudec && mpctx->stream->type == STREAMTYPE_DVD + && dvdsub_id >= 0) { + char lang[3]; + int code = dvd_lang_from_sid(mpctx->stream, dvdsub_id); + lang[0] = code >> 8; + lang[1] = code; + lang[2] = 0; + snprintf(*(char **) arg, 63, "(%d) %s", dvdsub_id, lang); + return M_PROPERTY_OK; + } +#endif + if (dvdsub_id >= 0) { + snprintf(*(char **) arg, 63, "(%d) %s", dvdsub_id, MSGTR_Unknown); + return M_PROPERTY_OK; + } + snprintf(*(char **) arg, 63, MSGTR_Disabled); + return M_PROPERTY_OK; + + case M_PROPERTY_SET: + if (!arg) + return M_PROPERTY_ERROR; + if (*(int *) arg < -1) + *(int *) arg = -1; + else if (*(int *) arg >= global_sub_size) + *(int *) arg = global_sub_size - 1; + mpctx->global_sub_pos = *(int *) arg; + break; + case M_PROPERTY_STEP_UP: + mpctx->global_sub_pos += 2; + mpctx->global_sub_pos = + (mpctx->global_sub_pos % (global_sub_size + 1)) - 1; + break; + case M_PROPERTY_STEP_DOWN: + mpctx->global_sub_pos += global_sub_size + 1; + mpctx->global_sub_pos = + (mpctx->global_sub_pos % (global_sub_size + 1)) - 1; + break; + default: + return M_PROPERTY_NOT_IMPLEMENTED; + } + + if (mpctx->global_sub_pos >= 0) + source = sub_source(mpctx); + + mp_msg(MSGT_CPLAYER, MSGL_DBG3, + "subtitles: %d subs, (v@%d s@%d d@%d), @%d, source @%d\n", + global_sub_size, + mpctx->global_sub_indices[SUB_SOURCE_VOBSUB], + mpctx->global_sub_indices[SUB_SOURCE_SUBS], + mpctx->global_sub_indices[SUB_SOURCE_DEMUX], + mpctx->global_sub_pos, source); + + mpctx->set_of_sub_pos = -1; + subdata = NULL; + vo_sub_last = vo_sub = NULL; + + vobsub_id = -1; + dvdsub_id = -1; + if (d_sub) { + if (d_sub->id > -2) + reset_spu = 1; + d_sub->id = -2; + } +#ifdef USE_ASS + ass_track = 0; +#endif + + if (source == SUB_SOURCE_VOBSUB) { + vobsub_id = + mpctx->global_sub_pos - + mpctx->global_sub_indices[SUB_SOURCE_VOBSUB]; + } else if (source == SUB_SOURCE_SUBS) { + mpctx->set_of_sub_pos = + mpctx->global_sub_pos - mpctx->global_sub_indices[SUB_SOURCE_SUBS]; +#ifdef USE_ASS + if (ass_enabled && mpctx->set_of_ass_tracks[mpctx->set_of_sub_pos]) + ass_track = mpctx->set_of_ass_tracks[mpctx->set_of_sub_pos]; + else +#endif + { + subdata = mpctx->set_of_subtitles[mpctx->set_of_sub_pos]; + vo_osd_changed(OSDTYPE_SUBTITLE); + } + } else if (source == SUB_SOURCE_DEMUX) { + dvdsub_id = + mpctx->global_sub_pos - mpctx->global_sub_indices[SUB_SOURCE_DEMUX]; + if (d_sub) { +#ifdef USE_DVDREAD + if (vo_spudec && mpctx->stream->type == STREAMTYPE_DVD) { + d_sub->id = dvdsub_id; + } +#endif + +#ifdef USE_DVDNAV + if (vo_spudec && mpctx->stream->type == STREAMTYPE_DVDNAV) { + d_sub->id = dvdsub_id; + } +#endif + if (mpctx->stream->type != STREAMTYPE_DVD + && mpctx->stream->type != STREAMTYPE_DVDNAV) { + int i = 0; + for (d_sub->id = 0; d_sub->id < MAX_S_STREAMS; d_sub->id++) { + if (mpctx->demuxer->s_streams[d_sub->id]) { + if (i == dvdsub_id) + break; + i++; + } + } + d_sub->sh = mpctx->demuxer->s_streams[d_sub->id]; + } + if (mpctx->demuxer->type == DEMUXER_TYPE_MATROSKA) + d_sub->id = demux_mkv_change_subs(mpctx->demuxer, dvdsub_id); + if (d_sub->sh && d_sub->id >= 0) { + sh_sub_t *sh = d_sub->sh; + if (sh->type == 'v') + init_vo_spudec(); +#ifdef USE_ASS + else if (ass_enabled && sh->type == 'a') + ass_track = sh->ass_track; +#endif + } + } + } +#ifdef USE_DVDREAD + if (vo_spudec + && (mpctx->stream->type == STREAMTYPE_DVD + || mpctx->stream->type == STREAMTYPE_DVDNAV) + && dvdsub_id < 0 && reset_spu) { + dvdsub_id = -2; + d_sub->id = dvdsub_id; + } +#endif + update_subtitles(mpctx->sh_video, d_sub, 1); + + return M_PROPERTY_OK; +} + +/// Subtitle delay (RW) +static int mp_property_sub_delay(m_option_t * prop, int action, void *arg, + MPContext * mpctx) +{ + if (!mpctx->sh_video) + return M_PROPERTY_UNAVAILABLE; + return m_property_delay(prop, action, arg, &sub_delay); +} + +/// Alignment of text subtitles (RW) +static int mp_property_sub_alignment(m_option_t * prop, int action, + void *arg, MPContext * mpctx) +{ + char *name[] = { MSGTR_Top, MSGTR_Center, MSGTR_Bottom }; + + if (!mpctx->sh_video || mpctx->global_sub_pos < 0 + || sub_source(mpctx) != SUB_SOURCE_SUBS) + return M_PROPERTY_UNAVAILABLE; + + switch (action) { + case M_PROPERTY_PRINT: + if (!arg) + return M_PROPERTY_ERROR; + M_PROPERTY_CLAMP(prop, sub_alignment); + *(char **) arg = strdup(name[sub_alignment]); + return M_PROPERTY_OK; + case M_PROPERTY_SET: + if (!arg) + return M_PROPERTY_ERROR; + case M_PROPERTY_STEP_UP: + case M_PROPERTY_STEP_DOWN: + vo_osd_changed(OSDTYPE_SUBTITLE); + default: + return m_property_choice(prop, action, arg, &sub_alignment); + } +} + +/// Subtitle visibility (RW) +static int mp_property_sub_visibility(m_option_t * prop, int action, + void *arg, MPContext * mpctx) +{ + if (!mpctx->sh_video) + return M_PROPERTY_UNAVAILABLE; + + switch (action) { + case M_PROPERTY_SET: + if (!arg) + return M_PROPERTY_ERROR; + case M_PROPERTY_STEP_UP: + case M_PROPERTY_STEP_DOWN: + vo_osd_changed(OSDTYPE_SUBTITLE); + if (vo_spudec) + vo_osd_changed(OSDTYPE_SPU); + default: + return m_property_flag(prop, action, arg, &sub_visibility); + } +} + +/// Show only forced subtitles (RW) +static int mp_property_sub_forced_only(m_option_t * prop, int action, + void *arg, MPContext * mpctx) +{ + if (!vo_spudec) + return M_PROPERTY_UNAVAILABLE; + + switch (action) { + case M_PROPERTY_SET: + if (!arg) + return M_PROPERTY_ERROR; + case M_PROPERTY_STEP_UP: + case M_PROPERTY_STEP_DOWN: + m_property_flag(prop, action, arg, &forced_subs_only); + spudec_set_forced_subs_only(vo_spudec, forced_subs_only); + return M_PROPERTY_OK; + default: + return m_property_flag(prop, action, arg, &forced_subs_only); + } + +} + +///@} + +/// \defgroup TVProperties TV properties +/// \ingroup Properties +///@{ + +#ifdef USE_TV + +/// TV color settings (RW) +static int mp_property_tv_color(m_option_t * prop, int action, void *arg, + MPContext * mpctx) +{ + int r, val; + tvi_handle_t *tvh = mpctx->demuxer->priv; + if (mpctx->demuxer->type != DEMUXER_TYPE_TV || !tvh) + return M_PROPERTY_UNAVAILABLE; + + switch (action) { + case M_PROPERTY_SET: + if (!arg) + return M_PROPERTY_ERROR; + M_PROPERTY_CLAMP(prop, *(int *) arg); + return tv_set_color_options(tvh, (int) prop->priv, *(int *) arg); + case M_PROPERTY_GET: + return tv_get_color_options(tvh, (int) prop->priv, arg); + case M_PROPERTY_STEP_UP: + case M_PROPERTY_STEP_DOWN: + if ((r = tv_get_color_options(tvh, (int) prop->priv, &val)) >= 0) { + if (!r) + return M_PROPERTY_ERROR; + val += (arg ? *(int *) arg : 1) * + (action == M_PROPERTY_STEP_DOWN ? -1 : 1); + M_PROPERTY_CLAMP(prop, val); + return tv_set_color_options(tvh, (int) prop->priv, val); + } + return M_PROPERTY_ERROR; + } + return M_PROPERTY_NOT_IMPLEMENTED; +} + +#endif + +///@} + +/// All properties available in MPlayer. +/** \ingroup Properties + */ +static m_option_t mp_properties[] = { + // General + { "osdlevel", mp_property_osdlevel, CONF_TYPE_INT, + M_OPT_RANGE, 0, 3, NULL }, + { "speed", mp_property_playback_speed, CONF_TYPE_FLOAT, + M_OPT_RANGE, 0.01, 100.0, NULL }, + { "filename", mp_property_filename, CONF_TYPE_STRING, + 0, 0, 0, NULL }, + { "path", mp_property_path, CONF_TYPE_STRING, + 0, 0, 0, NULL }, + { "demuxer", mp_property_demuxer, CONF_TYPE_STRING, + 0, 0, 0, NULL }, + { "stream_pos", mp_property_stream_pos, CONF_TYPE_POSITION, + M_OPT_MIN, 0, 0, NULL }, + { "stream_start", mp_property_stream_start, CONF_TYPE_POSITION, + M_OPT_MIN, 0, 0, NULL }, + { "stream_end", mp_property_stream_end, CONF_TYPE_POSITION, + M_OPT_MIN, 0, 0, NULL }, + { "stream_length", mp_property_stream_length, CONF_TYPE_POSITION, + M_OPT_MIN, 0, 0, NULL }, + { "length", mp_property_length, CONF_TYPE_DOUBLE, + 0, 0, 0, NULL }, + + // Audio + { "volume", mp_property_volume, CONF_TYPE_FLOAT, + M_OPT_RANGE, 0, 100, NULL }, + { "mute", mp_property_mute, CONF_TYPE_FLAG, + M_OPT_RANGE, 0, 1, NULL }, + { "audio_delay", mp_property_audio_delay, CONF_TYPE_FLOAT, + M_OPT_RANGE, -100, 100, NULL }, + { "audio_format", mp_property_audio_format, CONF_TYPE_INT, + 0, 0, 0, NULL }, + { "audio_bitrate", mp_property_audio_bitrate, CONF_TYPE_INT, + 0, 0, 0, NULL }, + { "samplerate", mp_property_samplerate, CONF_TYPE_INT, + 0, 0, 0, NULL }, + { "channels", mp_property_channels, CONF_TYPE_INT, + 0, 0, 0, NULL }, + { "switch_audio", mp_property_audio, CONF_TYPE_INT, + CONF_RANGE, -2, MAX_A_STREAMS - 1, NULL }, + + // Video + { "fullscreen", mp_property_fullscreen, CONF_TYPE_FLAG, + M_OPT_RANGE, 0, 1, NULL }, + { "deinterlace", mp_property_deinterlace, CONF_TYPE_FLAG, + M_OPT_RANGE, 0, 1, NULL }, + { "ontop", mp_property_ontop, CONF_TYPE_FLAG, + M_OPT_RANGE, 0, 1, NULL }, + { "rootwin", mp_property_rootwin, CONF_TYPE_FLAG, + M_OPT_RANGE, 0, 1, NULL }, + { "border", mp_property_border, CONF_TYPE_FLAG, + M_OPT_RANGE, 0, 1, NULL }, + { "framedropping", mp_property_framedropping, CONF_TYPE_INT, + M_OPT_RANGE, 0, 2, NULL }, + { "gamma", mp_property_gamma, CONF_TYPE_INT, + M_OPT_RANGE, -100, 100, &vo_gamma_gamma }, + { "brightness", mp_property_gamma, CONF_TYPE_INT, + M_OPT_RANGE, -100, 100, &vo_gamma_brightness }, + { "contrast", mp_property_gamma, CONF_TYPE_INT, + M_OPT_RANGE, -100, 100, &vo_gamma_contrast }, + { "saturation", mp_property_gamma, CONF_TYPE_INT, + M_OPT_RANGE, -100, 100, &vo_gamma_saturation }, + { "hue", mp_property_gamma, CONF_TYPE_INT, + M_OPT_RANGE, -100, 100, &vo_gamma_hue }, + { "panscan", mp_property_panscan, CONF_TYPE_FLOAT, + M_OPT_RANGE, 0, 1, NULL }, + { "vsync", mp_property_vsync, CONF_TYPE_FLAG, + M_OPT_RANGE, 0, 1, NULL }, + { "video_format", mp_property_video_format, CONF_TYPE_INT, + 0, 0, 0, NULL }, + { "video_bitrate", mp_property_video_bitrate, CONF_TYPE_INT, + 0, 0, 0, NULL }, + { "width", mp_property_width, CONF_TYPE_INT, + 0, 0, 0, NULL }, + { "height", mp_property_height, CONF_TYPE_INT, + 0, 0, 0, NULL }, + { "fps", mp_property_fps, CONF_TYPE_FLOAT, + 0, 0, 0, NULL }, + { "aspect", mp_property_aspect, CONF_TYPE_FLOAT, + 0, 0, 0, NULL }, + { "switch_video", mp_property_video, CONF_TYPE_INT, + CONF_RANGE, -2, MAX_V_STREAMS - 1, NULL }, + { "switch_program", mp_property_program, CONF_TYPE_INT, + CONF_RANGE, -1, 65535, NULL }, + + // Subs + { "sub", mp_property_sub, CONF_TYPE_INT, + M_OPT_MIN, -1, 0, NULL }, + { "sub_delay", mp_property_sub_delay, CONF_TYPE_FLOAT, + 0, 0, 0, NULL }, + { "sub_pos", mp_property_sub_pos, CONF_TYPE_INT, + M_OPT_RANGE, 0, 100, NULL }, + { "sub_alignment", mp_property_sub_alignment, CONF_TYPE_INT, + M_OPT_RANGE, 0, 2, NULL }, + { "sub_visibility", mp_property_sub_visibility, CONF_TYPE_FLAG, + M_OPT_RANGE, 0, 1, NULL }, + { "sub_forced_only", mp_property_sub_forced_only, CONF_TYPE_FLAG, + M_OPT_RANGE, 0, 1, NULL }, + +#ifdef USE_TV + { "tv_brightness", mp_property_tv_color, CONF_TYPE_INT, + M_OPT_RANGE, -100, 100, (void *) TV_COLOR_BRIGHTNESS }, + { "tv_contrast", mp_property_tv_color, CONF_TYPE_INT, + M_OPT_RANGE, -100, 100, (void *) TV_COLOR_CONTRAST }, + { "tv_saturation", mp_property_tv_color, CONF_TYPE_INT, + M_OPT_RANGE, -100, 100, (void *) TV_COLOR_SATURATION }, + { "tv_hue", mp_property_tv_color, CONF_TYPE_INT, + M_OPT_RANGE, -100, 100, (void *) TV_COLOR_HUE }, +#endif + + { NULL, NULL, NULL, 0, 0, 0, NULL } +}; + + +m_option_t *mp_property_find(const char *name) +{ + return m_option_list_find(mp_properties, name); +} + +int mp_property_do(const char *name, int action, void *val, void *ctx) +{ + m_option_t *p = mp_property_find(name); + if (!p) + return M_PROPERTY_UNAVAILABLE; + return m_property_do(p, action, val, ctx); +} + +char *property_expand_string(MPContext * mpctx, char *str) +{ + return m_properties_expand_string(mp_properties, str, mpctx); +} + +void property_print_help(void) +{ + m_properties_print_help_list(mp_properties); +} + + +///@} +// Properties group + + +/** + * \defgroup Command2Property Command to property bridge + * + * It is used to handle most commands that just set a property + * and optionally display something on the OSD. + * Two kinds of commands are handled: adjust or toggle. + * + * Adjust commands take 1 or 2 parameters: <value> <abs> + * If <abs> is non-zero the property is set to the given value + * otherwise it is adjusted. + * + * Toggle commands take 0 or 1 parameters. With no parameter + * or a value less than the property minimum it just steps the + * property to its next value. Otherwise it sets it to the given + * value. + * + *@{ + */ + +/// List of the commands that can be handled by setting a property. +static struct { + /// property name + const char *name; + /// cmd id + int cmd; + /// set/adjust or toggle command + int toggle; + /// progressbar type + int osd_progbar; + /// osd msg id if it must be shared + int osd_id; + /// osd msg template + const char *osd_msg; +} set_prop_cmd[] = { + // audio + { "volume", MP_CMD_VOLUME, 0, OSD_VOLUME, -1, MSGTR_Volume }, + { "mute", MP_CMD_MUTE, 1, 0, -1, MSGTR_MuteStatus }, + { "audio_delay", MP_CMD_AUDIO_DELAY, 0, 0, -1, MSGTR_AVDelayStatus }, + { "switch_audio", MP_CMD_SWITCH_AUDIO, 1, 0, -1, MSGTR_OSDAudio }, + // video + { "fullscreen", MP_CMD_VO_FULLSCREEN, 1, 0, -1, NULL }, + { "panscan", MP_CMD_PANSCAN, 0, OSD_PANSCAN, -1, MSGTR_Panscan }, + { "ontop", MP_CMD_VO_ONTOP, 1, 0, -1, MSGTR_OnTopStatus }, + { "rootwin", MP_CMD_VO_ROOTWIN, 1, 0, -1, MSGTR_RootwinStatus }, + { "border", MP_CMD_VO_BORDER, 1, 0, -1, MSGTR_BorderStatus }, + { "framedropping", MP_CMD_FRAMEDROPPING, 1, 0, -1, MSGTR_FramedroppingStatus }, + { "gamma", MP_CMD_GAMMA, 0, OSD_BRIGHTNESS, -1, MSGTR_Gamma }, + { "brightness", MP_CMD_BRIGHTNESS, 0, OSD_BRIGHTNESS, -1, MSGTR_Brightness }, + { "contrast", MP_CMD_CONTRAST, 0, OSD_CONTRAST, -1, MSGTR_Contrast }, + { "saturation", MP_CMD_SATURATION, 0, OSD_SATURATION, -1, MSGTR_Saturation }, + { "hue", MP_CMD_HUE, 0, OSD_HUE, -1, MSGTR_Hue }, + { "vsync", MP_CMD_SWITCH_VSYNC, 1, 0, -1, MSGTR_VSyncStatus }, + // subs + { "sub", MP_CMD_SUB_SELECT, 1, 0, -1, MSGTR_SubSelectStatus }, + { "sub_pos", MP_CMD_SUB_POS, 0, 0, -1, MSGTR_SubPosStatus }, + { "sub_alignment", MP_CMD_SUB_ALIGNMENT, 1, 0, -1, MSGTR_SubAlignStatus }, + { "sub_delay", MP_CMD_SUB_DELAY, 0, 0, OSD_MSG_SUB_DELAY, MSGTR_SubDelayStatus }, + { "sub_visibility", MP_CMD_SUB_VISIBILITY, 1, 0, -1, MSGTR_SubVisibleStatus }, + { "sub_forced_only", MP_CMD_SUB_FORCED_ONLY, 1, 0, -1, MSGTR_SubForcedOnlyStatus }, +#ifdef USE_TV + { "tv_brightness", MP_CMD_TV_SET_BRIGHTNESS, 0, OSD_BRIGHTNESS, -1, MSGTR_Brightness }, + { "tv_hue", MP_CMD_TV_SET_HUE, 0, OSD_HUE, -1, MSGTR_Hue }, + { "tv_saturation", MP_CMD_TV_SET_SATURATION, 0, OSD_SATURATION, -1, MSGTR_Saturation }, + { "tv_contrast", MP_CMD_TV_SET_CONTRAST, 0, OSD_CONTRAST, -1, MSGTR_Contrast }, +#endif + { NULL, 0, 0, 0, -1, NULL } +}; + + +/// Handle commands that set a property. +static int set_property_command(MPContext * mpctx, mp_cmd_t * cmd) +{ + int i, r; + m_option_t *prop; + + // look for the command + for (i = 0; set_prop_cmd[i].name; i++) + if (set_prop_cmd[i].cmd == cmd->id) + break; + if (!set_prop_cmd[i].name) + return 0; + + // get the property + prop = mp_property_find(set_prop_cmd[i].name); + if (!prop) + return 0; + + // toggle command + if (set_prop_cmd[i].toggle) { + // set to value + if (cmd->nargs > 0 && cmd->args[0].v.i >= prop->min) + r = m_property_do(prop, M_PROPERTY_SET, &cmd->args[0].v.i, mpctx); + else + r = m_property_do(prop, M_PROPERTY_STEP_UP, NULL, mpctx); + } else if (cmd->args[1].v.i) //set + r = m_property_do(prop, M_PROPERTY_SET, &cmd->args[0].v, mpctx); + else // adjust + r = m_property_do(prop, M_PROPERTY_STEP_UP, &cmd->args[0].v, mpctx); + + if (r <= 0) + return 1; + + if (set_prop_cmd[i].osd_progbar) { + if (prop->type == CONF_TYPE_INT) { + if (m_property_do(prop, M_PROPERTY_GET, &r, mpctx) > 0) + set_osd_bar(set_prop_cmd[i].osd_progbar, + set_prop_cmd[i].osd_msg, prop->min, prop->max, r); + } else if (prop->type == CONF_TYPE_FLOAT) { + float f; + if (m_property_do(prop, M_PROPERTY_GET, &f, mpctx) > 0) + set_osd_bar(set_prop_cmd[i].osd_progbar, + set_prop_cmd[i].osd_msg, prop->min, prop->max, f); + } else + mp_msg(MSGT_CPLAYER, MSGL_ERR, + "Property use an unsupported type.\n"); + return 1; + } + + if (set_prop_cmd[i].osd_msg) { + char *val = m_property_print(prop, mpctx); + if (val) { + set_osd_msg(set_prop_cmd[i].osd_id >= + 0 ? set_prop_cmd[i].osd_id : OSD_MSG_PROPERTY + i, + 1, osd_duration, set_prop_cmd[i].osd_msg, val); + free(val); + } + } + return 1; +} + + +int run_command(MPContext * mpctx, mp_cmd_t * cmd) +{ + sh_audio_t * const sh_audio = mpctx->sh_audio; + sh_video_t * const sh_video = mpctx->sh_video; + int brk_cmd = 0; + if (!set_property_command(mpctx, cmd)) + switch (cmd->id) { + case MP_CMD_SEEK:{ + float v; + int abs; + if (sh_video) + mpctx->osd_show_percentage = sh_video->fps; + v = cmd->args[0].v.f; + abs = (cmd->nargs > 1) ? cmd->args[1].v.i : 0; + if (abs == 2) { /* Absolute seek to a specific timestamp in seconds */ + abs_seek_pos = 1; + if (sh_video) + mpctx->osd_function = + (v > sh_video->pts) ? OSD_FFW : OSD_REW; + rel_seek_secs = v; + } else if (abs) { /* Absolute seek by percentage */ + abs_seek_pos = 3; + if (sh_video) + mpctx->osd_function = OSD_FFW; // Direction isn't set correctly + rel_seek_secs = v / 100.0; + } else { + rel_seek_secs += v; + mpctx->osd_function = (v > 0) ? OSD_FFW : OSD_REW; + } + brk_cmd = 1; + } + break; + + case MP_CMD_SET_PROPERTY:{ + m_option_t *prop = mp_property_find(cmd->args[0].v.s); + if (!prop) + mp_msg(MSGT_CPLAYER, MSGL_WARN, + "Unknown property: '%s'\n", cmd->args[0].v.s); + else if (m_property_parse(prop, cmd->args[1].v.s, mpctx) <= 0) + mp_msg(MSGT_CPLAYER, MSGL_WARN, + "Failed to set property '%s' to '%s'.\n", + cmd->args[0].v.s, cmd->args[1].v.s); + } + break; + + case MP_CMD_STEP_PROPERTY:{ + m_option_t *prop = mp_property_find(cmd->args[0].v.s); + float arg = cmd->args[1].v.f; + if (!prop) + mp_msg(MSGT_CPLAYER, MSGL_WARN, + "Unknown property: '%s'\n", cmd->args[0].v.s); + else if (m_property_do + (prop, M_PROPERTY_STEP_UP, + arg ? &arg : NULL, mpctx) <= 0) + mp_msg(MSGT_CPLAYER, MSGL_WARN, + "Failed to increment property '%s' by %f.\n", + cmd->args[0].v.s, arg); + } + break; + + case MP_CMD_GET_PROPERTY:{ + m_option_t *prop; + void *val; + prop = mp_property_find(cmd->args[0].v.s); + if (!prop) { + mp_msg(MSGT_CPLAYER, MSGL_WARN, + "Unknown property: '%s'\n", cmd->args[0].v.s); + break; + } + /* Use m_option_print directly to get easily parseable values. */ + val = calloc(1, prop->type->size); + if (m_property_do(prop, M_PROPERTY_GET, val, mpctx) <= 0) { + mp_msg(MSGT_CPLAYER, MSGL_WARN, + "Failed to get value of property '%s'.\n", + cmd->args[0].v.s); + break; + } + char *tmp = m_option_print(prop, val); + if (!tmp || tmp == (char *) -1) { + mp_msg(MSGT_CPLAYER, MSGL_WARN, + "Failed to print value of property '%s'.\n", + cmd->args[0].v.s); + break; + } + mp_msg(MSGT_GLOBAL, MSGL_INFO, "ANS_%s=%s\n", + cmd->args[0].v.s, tmp); + free(tmp); + } + break; + + case MP_CMD_EDL_MARK: + if (edl_fd) { + float v = sh_video ? sh_video->pts : + playing_audio_pts(sh_audio, mpctx->d_audio, + mpctx->audio_out); + + if (mpctx->begin_skip == MP_NOPTS_VALUE) { + mpctx->begin_skip = v; + mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_EdloutStartSkip); + } else { + if (mpctx->begin_skip > v) + mp_msg(MSGT_CPLAYER, MSGL_WARN, MSGTR_EdloutBadStop); + else { + fprintf(edl_fd, "%f %f %d\n", mpctx->begin_skip, v, 0); + mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_EdloutEndSkip); + } + mpctx->begin_skip = MP_NOPTS_VALUE; + } + } + break; + + case MP_CMD_SWITCH_RATIO: + if (cmd->nargs == 0 || cmd->args[0].v.f == -1) + movie_aspect = (float) sh_video->disp_w / sh_video->disp_h; + else + movie_aspect = cmd->args[0].v.f; + mpcodecs_config_vo(sh_video, sh_video->disp_w, sh_video->disp_h, 0); + break; + + case MP_CMD_SPEED_INCR:{ + float v = cmd->args[0].v.f; + playback_speed += v; + build_afilter_chain(sh_audio, &ao_data); + set_osd_msg(OSD_MSG_SPEED, 1, osd_duration, MSGTR_OSDSpeed, + playback_speed); + } break; + + case MP_CMD_SPEED_MULT:{ + float v = cmd->args[0].v.f; + playback_speed *= v; + build_afilter_chain(sh_audio, &ao_data); + set_osd_msg(OSD_MSG_SPEED, 1, osd_duration, MSGTR_OSDSpeed, + playback_speed); + } break; + + case MP_CMD_SPEED_SET:{ + float v = cmd->args[0].v.f; + playback_speed = v; + build_afilter_chain(sh_audio, &ao_data); + set_osd_msg(OSD_MSG_SPEED, 1, osd_duration, MSGTR_OSDSpeed, + playback_speed); + } break; + + case MP_CMD_FRAME_STEP: + case MP_CMD_PAUSE: + cmd->pausing = 1; + brk_cmd = 1; + break; + + case MP_CMD_FILE_FILTER: + file_filter = cmd->args[0].v.i; + break; + + case MP_CMD_QUIT: + exit_player_with_rc(MSGTR_Exit_quit, + (cmd->nargs > 0) ? cmd->args[0].v.i : 0); + + case MP_CMD_PLAY_TREE_STEP:{ + int n = cmd->args[0].v.i == 0 ? 1 : cmd->args[0].v.i; + int force = cmd->args[1].v.i; + +#ifdef HAVE_NEW_GUI + if (use_gui) { + int i = 0; + if (n > 0) + for (i = 0; i < n; i++) + mplNext(); + else + for (i = 0; i < -1 * n; i++) + mplPrev(); + } else +#endif + { + if (!force && mpctx->playtree_iter) { + play_tree_iter_t *i = + play_tree_iter_new_copy(mpctx->playtree_iter); + if (play_tree_iter_step(i, n, 0) == + PLAY_TREE_ITER_ENTRY) + mpctx->eof = + (n > 0) ? PT_NEXT_ENTRY : PT_PREV_ENTRY; + play_tree_iter_free(i); + } else + mpctx->eof = (n > 0) ? PT_NEXT_ENTRY : PT_PREV_ENTRY; + if (mpctx->eof) + mpctx->play_tree_step = n; + brk_cmd = 1; + } + } + break; + + case MP_CMD_PLAY_TREE_UP_STEP:{ + int n = cmd->args[0].v.i > 0 ? 1 : -1; + int force = cmd->args[1].v.i; + + if (!force && mpctx->playtree_iter) { + play_tree_iter_t *i = + play_tree_iter_new_copy(mpctx->playtree_iter); + if (play_tree_iter_up_step(i, n, 0) == PLAY_TREE_ITER_ENTRY) + mpctx->eof = (n > 0) ? PT_UP_NEXT : PT_UP_PREV; + play_tree_iter_free(i); + } else + mpctx->eof = (n > 0) ? PT_UP_NEXT : PT_UP_PREV; + brk_cmd = 1; + } + break; + + case MP_CMD_PLAY_ALT_SRC_STEP: + if (mpctx->playtree_iter && mpctx->playtree_iter->num_files > 1) { + int v = cmd->args[0].v.i; + if (v > 0 + && mpctx->playtree_iter->file < + mpctx->playtree_iter->num_files) + mpctx->eof = PT_NEXT_SRC; + else if (v < 0 && mpctx->playtree_iter->file > 1) + mpctx->eof = PT_PREV_SRC; + } + brk_cmd = 1; + break; + + case MP_CMD_SUB_STEP: + if (sh_video) { + int movement = cmd->args[0].v.i; + step_sub(subdata, sh_video->pts, movement); +#ifdef USE_ASS + if (ass_track) + sub_delay += + ass_step_sub(ass_track, + (sh_video->pts + + sub_delay) * 1000 + .5, movement) / 1000.; +#endif + set_osd_msg(OSD_MSG_SUB_DELAY, 1, osd_duration, + MSGTR_OSDSubDelay, ROUND(sub_delay * 1000)); + } + break; + + case MP_CMD_SUB_LOG: + log_sub(); + break; + + case MP_CMD_OSD:{ + int v = cmd->args[0].v.i; + int max = (term_osd + && !sh_video) ? MAX_TERM_OSD_LEVEL : MAX_OSD_LEVEL; + if (osd_level > max) + osd_level = max; + if (v < 0) + osd_level = (osd_level + 1) % (max + 1); + else + osd_level = v > max ? max : v; + /* Show OSD state when disabled, but not when an explicit + argument is given to the OSD command, i.e. in slave mode. */ + if (v == -1 && osd_level <= 1) + set_osd_msg(OSD_MSG_OSD_STATUS, 0, osd_duration, + MSGTR_OSDosd, + osd_level ? MSGTR_OSDenabled : + MSGTR_OSDdisabled); + else + rm_osd_msg(OSD_MSG_OSD_STATUS); + } + break; + + case MP_CMD_OSD_SHOW_TEXT: + set_osd_msg(OSD_MSG_TEXT, cmd->args[2].v.i, + (cmd->args[1].v.i < + 0 ? osd_duration : cmd->args[1].v.i), + "%-.63s", cmd->args[0].v.s); + break; + + case MP_CMD_OSD_SHOW_PROPERTY_TEXT:{ + char *txt = m_properties_expand_string(mp_properties, + cmd->args[0].v.s, + mpctx); + /* if no argument supplied take default osd_duration, else <arg> ms. */ + if (txt) { + set_osd_msg(OSD_MSG_TEXT, cmd->args[2].v.i, + (cmd->args[1].v.i < + 0 ? osd_duration : cmd->args[1].v.i), + "%-.63s", txt); + free(txt); + } + } + break; + + case MP_CMD_LOADFILE:{ + play_tree_t *e = play_tree_new(); + play_tree_add_file(e, cmd->args[0].v.s); + + if (cmd->args[1].v.i) // append + play_tree_append_entry(mpctx->playtree, e); + else { + // Go back to the starting point. + while (play_tree_iter_up_step + (mpctx->playtree_iter, 0, 1) != PLAY_TREE_ITER_END) + /* NOP */ ; + play_tree_free_list(mpctx->playtree->child, 1); + play_tree_set_child(mpctx->playtree, e); + play_tree_iter_step(mpctx->playtree_iter, 0, 0); + mpctx->eof = PT_NEXT_SRC; + } + brk_cmd = 1; + } + break; + + case MP_CMD_LOADLIST:{ + play_tree_t *e = parse_playlist_file(cmd->args[0].v.s); + if (!e) + mp_msg(MSGT_CPLAYER, MSGL_ERR, + MSGTR_PlaylistLoadUnable, cmd->args[0].v.s); + else { + if (cmd->args[1].v.i) // append + play_tree_append_entry(mpctx->playtree, e); + else { + // Go back to the starting point. + while (play_tree_iter_up_step + (mpctx->playtree_iter, 0, 1) + != PLAY_TREE_ITER_END) + /* NOP */ ; + play_tree_free_list(mpctx->playtree->child, 1); + play_tree_set_child(mpctx->playtree, e); + play_tree_iter_step(mpctx->playtree_iter, 0, 0); + mpctx->eof = PT_NEXT_SRC; + } + } + brk_cmd = 1; + } + break; + +#ifdef USE_RADIO + case MP_CMD_RADIO_STEP_CHANNEL: + if (mpctx->demuxer->stream->type == STREAMTYPE_RADIO) { + int v = cmd->args[0].v.i; + if (v > 0) + radio_step_channel(mpctx->demuxer->stream, + RADIO_CHANNEL_HIGHER); + else + radio_step_channel(mpctx->demuxer->stream, + RADIO_CHANNEL_LOWER); + if (radio_get_channel_name(mpctx->demuxer->stream)) { + set_osd_msg(OSD_MSG_RADIO_CHANNEL, 1, osd_duration, + MSGTR_OSDChannel, + radio_get_channel_name(mpctx->demuxer->stream)); + } + } + break; + + case MP_CMD_RADIO_SET_CHANNEL: + if (mpctx->demuxer->stream->type == STREAMTYPE_RADIO) { + radio_set_channel(mpctx->demuxer->stream, cmd->args[0].v.s); + if (radio_get_channel_name(mpctx->demuxer->stream)) { + set_osd_msg(OSD_MSG_RADIO_CHANNEL, 1, osd_duration, + MSGTR_OSDChannel, + radio_get_channel_name(mpctx->demuxer->stream)); + } + } + break; + + case MP_CMD_RADIO_SET_FREQ: + if (mpctx->demuxer->stream->type == STREAMTYPE_RADIO) + radio_set_freq(mpctx->demuxer->stream, cmd->args[0].v.f); + break; + + case MP_CMD_RADIO_STEP_FREQ: + if (mpctx->demuxer->stream->type == STREAMTYPE_RADIO) + radio_step_freq(mpctx->demuxer->stream, cmd->args[0].v.f); + break; +#endif + +#ifdef USE_TV + case MP_CMD_TV_SET_FREQ: + if (mpctx->file_format == DEMUXER_TYPE_TV) + tv_set_freq((tvi_handle_t *) (mpctx->demuxer->priv), + cmd->args[0].v.f * 16.0); + break; + + case MP_CMD_TV_SET_NORM: + if (mpctx->file_format == DEMUXER_TYPE_TV) + tv_set_norm((tvi_handle_t *) (mpctx->demuxer->priv), + cmd->args[0].v.s); + break; + + case MP_CMD_TV_STEP_CHANNEL:{ + if (mpctx->file_format == DEMUXER_TYPE_TV) { + int v = cmd->args[0].v.i; + if (v > 0) { + tv_step_channel((tvi_handle_t *) (mpctx-> + demuxer->priv), + TV_CHANNEL_HIGHER); + } else { + tv_step_channel((tvi_handle_t *) (mpctx-> + demuxer->priv), + TV_CHANNEL_LOWER); + } + if (tv_channel_list) { + set_osd_msg(OSD_MSG_TV_CHANNEL, 1, osd_duration, + MSGTR_OSDChannel, tv_channel_current->name); + //vo_osd_changed(OSDTYPE_SUBTITLE); + } + } + } +#ifdef HAS_DVBIN_SUPPORT + if ((mpctx->stream->type == STREAMTYPE_DVB) + && mpctx->stream->priv) { + dvb_priv_t *priv = (dvb_priv_t *) mpctx->stream->priv; + if (priv->is_on) { + int dir; + int v = cmd->args[0].v.i; + + mpctx->last_dvb_step = v; + if (v > 0) + dir = DVB_CHANNEL_HIGHER; + else + dir = DVB_CHANNEL_LOWER; + + + if (dvb_step_channel(priv, dir)) + mpctx->eof = mpctx->dvbin_reopen = 1; + } + } +#endif /* HAS_DVBIN_SUPPORT */ + break; + + case MP_CMD_TV_SET_CHANNEL: + if (mpctx->file_format == DEMUXER_TYPE_TV) { + tv_set_channel((tvi_handle_t *) (mpctx->demuxer->priv), + cmd->args[0].v.s); + if (tv_channel_list) { + set_osd_msg(OSD_MSG_TV_CHANNEL, 1, osd_duration, + MSGTR_OSDChannel, tv_channel_current->name); + //vo_osd_changed(OSDTYPE_SUBTITLE); + } + } + break; + +#ifdef HAS_DVBIN_SUPPORT + case MP_CMD_DVB_SET_CHANNEL: + if ((mpctx->stream->type == STREAMTYPE_DVB) + && mpctx->stream->priv) { + dvb_priv_t *priv = (dvb_priv_t *) mpctx->stream->priv; + if (priv->is_on) { + if (priv->list->current <= cmd->args[0].v.i) + mpctx->last_dvb_step = 1; + else + mpctx->last_dvb_step = -1; + + if (dvb_set_channel + (priv, cmd->args[1].v.i, cmd->args[0].v.i)) + mpctx->eof = mpctx->dvbin_reopen = 1; + } + } + break; +#endif /* HAS_DVBIN_SUPPORT */ + + case MP_CMD_TV_LAST_CHANNEL: + if (mpctx->file_format == DEMUXER_TYPE_TV) { + tv_last_channel((tvi_handle_t *) (mpctx->demuxer->priv)); + if (tv_channel_list) { + set_osd_msg(OSD_MSG_TV_CHANNEL, 1, osd_duration, + MSGTR_OSDChannel, tv_channel_current->name); + //vo_osd_changed(OSDTYPE_SUBTITLE); + } + } + break; + + case MP_CMD_TV_STEP_NORM: + if (mpctx->file_format == DEMUXER_TYPE_TV) + tv_step_norm((tvi_handle_t *) (mpctx->demuxer->priv)); + break; + + case MP_CMD_TV_STEP_CHANNEL_LIST: + if (mpctx->file_format == DEMUXER_TYPE_TV) + tv_step_chanlist((tvi_handle_t *) (mpctx->demuxer->priv)); + break; +#endif /* USE_TV */ + + case MP_CMD_SUB_LOAD: + if (sh_video) { + int n = mpctx->set_of_sub_size; + add_subtitles(cmd->args[0].v.s, sh_video->fps, 0); + if (n != mpctx->set_of_sub_size) { + if (mpctx->global_sub_indices[SUB_SOURCE_SUBS] < 0) + mpctx->global_sub_indices[SUB_SOURCE_SUBS] = + mpctx->global_sub_size; + ++mpctx->global_sub_size; + } + } + break; + + case MP_CMD_SUB_REMOVE: + if (sh_video) { + int v = cmd->args[0].v.i; + sub_data *subd; + if (v < 0) { + for (v = 0; v < mpctx->set_of_sub_size; ++v) { + subd = mpctx->set_of_subtitles[v]; + mp_msg(MSGT_CPLAYER, MSGL_STATUS, + MSGTR_RemovedSubtitleFile, v + 1, + filename_recode(subd->filename)); + sub_free(subd); + mpctx->set_of_subtitles[v] = NULL; + } + mpctx->global_sub_indices[SUB_SOURCE_SUBS] = -1; + mpctx->global_sub_size -= mpctx->set_of_sub_size; + mpctx->set_of_sub_size = 0; + if (mpctx->set_of_sub_pos >= 0) { + mpctx->global_sub_pos = -2; + vo_sub_last = vo_sub = NULL; + vo_osd_changed(OSDTYPE_SUBTITLE); + vo_update_osd(sh_video->disp_w, sh_video->disp_h); + mp_input_queue_cmd(mp_input_parse_cmd("sub_select")); + } + } else if (v < mpctx->set_of_sub_size) { + subd = mpctx->set_of_subtitles[v]; + mp_msg(MSGT_CPLAYER, MSGL_STATUS, + MSGTR_RemovedSubtitleFile, v + 1, + filename_recode(subd->filename)); + sub_free(subd); + if (mpctx->set_of_sub_pos == v) { + mpctx->global_sub_pos = -2; + vo_sub_last = vo_sub = NULL; + vo_osd_changed(OSDTYPE_SUBTITLE); + vo_update_osd(sh_video->disp_w, sh_video->disp_h); + mp_input_queue_cmd(mp_input_parse_cmd("sub_select")); + } else if (mpctx->set_of_sub_pos > v) { + --mpctx->set_of_sub_pos; + --mpctx->global_sub_pos; + } + while (++v < mpctx->set_of_sub_size) + mpctx->set_of_subtitles[v - 1] = + mpctx->set_of_subtitles[v]; + --mpctx->set_of_sub_size; + --mpctx->global_sub_size; + if (mpctx->set_of_sub_size <= 0) + mpctx->global_sub_indices[SUB_SOURCE_SUBS] = -1; + mpctx->set_of_subtitles[mpctx->set_of_sub_size] = NULL; + } + } + break; + + case MP_CMD_GET_SUB_VISIBILITY: + if (sh_video) { + mp_msg(MSGT_GLOBAL, MSGL_INFO, + "ANS_SUB_VISIBILITY=%d\n", sub_visibility); + } + break; + + case MP_CMD_SCREENSHOT: + if (vo_config_count) { + mp_msg(MSGT_CPLAYER, MSGL_INFO, "sending VFCTRL_SCREENSHOT!\n"); + if (CONTROL_OK != + ((vf_instance_t *) sh_video->vfilter)-> + control(sh_video->vfilter, VFCTRL_SCREENSHOT, + &cmd->args[0].v.i)) + mpctx->video_out->control(VOCTRL_SCREENSHOT, NULL); + } + break; + + case MP_CMD_VF_CHANGE_RECTANGLE: + set_rectangle(sh_video, cmd->args[0].v.i, cmd->args[1].v.i); + break; + + case MP_CMD_GET_TIME_LENGTH:{ + mp_msg(MSGT_GLOBAL, MSGL_INFO, "ANS_LENGTH=%.2lf\n", + demuxer_get_time_length(mpctx->demuxer)); + } + break; + + case MP_CMD_GET_FILENAME:{ + mp_msg(MSGT_GLOBAL, MSGL_INFO, "ANS_FILENAME='%s'\n", + get_metadata(META_NAME)); + } + break; + + case MP_CMD_GET_VIDEO_CODEC:{ + char *inf = get_metadata(META_VIDEO_CODEC); + if (!inf) + inf = strdup(""); + mp_msg(MSGT_GLOBAL, MSGL_INFO, "ANS_VIDEO_CODEC='%s'\n", inf); + free(inf); + } + break; + + case MP_CMD_GET_VIDEO_BITRATE:{ + char *inf = get_metadata(META_VIDEO_BITRATE); + if (!inf) + inf = strdup(""); + mp_msg(MSGT_GLOBAL, MSGL_INFO, "ANS_VIDEO_BITRATE='%s'\n", inf); + free(inf); + } + break; + + case MP_CMD_GET_VIDEO_RESOLUTION:{ + char *inf = get_metadata(META_VIDEO_RESOLUTION); + if (!inf) + inf = strdup(""); + mp_msg(MSGT_GLOBAL, MSGL_INFO, + "ANS_VIDEO_RESOLUTION='%s'\n", inf); + free(inf); + } + break; + + case MP_CMD_GET_AUDIO_CODEC:{ + char *inf = get_metadata(META_AUDIO_CODEC); + if (!inf) + inf = strdup(""); + mp_msg(MSGT_GLOBAL, MSGL_INFO, "ANS_AUDIO_CODEC='%s'\n", inf); + free(inf); + } + break; + + case MP_CMD_GET_AUDIO_BITRATE:{ + char *inf = get_metadata(META_AUDIO_BITRATE); + if (!inf) + inf = strdup(""); + mp_msg(MSGT_GLOBAL, MSGL_INFO, "ANS_AUDIO_BITRATE='%s'\n", inf); + free(inf); + } + break; + + case MP_CMD_GET_AUDIO_SAMPLES:{ + char *inf = get_metadata(META_AUDIO_SAMPLES); + if (!inf) + inf = strdup(""); + mp_msg(MSGT_GLOBAL, MSGL_INFO, "ANS_AUDIO_SAMPLES='%s'\n", inf); + free(inf); + } + break; + + case MP_CMD_GET_META_TITLE:{ + char *inf = get_metadata(META_INFO_TITLE); + if (!inf) + inf = strdup(""); + mp_msg(MSGT_GLOBAL, MSGL_INFO, "ANS_META_TITLE='%s'\n", inf); + free(inf); + } + break; + + case MP_CMD_GET_META_ARTIST:{ + char *inf = get_metadata(META_INFO_ARTIST); + if (!inf) + inf = strdup(""); + mp_msg(MSGT_GLOBAL, MSGL_INFO, "ANS_META_ARTIST='%s'\n", inf); + free(inf); + } + break; + + case MP_CMD_GET_META_ALBUM:{ + char *inf = get_metadata(META_INFO_ALBUM); + if (!inf) + inf = strdup(""); + mp_msg(MSGT_GLOBAL, MSGL_INFO, "ANS_META_ALBUM='%s'\n", inf); + free(inf); + } + break; + + case MP_CMD_GET_META_YEAR:{ + char *inf = get_metadata(META_INFO_YEAR); + if (!inf) + inf = strdup(""); + mp_msg(MSGT_GLOBAL, MSGL_INFO, "ANS_META_YEAR='%s'\n", inf); + free(inf); + } + break; + + case MP_CMD_GET_META_COMMENT:{ + char *inf = get_metadata(META_INFO_COMMENT); + if (!inf) + inf = strdup(""); + mp_msg(MSGT_GLOBAL, MSGL_INFO, "ANS_META_COMMENT='%s'\n", inf); + free(inf); + } + break; + + case MP_CMD_GET_META_TRACK:{ + char *inf = get_metadata(META_INFO_TRACK); + if (!inf) + inf = strdup(""); + mp_msg(MSGT_GLOBAL, MSGL_INFO, "ANS_META_TRACK='%s'\n", inf); + free(inf); + } + break; + + case MP_CMD_GET_META_GENRE:{ + char *inf = get_metadata(META_INFO_GENRE); + if (!inf) + inf = strdup(""); + mp_msg(MSGT_GLOBAL, MSGL_INFO, "ANS_META_GENRE='%s'\n", inf); + free(inf); + } + break; + + case MP_CMD_GET_VO_FULLSCREEN: + if (mpctx->video_out && vo_config_count) + mp_msg(MSGT_GLOBAL, MSGL_INFO, "ANS_VO_FULLSCREEN=%d\n", vo_fs); + break; + + case MP_CMD_GET_PERCENT_POS: + mp_msg(MSGT_GLOBAL, MSGL_INFO, "ANS_PERCENT_POSITION=%d\n", + demuxer_get_percent_pos(mpctx->demuxer)); + break; + + case MP_CMD_GET_TIME_POS:{ + float pos = 0; + if (sh_video) + pos = sh_video->pts; + else if (sh_audio && mpctx->audio_out) + pos = + playing_audio_pts(sh_audio, mpctx->d_audio, + mpctx->audio_out); + mp_msg(MSGT_GLOBAL, MSGL_INFO, "ANS_TIME_POSITION=%.1f\n", pos); + } + break; + + case MP_CMD_RUN: +#ifndef __MINGW32__ + if (!fork()) { + execl("/bin/sh", "sh", "-c", cmd->args[0].v.s, NULL); + exit(0); + } +#endif + break; + + case MP_CMD_KEYDOWN_EVENTS: + mplayer_put_key(cmd->args[0].v.i); + break; + + case MP_CMD_SEEK_CHAPTER:{ + int seek = cmd->args[0].v.i; + int abs = (cmd->nargs > 1) ? cmd->args[1].v.i : 0; + int chap; + float next_pts = 0; + int num_chapters; + char *chapter_name; + + rel_seek_secs = 0; + abs_seek_pos = 0; + chap = + demuxer_seek_chapter(mpctx->demuxer, seek, abs, + &next_pts, &num_chapters, + &chapter_name); + if (chap != -1) { + if (next_pts > -1.0) { + abs_seek_pos = 1; + rel_seek_secs = next_pts; + } + if (chapter_name) { + set_osd_msg(OSD_MSG_TEXT, 1, osd_duration, + MSGTR_OSDChapter, chap + 1, chapter_name); + free(chapter_name); + } + } else { + if (seek > 0) + rel_seek_secs = 1000000000.; + else + set_osd_msg(OSD_MSG_TEXT, 1, osd_duration, + MSGTR_OSDChapter, 0, MSGTR_Unknown); + } + break; + } + break; + + case MP_CMD_SET_MOUSE_POS:{ + int button = -1, pointer_x, pointer_y; + double dx, dy; + pointer_x = cmd->args[0].v.i; + pointer_y = cmd->args[1].v.i; + rescale_input_coordinates(pointer_x, pointer_y, &dx, &dy); +#ifdef USE_DVDNAV + if (mpctx->stream->type == STREAMTYPE_DVDNAV + && dx > 0.0 && dy > 0.0) { + pointer_x = (int) (dx * (double) sh_video->disp_w); + pointer_y = (int) (dy * (double) sh_video->disp_h); + mp_dvdnav_update_mouse_pos(mpctx->stream, + pointer_x, pointer_y, &button); + if (button > 0) + set_osd_msg(OSD_MSG_TEXT, 1, osd_duration, + "Selected button number %d", button); + } +#endif + } + break; + +#ifdef USE_DVDNAV + case MP_CMD_DVDNAV:{ + int button = -1; + if (mpctx->stream->type != STREAMTYPE_DVDNAV) + break; + + if (mp_dvdnav_handle_input + (mpctx->stream, cmd->args[0].v.i, &button)) { + uninit_player(INITED_ALL - (INITED_STREAM | INITED_INPUT | + (fixed_vo ? INITED_VO : 0))); + brk_cmd = 2; + } else if (button > 0) + set_osd_msg(OSD_MSG_TEXT, 1, osd_duration, + "Selected button number %d", button); + } + break; +#endif + + default: +#ifdef HAVE_NEW_GUI + if ((use_gui) && (cmd->id > MP_CMD_GUI_EVENTS)) + guiGetEvent(guiIEvent, (char *) cmd->id); + else +#endif + mp_msg(MSGT_CPLAYER, MSGL_V, + "Received unknown cmd %s\n", cmd->name); + } + + switch (cmd->pausing) { + case 1: // "pausing" + mpctx->osd_function = OSD_PAUSE; + break; + case 3: // "pausing_toggle" + mpctx->was_paused = !mpctx->was_paused; + // fall through + case 2: // "pausing_keep" + if (mpctx->was_paused) + mpctx->osd_function = OSD_PAUSE; + } + return brk_cmd; +} Added: trunk/command.h ============================================================================== --- (empty file) +++ trunk/command.h Wed Feb 21 01:49:24 2007 @@ -0,0 +1,3 @@ +int run_command(MPContext *mpctx, mp_cmd_t *cmd); +char *property_expand_string(MPContext *mpctx, char *str); +void property_print_help(void); Modified: trunk/m_property.c ============================================================================== --- trunk/m_property.c (original) +++ trunk/m_property.c Wed Feb 21 01:49:24 2007 @@ -17,13 +17,13 @@ #define ROUND(x) ((int)((x)<0 ? (x)-0.5 : (x)+0.5)) -int m_property_do(m_option_t* prop, int action, void* arg) { +int m_property_do(m_option_t* prop, int action, void* arg, void *ctx) { if(!prop) return M_PROPERTY_UNKNOWN; - return ((m_property_ctrl_f)prop->p)(prop,action,arg); + return ((m_property_ctrl_f)prop->p)(prop,action,arg,ctx); } -char* m_property_print(m_option_t* prop) { +char* m_property_print(m_option_t* prop, void *ctx) { m_property_ctrl_f ctrl; void* val; char* ret; @@ -32,11 +32,11 @@ ctrl = prop->p; // look if the property have it's own print func - if(ctrl(prop,M_PROPERTY_PRINT,&ret) >= 0) + if(ctrl(prop,M_PROPERTY_PRINT,&ret, ctx) >= 0) return ret; // fallback on the default print for this type val = calloc(1,prop->type->size); - if(ctrl(prop,M_PROPERTY_GET,val) <= 0) { + if(ctrl(prop,M_PROPERTY_GET,val,ctx) <= 0) { free(val); return NULL; } @@ -45,7 +45,7 @@ return ret == (char*)-1 ? NULL : ret; } -int m_property_parse(m_option_t* prop, char* txt) { +int m_property_parse(m_option_t* prop, char* txt, void *ctx) { m_property_ctrl_f ctrl; void* val; int r; @@ -54,7 +54,7 @@ ctrl = prop->p; // try the property own parsing func - if((r = ctrl(prop,M_PROPERTY_PARSE,txt)) != M_PROPERTY_NOT_IMPLEMENTED) + if((r = ctrl(prop,M_PROPERTY_PARSE,txt,ctx)) != M_PROPERTY_NOT_IMPLEMENTED) return r; // fallback on the default val = calloc(1,prop->type->size); @@ -62,13 +62,13 @@ free(val); return r; } - r = ctrl(prop,M_PROPERTY_SET,val); + r = ctrl(prop,M_PROPERTY_SET,val,ctx); m_option_free(prop,val); free(val); return r; } -char* m_properties_expand_string(m_option_t* prop_list,char* str) { +char* m_properties_expand_string(m_option_t* prop_list,char* str, void *ctx) { int l,fr=0,pos=0,size=strlen(str)+512; char *p = NULL,*e,*ret = malloc(size), num_val; int skip = 0, lvl = 0, skip_lvl = 0; @@ -110,7 +110,7 @@ memcpy(pname,str+2,pl); pname[pl] = 0; if((prop = m_option_list_find(prop_list,pname)) && - (p = m_property_print(prop))) + (p = m_property_print(prop, ctx))) l = strlen(p), fr = 1; else l = 0; @@ -124,7 +124,7 @@ memcpy(pname,str+2,pl); pname[pl] = 0; if(!(prop = m_option_list_find(prop_list,pname)) || - m_property_do(prop,M_PROPERTY_GET,NULL) < 0) + m_property_do(prop,M_PROPERTY_GET,NULL, ctx) < 0) skip = 1, skip_lvl = lvl; } str = e+1, l = 0; Modified: trunk/m_property.h ============================================================================== --- trunk/m_property.h (original) +++ trunk/m_property.h Wed Feb 21 01:49:24 2007 @@ -78,7 +78,7 @@ /// \ingroup Properties /// \brief Property action callback. -typedef int(*m_property_ctrl_f)(m_option_t* prop,int action,void* arg); +typedef int(*m_property_ctrl_f)(m_option_t* prop,int action,void* arg,void *ctx); /// Do an action on a property. /** \param prop The property. @@ -86,20 +86,20 @@ * \param arg Argument, usually a pointer to the data type used by the property. * \return See \ref PropertyActionsReturn. */ -int m_property_do(m_option_t* prop, int action, void* arg); +int m_property_do(m_option_t* prop, int action, void* arg, void *ctx); /// Print the current value of a property. /** \param prop The property. * \return A newly allocated string with the current value or NULL on error. */ -char* m_property_print(m_option_t* prop); +char* m_property_print(m_option_t* prop, void *ctx); /// Set a property. /** \param prop The property. * \param txt The value to set. * \return 1 on success, 0 on error. */ -int m_property_parse(m_option_t* prop, char* txt); +int m_property_parse(m_option_t* prop, char* txt, void *ctx); /// Print a list of properties. void m_properties_print_help_list(m_option_t* list); @@ -115,7 +115,7 @@ * \param str The string to expand. * \return The newly allocated expanded string. */ -char* m_properties_expand_string(m_option_t* prop_list,char* str); +char* m_properties_expand_string(m_option_t* prop_list,char* str, void *ctx); // Helpers to use MPlayer's properties @@ -123,7 +123,7 @@ m_option_t* mp_property_find(const char* name); /// Do an action with an MPlayer property. -int mp_property_do(const char* name,int action, void* val); +int mp_property_do(const char* name,int action, void* val, void *ctx); /// \defgroup PropertyImplHelper Property implementation helpers /// \ingroup Properties Added: trunk/mp_core.h ============================================================================== --- (empty file) +++ trunk/mp_core.h Wed Feb 21 01:49:24 2007 @@ -0,0 +1,128 @@ +// definitions used internally by the core player code + +#define INITED_VO 1 +#define INITED_AO 2 +#define INITED_GUI 4 +#define INITED_GETCH2 8 +#define INITED_SPUDEC 32 +#define INITED_STREAM 64 +#define INITED_INPUT 128 +#define INITED_VOBSUB 256 +#define INITED_DEMUXER 512 +#define INITED_ACODEC 1024 +#define INITED_VCODEC 2048 +#define INITED_ALL 0xFFFF + + +#define SUB_SOURCE_SUBS 0 +#define SUB_SOURCE_VOBSUB 1 +#define SUB_SOURCE_DEMUX 2 +#define SUB_SOURCES 3 + + +#define PT_NEXT_ENTRY 1 +#define PT_PREV_ENTRY -1 +#define PT_NEXT_SRC 2 +#define PT_PREV_SRC -2 +#define PT_UP_NEXT 3 +#define PT_UP_PREV -3 + + +#define OSD_MSG_TV_CHANNEL 0 +#define OSD_MSG_TEXT 1 +#define OSD_MSG_SUB_DELAY 2 +#define OSD_MSG_SPEED 3 +#define OSD_MSG_OSD_STATUS 4 +#define OSD_MSG_BAR 5 +#define OSD_MSG_PAUSE 6 +#define OSD_MSG_RADIO_CHANNEL 7 +/// Base id for messages generated from the commmand to property bridge. +#define OSD_MSG_PROPERTY 0x100 + +#define MAX_OSD_LEVEL 3 +#define MAX_TERM_OSD_LEVEL 1 + + +typedef struct MPContext { + int osd_show_percentage; + int osd_function; + demux_stream_t *d_audio; + ao_functions_t *audio_out; + float begin_skip; ///< start time of the current skip while on edlout mode + play_tree_t *playtree; + play_tree_iter_t *playtree_iter; + int eof; + int play_tree_step; + + stream_t *stream; + demuxer_t *demuxer; + sh_audio_t *sh_audio; + sh_video_t *sh_video; + demux_stream_t *d_video; + demux_stream_t *d_sub; + mixer_t mixer; + vo_functions_t *video_out; + + short edl_muted; ///< Stores whether EDL is currently in muted mode. + short user_muted; ///< Stores whether user wanted muted mode. + + int global_sub_size; // this encompasses all subtitle sources + int global_sub_pos; // this encompasses all subtitle sources + int set_of_sub_pos; + int set_of_sub_size; + int global_sub_indices[SUB_SOURCES]; +#ifdef USE_ASS + // set_of_ass_tracks[i] contains subtitles from set_of_subtitles[i] + // parsed by libass or NULL if format unsupported + ass_track_t* set_of_ass_tracks[MAX_SUBTITLE_FILES]; +#endif + sub_data* set_of_subtitles[MAX_SUBTITLE_FILES]; + + int file_format; + +#ifdef HAS_DVBIN_SUPPORT + int last_dvb_step; + int dvbin_reopen; +#endif + + int was_paused; +} MPContext; + + +// Most of these should not be globals +extern int abs_seek_pos; +extern float rel_seek_secs; +extern FILE *edl_fd; +extern int file_filter; +// These appear in options list +extern float playback_speed; +extern int osd_duration; +extern int term_osd; +extern int fixed_vo; +extern int ass_enabled; +extern int fixed_vo; +extern int forced_subs_only; + +// These were listed as externs in mplayer.c, should be in some other header +extern int vo_gamma_gamma; +extern int vo_gamma_brightness; +extern int vo_gamma_contrast; +extern int vo_gamma_saturation; +extern int vo_gamma_hue; + + + +int build_afilter_chain(sh_audio_t *sh_audio, ao_data_t *ao_data); +void uninit_player(unsigned int mask); +void reinit_audio_chain(void); +void init_vo_spudec(void); +void set_osd_bar(int type,const char* name,double min,double max,double val); +void set_osd_msg(int id, int level, int time, const char* fmt, ...); +double playing_audio_pts(sh_audio_t *sh_audio, demux_stream_t *d_audio, + ao_functions_t *audio_out); +void exit_player_with_rc(const char* how, int rc); +char *get_path(const char *filename); +void rm_osd_msg(int id); +void add_subtitles(char *filename, float fps, int silent); +void mplayer_put_key(int code); +int reinit_video_chain(void); Modified: trunk/mplayer.c ============================================================================== --- trunk/mplayer.c (original) +++ trunk/mplayer.c Wed Feb 21 01:49:24 2007 @@ -111,8 +111,6 @@ #ifdef HAS_DVBIN_SUPPORT #include "stream/dvbin.h" -static int last_dvb_step = 1; -static int dvbin_reopen = 0; #include "stream/cache2.h" #endif @@ -127,17 +125,6 @@ extern int import_initial_playtree_into_gui(play_tree_t* my_playtree, m_config_t* config, int enqueue); #endif -play_tree_t* playtree; -play_tree_iter_t* playtree_iter = NULL; -static int play_tree_step = 1; - -#define PT_NEXT_ENTRY 1 -#define PT_PREV_ENTRY -1 -#define PT_NEXT_SRC 2 -#define PT_PREV_SRC -2 -#define PT_UP_NEXT 3 -#define PT_UP_PREV -3 - //**************************************************************************// // Config //**************************************************************************// @@ -193,9 +180,9 @@ #include "libmpcodecs/vf.h" #include "libmpcodecs/vd.h" -//**************************************************************************// +#include "mixer.h" -static void reinit_audio_chain(void); +#include "mp_core.h" //**************************************************************************// //**************************************************************************// @@ -205,11 +192,18 @@ int noconsolecontrols=0; //**************************************************************************// -vo_functions_t *video_out=NULL; -ao_functions_t *audio_out=NULL; +// Not all functions in mplayer.c take the context as an argument yet +static MPContext *mpctx = &(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, +}; int fixed_vo=0; -int eof=0; // benchmark: double video_time_usage=0; @@ -234,17 +228,12 @@ static int list_properties = 0; -#define MAX_OSD_LEVEL 3 -#define MAX_TERM_OSD_LEVEL 1 - int osd_level=1; // if nonzero, hide current OSD contents when GetTimerMS() reaches this unsigned int osd_visible; -static int osd_function=OSD_PLAY; -static int osd_show_percentage = 0; -static int osd_duration = 1000; +int osd_duration = 1000; -static int term_osd = 1; +int term_osd = 1; static char* term_osd_esc = "\x1b[A\r\x1b[K"; static char* playing_msg = NULL; // seek: @@ -342,45 +331,16 @@ int subcc_enabled=0; int suboverlap_enabled = 1; -sub_data* set_of_subtitles[MAX_SUBTITLE_FILES]; -int set_of_sub_size = 0; -int set_of_sub_pos = -1; - -int global_sub_size = 0; // this encompasses all subtitle sources -int global_sub_pos = -1; // this encompasses all subtitle sources -#define SUB_SOURCE_SUBS 0 -#define SUB_SOURCE_VOBSUB 1 -#define SUB_SOURCE_DEMUX 2 -#define SUB_SOURCES 3 -int global_sub_indices[SUB_SOURCES]; - #ifdef USE_ASS #include "libass/ass.h" #include "libass/ass_mp.h" - -// set_of_ass_tracks[i] contains subtitles from set_of_subtitles[i] parsed by libass -// or NULL if format unsupported -ass_track_t* set_of_ass_tracks[MAX_SUBTITLE_FILES]; #endif extern int mp_msg_levels[MSGT_MAX]; extern int mp_msg_level_all; -static stream_t* stream=NULL; -static demuxer_t *demuxer=NULL; -static sh_audio_t *sh_audio=NULL; -static sh_video_t *sh_video=NULL; -static demux_stream_t *d_audio=NULL; -static demux_stream_t *d_video=NULL; -static demux_stream_t *d_dvdsub=NULL; - char* current_module=NULL; // for debugging -extern int vo_gamma_gamma; -extern int vo_gamma_brightness; -extern int vo_gamma_contrast; -extern int vo_gamma_saturation; -extern int vo_gamma_hue; // --- @@ -407,27 +367,13 @@ edl_record_ptr edl_records = NULL; ///< EDL entries memory area edl_record_ptr next_edl_record = NULL; ///< only for traversing edl_records -short user_muted = 0; ///< Stores whether user wanted muted mode. -short edl_muted = 0; ///< Stores whether EDL is currently in muted mode. short edl_decision = 0; ///< 1 when an EDL operation has been made. FILE* edl_fd = NULL; ///< fd to write to when in -edlout mode. -float begin_skip = MP_NOPTS_VALUE; ///< start time of the current skip while on edlout mode int use_filedir_conf; static unsigned int inited_flags=0; #include "mpcommon.h" -#define INITED_VO 1 -#define INITED_AO 2 -#define INITED_GUI 4 -#define INITED_GETCH2 8 -#define INITED_SPUDEC 32 -#define INITED_STREAM 64 -#define INITED_INPUT 128 -#define INITED_VOBSUB 256 -#define INITED_DEMUXER 512 -#define INITED_ACODEC 1024 -#define INITED_VCODEC 2048 -#define INITED_ALL 0xFFFF +#include "command.h" #include "metadata.h" @@ -441,7 +387,7 @@ case META_VIDEO_BITRATE: case META_VIDEO_RESOLUTION: { - if (!sh_video) + if (!mpctx->sh_video) return 0; break; } @@ -451,7 +397,7 @@ case META_AUDIO_BITRATE: case META_AUDIO_SAMPLES: { - if (!sh_audio) + if (!mpctx->sh_audio) return 0; break; } @@ -465,7 +411,7 @@ case META_INFO_TRACK: case META_INFO_GENRE: { - if (!demuxer) + if (!mpctx->demuxer) return 0; break; } @@ -478,7 +424,7 @@ } static char *get_demuxer_info (char *tag) { - char **info = demuxer->info; + char **info = mpctx->demuxer->info; int n; if (!info || !tag) @@ -493,10 +439,12 @@ char *get_metadata (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)) return NULL; - + switch (type) { case META_NAME: @@ -591,12 +539,10 @@ return meta; } -#include "mixer.h" -mixer_t mixer; /// step size of mixer changes int volstep = 3; -static void uninit_player(unsigned int mask){ +void uninit_player(unsigned int mask){ mask=inited_flags&mask; mp_msg(MSGT_CPLAYER,MSGL_DBG2,"\n*** uninit(0x%X)\n",mask); @@ -604,18 +550,18 @@ if(mask&INITED_ACODEC){ inited_flags&=~INITED_ACODEC; current_module="uninit_acodec"; - if(sh_audio) uninit_audio(sh_audio); + if(mpctx->sh_audio) uninit_audio(mpctx->sh_audio); #ifdef HAVE_NEW_GUI guiGetEvent(guiSetAfilter, (char *)NULL); #endif - sh_audio=NULL; + mpctx->sh_audio=NULL; } if(mask&INITED_VCODEC){ inited_flags&=~INITED_VCODEC; current_module="uninit_vcodec"; - if(sh_video) uninit_video(sh_video); - sh_video=NULL; + if(mpctx->sh_video) uninit_video(mpctx->sh_video); + mpctx->sh_video=NULL; #ifdef HAVE_MENU vf_menu=NULL; #endif @@ -624,26 +570,26 @@ if(mask&INITED_DEMUXER){ inited_flags&=~INITED_DEMUXER; current_module="free_demuxer"; - if(demuxer){ - stream=demuxer->stream; - free_demuxer(demuxer); + if(mpctx->demuxer){ + mpctx->stream=mpctx->demuxer->stream; + free_demuxer(mpctx->demuxer); } - demuxer=NULL; + mpctx->demuxer=NULL; } // kill the cache process: if(mask&INITED_STREAM){ inited_flags&=~INITED_STREAM; current_module="uninit_stream"; - if(stream) free_stream(stream); - stream=NULL; + if(mpctx->stream) free_stream(mpctx->stream); + mpctx->stream=NULL; } if(mask&INITED_VO){ inited_flags&=~INITED_VO; current_module="uninit_vo"; - video_out->uninit(); - video_out=NULL; + mpctx->video_out->uninit(); + mpctx->video_out=NULL; } // Must be after libvo uninit, as few vo drivers (svgalib) have tty code. @@ -672,8 +618,8 @@ if(mask&INITED_AO){ inited_flags&=~INITED_AO; current_module="uninit_ao"; - if (user_muted | edl_muted) mixer_mute(&mixer); - audio_out->uninit(eof?0:1); audio_out=NULL; + if (mpctx->user_muted | mpctx->edl_muted) mixer_mute(&mpctx->mixer); + mpctx->audio_out->uninit(mpctx->eof?0:1); mpctx->audio_out=NULL; } #ifdef HAVE_NEW_GUI @@ -693,7 +639,7 @@ current_module=NULL; } -static void exit_player_with_rc(const char* how, int rc){ +void exit_player_with_rc(const char* how, int rc){ uninit_player(INITED_ALL); #ifdef HAVE_X11 @@ -721,8 +667,8 @@ if(mconfig) m_config_free(mconfig); - if(playtree) - play_tree_free(playtree, 1); + if(mpctx->playtree) + play_tree_free(mpctx->playtree, 1); if(edl_records != NULL) free(edl_records); // free mem allocated for EDL @@ -896,7 +842,7 @@ exit_player_with_rc(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; - play_tree_step = (cmd->args[0].v.i == 0) ? 1 : cmd->args[0].v.i; + 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; @@ -926,22 +872,22 @@ #endif { if(!entry) { - entry = playtree_iter->tree; - if(play_tree_iter_step(playtree_iter,1,0) != PLAY_TREE_ITER_ENTRY) { + entry = mpctx->playtree_iter->tree; + if(play_tree_iter_step(mpctx->playtree_iter,1,0) != PLAY_TREE_ITER_ENTRY) { return PT_NEXT_ENTRY; } - if(playtree_iter->tree == entry ) { // Loop with a single file - if(play_tree_iter_up_step(playtree_iter,1,0) != PLAY_TREE_ITER_ENTRY) { + if(mpctx->playtree_iter->tree == entry ) { // Loop with a single file + if(play_tree_iter_up_step(mpctx->playtree_iter,1,0) != PLAY_TREE_ITER_ENTRY) { return PT_NEXT_ENTRY; } } play_tree_remove(entry,1,1); return PT_NEXT_SRC; } - play_tree_insert_entry(playtree_iter->tree,entry); - play_tree_set_params_from(entry,playtree_iter->tree); - entry = playtree_iter->tree; - if(play_tree_iter_step(playtree_iter,1,0) != PLAY_TREE_ITER_ENTRY) { + play_tree_insert_entry(mpctx->playtree_iter->tree,entry); + play_tree_set_params_from(entry,mpctx->playtree_iter->tree); + entry = mpctx->playtree_iter->tree; + if(play_tree_iter_step(mpctx->playtree_iter,1,0) != PLAY_TREE_ITER_ENTRY) { return PT_NEXT_ENTRY; } play_tree_remove(entry,1,1); @@ -949,21 +895,6 @@ return PT_NEXT_SRC; } -int sub_source(void) -{ - int source = -1; - int top = -1; - int i; - for (i = 0; i < SUB_SOURCES; i++) { - int j = global_sub_indices[i]; - if ((j >= 0) && (j > top) && (global_sub_pos >= j)) { - source = i; - top = j; - } - } - return source; -} - void add_subtitles(char *filename, float fps, int silent) { sub_data *subd; @@ -971,7 +902,7 @@ ass_track_t *asst = 0; #endif - if (filename == NULL || set_of_sub_size >= MAX_SUBTITLE_FILES) { + if (filename == NULL || mpctx->set_of_sub_size >= MAX_SUBTITLE_FILES) { return; } @@ -995,16 +926,16 @@ #ifdef USE_ASS if (!asst && !subd) return; - set_of_ass_tracks[set_of_sub_size] = asst; + mpctx->set_of_ass_tracks[mpctx->set_of_sub_size] = asst; #else if (!subd) return; #endif - set_of_subtitles[set_of_sub_size] = subd; - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_FILE_SUB_ID=%d\n", set_of_sub_size); + mpctx->set_of_subtitles[mpctx->set_of_sub_size] = subd; + mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_FILE_SUB_ID=%d\n", mpctx->set_of_sub_size); mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_FILE_SUB_FILENAME=%s\n", filename_recode(filename)); - ++set_of_sub_size; - mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_AddedSubtitleFile, set_of_sub_size, + ++mpctx->set_of_sub_size; + mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_AddedSubtitleFile, mpctx->set_of_sub_size, filename_recode(filename)); } @@ -1012,20 +943,21 @@ void update_set_of_subtitles(void) // subdata was changed, set_of_sub... have to be updated. { + sub_data ** const set_of_subtitles = mpctx->set_of_subtitles; int i; - if (set_of_sub_size > 0 && subdata == NULL) { // *subdata was deleted - for (i = set_of_sub_pos + 1; i < set_of_sub_size; ++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[set_of_sub_size-1] = NULL; - --set_of_sub_size; - if (set_of_sub_size > 0) subdata = set_of_subtitles[set_of_sub_pos=0]; - } - else if (set_of_sub_size > 0 && subdata != NULL) { // *subdata was changed - set_of_subtitles[set_of_sub_pos] = subdata; - } - else if (set_of_sub_size <= 0 && subdata != NULL) { // *subdata was added - set_of_subtitles[set_of_sub_pos=set_of_sub_size] = subdata; - ++set_of_sub_size; + 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; } } @@ -1042,24 +974,24 @@ } #ifdef USE_DVDREAD - if (vo_spudec==NULL && stream->type==STREAMTYPE_DVD) { + if (vo_spudec==NULL && mpctx->stream->type==STREAMTYPE_DVD) { current_module="spudec_init_dvdread"; - vo_spudec=spudec_new_scaled(((dvd_priv_t *)(stream->priv))->cur_pgc->palette, - sh_video->disp_w, sh_video->disp_h); + vo_spudec=spudec_new_scaled(((dvd_priv_t *)(mpctx->stream->priv))->cur_pgc->palette, + mpctx->sh_video->disp_w, mpctx->sh_video->disp_h); } #endif #ifdef USE_DVDNAV - if (vo_spudec==NULL && stream->type==STREAMTYPE_DVDNAV) { - unsigned int *palette = mp_dvdnav_get_spu_clut(stream); + if (vo_spudec==NULL && mpctx->stream->type==STREAMTYPE_DVDNAV) { + unsigned int *palette = mp_dvdnav_get_spu_clut(mpctx->stream); current_module="spudec_init_dvdnav"; - vo_spudec=spudec_new_scaled(palette, sh_video->disp_w, sh_video->disp_h); + vo_spudec=spudec_new_scaled(palette, mpctx->sh_video->disp_w, mpctx->sh_video->disp_h); } #endif - if ((vo_spudec == NULL) && (demuxer->type == DEMUXER_TYPE_MATROSKA) && - (d_dvdsub->sh != NULL) && (((sh_sub_t *)d_dvdsub->sh)->type == 'v')) { - sh_sub_t *mkv_sh_sub = (sh_sub_t *)d_dvdsub->sh; + if ((vo_spudec == NULL) && (mpctx->demuxer->type == DEMUXER_TYPE_MATROSKA) && + (mpctx->d_sub->sh != NULL) && (((sh_sub_t *)mpctx->d_sub->sh)->type == 'v')) { + sh_sub_t *mkv_sh_sub = (sh_sub_t *)mpctx->d_sub->sh; current_module = "spudec_init_matroska"; vo_spudec = spudec_new_scaled_vobsub(mkv_sh_sub->palette, mkv_sh_sub->colors, @@ -1069,12 +1001,12 @@ } if (vo_spudec==NULL) { - sh_sub_t *sh = (sh_sub_t *)d_dvdsub->sh; + sh_sub_t *sh = (sh_sub_t *)mpctx->d_sub->sh; unsigned int *palette = NULL; if (sh && sh->has_palette) palette = sh->palette; current_module="spudec_init_normal"; - vo_spudec=spudec_new_scaled(palette, sh_video->disp_w, sh_video->disp_h); + vo_spudec=spudec_new_scaled(palette, mpctx->sh_video->disp_w, mpctx->sh_video->disp_h); spudec_set_font_factor(vo_spudec,font_factor); } @@ -1142,6 +1074,7 @@ */ static void print_status(float a_pos, float a_v, float corr) { + sh_video_t * const sh_video = mpctx->sh_video; int width; char *line; unsigned pos = 0; @@ -1158,10 +1091,10 @@ line = malloc(width + 1); // one additional char for the terminating null // Audio time - if (sh_audio) { + if (mpctx->sh_audio) { saddf(line, &pos, width, "A:%6.1f ", a_pos); if (!sh_video) { - float len = demuxer_get_time_length(demuxer); + float len = demuxer_get_time_length(mpctx->demuxer); saddf(line, &pos, width, "("); sadd_hhmmssf(line, &pos, width, a_pos); saddf(line, &pos, width, ") of %.1f (", len); @@ -1175,7 +1108,7 @@ saddf(line, &pos, width, "V:%6.1f ", sh_video->pts); // A-V sync - if (sh_audio && sh_video) + if (mpctx->sh_audio && sh_video) saddf(line, &pos, width, "A-V:%7.3f ct:%7.3f ", a_v, corr); // Video stats @@ -1193,10 +1126,10 @@ (100.0*audio_time_usage*playback_speed/(double)sh_video->timer)); else saddf(line, &pos, width, "??%% ??%% ??,?%% "); - } else if (sh_audio) { - if (sh_audio->delay > 0.5) + } else if (mpctx->sh_audio) { + if (mpctx->sh_audio->delay > 0.5) saddf(line, &pos, width, "%4.1f%% ", - 100.0*audio_time_usage/(double)sh_audio->delay); + 100.0*audio_time_usage/(double)mpctx->sh_audio->delay); else saddf(line, &pos, width, "??,?%% "); } @@ -1233,7 +1166,7 @@ * \param sh_audio describes the requested input format of the chain. * \param ao_data describes the requested output format of the chain. */ -static int build_afilter_chain(sh_audio_t *sh_audio, ao_data_t *ao_data) +int build_afilter_chain(sh_audio_t *sh_audio, ao_data_t *ao_data) { int new_srate; int result; @@ -1242,7 +1175,7 @@ #ifdef HAVE_NEW_GUI guiGetEvent(guiSetAfilter, (char *)NULL); #endif - mixer.afilter = NULL; + mpctx->mixer.afilter = NULL; return 0; } new_srate = sh_audio->samplerate * playback_speed; @@ -1258,63 +1191,13 @@ sh_audio->channels, sh_audio->sample_format, &ao_data->samplerate, &ao_data->channels, &ao_data->format, ao_data->outburst * 4, ao_data->buffersize); - mixer.afilter = sh_audio->afilter; + mpctx->mixer.afilter = sh_audio->afilter; #ifdef HAVE_NEW_GUI guiGetEvent(guiSetAfilter, (char *)sh_audio->afilter); #endif return result; } -/** - * \brief Log the currently displayed subtitle to a file - * - * Logs the current or last displayed subtitle together with filename - * and time information to ~/.mplayer/subtitle_log - * - * Intended purpose is to allow convenient marking of bogus subtitles - * which need to be fixed while watching the movie. - */ - -static void log_sub(void){ - char *fname; - FILE *f; - int i; - - if (subdata == NULL || vo_sub_last == NULL) return; - fname = get_path("subtitle_log"); - f = fopen(fname, "a"); - if (!f) return; - fprintf(f, "----------------------------------------------------------\n"); - if (subdata->sub_uses_time) { - fprintf(f, "N: %s S: %02ld:%02ld:%02ld.%02ld E: %02ld:%02ld:%02ld.%02ld\n", filename, - vo_sub_last->start/360000, (vo_sub_last->start/6000)%60, - (vo_sub_last->start/100)%60, vo_sub_last->start%100, - vo_sub_last->end/360000, (vo_sub_last->end/6000)%60, - (vo_sub_last->end/100)%60, vo_sub_last->end%100); - } else { - fprintf(f, "N: %s S: %ld E: %ld\n", filename, vo_sub_last->start, vo_sub_last->end); - } - for (i = 0; i < vo_sub_last->lines; i++) { - fprintf(f, "%s\n", vo_sub_last->text[i]); - } - fclose(f); -} - -/// \defgroup OSDMsgStack OSD message stack -/// -///@{ - -#define OSD_MSG_TV_CHANNEL 0 -#define OSD_MSG_TEXT 1 -#define OSD_MSG_SUB_DELAY 2 -#define OSD_MSG_SPEED 3 -#define OSD_MSG_OSD_STATUS 4 -#define OSD_MSG_BAR 5 -#define OSD_MSG_PAUSE 6 -#define OSD_MSG_RADIO_CHANNEL 7 -/// Base id for messages generated from the commmand to property bridge. -#define OSD_MSG_PROPERTY 0x100 - typedef struct mp_osd_msg mp_osd_msg_t; struct mp_osd_msg { @@ -1338,7 +1221,7 @@ * */ -static void set_osd_msg(int id, int level, int time, const char* fmt, ...) { +void set_osd_msg(int id, int level, int time, const char* fmt, ...) { mp_osd_msg_t *msg,*last=NULL; va_list va; int r; @@ -1375,7 +1258,7 @@ * */ -static void rm_osd_msg(int id) { +void rm_osd_msg(int id) { mp_osd_msg_t *msg,*last=NULL; // Search for the msg @@ -1461,11 +1344,11 @@ * */ -static void set_osd_bar(int type,const char* name,double min,double max,double val) { +void set_osd_bar(int type,const char* name,double min,double max,double val) { if(osd_level < 1) return; - if(sh_video) { + if(mpctx->sh_video) { osd_visible = (GetTimerMS() + 1000) | 1; vo_osd_progbar_type = type; vo_osd_progbar_value = 256*(val-min)/(max-min); @@ -1499,22 +1382,22 @@ if((msg = get_osd_msg())) { if(strcmp(osd_text,msg->msg)) { strncpy((char*)osd_text, msg->msg, 63); - if(sh_video) vo_osd_changed(OSDTYPE_OSD); else + 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); } return; } - if(sh_video) { + if(mpctx->sh_video) { // fallback on the timer if(osd_level>=2) { - int len = demuxer_get_time_length(demuxer); + int len = demuxer_get_time_length(mpctx->demuxer); int percentage = -1; char percentage_text[10]; - int pts = demuxer_get_current_time(demuxer); + int pts = demuxer_get_current_time(mpctx->demuxer); - if (osd_show_percentage) - percentage = demuxer_get_percent_pos(demuxer); + if (mpctx->osd_show_percentage) + percentage = demuxer_get_percent_pos(mpctx->demuxer); if (percentage >= 0) snprintf(percentage_text, 9, " (%d%%)", percentage); @@ -1524,18 +1407,18 @@ if (osd_level == 3) snprintf(osd_text_timer, 63, "%c %02d:%02d:%02d / %02d:%02d:%02d%s", - osd_function,pts/3600,(pts/60)%60,pts%60, + mpctx->osd_function,pts/3600,(pts/60)%60,pts%60, len/3600,(len/60)%60,len%60,percentage_text); else snprintf(osd_text_timer, 63, "%c %02d:%02d:%02d%s", - osd_function,pts/3600,(pts/60)%60, + mpctx->osd_function,pts/3600,(pts/60)%60, pts%60,percentage_text); } else osd_text_timer[0]=0; // always decrement the percentage timer - if(osd_show_percentage) - osd_show_percentage--; + if(mpctx->osd_show_percentage) + mpctx->osd_show_percentage--; if(strcmp(osd_text,osd_text_timer)) { strncpy(osd_text, osd_text_timer, 63); @@ -1554,1217 +1437,14 @@ ///@} // OSDMsgStack -/// \defgroup Properties -///@{ - -/// \defgroup GeneralProperties General properties -/// \ingroup Properties -///@{ - -/// OSD level (RW) -static int mp_property_osdlevel(m_option_t* prop,int action,void* arg) { - return m_property_choice(prop,action,arg,&osd_level); -} - -/// Playback speed (RW) -static int mp_property_playback_speed(m_option_t* prop,int action,void* arg) { - switch(action) { - case M_PROPERTY_SET: - if(!arg) return M_PROPERTY_ERROR; - M_PROPERTY_CLAMP(prop,*(float*)arg); - playback_speed = *(float*)arg; - build_afilter_chain(sh_audio, &ao_data); - return M_PROPERTY_OK; - case M_PROPERTY_STEP_UP: - case M_PROPERTY_STEP_DOWN: - playback_speed += (arg ? *(float*)arg : 0.1) * - (action == M_PROPERTY_STEP_DOWN ? -1 : 1); - M_PROPERTY_CLAMP(prop,playback_speed); - build_afilter_chain(sh_audio, &ao_data); - return M_PROPERTY_OK; - } - return m_property_float_range(prop,action,arg,&playback_speed); -} - -/// filename with path (RO) -static int mp_property_path(m_option_t* prop,int action,void* arg) { - return m_property_string_ro(prop,action,arg,filename); -} - -/// filename without path (RO) -static int mp_property_filename(m_option_t* prop,int action,void* arg) { - char* f; - if(!filename) return M_PROPERTY_UNAVAILABLE; - if(((f = strrchr(filename,'/')) || (f = strrchr(filename,'\\'))) && f[1]) - f++; - else - f = filename; - return m_property_string_ro(prop,action,arg,f); -} - -/// Demuxer name (RO) -static int mp_property_demuxer(m_option_t* prop,int action,void* arg) { - if(!demuxer) return M_PROPERTY_UNAVAILABLE; - return m_property_string_ro(prop,action,arg,(char*)demuxer->desc->name); -} - -/// Position in the stream (RW) -static int mp_property_stream_pos(m_option_t* prop,int action,void* arg) { - if (!demuxer || !demuxer->stream) return M_PROPERTY_UNAVAILABLE; - if (!arg) return M_PROPERTY_ERROR; - switch (action) { - case M_PROPERTY_GET: - *(off_t*)arg = stream_tell(demuxer->stream); - return M_PROPERTY_OK; - case M_PROPERTY_SET: - M_PROPERTY_CLAMP(prop,*(off_t*)arg); - stream_seek(demuxer->stream, *(off_t*)arg); - return M_PROPERTY_OK; - } - return M_PROPERTY_NOT_IMPLEMENTED; -} - -/// Stream start offset (RO) -static int mp_property_stream_start(m_option_t* prop,int action,void* arg) { - if (!demuxer || !demuxer->stream) return M_PROPERTY_UNAVAILABLE; - switch (action) { - case M_PROPERTY_GET: - *(off_t*)arg = demuxer->stream->start_pos; - return M_PROPERTY_OK; - } - return M_PROPERTY_NOT_IMPLEMENTED; -} - -/// Stream end offset (RO) -static int mp_property_stream_end(m_option_t* prop,int action,void* arg) { - if (!demuxer || !demuxer->stream) return M_PROPERTY_UNAVAILABLE; - switch (action) { - case M_PROPERTY_GET: - *(off_t*)arg = demuxer->stream->end_pos; - return M_PROPERTY_OK; - } - return M_PROPERTY_NOT_IMPLEMENTED; -} - -/// Stream length (RO) -static int mp_property_stream_length(m_option_t* prop,int action,void* arg) { - if (!demuxer || !demuxer->stream) return M_PROPERTY_UNAVAILABLE; - switch (action) { - case M_PROPERTY_GET: - *(off_t*)arg = demuxer->stream->end_pos - demuxer->stream->start_pos; - return M_PROPERTY_OK; - } - return M_PROPERTY_NOT_IMPLEMENTED; -} - -/// Media length in seconds (RO) -static int mp_property_length(m_option_t* prop,int action,void* arg) { - double len; - - if(!demuxer || - !(int)(len = demuxer_get_time_length(demuxer))) - return M_PROPERTY_UNAVAILABLE; - - switch(action) { - case M_PROPERTY_PRINT: - if(!arg) return M_PROPERTY_ERROR; - else { - int h, m, s = len; - h = s/3600; - s -= h*3600; - m = s/60; - s -= m*60; - *(char**)arg = malloc(20); - if(h > 0) sprintf(*(char**)arg,"%d:%02d:%02d",h,m,s); - else if(m > 0) sprintf(*(char**)arg,"%d:%02d",m,s); - else sprintf(*(char**)arg,"%d",s); - return M_PROPERTY_OK; - } - break; - } - return m_property_double_ro(prop,action,arg,len); -} - -///@} - -/// \defgroup AudioProperties Audio properties -/// \ingroup Properties -///@{ - -/// Volume (RW) -static int mp_property_volume(m_option_t* prop,int action,void* arg) { - - if(!sh_audio) return M_PROPERTY_UNAVAILABLE; - - switch(action) { - case M_PROPERTY_GET: - if(!arg) return M_PROPERTY_ERROR; - mixer_getbothvolume(&mixer,arg); - return M_PROPERTY_OK; - case M_PROPERTY_PRINT:{ - float vol; - if(!arg) return M_PROPERTY_ERROR; - mixer_getbothvolume(&mixer,&vol); - return m_property_float_range(prop,action,arg,&vol); - } - case M_PROPERTY_STEP_UP: - case M_PROPERTY_STEP_DOWN: - case M_PROPERTY_SET: - break; - default: - return M_PROPERTY_NOT_IMPLEMENTED; - } - - if (edl_muted) return M_PROPERTY_DISABLED; - user_muted = 0; - - switch(action) { - case M_PROPERTY_SET: - if(!arg) return M_PROPERTY_ERROR; - M_PROPERTY_CLAMP(prop,*(float*)arg); - mixer_setvolume(&mixer,*(float*)arg,*(float*)arg); - return M_PROPERTY_OK; - case M_PROPERTY_STEP_UP: - if(arg && *(float*)arg <= 0) - mixer_decvolume(&mixer); - else - mixer_incvolume(&mixer); - return M_PROPERTY_OK; - case M_PROPERTY_STEP_DOWN: - if(arg && *(float*)arg <= 0) - mixer_incvolume(&mixer); - else - mixer_decvolume(&mixer); - return M_PROPERTY_OK; - } - return M_PROPERTY_NOT_IMPLEMENTED; -} - -/// Mute (RW) -static int mp_property_mute(m_option_t* prop,int action,void* arg) { - - if(!sh_audio) return M_PROPERTY_UNAVAILABLE; - - switch(action) { - case M_PROPERTY_SET: - if(edl_muted) return M_PROPERTY_DISABLED; - if(!arg) return M_PROPERTY_ERROR; - if((!!*(int*)arg) != mixer.muted) - mixer_mute(&mixer); - user_muted = mixer.muted; - return M_PROPERTY_OK; - case M_PROPERTY_STEP_UP: - case M_PROPERTY_STEP_DOWN: - if(edl_muted) return M_PROPERTY_DISABLED; - mixer_mute(&mixer); - user_muted = mixer.muted; - return M_PROPERTY_OK; - case M_PROPERTY_PRINT: - if(!arg) return M_PROPERTY_ERROR; - if(edl_muted) { - *(char**)arg = strdup(MSGTR_EnabledEdl); - return M_PROPERTY_OK; - } - default: - return m_property_flag(prop,action,arg,&mixer.muted); - - } -} - -/// Audio delay (RW) -static int mp_property_audio_delay(m_option_t* prop,int action,void* arg) { - if(!(sh_audio && sh_video)) return M_PROPERTY_UNAVAILABLE; - switch(action) { - case M_PROPERTY_SET: - case M_PROPERTY_STEP_UP: - case M_PROPERTY_STEP_DOWN: - if(!arg) return M_PROPERTY_ERROR; - else { - float delay = audio_delay; - m_property_delay(prop,action,arg,&audio_delay); - if(sh_audio) sh_audio->delay -= audio_delay-delay; - } - return M_PROPERTY_OK; - default: - return m_property_delay(prop,action,arg,&audio_delay); - } -} - -/// Audio codec tag (RO) -static int mp_property_audio_format(m_option_t* prop,int action,void* arg) { - if(!sh_audio) return M_PROPERTY_UNAVAILABLE; - return m_property_int_ro(prop,action,arg,sh_audio->format); -} - -/// Audio bitrate (RO) -static int mp_property_audio_bitrate(m_option_t* prop,int action,void* arg) { - if(!sh_audio) return M_PROPERTY_UNAVAILABLE; - return m_property_int_ro(prop,action,arg,sh_audio->i_bps); -} - -/// Samplerate (RO) -static int mp_property_samplerate(m_option_t* prop,int action,void* arg) { - if(!sh_audio) return M_PROPERTY_UNAVAILABLE; - return m_property_int_ro(prop,action,arg,sh_audio->samplerate); -} - -/// Number of channels (RO) -static int mp_property_channels(m_option_t* prop,int action,void* arg) { - if(!sh_audio) return M_PROPERTY_UNAVAILABLE; - switch(action) { - case M_PROPERTY_PRINT: - if(!arg) return M_PROPERTY_ERROR; - switch(sh_audio->channels) { - case 1: *(char**)arg = strdup("mono"); break; - case 2: *(char**)arg = strdup("stereo"); break; - default: - *(char**)arg = malloc(32); - sprintf(*(char**)arg,"%d channels",sh_audio->channels); - } - return M_PROPERTY_OK; - } - return m_property_int_ro(prop,action,arg,sh_audio->channels); -} - -/// Selected audio id (RW) -static int mp_property_audio(m_option_t* prop,int action,void* arg) { - int current_id = -1, tmp; - - switch(action) { - case M_PROPERTY_GET: - if(!sh_audio) return M_PROPERTY_UNAVAILABLE; - if(!arg) return M_PROPERTY_ERROR; - *(int*)arg = audio_id; - return M_PROPERTY_OK; - case M_PROPERTY_PRINT: - if(!sh_audio) return M_PROPERTY_UNAVAILABLE; - if(!arg) return M_PROPERTY_ERROR; - - if (audio_id < 0) - *(char**)arg = strdup(MSGTR_Disabled); - else { - char lang[40] = MSGTR_Unknown; - if (demuxer->type == DEMUXER_TYPE_MATROSKA) - demux_mkv_get_audio_lang(demuxer, audio_id, lang, 9); -#ifdef USE_DVDREAD - else if(stream->type == STREAMTYPE_DVD) { - int code = dvd_lang_from_aid(stream, audio_id); - if (code) { - lang[0] = code >> 8; - lang[1] = code; - lang[2] = 0; - } - } -#endif - -#ifdef USE_DVDNAV - else if(stream->type == STREAMTYPE_DVDNAV) - dvdnav_lang_from_aid(stream, audio_id, lang); -#endif - *(char**)arg = malloc(64); - snprintf(*(char**)arg, 64, "(%d) %s", audio_id, lang); - } - return M_PROPERTY_OK; - - case M_PROPERTY_STEP_UP: - case M_PROPERTY_SET: - if(action==M_PROPERTY_SET && arg) - tmp = *((int*)arg); - else - tmp = -1; - current_id = demuxer->audio->id; - audio_id = demuxer_switch_audio(demuxer, tmp); - if(audio_id == -2 || (audio_id > -1 && demuxer->audio->id != current_id && current_id != -2)) - uninit_player(INITED_AO | INITED_ACODEC); - if(audio_id > -1 && demuxer->audio->id != current_id) { - sh_audio_t *sh2; - sh2 = demuxer->a_streams[demuxer->audio->id]; - if(sh2) { - sh2->ds = demuxer->audio; - sh_audio = sh2; - reinit_audio_chain(); - } - } - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AUDIO_TRACK=%d\n", audio_id); - return M_PROPERTY_OK; - default: - return M_PROPERTY_NOT_IMPLEMENTED; - } - -} - -static int reinit_video_chain(void); -/// Selected video id (RW) -static int mp_property_video(m_option_t* prop,int action,void* arg) { - int current_id = -1, tmp; - - switch(action) { - case M_PROPERTY_GET: - if(!sh_video) return M_PROPERTY_UNAVAILABLE; - if(!arg) return M_PROPERTY_ERROR; - *(int*)arg = video_id; - return M_PROPERTY_OK; - case M_PROPERTY_PRINT: - if(!sh_video) return M_PROPERTY_UNAVAILABLE; - if(!arg) return M_PROPERTY_ERROR; - - if (video_id < 0) - *(char**)arg = strdup(MSGTR_Disabled); - else { - char lang[40] = MSGTR_Unknown; - *(char**)arg = malloc(64); - snprintf(*(char**)arg, 64, "(%d) %s", video_id, lang); - } - return M_PROPERTY_OK; - - case M_PROPERTY_STEP_UP: - case M_PROPERTY_SET: - current_id = demuxer->video->id; - if(action==M_PROPERTY_SET && arg) - tmp = *((int*)arg); - else - tmp = -1; - video_id = demuxer_switch_video(demuxer, tmp); - if(video_id == -2 || (video_id > -1 && demuxer->video->id != current_id && current_id != -2)) - uninit_player(INITED_VCODEC | (fixed_vo && video_id != -2 ? 0 : INITED_VO)); - if(video_id > -1 && demuxer->video->id != current_id) { - sh_video_t *sh2; - sh2 = demuxer->v_streams[demuxer->video->id]; - if(sh2) { - sh2->ds = demuxer->video; - sh_video = sh2; - reinit_video_chain(); - } - } - mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_VIDEO_TRACK=%d\n", video_id); - return M_PROPERTY_OK; - - default: - return M_PROPERTY_NOT_IMPLEMENTED; - } -} - -static int mp_property_program(m_option_t* prop,int action,void* arg) { - demux_program_t prog; - - switch(action) { - case M_PROPERTY_STEP_UP: - case M_PROPERTY_SET: - if(action==M_PROPERTY_SET && arg) - prog.progid = *((int*)arg); - else - prog.progid = -1; - if(demux_control(demuxer, DEMUXER_CTRL_IDENTIFY_PROGRAM, &prog) == DEMUXER_CTRL_NOTIMPL) - return M_PROPERTY_ERROR; - - mp_property_do("switch_audio", M_PROPERTY_SET, &prog.aid); - mp_property_do("switch_video", M_PROPERTY_SET, &prog.vid); - return M_PROPERTY_OK; - - default: - return M_PROPERTY_NOT_IMPLEMENTED; - } -} - -///@} - -/// \defgroup VideoProperties Video properties -/// \ingroup Properties -///@{ - -/// Fullscreen state (RW) -static int mp_property_fullscreen(m_option_t* prop,int action,void* arg) { - - if(!video_out) return M_PROPERTY_UNAVAILABLE; - - switch(action) { - case M_PROPERTY_SET: - if(!arg) return M_PROPERTY_ERROR; - M_PROPERTY_CLAMP(prop,*(int*)arg); - if(vo_fs == !!*(int*)arg) return M_PROPERTY_OK; - case M_PROPERTY_STEP_UP: - case M_PROPERTY_STEP_DOWN: -#ifdef HAVE_NEW_GUI - if(use_gui) guiGetEvent(guiIEvent,(char*)MP_CMD_GUI_FULLSCREEN); - else -#endif - if(vo_config_count) video_out->control(VOCTRL_FULLSCREEN, 0); - return M_PROPERTY_OK; - default: - return m_property_flag(prop,action,arg,&vo_fs); - } -} - -static int mp_property_deinterlace(m_option_t* prop,int action,void* arg) { - int deinterlace; - vf_instance_t *vf; - if (!sh_video || !sh_video->vfilter) return M_PROPERTY_UNAVAILABLE; - vf = sh_video->vfilter; - switch(action) { - case M_PROPERTY_GET: - if(!arg) return M_PROPERTY_ERROR; - vf->control(vf, VFCTRL_GET_DEINTERLACE, arg); - return M_PROPERTY_OK; - case M_PROPERTY_SET: - if(!arg) return M_PROPERTY_ERROR; - M_PROPERTY_CLAMP(prop,*(int*)arg); - vf->control(vf, VFCTRL_SET_DEINTERLACE, arg); - return M_PROPERTY_OK; - case M_PROPERTY_STEP_UP: - case M_PROPERTY_STEP_DOWN: - vf->control(vf, VFCTRL_GET_DEINTERLACE, &deinterlace); - deinterlace = !deinterlace; - vf->control(vf, VFCTRL_SET_DEINTERLACE, &deinterlace); - return M_PROPERTY_OK; - } - return M_PROPERTY_NOT_IMPLEMENTED; -} - -/// Panscan (RW) -static int mp_property_panscan(m_option_t* prop,int action,void* arg) { - - if(!video_out || video_out->control(VOCTRL_GET_PANSCAN,NULL ) != VO_TRUE) - return M_PROPERTY_UNAVAILABLE; - - switch(action) { - case M_PROPERTY_SET: - if(!arg) return M_PROPERTY_ERROR; - M_PROPERTY_CLAMP(prop,*(float*)arg); - vo_panscan = *(float*)arg; - video_out->control(VOCTRL_SET_PANSCAN,NULL); - return M_PROPERTY_OK; - case M_PROPERTY_STEP_UP: - case M_PROPERTY_STEP_DOWN: - vo_panscan += (arg ? *(float*)arg : 0.1) * - (action == M_PROPERTY_STEP_DOWN ? -1 : 1); - if(vo_panscan > 1) vo_panscan = 1; - else if(vo_panscan < 0) vo_panscan = 0; - video_out->control(VOCTRL_SET_PANSCAN,NULL); - return M_PROPERTY_OK; - default: - return m_property_float_range(prop,action,arg,&vo_panscan); - } -} - -/// Helper to set vo flags. -/** \ingroup PropertyImplHelper - */ -static int mp_property_vo_flag(m_option_t* prop,int action,void* arg, - int vo_ctrl,int* vo_var) { - - if(!video_out) return M_PROPERTY_UNAVAILABLE; - - switch(action) { - case M_PROPERTY_SET: - if(!arg) return M_PROPERTY_ERROR; - M_PROPERTY_CLAMP(prop,*(int*)arg); - if(*vo_var == !!*(int*)arg) return M_PROPERTY_OK; - case M_PROPERTY_STEP_UP: - case M_PROPERTY_STEP_DOWN: - if(vo_config_count) video_out->control(vo_ctrl, 0); - return M_PROPERTY_OK; - default: - return m_property_flag(prop,action,arg,vo_var); - } -} - -/// Window always on top (RW) -static int mp_property_ontop(m_option_t* prop,int action,void* arg) { - return mp_property_vo_flag(prop,action,arg,VOCTRL_ONTOP,&vo_ontop); -} - -/// Display in the root window (RW) -static int mp_property_rootwin(m_option_t* prop,int action,void* arg) { - return mp_property_vo_flag(prop,action,arg,VOCTRL_ROOTWIN,&vo_rootwin); -} - -/// Show window borders (RW) -static int mp_property_border(m_option_t* prop,int action,void* arg) { - return mp_property_vo_flag(prop,action,arg,VOCTRL_BORDER,&vo_border); -} - -/// Framedropping state (RW) -static int mp_property_framedropping(m_option_t* prop,int action,void* arg) { - - if(!sh_video) return M_PROPERTY_UNAVAILABLE; - - switch(action) { - case M_PROPERTY_PRINT: - if(!arg) return M_PROPERTY_ERROR; - *(char**)arg = strdup(frame_dropping == 1 ? MSGTR_Enabled : - (frame_dropping == 2 ? MSGTR_HardFrameDrop : MSGTR_Disabled)); - return M_PROPERTY_OK; - default: - return m_property_choice(prop,action,arg,&frame_dropping); - } -} - -/// Color settings, try to use vf/vo then fall back on TV. (RW) -static int mp_property_gamma(m_option_t* prop,int action,void* arg) { - int* gamma = prop->priv, r; - - if(!sh_video) return M_PROPERTY_UNAVAILABLE; - - if(gamma[0] == 1000) { - gamma[0] = 0; - get_video_colors (sh_video, prop->name, gamma); - } - - switch(action) { - case M_PROPERTY_SET: - if(!arg) return M_PROPERTY_ERROR; - M_PROPERTY_CLAMP(prop,*(int*)arg); - *gamma = *(int*)arg; - r = set_video_colors(sh_video, prop->name, *gamma); - if(r <= 0) break; - return r; - case M_PROPERTY_GET: - if(!arg) return M_PROPERTY_ERROR; - r = get_video_colors (sh_video, prop->name, arg); - if(r <= 0) break; - return r; - case M_PROPERTY_STEP_UP: - case M_PROPERTY_STEP_DOWN: - *gamma += (arg ? *(int*)arg : 1) * - (action == M_PROPERTY_STEP_DOWN ? -1 : 1); - M_PROPERTY_CLAMP(prop,*gamma); - r = set_video_colors(sh_video, prop->name, *gamma); - if(r <= 0) break; - return r; - default: - return M_PROPERTY_NOT_IMPLEMENTED; - } - -#ifdef USE_TV - if(demuxer->type == DEMUXER_TYPE_TV) { - int l = strlen(prop->name); - char tv_prop[3+l+1]; - sprintf(tv_prop,"tv_%s",prop->name); - return mp_property_do(tv_prop,action,arg); - } -#endif - - return M_PROPERTY_UNAVAILABLE; -} - -/// VSync (RW) -static int mp_property_vsync(m_option_t* prop,int action,void* arg) { - return m_property_flag(prop,action,arg,&vo_vsync); -} - -/// Video codec tag (RO) -static int mp_property_video_format(m_option_t* prop,int action,void* arg) { - if(!sh_video) return M_PROPERTY_UNAVAILABLE; - return m_property_int_ro(prop,action,arg,sh_video->format); -} - -/// Video bitrate (RO) -static int mp_property_video_bitrate(m_option_t* prop,int action,void* arg) { - if(!sh_video) return M_PROPERTY_UNAVAILABLE; - return m_property_int_ro(prop,action,arg,sh_video->i_bps); -} - -/// Video display width (RO) -static int mp_property_width(m_option_t* prop,int action,void* arg) { - if(!sh_video) return M_PROPERTY_UNAVAILABLE; - return m_property_int_ro(prop,action,arg,sh_video->disp_w); -} - -/// Video display height (RO) -static int mp_property_height(m_option_t* prop,int action,void* arg) { - if(!sh_video) return M_PROPERTY_UNAVAILABLE; - return m_property_int_ro(prop,action,arg,sh_video->disp_h); -} - -/// Video fps (RO) -static int mp_property_fps(m_option_t* prop,int action,void* arg) { - if(!sh_video) return M_PROPERTY_UNAVAILABLE; - return m_property_float_ro(prop,action,arg,sh_video->fps); -} - -/// Video aspect (RO) -static int mp_property_aspect(m_option_t* prop,int action,void* arg) { - if(!sh_video) return M_PROPERTY_UNAVAILABLE; - return m_property_float_ro(prop,action,arg,sh_video->aspect); -} - -///@} - -/// \defgroup SubProprties Subtitles properties -/// \ingroup Properties -///@{ - -/// Text subtitle position (RW) -static int mp_property_sub_pos(m_option_t* prop,int action,void* arg) { - if(!sh_video) return M_PROPERTY_UNAVAILABLE; - - switch(action) { - case M_PROPERTY_SET: - if(!arg) return M_PROPERTY_ERROR; - case M_PROPERTY_STEP_UP: - case M_PROPERTY_STEP_DOWN: - vo_osd_changed(OSDTYPE_SUBTITLE); - default: - return m_property_int_range(prop,action,arg,&sub_pos); - } -} - -/// Selected subtitles (RW) -static int mp_property_sub(m_option_t* prop,int action,void* arg) { - int source = -1, reset_spu = 0; - char* sub_name; - - if(global_sub_size <= 0) return M_PROPERTY_UNAVAILABLE; - - switch(action) { - case M_PROPERTY_GET: - if(!arg) return M_PROPERTY_ERROR; - *(int*)arg = global_sub_pos; - return M_PROPERTY_OK; - case M_PROPERTY_PRINT: - if(!arg) return M_PROPERTY_ERROR; - *(char**)arg = malloc(64); - (*(char**)arg)[63] = 0; - sub_name = 0; - if(subdata) - sub_name = subdata->filename; -#ifdef USE_ASS - if (ass_track && ass_track->name) - sub_name = ass_track->name; -#endif - if(sub_name) { - char *tmp,*tmp2; - tmp = sub_name; - if ((tmp2 = strrchr(tmp, '/'))) - tmp = tmp2+1; - - snprintf(*(char**)arg, 63, "(%d) %s%s", - set_of_sub_pos + 1, - strlen(tmp) < 20 ? "" : "...", - strlen(tmp) < 20 ? tmp : tmp+strlen(tmp)-19); - return M_PROPERTY_OK; - } - -#ifdef USE_DVDNAV - if(stream->type==STREAMTYPE_DVDNAV) { - if(vo_spudec && dvdsub_id >= 0) { - unsigned char lang[3]; - if(dvdnav_lang_from_sid(stream, dvdsub_id, lang)) { - snprintf(*(char**)arg, 63, "(%d) %s", dvdsub_id, lang); - return M_PROPERTY_OK; - } - } - } -#endif - - if (demuxer->type == DEMUXER_TYPE_MATROSKA && dvdsub_id >= 0) { - char lang[40] = MSGTR_Unknown; - demux_mkv_get_sub_lang(demuxer, dvdsub_id, lang, 9); - snprintf(*(char**)arg, 63, "(%d) %s", dvdsub_id, lang); - return M_PROPERTY_OK; - } -#ifdef HAVE_OGGVORBIS - if (demuxer->type == DEMUXER_TYPE_OGG && d_dvdsub && dvdsub_id >= 0) { - char *lang = demux_ogg_sub_lang(demuxer, dvdsub_id); - if (!lang) lang = MSGTR_Unknown; - snprintf(*(char**)arg, 63, "(%d) %s", - dvdsub_id, lang); - return M_PROPERTY_OK; - } -#endif - if (vo_vobsub && vobsub_id >= 0) { - const char *language = MSGTR_Unknown; - language = vobsub_get_id(vo_vobsub, (unsigned int) vobsub_id); - snprintf(*(char**)arg, 63, "(%d) %s", - vobsub_id, language ? language : MSGTR_Unknown); - return M_PROPERTY_OK; - } -#ifdef USE_DVDREAD - if (vo_spudec && stream->type == STREAMTYPE_DVD && dvdsub_id >= 0) { - char lang[3]; - int code = dvd_lang_from_sid(stream, dvdsub_id); - lang[0] = code >> 8; - lang[1] = code; - lang[2] = 0; - snprintf(*(char**)arg, 63, "(%d) %s", - dvdsub_id, lang); - return M_PROPERTY_OK; - } -#endif - if (dvdsub_id >= 0) { - snprintf(*(char**)arg, 63, "(%d) %s", dvdsub_id, MSGTR_Unknown); - return M_PROPERTY_OK; - } - snprintf(*(char**)arg, 63, MSGTR_Disabled); - return M_PROPERTY_OK; - - case M_PROPERTY_SET: - if(!arg) return M_PROPERTY_ERROR; - if(*(int*)arg < -1) *(int*)arg = -1; - else if(*(int*)arg >= global_sub_size) *(int*)arg = global_sub_size-1; - global_sub_pos = *(int*)arg; - break; - case M_PROPERTY_STEP_UP: - global_sub_pos += 2; - global_sub_pos = (global_sub_pos % (global_sub_size+1)) - 1; - break; - case M_PROPERTY_STEP_DOWN: - global_sub_pos += global_sub_size+1; - global_sub_pos = (global_sub_pos % (global_sub_size+1)) - 1; - break; - default: - return M_PROPERTY_NOT_IMPLEMENTED; - } - - if (global_sub_pos >= 0) - source = sub_source(); - - mp_msg(MSGT_CPLAYER, MSGL_DBG3, - "subtitles: %d subs, (v@%d s@%d d@%d), @%d, source @%d\n", - global_sub_size, global_sub_indices[SUB_SOURCE_VOBSUB], - global_sub_indices[SUB_SOURCE_SUBS], - global_sub_indices[SUB_SOURCE_DEMUX], - global_sub_pos, source); - - set_of_sub_pos = -1; - subdata = NULL; - vo_sub_last = vo_sub = NULL; - - vobsub_id = -1; - dvdsub_id = -1; - if (d_dvdsub) { - if(d_dvdsub->id > -2) reset_spu = 1; - d_dvdsub->id = -2; - } -#ifdef USE_ASS - ass_track = 0; -#endif - - if (source == SUB_SOURCE_VOBSUB) { - vobsub_id = global_sub_pos - global_sub_indices[SUB_SOURCE_VOBSUB]; - } else if (source == SUB_SOURCE_SUBS) { - set_of_sub_pos = global_sub_pos - global_sub_indices[SUB_SOURCE_SUBS]; -#ifdef USE_ASS - if (ass_enabled && set_of_ass_tracks[set_of_sub_pos]) - ass_track = set_of_ass_tracks[set_of_sub_pos]; - else -#endif - { - subdata = set_of_subtitles[set_of_sub_pos]; - vo_osd_changed(OSDTYPE_SUBTITLE); - } - } else if (source == SUB_SOURCE_DEMUX) { - dvdsub_id = global_sub_pos - global_sub_indices[SUB_SOURCE_DEMUX]; - if (d_dvdsub) { -#ifdef USE_DVDREAD - if (vo_spudec && stream->type == STREAMTYPE_DVD) { - d_dvdsub->id = dvdsub_id; - } -#endif -#ifdef USE_DVDNAV - if (vo_spudec && stream->type == STREAMTYPE_DVDNAV) { - d_dvdsub->id = dvdsub_id; - } -#endif - if (stream->type != STREAMTYPE_DVD && stream->type != STREAMTYPE_DVDNAV) { - int i = 0; - for (d_dvdsub->id = 0; d_dvdsub->id < MAX_S_STREAMS; d_dvdsub->id++) { - if (demuxer->s_streams[d_dvdsub->id]) { - if (i == dvdsub_id) break; - i++; - } - } - d_dvdsub->sh = demuxer->s_streams[d_dvdsub->id]; - } - if (demuxer->type == DEMUXER_TYPE_MATROSKA) { - d_dvdsub->id = demux_mkv_change_subs(demuxer, dvdsub_id); - } - if (d_dvdsub->sh && d_dvdsub->id >= 0) { - sh_sub_t *sh = d_dvdsub->sh; - if (sh->type == 'v') - init_vo_spudec(); -#ifdef USE_ASS - else if (ass_enabled && sh->type == 'a') - ass_track = sh->ass_track; -#endif - } - } - } -#ifdef USE_DVDREAD - if (vo_spudec && (stream->type == STREAMTYPE_DVD || stream->type == STREAMTYPE_DVDNAV) && dvdsub_id < 0 && reset_spu) { - dvdsub_id = -2; - d_dvdsub->id = dvdsub_id; - } -#endif - update_subtitles(sh_video, d_dvdsub, 1); - - return M_PROPERTY_OK; -} - -/// Subtitle delay (RW) -static int mp_property_sub_delay(m_option_t* prop,int action,void* arg) { - if(!sh_video) return M_PROPERTY_UNAVAILABLE; - return m_property_delay(prop,action,arg,&sub_delay); -} - -/// Alignment of text subtitles (RW) -static int mp_property_sub_alignment(m_option_t* prop,int action,void* arg) { - char* name[] = { MSGTR_Top, MSGTR_Center, MSGTR_Bottom }; - - if(!sh_video || global_sub_pos < 0 || sub_source() != SUB_SOURCE_SUBS) - return M_PROPERTY_UNAVAILABLE; - - switch(action) { - case M_PROPERTY_PRINT: - if(!arg) return M_PROPERTY_ERROR; - M_PROPERTY_CLAMP(prop,sub_alignment); - *(char**)arg = strdup(name[sub_alignment]); - return M_PROPERTY_OK; - case M_PROPERTY_SET: - if(!arg) return M_PROPERTY_ERROR; - case M_PROPERTY_STEP_UP: - case M_PROPERTY_STEP_DOWN: - vo_osd_changed(OSDTYPE_SUBTITLE); - default: - return m_property_choice(prop,action,arg,&sub_alignment); - } -} - -/// Subtitle visibility (RW) -static int mp_property_sub_visibility(m_option_t* prop,int action,void* arg) { - if(!sh_video) return M_PROPERTY_UNAVAILABLE; - - switch(action) { - case M_PROPERTY_SET: - if(!arg) return M_PROPERTY_ERROR; - case M_PROPERTY_STEP_UP: - case M_PROPERTY_STEP_DOWN: - vo_osd_changed(OSDTYPE_SUBTITLE); - if(vo_spudec) vo_osd_changed(OSDTYPE_SPU); - default: - return m_property_flag(prop,action,arg,&sub_visibility); - } -} - -/// Show only forced subtitles (RW) -static int mp_property_sub_forced_only(m_option_t* prop,int action,void* arg) { - if(!vo_spudec) return M_PROPERTY_UNAVAILABLE; - - switch(action) { - case M_PROPERTY_SET: - if(!arg) return M_PROPERTY_ERROR; - case M_PROPERTY_STEP_UP: - case M_PROPERTY_STEP_DOWN: - m_property_flag(prop,action,arg,&forced_subs_only); - spudec_set_forced_subs_only(vo_spudec,forced_subs_only); - return M_PROPERTY_OK; - default: - return m_property_flag(prop,action,arg,&forced_subs_only); - } - -} - -///@} - -/// \defgroup TVProperties TV properties -/// \ingroup Properties -///@{ - -#ifdef USE_TV - -/// TV color settings (RW) -static int mp_property_tv_color(m_option_t* prop,int action,void* arg) { - int r,val; - tvi_handle_t* tvh = demuxer->priv; - if(demuxer->type != DEMUXER_TYPE_TV || !tvh) return M_PROPERTY_UNAVAILABLE; - - switch(action) { - case M_PROPERTY_SET: - if(!arg) return M_PROPERTY_ERROR; - M_PROPERTY_CLAMP(prop,*(int*)arg); - return tv_set_color_options(tvh,(int)prop->priv,*(int*)arg); - case M_PROPERTY_GET: - return tv_get_color_options(tvh,(int)prop->priv,arg); - case M_PROPERTY_STEP_UP: - case M_PROPERTY_STEP_DOWN: - if((r = tv_get_color_options(tvh,(int)prop->priv,&val)) >= 0) { - if(!r) return M_PROPERTY_ERROR; - val += (arg ? *(int*)arg : 1) * - (action == M_PROPERTY_STEP_DOWN ? -1 : 1); - M_PROPERTY_CLAMP(prop,val); - return tv_set_color_options(tvh,(int)prop->priv,val); - } - return M_PROPERTY_ERROR; - } - return M_PROPERTY_NOT_IMPLEMENTED; -} - -#endif - -///@} - -/// All properties available in MPlayer. -/** \ingroup Properties - */ -static m_option_t mp_properties[] = { - // General - { "osdlevel", mp_property_osdlevel, CONF_TYPE_INT, - M_OPT_RANGE, 0, 3, NULL }, - { "speed", mp_property_playback_speed, CONF_TYPE_FLOAT, - M_OPT_RANGE, 0.01, 100.0, NULL }, - { "filename", mp_property_filename, CONF_TYPE_STRING, - 0, 0, 0, NULL }, - { "path", mp_property_path, CONF_TYPE_STRING, - 0, 0, 0, NULL }, - { "demuxer", mp_property_demuxer, CONF_TYPE_STRING, - 0, 0, 0, NULL }, - { "stream_pos", mp_property_stream_pos, CONF_TYPE_POSITION, - M_OPT_MIN, 0, 0, NULL }, - { "stream_start", mp_property_stream_start, CONF_TYPE_POSITION, - M_OPT_MIN, 0, 0, NULL }, - { "stream_end", mp_property_stream_end, CONF_TYPE_POSITION, - M_OPT_MIN, 0, 0, NULL }, - { "stream_length", mp_property_stream_length, CONF_TYPE_POSITION, - M_OPT_MIN, 0, 0, NULL }, - { "length", mp_property_length, CONF_TYPE_DOUBLE, - 0, 0, 0, NULL }, - - // Audio - { "volume", mp_property_volume, CONF_TYPE_FLOAT, - M_OPT_RANGE, 0, 100, NULL }, - { "mute", mp_property_mute, CONF_TYPE_FLAG, - M_OPT_RANGE, 0, 1, NULL }, - { "audio_delay", mp_property_audio_delay, CONF_TYPE_FLOAT, - M_OPT_RANGE, -100, 100, NULL }, - { "audio_format", mp_property_audio_format, CONF_TYPE_INT, - 0, 0, 0, NULL }, - { "audio_bitrate", mp_property_audio_bitrate, CONF_TYPE_INT, - 0, 0, 0, NULL }, - { "samplerate", mp_property_samplerate, CONF_TYPE_INT, - 0, 0, 0, NULL }, - { "channels", mp_property_channels, CONF_TYPE_INT, - 0, 0, 0, NULL }, - { "switch_audio", mp_property_audio, CONF_TYPE_INT, - CONF_RANGE, -2, MAX_A_STREAMS-1, NULL }, - - // Video - { "fullscreen", mp_property_fullscreen, CONF_TYPE_FLAG, - M_OPT_RANGE, 0, 1, NULL }, - { "deinterlace", mp_property_deinterlace, CONF_TYPE_FLAG, - M_OPT_RANGE, 0, 1, NULL }, - { "ontop", mp_property_ontop, CONF_TYPE_FLAG, - M_OPT_RANGE, 0, 1, NULL }, - { "rootwin", mp_property_rootwin, CONF_TYPE_FLAG, - M_OPT_RANGE, 0, 1, NULL }, - { "border", mp_property_border, CONF_TYPE_FLAG, - M_OPT_RANGE, 0, 1, NULL }, - { "framedropping", mp_property_framedropping, CONF_TYPE_INT, - M_OPT_RANGE, 0, 2, NULL }, - { "gamma", mp_property_gamma, CONF_TYPE_INT, - M_OPT_RANGE, -100, 100, &vo_gamma_gamma }, - { "brightness", mp_property_gamma, CONF_TYPE_INT, - M_OPT_RANGE, -100, 100, &vo_gamma_brightness }, - { "contrast", mp_property_gamma, CONF_TYPE_INT, - M_OPT_RANGE, -100, 100, &vo_gamma_contrast }, - { "saturation", mp_property_gamma, CONF_TYPE_INT, - M_OPT_RANGE, -100, 100, &vo_gamma_saturation }, - { "hue", mp_property_gamma, CONF_TYPE_INT, - M_OPT_RANGE, -100, 100, &vo_gamma_hue }, - { "panscan", mp_property_panscan, CONF_TYPE_FLOAT, - M_OPT_RANGE, 0, 1, NULL }, - { "vsync", mp_property_vsync, CONF_TYPE_FLAG, - M_OPT_RANGE, 0, 1, NULL }, - { "video_format", mp_property_video_format, CONF_TYPE_INT, - 0, 0, 0, NULL }, - { "video_bitrate", mp_property_video_bitrate, CONF_TYPE_INT, - 0, 0, 0, NULL }, - { "width", mp_property_width, CONF_TYPE_INT, - 0, 0, 0, NULL }, - { "height", mp_property_height, CONF_TYPE_INT, - 0, 0, 0, NULL }, - { "fps", mp_property_fps, CONF_TYPE_FLOAT, - 0, 0, 0, NULL }, - { "aspect", mp_property_aspect, CONF_TYPE_FLOAT, - 0, 0, 0, NULL }, - { "switch_video", mp_property_video, CONF_TYPE_INT, - CONF_RANGE, -2, MAX_V_STREAMS-1, NULL }, - { "switch_program", mp_property_program, CONF_TYPE_INT, - CONF_RANGE, -1, 65535, NULL }, - - // Subs - { "sub", mp_property_sub, CONF_TYPE_INT, - M_OPT_MIN, -1, 0, NULL }, - { "sub_delay", mp_property_sub_delay, CONF_TYPE_FLOAT, - 0, 0, 0, NULL }, - { "sub_pos", mp_property_sub_pos, CONF_TYPE_INT, - M_OPT_RANGE, 0, 100, NULL }, - { "sub_alignment", mp_property_sub_alignment, CONF_TYPE_INT, - M_OPT_RANGE, 0, 2, NULL }, - { "sub_visibility", mp_property_sub_visibility, CONF_TYPE_FLAG, - M_OPT_RANGE, 0, 1, NULL }, - { "sub_forced_only", mp_property_sub_forced_only, CONF_TYPE_FLAG, - M_OPT_RANGE, 0, 1, NULL }, - -#ifdef USE_TV - { "tv_brightness", mp_property_tv_color, CONF_TYPE_INT, - M_OPT_RANGE, -100, 100, (void*)TV_COLOR_BRIGHTNESS }, - { "tv_contrast", mp_property_tv_color, CONF_TYPE_INT, - M_OPT_RANGE, -100, 100, (void*)TV_COLOR_CONTRAST }, - { "tv_saturation", mp_property_tv_color, CONF_TYPE_INT, - M_OPT_RANGE, -100, 100, (void*)TV_COLOR_SATURATION }, - { "tv_hue", mp_property_tv_color, CONF_TYPE_INT, - M_OPT_RANGE, -100, 100, (void*)TV_COLOR_HUE }, -#endif - - { NULL, NULL, NULL, 0, 0, 0, NULL } -}; - -m_option_t* mp_property_find(const char* name) { - return m_option_list_find(mp_properties,name); -} - -int mp_property_do(const char* name,int action, void* val) { - m_option_t* p = mp_property_find(name); - if(!p) return M_PROPERTY_UNAVAILABLE; - return m_property_do(p,action,val); -} - -///@} -// Properties group - - -/** - * \defgroup Command2Property Command to property bridge - * - * It is used to handle most commands that just set a property - * and optionally display something on the OSD. - * Two kinds of commands are handled: adjust or toggle. - * - * Adjust commands take 1 or 2 parameters: <value> <abs> - * If <abs> is non-zero the property is set to the given value - * otherwise it is adjusted. - * - * Toggle commands take 0 or 1 parameters. With no parameter - * or a value less than the property minimum it just steps the - * property to its next value. Otherwise it sets it to the given - * value. - * - *@{ - */ - -/// List of the commands that can be handled by setting a property. -static struct { - /// property name - const char* name; - /// cmd id - int cmd; - /// set/adjust or toggle command - int toggle; - /// progressbar type - int osd_progbar; - /// osd msg id if it must be shared - int osd_id; - /// osd msg template - const char* osd_msg; -} set_prop_cmd[] = { - // audio - { "volume", MP_CMD_VOLUME, 0, OSD_VOLUME, -1, MSGTR_Volume }, - { "mute", MP_CMD_MUTE, 1, 0, -1, MSGTR_MuteStatus }, - { "audio_delay", MP_CMD_AUDIO_DELAY, 0, 0, -1, MSGTR_AVDelayStatus }, - { "switch_audio", MP_CMD_SWITCH_AUDIO, 1, 0, -1, MSGTR_OSDAudio }, - // video - { "fullscreen", MP_CMD_VO_FULLSCREEN, 1, 0, -1, NULL }, - { "panscan", MP_CMD_PANSCAN, 0, OSD_PANSCAN, -1, MSGTR_Panscan }, - { "ontop", MP_CMD_VO_ONTOP, 1, 0, -1, MSGTR_OnTopStatus }, - { "rootwin", MP_CMD_VO_ROOTWIN, 1, 0, -1, MSGTR_RootwinStatus }, - { "border", MP_CMD_VO_BORDER, 1, 0, -1, MSGTR_BorderStatus }, - { "framedropping", MP_CMD_FRAMEDROPPING, 1, 0, -1, MSGTR_FramedroppingStatus }, - { "gamma", MP_CMD_GAMMA, 0, OSD_BRIGHTNESS, -1, MSGTR_Gamma }, - { "brightness", MP_CMD_BRIGHTNESS, 0, OSD_BRIGHTNESS, -1, MSGTR_Brightness }, - { "contrast", MP_CMD_CONTRAST, 0, OSD_CONTRAST, -1, MSGTR_Contrast }, - { "saturation", MP_CMD_SATURATION, 0, OSD_SATURATION, -1, MSGTR_Saturation }, - { "hue", MP_CMD_HUE, 0, OSD_HUE, -1, MSGTR_Hue }, - { "vsync", MP_CMD_SWITCH_VSYNC, 1, 0, -1, MSGTR_VSyncStatus }, - // subs - { "sub", MP_CMD_SUB_SELECT, 1, 0, -1, MSGTR_SubSelectStatus }, - { "sub_pos", MP_CMD_SUB_POS, 0, 0, -1, MSGTR_SubPosStatus }, - { "sub_alignment", MP_CMD_SUB_ALIGNMENT, 1, 0, -1, MSGTR_SubAlignStatus }, - { "sub_delay", MP_CMD_SUB_DELAY, 0, 0, OSD_MSG_SUB_DELAY, MSGTR_SubDelayStatus }, - { "sub_visibility", MP_CMD_SUB_VISIBILITY, 1, 0, -1, MSGTR_SubVisibleStatus }, - { "sub_forced_only", MP_CMD_SUB_FORCED_ONLY, 1, 0, -1, MSGTR_SubForcedOnlyStatus }, -#ifdef USE_TV - { "tv_brightness", MP_CMD_TV_SET_BRIGHTNESS, 0, OSD_BRIGHTNESS, -1, MSGTR_Brightness }, - { "tv_hue", MP_CMD_TV_SET_HUE, 0, OSD_HUE, -1, MSGTR_Hue }, - { "tv_saturation", MP_CMD_TV_SET_SATURATION, 0, OSD_SATURATION, -1, MSGTR_Saturation }, - { "tv_contrast", MP_CMD_TV_SET_CONTRAST, 0, OSD_CONTRAST, -1, MSGTR_Contrast }, -#endif - { NULL, 0, 0, 0, -1, NULL } -}; - -/// Handle commands that set a property. -static int set_property_command(mp_cmd_t* cmd) { - int i,r; - m_option_t* prop; - - // look for the command - for(i = 0 ; set_prop_cmd[i].name ; i++) - if(set_prop_cmd[i].cmd == cmd->id) break; - if(!set_prop_cmd[i].name) return 0; - - // get the property - prop = mp_property_find(set_prop_cmd[i].name); - if(!prop) return 0; - - // toggle command - if(set_prop_cmd[i].toggle) { - // set to value - if(cmd->nargs > 0 && cmd->args[0].v.i >= prop->min) - r = m_property_do(prop,M_PROPERTY_SET,&cmd->args[0].v.i); - else - r = m_property_do(prop,M_PROPERTY_STEP_UP,NULL); - } else if(cmd->args[1].v.i) //set - r = m_property_do(prop,M_PROPERTY_SET,&cmd->args[0].v); - else // adjust - r = m_property_do(prop,M_PROPERTY_STEP_UP,&cmd->args[0].v); - - if(r <= 0) return 1; - - if(set_prop_cmd[i].osd_progbar) { - if(prop->type == CONF_TYPE_INT) { - if(m_property_do(prop,M_PROPERTY_GET,&r) > 0) - set_osd_bar(set_prop_cmd[i].osd_progbar, - set_prop_cmd[i].osd_msg, - prop->min,prop->max,r); - } else if(prop->type == CONF_TYPE_FLOAT) { - float f; - if(m_property_do(prop,M_PROPERTY_GET,&f) > 0) - set_osd_bar(set_prop_cmd[i].osd_progbar,set_prop_cmd[i].osd_msg, - prop->min,prop->max,f); - } else - mp_msg(MSGT_CPLAYER,MSGL_ERR, "Property use an unsupported type.\n"); - return 1; - } - - if(set_prop_cmd[i].osd_msg) { - char* val = m_property_print(prop); - if(val) { - set_osd_msg(set_prop_cmd[i].osd_id >= 0 ? set_prop_cmd[i].osd_id : - OSD_MSG_PROPERTY+i,1,osd_duration, - set_prop_cmd[i].osd_msg,val); - free(val); - } - } - return 1; -} - -static void reinit_audio_chain(void) { -if(sh_audio){ +void reinit_audio_chain(void) { +if(mpctx->sh_audio){ current_module="init_audio_codec"; mp_msg(MSGT_CPLAYER,MSGL_INFO,"==========================================================================\n"); - if(!init_best_audio_codec(sh_audio,audio_codec_list,audio_fm_list)){ - sh_audio=d_audio->sh=NULL; // failed to init :( - d_audio->id = -2; + if(!init_best_audio_codec(mpctx->sh_audio,audio_codec_list,audio_fm_list)){ + mpctx->sh_audio=mpctx->d_audio->sh=NULL; // failed to init :( + mpctx->d_audio->id = -2; return; } else inited_flags|=INITED_ACODEC; @@ -2778,10 +1458,10 @@ ao_data.format=audio_output_format; #if 1 // first init to detect best values - if(!preinit_audio_filters(sh_audio, + if(!preinit_audio_filters(mpctx->sh_audio, // input: - (int)(sh_audio->samplerate*playback_speed), - sh_audio->channels, sh_audio->sample_format, + (int)(mpctx->sh_audio->samplerate*playback_speed), + mpctx->sh_audio->channels, mpctx->sh_audio->sample_format, // output: &ao_data.samplerate, &ao_data.channels, &ao_data.format)){ mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_AudioFilterChainPreinitError); @@ -2789,7 +1469,7 @@ } #endif current_module="ao2_init"; - if(!(audio_out=init_best_audio_out(audio_driver_list, + if(!(mpctx->audio_out=init_best_audio_out(audio_driver_list, 0, // plugin flag ao_data.samplerate, ao_data.channels, @@ -2797,34 +1477,34 @@ // FAILED: mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_CannotInitAO); uninit_player(INITED_ACODEC); // close codec - sh_audio=d_audio->sh=NULL; // -> nosound - d_audio->id = -2; + mpctx->sh_audio=mpctx->d_audio->sh=NULL; // -> nosound + mpctx->d_audio->id = -2; return; } else { // SUCCESS: inited_flags|=INITED_AO; mp_msg(MSGT_CPLAYER,MSGL_INFO,"AO: [%s] %dHz %dch %s (%d bytes per sample)\n", - audio_out->info->short_name, + mpctx->audio_out->info->short_name, ao_data.samplerate, ao_data.channels, af_fmt2str_short(ao_data.format), af_fmt2bits(ao_data.format)/8 ); mp_msg(MSGT_CPLAYER,MSGL_V,"AO: Description: %s\nAO: Author: %s\n", - audio_out->info->name, audio_out->info->author); - if(strlen(audio_out->info->comment) > 0) - mp_msg(MSGT_CPLAYER,MSGL_V,"AO: Comment: %s\n", audio_out->info->comment); + mpctx->audio_out->info->name, mpctx->audio_out->info->author); + if(strlen(mpctx->audio_out->info->comment) > 0) + mp_msg(MSGT_CPLAYER,MSGL_V,"AO: Comment: %s\n", mpctx->audio_out->info->comment); // init audio filters: #if 1 current_module="af_init"; - if(!build_afilter_chain(sh_audio, &ao_data)) { + if(!build_afilter_chain(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(INITED_ACODEC|INITED_AO); // close codec & ao -// sh_audio=d_audio->sh=NULL; // -> nosound +// sh_audio=mpctx->d_audio->sh=NULL; // -> nosound } #endif } - mixer.audio_out = audio_out; - mixer.volstep = volstep; + mpctx->mixer.audio_out = mpctx->audio_out; + mpctx->mixer.volstep = volstep; } } @@ -2877,7 +1557,7 @@ } // Return pts value corresponding to currently playing audio. -static double playing_audio_pts(sh_audio_t *sh_audio, demux_stream_t *d_audio, +double playing_audio_pts(sh_audio_t *sh_audio, demux_stream_t *d_audio, ao_functions_t *audio_out) { return written_audio_pts(sh_audio, d_audio) - playback_speed * @@ -2913,7 +1593,7 @@ current_module = "decode video"; decoded_frame = decode_video(sh_video, start, in_size, 0, pts); if (decoded_frame) { - update_subtitles(sh_video, d_dvdsub, 0); + update_subtitles(sh_video, mpctx->d_sub, 0); update_osd_msg(); current_module = "filter video"; if (filter_video(sh_video, decoded_frame, sh_video->pts)) @@ -2925,25 +1605,6 @@ return 1; } -static void rescale_input_coordinates(int ix, int iy, double *dx, double *dy) { - //remove the borders, if any, and rescale to the range [0,1],[0,1] - if(vo_fs) { //we are in full-screen mode - if(vo_screenwidth > vo_dwidth) //there are borders along the x axis - ix -= (vo_screenwidth - vo_dwidth) / 2; - if(vo_screenheight > vo_dheight) //there are borders along the y axis (usual way) - iy -= (vo_screenheight - vo_dheight) / 2; - - if(ix < 0 || ix > vo_dwidth) {*dx = *dy = -1.0; return; } //we are on one of the borders - if(iy < 0 || iy > vo_dheight) {*dx = *dy = -1.0; return; } //we are on one of the borders - } - - *dx = (double) ix / (double) vo_dwidth; - *dy = (double) iy / (double) vo_dheight; - - mp_msg(MSGT_CPLAYER,MSGL_V, "\r\nrescaled coordinates: %.3lf, %.3lf, screen (%d x %d), vodisplay: (%d, %d), fullscreen: %d\r\n", - *dx, *dy, vo_screenwidth, vo_screenheight, vo_dwidth, vo_dheight, vo_fs); -} - #ifdef HAVE_RTC int rtc_fd = -1; #endif @@ -2996,7 +1657,7 @@ { current_module="av_sync"; - if(sh_audio){ + if(mpctx->sh_audio){ double a_pts, v_pts; if (autosync) @@ -3011,11 +1672,11 @@ * value here, even a "corrected" one, would be incompatible with * autosync mode.) */ - a_pts = written_audio_pts(sh_audio, d_audio) - sh_audio->delay; + a_pts = written_audio_pts(mpctx->sh_audio, mpctx->d_audio) - mpctx->sh_audio->delay; else - a_pts = playing_audio_pts(sh_audio, d_audio, audio_out); + a_pts = playing_audio_pts(mpctx->sh_audio, mpctx->d_audio, mpctx->audio_out); - v_pts = sh_video->pts; + v_pts = mpctx->sh_video->pts; { static int drop_message=0; @@ -3039,9 +1700,9 @@ if (default_max_pts_correction >= 0) max_pts_correction = default_max_pts_correction; else - max_pts_correction = sh_video->frametime*0.10; // +-10% of time + max_pts_correction = mpctx->sh_video->frametime*0.10; // +-10% of time if (!between_frames) { - sh_audio->delay+=x; + mpctx->sh_audio->delay+=x; c_total+=x; } if(!quiet) @@ -3064,6 +1725,7 @@ int playflags=0; int audio_eof=0; int bytes_to_write; + sh_audio_t * const sh_audio = mpctx->sh_audio; current_module="play_audio"; @@ -3071,9 +1733,9 @@ // all the current uses of ao_data.pts seem to be in aos that handle // sync completely wrong; there should be no need to use ao_data.pts // in get_space() - ao_data.pts = ((sh_video?sh_video->timer:0)+sh_audio->delay)*90000.0; - bytes_to_write = audio_out->get_space(); - if (sh_video || bytes_to_write >= ao_data.outburst) + ao_data.pts = ((mpctx->sh_video?mpctx->sh_video->timer:0)+sh_audio->delay)*90000.0; + bytes_to_write = mpctx->audio_out->get_space(); + if (mpctx->sh_video || bytes_to_write >= ao_data.outburst) break; // handle audio-only case: @@ -3098,7 +1760,7 @@ sh_audio->a_out_buffer_size - buflen // max ); if (ret <= 0) { // EOF? - if (d_audio->eof) { + if (mpctx->d_audio->eof) { audio_eof = 1; if (sh_audio->a_out_buffer_len == 0) return 0; @@ -3123,8 +1785,8 @@ // Is this pts value actually useful for the aos that access it? // They're obviously badly broken in the way they handle av sync; // would not having access to this make them more broken? - ao_data.pts = ((sh_video?sh_video->timer:0)+sh_audio->delay)*90000.0; - playsize = audio_out->play(sh_audio->a_out_buffer, playsize, playflags); + ao_data.pts = ((mpctx->sh_video?mpctx->sh_video->timer:0)+sh_audio->delay)*90000.0; + playsize = mpctx->audio_out->play(sh_audio->a_out_buffer, playsize, playflags); if (playsize > 0) { sh_audio->a_out_buffer_len -= playsize; @@ -3132,7 +1794,7 @@ sh_audio->a_out_buffer_len); sh_audio->delay += playback_speed*playsize/(double)ao_data.bps; } - else if (audio_eof && audio_out->get_delay() < .04) { + else if (audio_eof && mpctx->audio_out->get_delay() < .04) { // Sanity check to avoid hanging in case current ao doesn't output // partial chunks and doesn't check for AOPLAY_FINAL_CHUNK mp_msg(MSGT_CPLAYER, MSGL_WARN, "Audio output truncated at end.\n"); @@ -3149,8 +1811,8 @@ *time_frame -= GetRelativeTime(); // reset timer - if (sh_audio && !d_audio->eof) { - float delay = audio_out->get_delay(); + if (mpctx->sh_audio && !mpctx->d_audio->eof) { + float delay = mpctx->audio_out->get_delay(); mp_dbg(MSGT_AVSYNC, MSGL_DBG2, "delay=%f\n", delay); if (autosync) { @@ -3163,12 +1825,12 @@ * sync to settle at the right value (but it eventually will.) * This settling time is very short for values below 100. */ - float predicted = sh_audio->delay / playback_speed + *time_frame; + float predicted = mpctx->sh_audio->delay / playback_speed + *time_frame; float difference = delay - predicted; delay = predicted + difference / (float)autosync; } - *time_frame = delay - sh_audio->delay / playback_speed; + *time_frame = delay - mpctx->sh_audio->delay / playback_speed; // delay = amount of audio buffered in soundcard/driver if (delay > 0.25) delay=0.25; else @@ -3198,25 +1860,26 @@ return frame_time_remaining; } -static int reinit_video_chain(void) { +int reinit_video_chain(void) { + sh_video_t * const sh_video = mpctx->sh_video; //================== Init VIDEO (codec & libvo) ========================== if(!fixed_vo || !(inited_flags&INITED_VO)){ current_module="preinit_libvo"; //shouldn't we set dvideo->id=-2 when we fail? vo_config_count=0; - //if((video_out->preinit(vo_subdevice))!=0){ - if(!(video_out=init_best_video_out(video_driver_list))){ + //if((mpctx->video_out->preinit(vo_subdevice))!=0){ + if(!(mpctx->video_out=init_best_video_out(video_driver_list))){ mp_msg(MSGT_CPLAYER,MSGL_FATAL,MSGTR_ErrorInitializingVODevice); goto err_out; } - sh_video->video_out=video_out; + sh_video->video_out=mpctx->video_out; inited_flags|=INITED_VO; } current_module="init_video_filters"; { - char* vf_arg[] = { "_oldargs_", (char*)video_out , NULL }; + char* vf_arg[] = { "_oldargs_", (char*)mpctx->video_out , NULL }; sh_video->vfilter=(void*)vf_open_filter(NULL,"vo",vf_arg); } #ifdef HAVE_MENU @@ -3298,12 +1961,13 @@ return 1; err_out: - sh_video = d_video->sh = NULL; + mpctx->sh_video = mpctx->d_video->sh = NULL; return 0; } static double update_video(int *blit_frame) { + 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 @@ -3322,20 +1986,20 @@ if (in_size > max_framesize) max_framesize = in_size; // stats sh_video->timer += frame_time; - if (sh_audio) - sh_audio->delay -= frame_time; + if (mpctx->sh_audio) + mpctx->sh_audio->delay -= frame_time; // video_read_frame can change fps (e.g. for ASF video) vo_fps = sh_video->fps; // check for frame-drop: current_module = "check_framedrop"; - if (sh_audio && !d_audio->eof) { + if (mpctx->sh_audio && !mpctx->d_audio->eof) { static int dropped_frames; - float delay = playback_speed*audio_out->get_delay(); - float d = delay-sh_audio->delay; + float delay = playback_speed*mpctx->audio_out->get_delay(); + float d = delay-mpctx->sh_audio->delay; // we should avoid dropping too many frames in sequence unless we // are too late. and we allow 100ms A-V delay here: if (d < -dropped_frames*frame_time-0.100 && - osd_function != OSD_PAUSE) { + mpctx->osd_function != OSD_PAUSE) { drop_frame = frame_dropping; ++drop_frame_cnt; ++dropped_frames; @@ -3343,7 +2007,7 @@ drop_frame = dropped_frames = 0; ++total_frame_cnt; } - update_subtitles(sh_video, d_dvdsub, 0); + update_subtitles(sh_video, mpctx->d_sub, 0); update_osd_msg(); current_module = "decode_video"; decoded_frame = decode_video(sh_video, start, in_size, drop_frame, @@ -3353,7 +2017,7 @@ sh_video->pts)); } else { - if (!generate_video_frame(sh_video, d_video)) + if (!generate_video_frame(sh_video, mpctx->d_video)) return -1; ((vf_instance_t *)sh_video->vfilter)->control(sh_video->vfilter, VFCTRL_GET_PTS, &sh_video->pts); @@ -3370,8 +2034,8 @@ frame_time = sh_video->pts - sh_video->last_pts; sh_video->last_pts = sh_video->pts; sh_video->timer += frame_time; - if(sh_audio) - sh_audio->delay -= frame_time; + if(mpctx->sh_audio) + mpctx->sh_audio->delay -= frame_time; *blit_frame = 1; } return frame_time; @@ -3384,7 +2048,7 @@ // Small hack to display the pause message on the OSD line. // The pause string is: "\n == PAUSE == \r" so we need to // take the first and the last char out - if (term_osd && !sh_video) { + if (term_osd && !mpctx->sh_video) { char msg[128] = MSGTR_Paused; int mlen = strlen(msg); msg[mlen-1] = '\0'; @@ -3399,15 +2063,15 @@ if (use_gui) guiGetEvent(guiCEvent, (char *)guiSetPause); #endif - if (video_out && sh_video && vo_config_count) - video_out->control(VOCTRL_PAUSE, NULL); + if (mpctx->video_out && mpctx->sh_video && vo_config_count) + mpctx->video_out->control(VOCTRL_PAUSE, NULL); - if (audio_out && sh_audio) - audio_out->pause(); // pause audio, keep data if possible + 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) { - if (sh_video && video_out && vo_config_count) - video_out->check_events(); + if (mpctx->sh_video && mpctx->video_out && vo_config_count) + mpctx->video_out->check_events(); #ifdef HAVE_NEW_GUI if (use_gui) { guiEventHandling(); @@ -3426,16 +2090,16 @@ cmd = mp_input_get_cmd(0,1,0); mp_cmd_free(cmd); } - osd_function=OSD_PLAY; - if (audio_out && sh_audio) - audio_out->resume(); // resume audio - if (video_out && sh_video && vo_config_count) - video_out->control(VOCTRL_RESUME, NULL); // resume video + 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 #ifdef HAVE_NEW_GUI if (use_gui) { if (guiIntfStruct.Playing == guiSetStop) - eof = 1; + mpctx->eof = 1; else guiGetEvent(guiCEvent, (char *)guiSetPlay); } @@ -3484,8 +2148,6 @@ char * mem_ptr; -int file_format=DEMUXER_TYPE_UNKNOWN; - // movie info: /* Flag indicating whether MPlayer should exit without playing anything. */ @@ -3494,7 +2156,6 @@ //float a_frame=0; // Audio int i; -char *tmp; int gui_no_filename=0; @@ -3542,19 +2203,19 @@ if ( use_gui ) cfg_read(); #endif - playtree = m_config_parse_mp_command_line(mconfig, argc, argv); - if(playtree == NULL) + mpctx->playtree = m_config_parse_mp_command_line(mconfig, argc, argv); + if(mpctx->playtree == NULL) opt_exit = 1; else { - playtree = play_tree_cleanup(playtree); - if(playtree) { - playtree_iter = play_tree_iter_new(playtree,mconfig); - if(playtree_iter) { - if(play_tree_iter_step(playtree_iter,0,0) != PLAY_TREE_ITER_ENTRY) { - play_tree_iter_free(playtree_iter); - playtree_iter = NULL; + mpctx->playtree = play_tree_cleanup(mpctx->playtree); + if(mpctx->playtree) { + mpctx->playtree_iter = play_tree_iter_new(mpctx->playtree,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(playtree_iter,1); + filename = play_tree_iter_get_file(mpctx->playtree_iter,1); } } } @@ -3598,20 +2259,20 @@ use_gui=0; } #endif - if (use_gui && playtree_iter){ + if (use_gui && mpctx->playtree_iter){ char cwd[PATH_MAX+2]; // Free Playtree and Playtree-Iter as it's not used by the GUI. - play_tree_iter_free(playtree_iter); - playtree_iter=NULL; + play_tree_iter_free(mpctx->playtree_iter); + mpctx->playtree_iter=NULL; if (getcwd(cwd, PATH_MAX) != (char *)NULL) { strcat(cwd, "/"); // Prefix relative paths with current working directory - play_tree_add_bpf(playtree, cwd); + play_tree_add_bpf(mpctx->playtree, cwd); } // Import initital playtree into GUI. - import_initial_playtree_into_gui(playtree, mconfig, enqueue); + import_initial_playtree_into_gui(mpctx->playtree, mconfig, enqueue); } #endif /* HAVE_NEW_GUI */ @@ -3690,7 +2351,7 @@ opt_exit = 1; } if(list_properties) { - m_properties_print_help_list(mp_properties); + property_print_help(); opt_exit = 1; } @@ -3883,8 +2544,8 @@ play_next_file: // init global sub numbers - global_sub_size = 0; - { int i; for (i = 0; i < SUB_SOURCES; i++) global_sub_indices[i] = -1; } + mpctx->global_sub_size = 0; + { int i; for (i = 0; i < SUB_SOURCES; i++) mpctx->global_sub_indices[i] = -1; } if (filename) load_per_file_config (mconfig, filename); @@ -3902,7 +2563,7 @@ // =================== GUI idle loop (STOP state) =========================== #ifdef HAVE_NEW_GUI if ( use_gui ) { - file_format=DEMUXER_TYPE_UNKNOWN; + mpctx->file_format=DEMUXER_TYPE_UNKNOWN; guiGetEvent( guiSetDefaults,0 ); while ( guiIntfStruct.Playing != 1 ) { @@ -3917,20 +2578,20 @@ { play_tree_t * entry = play_tree_new(); play_tree_add_file( entry,guiIntfStruct.Filename ); - if ( playtree ) play_tree_free_list( playtree->child,1 ); - else playtree=play_tree_new(); - play_tree_set_child( playtree,entry ); - if(playtree) + if ( mpctx->playtree ) play_tree_free_list( mpctx->playtree->child,1 ); + else mpctx->playtree=play_tree_new(); + play_tree_set_child( mpctx->playtree,entry ); + if(mpctx->playtree) { - playtree_iter = play_tree_iter_new(playtree,mconfig); - if(playtree_iter) + mpctx->playtree_iter = play_tree_iter_new(mpctx->playtree,mconfig); + if(mpctx->playtree_iter) { - if(play_tree_iter_step(playtree_iter,0,0) != PLAY_TREE_ITER_ENTRY) + if(play_tree_iter_step(mpctx->playtree_iter,0,0) != PLAY_TREE_ITER_ENTRY) { - play_tree_iter_free(playtree_iter); - playtree_iter = NULL; + play_tree_iter_free(mpctx->playtree_iter); + mpctx->playtree_iter = NULL; } - filename = play_tree_iter_get_file(playtree_iter,1); + filename = play_tree_iter_get_file(mpctx->playtree_iter,1); } } } @@ -3941,7 +2602,7 @@ play_tree_t * entry = NULL; mp_cmd_t * cmd; while (!(cmd = mp_input_get_cmd(0,1,0))) { // wait for command - if (video_out && vo_config_count) video_out->check_events(); + if (mpctx->video_out && vo_config_count) mpctx->video_out->check_events(); usec_sleep(20000); } switch (cmd->id) { @@ -3962,26 +2623,26 @@ mp_cmd_free(cmd); if (entry) { // user entered a command that gave a valid entry - if (playtree) // the playtree is always a node with one child. let's clear it - play_tree_free_list(playtree->child, 1); - else playtree=play_tree_new(); // .. or make a brand new playtree + if (mpctx->playtree) // the playtree is always a node with one child. let's clear it + play_tree_free_list(mpctx->playtree->child, 1); + else mpctx->playtree=play_tree_new(); // .. or make a brand new playtree - if (!playtree) continue; // couldn't make playtree! wait for next command + if (!mpctx->playtree) continue; // couldn't make playtree! wait for next command - play_tree_set_child(playtree, entry); + play_tree_set_child(mpctx->playtree, entry); /* Make iterator start at the top the of tree. */ - playtree_iter = play_tree_iter_new(playtree, mconfig); - if (!playtree_iter) continue; + mpctx->playtree_iter = play_tree_iter_new(mpctx->playtree, mconfig); + if (!mpctx->playtree_iter) continue; // find the first real item in the tree - if (play_tree_iter_step(playtree_iter,0,0) != PLAY_TREE_ITER_ENTRY) { + if (play_tree_iter_step(mpctx->playtree_iter,0,0) != PLAY_TREE_ITER_ENTRY) { // no items! - play_tree_iter_free(playtree_iter); - playtree_iter = NULL; + play_tree_iter_free(mpctx->playtree_iter); + mpctx->playtree_iter = NULL; continue; // wait for next command } - filename = play_tree_iter_get_file(playtree_iter, 1); + filename = play_tree_iter_get_file(mpctx->playtree_iter, 1); } } //--------------------------------------------------------------------------- @@ -4042,67 +2703,67 @@ forced_subs_only=vobsub_get_forced_subs_flag(vo_vobsub); // setup global sub numbering - global_sub_indices[SUB_SOURCE_VOBSUB] = global_sub_size; // the global # of the first vobsub. - global_sub_size += vobsub_get_indexes_count(vo_vobsub); + mpctx->global_sub_indices[SUB_SOURCE_VOBSUB] = mpctx->global_sub_size; // the global # of the first vobsub. + mpctx->global_sub_size += vobsub_get_indexes_count(vo_vobsub); } //============ Open & Sync STREAM --- fork cache2 ==================== - stream=NULL; - demuxer=NULL; - if (d_audio) { - //free_demuxer_stream(d_audio); - d_audio=NULL; + mpctx->stream=NULL; + mpctx->demuxer=NULL; + if (mpctx->d_audio) { + //free_demuxer_stream(mpctx->d_audio); + mpctx->d_audio=NULL; } - if (d_video) { + if (mpctx->d_video) { //free_demuxer_stream(d_video); - d_video=NULL; + mpctx->d_video=NULL; } - sh_audio=NULL; - sh_video=NULL; + mpctx->sh_audio=NULL; + mpctx->sh_video=NULL; current_module="open_stream"; - stream=open_stream(filename,0,&file_format); - if(!stream) { // error... - eof = libmpdemux_was_interrupted(PT_NEXT_ENTRY); + mpctx->stream=open_stream(filename,0,&mpctx->file_format); + if(!mpctx->stream) { // error... + mpctx->eof = libmpdemux_was_interrupted(PT_NEXT_ENTRY); goto goto_next_file; } inited_flags|=INITED_STREAM; #ifdef HAVE_NEW_GUI - if ( use_gui ) guiGetEvent( guiSetStream,(char *)stream ); + if ( use_gui ) guiGetEvent( guiSetStream,(char *)mpctx->stream ); #endif - if(file_format == DEMUXER_TYPE_PLAYLIST) { + if(mpctx->file_format == DEMUXER_TYPE_PLAYLIST) { 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(stream,0); - eof=playtree_add_playlist(entry); + entry = parse_playtree(mpctx->stream,0); + mpctx->eof=playtree_add_playlist(entry); goto goto_next_file; } - stream->start_pos+=seek_to_byte; + mpctx->stream->start_pos+=seek_to_byte; if(stream_dump_type==5){ unsigned char buf[4096]; int len; FILE *f; current_module="dumpstream"; - if(stream->type==STREAMTYPE_STREAM && stream->fd<0){ + if(mpctx->stream->type==STREAMTYPE_STREAM && mpctx->stream->fd<0){ mp_msg(MSGT_CPLAYER,MSGL_FATAL,MSGTR_DumpstreamFdUnavailable); exit_player(MSGTR_Exit_error); } - stream_reset(stream); - stream_seek(stream,stream->start_pos); + 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); } - while(!stream->eof){ - len=stream_read(stream,buf,4096); + while(!mpctx->stream->eof){ + len=stream_read(mpctx->stream,buf,4096); if(len>0) { if(fwrite(buf,len,1,f) != 1) { mp_msg(MSGT_MENCODER,MSGL_FATAL,MSGTR_ErrorWritingFile,stream_dump_name); @@ -4119,27 +2780,27 @@ } #ifdef USE_DVDREAD -if(stream->type==STREAMTYPE_DVD){ +if(mpctx->stream->type==STREAMTYPE_DVD){ current_module="dvd lang->id"; - if(audio_id==-1) audio_id=dvd_aid_from_lang(stream,audio_lang); + 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(stream,dvdsub_lang); + if(dvdsub_lang && dvdsub_id==-1) dvdsub_id=dvd_sid_from_lang(mpctx->stream,dvdsub_lang); // setup global sub numbering - global_sub_indices[SUB_SOURCE_DEMUX] = global_sub_size; // the global # of the first demux-specific sub. - global_sub_size += dvd_number_of_subs(stream); + 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); current_module=NULL; } #endif #ifdef USE_DVDNAV -if(stream->type==STREAMTYPE_DVDNAV){ +if(mpctx->stream->type==STREAMTYPE_DVDNAV){ current_module="dvdnav lang->id"; - if(audio_id==-1) audio_id=dvdnav_aid_from_lang(stream,audio_lang); + if(audio_id==-1) audio_id=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=dvdnav_sid_from_lang(stream,dvdsub_lang); + if(dvdsub_lang && dvdsub_id==-1) dvdsub_id=dvdnav_sid_from_lang(mpctx->stream,dvdsub_lang); // setup global sub numbering - global_sub_indices[SUB_SOURCE_DEMUX] = global_sub_size; // the global # of the first demux-specific sub. - global_sub_size += dvdnav_number_of_subs(stream); + mpctx->global_sub_indices[SUB_SOURCE_DEMUX] = mpctx->global_sub_size; // the global # of the first demux-specific sub. + mpctx->global_sub_size += dvdnav_number_of_subs(mpctx->stream); current_module=NULL; } #endif @@ -4148,26 +2809,26 @@ goto_enable_cache: if(stream_cache_size>0){ current_module="enable_cache"; - if(!stream_enable_cache(stream,stream_cache_size*1024, + 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((eof = libmpdemux_was_interrupted(PT_NEXT_ENTRY))) goto goto_next_file; + if((mpctx->eof = libmpdemux_was_interrupted(PT_NEXT_ENTRY))) goto goto_next_file; } //============ Open DEMUXERS --- DETECT file type ======================= current_module="demux_open"; -demuxer=demux_open(stream,file_format,audio_id,video_id,dvdsub_id,filename); +mpctx->demuxer=demux_open(mpctx->stream,mpctx->file_format,audio_id,video_id,dvdsub_id,filename); // HACK to get MOV Reference Files working -if (demuxer && demuxer->type==DEMUXER_TYPE_PLAYLIST) +if (mpctx->demuxer && mpctx->demuxer->type==DEMUXER_TYPE_PLAYLIST) { unsigned char* playlist_entry; play_tree_t *list = NULL, *entry = NULL; current_module="handle_demux_playlist"; - while (ds_get_packet(demuxer->video,&playlist_entry)>0) + while (ds_get_packet(mpctx->demuxer->video,&playlist_entry)>0) { char *temp, *bname; @@ -4204,25 +2865,25 @@ else play_tree_append_entry(list,entry); } - free_demuxer(demuxer); - demuxer = NULL; + free_demuxer(mpctx->demuxer); + mpctx->demuxer = NULL; if (list) { entry = play_tree_new(); play_tree_set_child(entry,list); - eof=playtree_add_playlist(entry); + mpctx->eof=playtree_add_playlist(entry); goto goto_next_file; } } -if(!demuxer) +if(!mpctx->demuxer) { #if 0 play_tree_t* entry; // Handle playlist current_module="handle_playlist"; - switch(stream->type){ + switch(mpctx->stream->type){ case STREAMTYPE_VCD: case STREAMTYPE_DVD: case STREAMTYPE_CDDA: @@ -4231,9 +2892,9 @@ goto goto_next_file; } mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_FallingBackOnPlaylist,filename); - stream_reset(stream); - stream_seek(stream,stream->start_pos); - entry = parse_playtree(stream,0); + stream_reset(mpctx->stream); + stream_seek(mpctx->stream,mpctx->stream->start_pos); + entry = parse_playtree(mpctx->stream,0); if(!entry) mp_msg(MSGT_DEMUXER,MSGL_ERR,MSGTR_FormatNotRecognized); else @@ -4243,23 +2904,23 @@ } inited_flags|=INITED_DEMUXER; -if (stream->type != STREAMTYPE_DVD && stream->type != STREAMTYPE_DVDNAV) { +if (mpctx->stream->type != STREAMTYPE_DVD && mpctx->stream->type != STREAMTYPE_DVDNAV) { int i; // setup global sub numbering - global_sub_indices[SUB_SOURCE_DEMUX] = global_sub_size; // the global # of the first demux-specific sub. + 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 (demuxer->s_streams[i]) - global_sub_size++; + if (mpctx->demuxer->s_streams[i]) + mpctx->global_sub_size++; } -if (global_sub_size <= dvdsub_id) global_sub_size = dvdsub_id + 1; +if (mpctx->global_sub_size <= dvdsub_id) mpctx->global_sub_size = dvdsub_id + 1; current_module="demux_open2"; //file_format=demuxer->file_format; -d_audio=demuxer->audio; -d_video=demuxer->video; -d_dvdsub=demuxer->sub; +mpctx->d_audio=mpctx->demuxer->audio; +mpctx->d_video=mpctx->demuxer->video; +mpctx->d_sub=mpctx->demuxer->sub; // DUMP STREAMS: if((stream_dump_type)&&(stream_dump_type<4)){ @@ -4268,18 +2929,18 @@ current_module="dump"; // select stream to dump switch(stream_dump_type){ - case 1: ds=d_audio;break; - case 2: ds=d_video;break; - case 3: ds=d_dvdsub;break; + case 1: ds=mpctx->d_audio;break; + case 2: ds=mpctx->d_video;break; + case 3: ds=mpctx->d_sub;break; } if(!ds){ mp_msg(MSGT_CPLAYER,MSGL_FATAL,MSGTR_DumpSelectedStreamMissing); exit_player(MSGTR_Exit_error); } // disable other streams: - if(d_audio && d_audio!=ds) {ds_free_packs(d_audio); d_audio->id=-2; } - if(d_video && d_video!=ds) {ds_free_packs(d_video); d_video->id=-2; } - if(d_dvdsub && d_dvdsub!=ds) {ds_free_packs(d_dvdsub); d_dvdsub->id=-2; } + if(mpctx->d_audio && mpctx->d_audio!=ds) {ds_free_packs(mpctx->d_audio); mpctx->d_audio->id=-2; } + if(mpctx->d_video && mpctx->d_video!=ds) {ds_free_packs(mpctx->d_video); mpctx->d_video->id=-2; } + if(mpctx->d_sub && mpctx->d_sub!=ds) {ds_free_packs(mpctx->d_sub); mpctx->d_sub->id=-2; } // let's dump it! f=fopen(stream_dump_name,"wb"); if(!f){ @@ -4289,7 +2950,7 @@ while(!ds->eof){ unsigned char* start; int in_size=ds_get_packet(ds,&start); - if( (demuxer->file_format==DEMUXER_TYPE_AVI || demuxer->file_format==DEMUXER_TYPE_ASF || demuxer->file_format==DEMUXER_TYPE_MOV) + if( (mpctx->demuxer->file_format==DEMUXER_TYPE_AVI || mpctx->demuxer->file_format==DEMUXER_TYPE_ASF || mpctx->demuxer->file_format==DEMUXER_TYPE_MOV) && stream_dump_type==2) fwrite(&in_size,1,4,f); if(in_size>0) fwrite(start,in_size,1,f); } @@ -4298,31 +2959,31 @@ exit_player_with_rc(MSGTR_Exit_eof, 0); } -sh_audio=d_audio->sh; -sh_video=d_video->sh; +mpctx->sh_audio=mpctx->d_audio->sh; +mpctx->sh_video=mpctx->d_video->sh; -if(sh_video){ +if(mpctx->sh_video){ current_module="video_read_properties"; - if(!video_read_properties(sh_video)) { + if(!video_read_properties(mpctx->sh_video)) { mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_CannotReadVideoProperties); - sh_video=d_video->sh=NULL; + mpctx->sh_video=mpctx->d_video->sh=NULL; } else { mp_msg(MSGT_CPLAYER,MSGL_V,"[V] filefmt:%d fourcc:0x%X size:%dx%d fps:%5.2f ftime:=%6.4f\n", - demuxer->file_format,sh_video->format, sh_video->disp_w,sh_video->disp_h, - sh_video->fps,sh_video->frametime + mpctx->demuxer->file_format,mpctx->sh_video->format, mpctx->sh_video->disp_w,mpctx->sh_video->disp_h, + mpctx->sh_video->fps,mpctx->sh_video->frametime ); /* need to set fps here for output encoders to pick it up in their init */ if(force_fps){ - sh_video->fps=force_fps; - sh_video->frametime=1.0f/sh_video->fps; + mpctx->sh_video->fps=force_fps; + mpctx->sh_video->frametime=1.0f/mpctx->sh_video->fps; } - vo_fps = sh_video->fps; + vo_fps = mpctx->sh_video->fps; - if(!sh_video->fps && !force_fps){ + if(!mpctx->sh_video->fps && !force_fps){ mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_FPSnotspecified); - sh_video=d_video->sh=NULL; + mpctx->sh_video=mpctx->d_video->sh=NULL; } } @@ -4330,23 +2991,23 @@ fflush(stdout); -if(!sh_video && !sh_audio){ +if(!mpctx->sh_video && !mpctx->sh_audio){ mp_msg(MSGT_CPLAYER,MSGL_FATAL, MSGTR_NoStreamFound); #ifdef HAS_DVBIN_SUPPORT - if((stream->type == STREAMTYPE_DVB) && stream->priv) + if((mpctx->stream->type == STREAMTYPE_DVB) && mpctx->stream->priv) { - dvb_priv_t *priv = (dvb_priv_t*) stream->priv; + dvb_priv_t *priv = (dvb_priv_t*) mpctx->stream->priv; if(priv->is_on) { int dir; - int v = last_dvb_step; + int v = mpctx->last_dvb_step; if(v > 0) dir = DVB_CHANNEL_HIGHER; else dir = DVB_CHANNEL_LOWER; if(dvb_step_channel(priv, dir)) - eof = dvbin_reopen = 1; + mpctx->eof = mpctx->dvbin_reopen = 1; } } #endif @@ -4354,11 +3015,11 @@ } /* display clip info */ -demux_info_print(demuxer); +demux_info_print(mpctx->demuxer); //================== Read SUBTITLES (DVD & TEXT) ========================== -if(vo_spudec==NULL && sh_video && - (stream->type==STREAMTYPE_DVD || stream->type == STREAMTYPE_DVDNAV || d_dvdsub->id >= 0)){ +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(); } @@ -4366,14 +3027,14 @@ if (vo_spudec!=NULL) spudec_set_forced_subs_only(vo_spudec,forced_subs_only); -if(sh_video) { +if(mpctx->sh_video) { // after reading video params we should load subtitles because // we know fps so now we can adjust subtitle time to ~6 seconds AST // check .sub current_module="read_subtitles_file"; if(sub_name){ for (i = 0; sub_name[i] != NULL; ++i) - add_subtitles (sub_name[i], sh_video->fps, 0); + add_subtitles (sub_name[i], mpctx->sh_video->fps, 0); } if(sub_auto) { // auto load sub file ... char *psub = get_path( "sub/" ); @@ -4381,90 +3042,90 @@ int i = 0; free(psub); // release the buffer created by get_path() above while (tmp[i]) { - add_subtitles (tmp[i], sh_video->fps, 0); + add_subtitles (tmp[i], mpctx->sh_video->fps, 0); free(tmp[i++]); } free(tmp); } - if (set_of_sub_size > 0) { + if (mpctx->set_of_sub_size > 0) { // setup global sub numbering - global_sub_indices[SUB_SOURCE_SUBS] = global_sub_size; // the global # of the first sub. - global_sub_size += set_of_sub_size; + mpctx->global_sub_indices[SUB_SOURCE_SUBS] = mpctx->global_sub_size; // the global # of the first sub. + mpctx->global_sub_size += mpctx->set_of_sub_size; } } -if (global_sub_size) { +if (mpctx->global_sub_size) { // find the best sub to use if (vobsub_id >= 0) { // if user asks for a vobsub id, use that first. - global_sub_pos = global_sub_indices[SUB_SOURCE_VOBSUB] + vobsub_id; - } else if (dvdsub_id >= 0 && global_sub_indices[SUB_SOURCE_DEMUX] >= 0) { + mpctx->global_sub_pos = mpctx->global_sub_indices[SUB_SOURCE_VOBSUB] + vobsub_id; + } else if (dvdsub_id >= 0 && mpctx->global_sub_indices[SUB_SOURCE_DEMUX] >= 0) { // if user asks for a dvd sub id, use that next. - global_sub_pos = global_sub_indices[SUB_SOURCE_DEMUX] + dvdsub_id; - } else if (global_sub_indices[SUB_SOURCE_SUBS] >= 0) { + mpctx->global_sub_pos = mpctx->global_sub_indices[SUB_SOURCE_DEMUX] + dvdsub_id; + } else if (mpctx->global_sub_indices[SUB_SOURCE_SUBS] >= 0) { // if there are text subs to use, use those. (autosubs come last here) - global_sub_pos = global_sub_indices[SUB_SOURCE_SUBS]; + mpctx->global_sub_pos = mpctx->global_sub_indices[SUB_SOURCE_SUBS]; /* - } else if (global_sub_indices[SUB_SOURCE_DEMUX] >= 0) { + } else if (mpctx->global_sub_indices[SUB_SOURCE_DEMUX] >= 0) { // if nothing else works, get subs from the demuxer. - global_sub_pos = global_sub_indices[SUB_SOURCE_DEMUX]; + mpctx->global_sub_pos = mpctx->global_sub_indices[SUB_SOURCE_DEMUX]; */ } else { // nothing worth doing automatically. - global_sub_pos = -1; + mpctx->global_sub_pos = -1; } // rather than duplicate code, use the SUB_SELECT handler to init the right one. - global_sub_pos--; - mp_property_do("sub",M_PROPERTY_STEP_UP,NULL); + mpctx->global_sub_pos--; + mp_property_do("sub",M_PROPERTY_STEP_UP,NULL, mpctx); if(subdata) switch (stream_dump_type) { case 3: list_sub_file(subdata); break; - case 4: dump_mpsub(subdata, sh_video->fps); break; - case 6: dump_srt(subdata, sh_video->fps); break; - case 7: dump_microdvd(subdata, sh_video->fps); break; - case 8: dump_jacosub(subdata, sh_video->fps); break; - case 9: dump_sami(subdata, sh_video->fps); break; + case 4: dump_mpsub(subdata, mpctx->sh_video->fps); break; + case 6: dump_srt(subdata, mpctx->sh_video->fps); break; + case 7: dump_microdvd(subdata, mpctx->sh_video->fps); break; + case 8: dump_jacosub(subdata, mpctx->sh_video->fps); break; + case 9: dump_sami(subdata, mpctx->sh_video->fps); break; } } mp_msg(MSGT_IDENTIFY,MSGL_INFO,"ID_FILENAME=%s\n", filename_recode(filename)); - mp_msg(MSGT_IDENTIFY,MSGL_INFO,"ID_DEMUXER=%s\n", demuxer->desc->name); - if (sh_video) { + mp_msg(MSGT_IDENTIFY,MSGL_INFO,"ID_DEMUXER=%s\n", mpctx->demuxer->desc->name); + if (mpctx->sh_video) { /* Assume FOURCC if all bytes >= 0x20 (' ') */ - if (sh_video->format >= 0x20202020) - mp_msg(MSGT_IDENTIFY,MSGL_INFO,"ID_VIDEO_FORMAT=%.4s\n", (char *)&sh_video->format); + if (mpctx->sh_video->format >= 0x20202020) + mp_msg(MSGT_IDENTIFY,MSGL_INFO,"ID_VIDEO_FORMAT=%.4s\n", (char *)&mpctx->sh_video->format); else - mp_msg(MSGT_IDENTIFY,MSGL_INFO,"ID_VIDEO_FORMAT=0x%08X\n", sh_video->format); - mp_msg(MSGT_IDENTIFY,MSGL_INFO,"ID_VIDEO_BITRATE=%d\n", sh_video->i_bps*8); - mp_msg(MSGT_IDENTIFY,MSGL_INFO,"ID_VIDEO_WIDTH=%d\n", sh_video->disp_w); - mp_msg(MSGT_IDENTIFY,MSGL_INFO,"ID_VIDEO_HEIGHT=%d\n", sh_video->disp_h); - mp_msg(MSGT_IDENTIFY,MSGL_INFO,"ID_VIDEO_FPS=%5.3f\n", sh_video->fps); - mp_msg(MSGT_IDENTIFY,MSGL_INFO,"ID_VIDEO_ASPECT=%1.4f\n", sh_video->aspect); + mp_msg(MSGT_IDENTIFY,MSGL_INFO,"ID_VIDEO_FORMAT=0x%08X\n", mpctx->sh_video->format); + mp_msg(MSGT_IDENTIFY,MSGL_INFO,"ID_VIDEO_BITRATE=%d\n", mpctx->sh_video->i_bps*8); + mp_msg(MSGT_IDENTIFY,MSGL_INFO,"ID_VIDEO_WIDTH=%d\n", mpctx->sh_video->disp_w); + mp_msg(MSGT_IDENTIFY,MSGL_INFO,"ID_VIDEO_HEIGHT=%d\n", mpctx->sh_video->disp_h); + mp_msg(MSGT_IDENTIFY,MSGL_INFO,"ID_VIDEO_FPS=%5.3f\n", mpctx->sh_video->fps); + mp_msg(MSGT_IDENTIFY,MSGL_INFO,"ID_VIDEO_ASPECT=%1.4f\n", mpctx->sh_video->aspect); } - if (sh_audio) { + if (mpctx->sh_audio) { /* Assume FOURCC if all bytes >= 0x20 (' ') */ - if (sh_audio->format >= 0x20202020) - mp_msg(MSGT_IDENTIFY,MSGL_INFO, "ID_AUDIO_FORMAT=%.4s\n", (char *)&sh_audio->format); + if (mpctx->sh_audio->format >= 0x20202020) + mp_msg(MSGT_IDENTIFY,MSGL_INFO, "ID_AUDIO_FORMAT=%.4s\n", (char *)&mpctx->sh_audio->format); else - mp_msg(MSGT_IDENTIFY,MSGL_INFO,"ID_AUDIO_FORMAT=%d\n", sh_audio->format); - mp_msg(MSGT_IDENTIFY,MSGL_INFO,"ID_AUDIO_BITRATE=%d\n", sh_audio->i_bps*8); - mp_msg(MSGT_IDENTIFY,MSGL_INFO,"ID_AUDIO_RATE=%d\n", sh_audio->samplerate); - mp_msg(MSGT_IDENTIFY,MSGL_INFO,"ID_AUDIO_NCH=%d\n", sh_audio->channels); + mp_msg(MSGT_IDENTIFY,MSGL_INFO,"ID_AUDIO_FORMAT=%d\n", mpctx->sh_audio->format); + mp_msg(MSGT_IDENTIFY,MSGL_INFO,"ID_AUDIO_BITRATE=%d\n", mpctx->sh_audio->i_bps*8); + mp_msg(MSGT_IDENTIFY,MSGL_INFO,"ID_AUDIO_RATE=%d\n", mpctx->sh_audio->samplerate); + mp_msg(MSGT_IDENTIFY,MSGL_INFO,"ID_AUDIO_NCH=%d\n", mpctx->sh_audio->channels); } - mp_msg(MSGT_IDENTIFY,MSGL_INFO,"ID_LENGTH=%.2lf\n", demuxer_get_time_length(demuxer)); + mp_msg(MSGT_IDENTIFY,MSGL_INFO,"ID_LENGTH=%.2lf\n", demuxer_get_time_length(mpctx->demuxer)); -if(!sh_video) goto main; // audio-only +if(!mpctx->sh_video) goto main; // audio-only if(!reinit_video_chain()) { - if(!sh_video){ - if(!sh_audio) goto goto_next_file; + 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) - spudec_set_hw_spu(vo_spudec,video_out); + spudec_set_hw_spu(vo_spudec,mpctx->video_out); #ifdef HAVE_FREETYPE force_load_font = 1; @@ -4475,7 +3136,7 @@ current_module="main"; if(playing_msg) { - char* msg = m_properties_expand_string(mp_properties,playing_msg); + char* msg = property_expand_string(mpctx, playing_msg); mp_msg(MSGT_CPLAYER,MSGL_INFO,"%s",msg); free(msg); } @@ -4493,7 +3154,6 @@ int frame_time_remaining=0; // flag int blit_frame=0; -int was_paused=0; // Make sure old OSD does not stay around, // e.g. with -fixed-vo and same-resolution files @@ -4502,57 +3162,57 @@ //================ SETUP AUDIO ========================== -if(sh_audio){ +if(mpctx->sh_audio){ reinit_audio_chain(); - if (sh_audio && sh_audio->codec) - mp_msg(MSGT_IDENTIFY,MSGL_INFO, "ID_AUDIO_CODEC=%s\n", sh_audio->codec->name); + if (mpctx->sh_audio && mpctx->sh_audio->codec) + mp_msg(MSGT_IDENTIFY,MSGL_INFO, "ID_AUDIO_CODEC=%s\n", mpctx->sh_audio->codec->name); } current_module="av_init"; -if(sh_video){ - sh_video->timer=0; +if(mpctx->sh_video){ + mpctx->sh_video->timer=0; if (! ignore_start) - audio_delay += sh_video->stream_delay; + audio_delay += mpctx->sh_video->stream_delay; } -if(sh_audio){ +if(mpctx->sh_audio){ if (! ignore_start) - audio_delay -= sh_audio->stream_delay; - sh_audio->delay=-audio_delay; + audio_delay -= mpctx->sh_audio->stream_delay; + mpctx->sh_audio->delay=-audio_delay; } -if(!sh_audio){ +if(!mpctx->sh_audio){ mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_NoSound); - mp_msg(MSGT_CPLAYER,MSGL_V,"Freeing %d unused audio chunks.\n",d_audio->packs); - ds_free_packs(d_audio); // free buffered chunks - //d_audio->id=-2; // do not read audio chunks + 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(INITED_AO); // close device } -if(!sh_video){ +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",d_video->packs); - ds_free_packs(d_video); - d_video->id=-2; + 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(INITED_VO); } -if (!sh_video && !sh_audio) +if (!mpctx->sh_video && !mpctx->sh_audio) goto goto_next_file; //if(demuxer->file_format!=DEMUXER_TYPE_AVI) pts_from_bps=0; // it must be 0 for mpeg/asf! -if(force_fps && sh_video){ - vo_fps = sh_video->fps=force_fps; - sh_video->frametime=1.0f/sh_video->fps; - mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_FPSforced,sh_video->fps,sh_video->frametime); +if(force_fps && mpctx->sh_video){ + vo_fps = mpctx->sh_video->fps=force_fps; + mpctx->sh_video->frametime=1.0f/mpctx->sh_video->fps; + mp_msg(MSGT_CPLAYER,MSGL_INFO,MSGTR_FPSforced,mpctx->sh_video->fps,mpctx->sh_video->frametime); } #ifdef HAVE_NEW_GUI if ( use_gui ) { - if ( sh_audio ) guiIntfStruct.AudioType=sh_audio->channels; else guiIntfStruct.AudioType=0; - if ( !sh_video && sh_audio ) guiGetEvent( guiSetAudioOnly,(char *)1 ); else guiGetEvent( guiSetAudioOnly,(char *)0 ); - guiGetEvent( guiSetFileFormat,(char *)demuxer->file_format ); - if ( guiGetEvent( guiSetValues,(char *)sh_video ) ) goto goto_next_file; - guiGetEvent( guiSetDemuxer,(char *)demuxer ); + if ( mpctx->sh_audio ) guiIntfStruct.AudioType=mpctx->sh_audio->channels; else guiIntfStruct.AudioType=0; + if ( !mpctx->sh_video && mpctx->sh_audio ) guiGetEvent( guiSetAudioOnly,(char *)1 ); else guiGetEvent( guiSetAudioOnly,(char *)0 ); + guiGetEvent( guiSetFileFormat,(char *)mpctx->demuxer->file_format ); + if ( guiGetEvent( guiSetValues,(char *)mpctx->sh_video ) ) goto goto_next_file; + guiGetEvent( guiSetDemuxer,(char *)mpctx->demuxer ); } #endif @@ -4569,55 +3229,55 @@ play_n_frames=play_n_frames_mf; if(play_n_frames==0){ - eof=PT_NEXT_ENTRY; goto goto_next_file; + mpctx->eof=PT_NEXT_ENTRY; goto goto_next_file; } -while(!eof){ +while(!mpctx->eof){ float aq_sleep_time=0; -if(!sh_audio && d_audio->sh) { - sh_audio = d_audio->sh; - sh_audio->ds = d_audio; +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(); } /*========================== PLAY AUDIO ============================*/ -if (sh_audio) +if (mpctx->sh_audio) if (!fill_audio_out_buffers()) // at eof, all audio at least written to ao - if (!sh_video) - eof = PT_NEXT_ENTRY; + if (!mpctx->sh_video) + mpctx->eof = PT_NEXT_ENTRY; -if(!sh_video) { +if(!mpctx->sh_video) { // handle audio-only case: double a_pos=0; if(!quiet || end_at.type == END_AT_TIME ) - a_pos = playing_audio_pts(sh_audio, d_audio, audio_out); + a_pos = playing_audio_pts(mpctx->sh_audio, mpctx->d_audio, mpctx->audio_out); if(!quiet) print_status(a_pos, 0, 0); if(end_at.type == END_AT_TIME && end_at.pos < a_pos) - eof = PT_NEXT_ENTRY; + mpctx->eof = PT_NEXT_ENTRY; update_osd_msg(); } else { /*========================== PLAY VIDEO ============================*/ - vo_pts=sh_video->timer*90000.0; - vo_fps=sh_video->fps; + vo_pts=mpctx->sh_video->timer*90000.0; + vo_fps=mpctx->sh_video->fps; if (!frame_time_remaining) { double frame_time = update_video(&blit_frame); mp_dbg(MSGT_AVSYNC,MSGL_DBG2,"*** ftime=%5.3f ***\n",frame_time); - if (sh_video->vf_inited < 0) { + if (mpctx->sh_video->vf_inited < 0) { mp_msg(MSGT_CPLAYER,MSGL_FATAL, MSGTR_NotInitializeVOPorVO); - eof = 1; goto goto_next_file; + mpctx->eof = 1; goto goto_next_file; } if (frame_time < 0) - eof = 1; + mpctx->eof = 1; else time_frame += frame_time / playback_speed; // for nosound } @@ -4625,14 +3285,14 @@ // ========================================================================== // current_module="draw_osd"; -// if(vo_config_count) video_out->draw_osd(); +// if(vo_config_count) mpctx->video_out->draw_osd(); #ifdef HAVE_NEW_GUI if(use_gui) guiEventHandling(); #endif current_module="vo_check_events"; - if (vo_config_count) video_out->check_events(); + if (vo_config_count) mpctx->video_out->check_events(); #ifdef HAVE_X11 if (stop_xscreensaver) { @@ -4649,7 +3309,7 @@ if (!frame_time_remaining && blit_frame) { unsigned int t2=GetTimer(); - if(vo_config_count) video_out->flip_page(); + if(vo_config_count) mpctx->video_out->flip_page(); vout_time_usage += (GetTimer() - t2) * 0.000001; } @@ -4674,26 +3334,26 @@ if(output_quality>0 && aq_sleep_time<-0.050f) // 50ms output_quality=0; // printf("total: %8.6f sleep: %8.6f q: %d\n",(0.000001f*aq_total_time),aq_sleep_time,output_quality); - set_video_quality(sh_video,output_quality); + set_video_quality(mpctx->sh_video,output_quality); } if (play_n_frames >= 0 && !frame_time_remaining && blit_frame) { --play_n_frames; - if (play_n_frames <= 0) eof = PT_NEXT_ENTRY; + if (play_n_frames <= 0) mpctx->eof = PT_NEXT_ENTRY; } // FIXME: add size based support for -endpos if (end_at.type == END_AT_TIME && - !frame_time_remaining && end_at.pos <= sh_video->pts) - eof = PT_NEXT_ENTRY; + !frame_time_remaining && end_at.pos <= mpctx->sh_video->pts) + mpctx->eof = PT_NEXT_ENTRY; -} // end if(sh_video) +} // end if(mpctx->sh_video) #ifdef USE_DVDNAV - if (stream->type == STREAMTYPE_DVDNAV) { + if (mpctx->stream->type == STREAMTYPE_DVDNAV) { nav_highlight_t hl; - mp_dvdnav_get_highlight (stream, &hl); + mp_dvdnav_get_highlight (mpctx->stream, &hl); osd_set_nav_box (hl.sx, hl.sy, hl.ex, hl.ey); vo_osd_changed (OSDTYPE_DVDNAV); } @@ -4710,41 +3370,41 @@ osd_visible = 0; vo_osd_progbar_type=-1; // disable vo_osd_changed(OSDTYPE_PROGBAR); - if (osd_function != OSD_PAUSE) - osd_function = OSD_PLAY; + if (mpctx->osd_function != OSD_PAUSE) + mpctx->osd_function = OSD_PLAY; } } - if (osd_function == OSD_PAUSE) { + if (mpctx->osd_function == OSD_PAUSE) { pause_loop(); - was_paused = 1; + mpctx->was_paused = 1; } // handle -sstep if(step_sec>0) { - osd_function=OSD_FFW; + mpctx->osd_function=OSD_FFW; rel_seek_secs+=step_sec; } //================= EDL ========================================= if( next_edl_record ) { // Are we (still?) doing EDL? - if ( !sh_video ) { + if ( !mpctx->sh_video ) { mp_msg( MSGT_CPLAYER, MSGL_ERR, MSGTR_EdlNOsh_video ); free_edl(edl_records); next_edl_record = NULL; edl_records = NULL; } else { - if( sh_video->pts >= next_edl_record->start_sec ) { + if( mpctx->sh_video->pts >= next_edl_record->start_sec ) { if( next_edl_record->action == EDL_SKIP ) { - osd_function = OSD_FFW; + mpctx->osd_function = OSD_FFW; abs_seek_pos = 0; 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 ); edl_decision = 1; } else if( next_edl_record->action == EDL_MUTE ) { - edl_muted = !edl_muted; - if ((user_muted | edl_muted) != mixer.muted) mixer_mute(&mixer); + mpctx->edl_muted = !mpctx->edl_muted; + if ((mpctx->user_muted | mpctx->edl_muted) != mpctx->mixer.muted) mixer_mute(&mpctx->mixer); mp_msg(MSGT_CPLAYER, MSGL_DBG4, "EDL_MUTE: [%f]\n", next_edl_record->start_sec ); } next_edl_record=next_edl_record->next; @@ -4760,677 +3420,13 @@ mp_cmd_t* cmd; int brk_cmd = 0; while( !brk_cmd && (cmd = mp_input_get_cmd(0,0,0)) != NULL) { - if(!set_property_command(cmd)) - switch(cmd->id) { - case MP_CMD_SEEK : { - float v; - int abs; - if(sh_video) - osd_show_percentage = sh_video->fps; - v = cmd->args[0].v.f; - abs = (cmd->nargs > 1) ? cmd->args[1].v.i : 0; - if(abs==2) { /* Absolute seek to a specific timestamp in seconds */ - abs_seek_pos = 1; - if(sh_video) - osd_function= (v > sh_video->pts) ? OSD_FFW : OSD_REW; - rel_seek_secs = v; - } - else if(abs) { /* Absolute seek by percentage */ - abs_seek_pos = 3; - if(sh_video) - osd_function= OSD_FFW; // Direction isn't set correctly - rel_seek_secs = v/100.0; - } - else { - rel_seek_secs+= v; - osd_function= (v > 0) ? OSD_FFW : OSD_REW; - } - brk_cmd = 1; - } break; - case MP_CMD_SET_PROPERTY: { - m_option_t* prop = mp_property_find(cmd->args[0].v.s); - if(!prop) mp_msg(MSGT_CPLAYER,MSGL_WARN,"Unknown property: '%s'\n",cmd->args[0].v.s); - else if(m_property_parse(prop,cmd->args[1].v.s) <= 0) - mp_msg(MSGT_CPLAYER,MSGL_WARN,"Failed to set property '%s' to '%s'.\n", - cmd->args[0].v.s,cmd->args[1].v.s); - - } break; - case MP_CMD_STEP_PROPERTY: { - m_option_t* prop = mp_property_find(cmd->args[0].v.s); - float arg = cmd->args[1].v.f; - if(!prop) mp_msg(MSGT_CPLAYER,MSGL_WARN, "Unknown property: '%s'\n",cmd->args[0].v.s); - else if(m_property_do(prop,M_PROPERTY_STEP_UP, arg ? &arg : NULL) <= 0) - mp_msg(MSGT_CPLAYER,MSGL_WARN, "Failed to increment property '%s' by %f.\n",cmd->args[0].v.s, arg); - } break; - case MP_CMD_GET_PROPERTY: { - m_option_t* prop; - void* val; - prop = mp_property_find(cmd->args[0].v.s); - if(!prop) { - mp_msg(MSGT_CPLAYER,MSGL_WARN,"Unknown property: '%s'\n",cmd->args[0].v.s); - break; - } - /* Use m_option_print directly to get easily parseable values. */ - val = calloc(1,prop->type->size); - if(m_property_do(prop,M_PROPERTY_GET,val) <= 0) { - mp_msg(MSGT_CPLAYER,MSGL_WARN,"Failed to get value of property '%s'.\n", - cmd->args[0].v.s); - break; - } - tmp = m_option_print(prop,val); - if(!tmp || tmp == (char*)-1) { - mp_msg(MSGT_CPLAYER,MSGL_WARN,"Failed to print value of property '%s'.\n", - cmd->args[0].v.s); - break; - } - mp_msg(MSGT_GLOBAL,MSGL_INFO, "ANS_%s=%s\n",cmd->args[0].v.s,tmp); - free(tmp); - } break; - case MP_CMD_EDL_MARK: - if( edl_fd ) { - float v = sh_video ? sh_video->pts : - playing_audio_pts(sh_audio, d_audio, audio_out); - - if(begin_skip == MP_NOPTS_VALUE) - { - begin_skip = v; - mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_EdloutStartSkip); - }else{ - if(begin_skip > v) - { - mp_msg(MSGT_CPLAYER, MSGL_WARN, MSGTR_EdloutBadStop); - }else{ - fprintf(edl_fd, "%f %f %d\n", begin_skip, v, 0); - mp_msg(MSGT_CPLAYER, MSGL_INFO, MSGTR_EdloutEndSkip); - } - begin_skip = MP_NOPTS_VALUE; - } - } - break; - case MP_CMD_SWITCH_RATIO : { - if (cmd->nargs == 0 || cmd->args[0].v.f == -1) - movie_aspect = (float) sh_video->disp_w / sh_video->disp_h; - else - movie_aspect = cmd->args[0].v.f; - mpcodecs_config_vo (sh_video, sh_video->disp_w, sh_video->disp_h, 0); - } break; - case MP_CMD_SPEED_INCR : { - float v = cmd->args[0].v.f; - playback_speed += v; - build_afilter_chain(sh_audio, &ao_data); - set_osd_msg(OSD_MSG_SPEED,1,osd_duration,MSGTR_OSDSpeed, playback_speed); - } break; - case MP_CMD_SPEED_MULT : { - float v = cmd->args[0].v.f; - playback_speed *= v; - build_afilter_chain(sh_audio, &ao_data); - set_osd_msg(OSD_MSG_SPEED,1,osd_duration,MSGTR_OSDSpeed, playback_speed); - } break; - case MP_CMD_SPEED_SET : { - float v = cmd->args[0].v.f; - playback_speed = v; - build_afilter_chain(sh_audio, &ao_data); - set_osd_msg(OSD_MSG_SPEED,1,osd_duration,MSGTR_OSDSpeed, playback_speed); - } break; - case MP_CMD_FRAME_STEP : - case MP_CMD_PAUSE : { - cmd->pausing = 1; - brk_cmd = 1; - } break; - case MP_CMD_FILE_FILTER : { - file_filter = cmd->args[0].v.i; - break; - } - case MP_CMD_QUIT : { - exit_player_with_rc(MSGTR_Exit_quit, (cmd->nargs > 0)? cmd->args[0].v.i : 0); - } - case MP_CMD_PLAY_TREE_STEP : { - int n = cmd->args[0].v.i == 0 ? 1 : cmd->args[0].v.i; - int force = cmd->args[1].v.i; - -#ifdef HAVE_NEW_GUI - if (use_gui) { - int i=0; - if (n>0) - for (i=0;i<n;i++) - mplNext(); - else - for (i=0;i<-1*n;i++) - mplPrev(); - } else -#endif - { - if(!force && playtree_iter) { - play_tree_iter_t* i = play_tree_iter_new_copy(playtree_iter); - - if(play_tree_iter_step(i,n,0) == PLAY_TREE_ITER_ENTRY) - eof = (n > 0) ? PT_NEXT_ENTRY : PT_PREV_ENTRY; - play_tree_iter_free(i); - } else - eof = (n > 0) ? PT_NEXT_ENTRY : PT_PREV_ENTRY; - if(eof) - play_tree_step = n; - brk_cmd = 1; - } - } break; - case MP_CMD_PLAY_TREE_UP_STEP : { - int n = cmd->args[0].v.i > 0 ? 1 : -1; - int force = cmd->args[1].v.i; - - if(!force && playtree_iter) { - play_tree_iter_t* i = play_tree_iter_new_copy(playtree_iter); - if(play_tree_iter_up_step(i,n,0) == PLAY_TREE_ITER_ENTRY) - eof = (n > 0) ? PT_UP_NEXT : PT_UP_PREV; - play_tree_iter_free(i); - } else - eof = (n > 0) ? PT_UP_NEXT : PT_UP_PREV; - brk_cmd = 1; - } break; - case MP_CMD_PLAY_ALT_SRC_STEP : { - if(playtree_iter && playtree_iter->num_files > 1) { - int v = cmd->args[0].v.i; - if(v > 0 && playtree_iter->file < playtree_iter->num_files) - eof = PT_NEXT_SRC; - else if(v < 0 && playtree_iter->file > 1) - eof = PT_PREV_SRC; - } - brk_cmd = 1; - } break; - case MP_CMD_SUB_STEP : { - if (sh_video) { - int movement = cmd->args[0].v.i; - step_sub(subdata, sh_video->pts, movement); -#ifdef USE_ASS - if (ass_track) - sub_delay += ass_step_sub(ass_track, (sh_video->pts + sub_delay) * 1000 + .5, movement) / 1000.; -#endif - set_osd_msg(OSD_MSG_SUB_DELAY,1,osd_duration, - MSGTR_OSDSubDelay, ROUND(sub_delay*1000)); - } - } break; - case MP_CMD_SUB_LOG : { - log_sub(); - } break; - case MP_CMD_OSD : { - int v = cmd->args[0].v.i; - int max = (term_osd && !sh_video) ? MAX_TERM_OSD_LEVEL : MAX_OSD_LEVEL; - if(osd_level > max) osd_level = max; - if(v < 0) - osd_level=(osd_level+1)%(max+1); - else - osd_level= v > max ? max : v; - /* Show OSD state when disabled, but not when an explicit - argument is given to the OSD command, i.e. in slave mode. */ - if (v == -1 && osd_level <= 1) - set_osd_msg(OSD_MSG_OSD_STATUS,0,osd_duration, - MSGTR_OSDosd, osd_level ? MSGTR_OSDenabled : MSGTR_OSDdisabled); - else - rm_osd_msg(OSD_MSG_OSD_STATUS); - } break; - case MP_CMD_OSD_SHOW_TEXT : { - set_osd_msg(OSD_MSG_TEXT,cmd->args[2].v.i, - (cmd->args[1].v.i < 0 ? osd_duration : cmd->args[1].v.i), - "%-.63s",cmd->args[0].v.s); - } break; - case MP_CMD_OSD_SHOW_PROPERTY_TEXT : { - char* txt = m_properties_expand_string(mp_properties,cmd->args[0].v.s); - /* if no argument supplied take default osd_duration, else <arg> ms. */ - if(txt) { - set_osd_msg(OSD_MSG_TEXT,cmd->args[2].v.i, - (cmd->args[1].v.i < 0 ? osd_duration : cmd->args[1].v.i), - "%-.63s",txt); - free(txt); - } - } break; - case MP_CMD_LOADFILE : { - play_tree_t* e = play_tree_new(); - play_tree_add_file(e,cmd->args[0].v.s); - - if (cmd->args[1].v.i) // append - play_tree_append_entry(playtree, e); - else { - // Go back to the starting point. - while(play_tree_iter_up_step(playtree_iter,0,1) != PLAY_TREE_ITER_END) - /* NOP */; - play_tree_free_list(playtree->child,1); - play_tree_set_child(playtree,e); - play_tree_iter_step(playtree_iter,0,0); - eof = PT_NEXT_SRC; - } - brk_cmd = 1; - } break; - case MP_CMD_LOADLIST : { - play_tree_t* e = parse_playlist_file(cmd->args[0].v.s); - if(!e) - mp_msg(MSGT_CPLAYER,MSGL_ERR,MSGTR_PlaylistLoadUnable,cmd->args[0].v.s); - else { - if (cmd->args[1].v.i) // append - play_tree_append_entry(playtree, e); - else { - // Go back to the starting point. - while(play_tree_iter_up_step(playtree_iter,0,1) != PLAY_TREE_ITER_END) - /* NOP */; - play_tree_free_list(playtree->child,1); - play_tree_set_child(playtree,e); - play_tree_iter_step(playtree_iter,0,0); - eof = PT_NEXT_SRC; - } - } - brk_cmd = 1; - } break; -#ifdef USE_RADIO - case MP_CMD_RADIO_STEP_CHANNEL : { - if (demuxer->stream->type==STREAMTYPE_RADIO) { - int v = cmd->args[0].v.i; - if(v > 0) - radio_step_channel(demuxer->stream, RADIO_CHANNEL_HIGHER); - else - radio_step_channel(demuxer->stream, RADIO_CHANNEL_LOWER); - if (radio_get_channel_name(demuxer->stream)) { - set_osd_msg(OSD_MSG_RADIO_CHANNEL,1,osd_duration, - MSGTR_OSDChannel, radio_get_channel_name(demuxer->stream)); - } - } - } break; - case MP_CMD_RADIO_SET_CHANNEL : { - if (demuxer->stream->type== STREAMTYPE_RADIO) { - radio_set_channel(demuxer->stream, cmd->args[0].v.s); - if (radio_get_channel_name(demuxer->stream)) { - set_osd_msg(OSD_MSG_RADIO_CHANNEL,1,osd_duration, - MSGTR_OSDChannel, radio_get_channel_name(demuxer->stream)); - } - } - } break; - case MP_CMD_RADIO_SET_FREQ : { - if (demuxer->stream->type== STREAMTYPE_RADIO) - radio_set_freq(demuxer->stream, cmd->args[0].v.f); - } break; - case MP_CMD_RADIO_STEP_FREQ : - if (demuxer->stream->type == STREAMTYPE_RADIO){ - radio_step_freq(demuxer->stream, cmd->args[0].v.f); - } - break; -#endif -#ifdef USE_TV - case MP_CMD_TV_SET_FREQ : { - if (file_format == DEMUXER_TYPE_TV) - tv_set_freq((tvi_handle_t*)(demuxer->priv), cmd->args[0].v.f * 16.0); - } break; - case MP_CMD_TV_SET_NORM : { - if (file_format == DEMUXER_TYPE_TV) - tv_set_norm((tvi_handle_t*)(demuxer->priv), cmd->args[0].v.s); - } break; - case MP_CMD_TV_STEP_CHANNEL : { - if (file_format == DEMUXER_TYPE_TV) { - int v = cmd->args[0].v.i; - if(v > 0){ - tv_step_channel((tvi_handle_t*)(demuxer->priv), TV_CHANNEL_HIGHER); - } else { - tv_step_channel((tvi_handle_t*)(demuxer->priv), TV_CHANNEL_LOWER); - } - if (tv_channel_list) { - set_osd_msg(OSD_MSG_TV_CHANNEL,1,osd_duration, - MSGTR_OSDChannel, tv_channel_current->name); - //vo_osd_changed(OSDTYPE_SUBTITLE); - } - } - } -#ifdef HAS_DVBIN_SUPPORT - if((stream->type == STREAMTYPE_DVB) && stream->priv) - { - dvb_priv_t *priv = (dvb_priv_t*) stream->priv; - if(priv->is_on) - { - int dir; - int v = cmd->args[0].v.i; - - last_dvb_step = v; - if(v > 0) - dir = DVB_CHANNEL_HIGHER; - else - dir = DVB_CHANNEL_LOWER; - - - if(dvb_step_channel(priv, dir)) - eof = dvbin_reopen = 1; - } - } -#endif /* HAS_DVBIN_SUPPORT */ - break; - case MP_CMD_TV_SET_CHANNEL : { - if (file_format == DEMUXER_TYPE_TV) { - tv_set_channel((tvi_handle_t*)(demuxer->priv), cmd->args[0].v.s); - if (tv_channel_list) { - set_osd_msg(OSD_MSG_TV_CHANNEL,1,osd_duration, - MSGTR_OSDChannel, tv_channel_current->name); - //vo_osd_changed(OSDTYPE_SUBTITLE); - } - } - } break; -#ifdef HAS_DVBIN_SUPPORT - case MP_CMD_DVB_SET_CHANNEL: - { - if((stream->type == STREAMTYPE_DVB) && stream->priv) - { - dvb_priv_t *priv = (dvb_priv_t*) stream->priv; - if(priv->is_on) - { - if(priv->list->current <= cmd->args[0].v.i) - last_dvb_step = 1; - else - last_dvb_step = -1; - - if(dvb_set_channel(priv, cmd->args[1].v.i, cmd->args[0].v.i)) - eof = dvbin_reopen = 1; - } - } - } - break; -#endif /* HAS_DVBIN_SUPPORT */ - case MP_CMD_TV_LAST_CHANNEL : { - if (file_format == DEMUXER_TYPE_TV) { - tv_last_channel((tvi_handle_t*)(demuxer->priv)); - if (tv_channel_list) { - set_osd_msg(OSD_MSG_TV_CHANNEL,1,osd_duration, - MSGTR_OSDChannel, tv_channel_current->name); - //vo_osd_changed(OSDTYPE_SUBTITLE); - } - } - } break; - case MP_CMD_TV_STEP_NORM : { - if (file_format == DEMUXER_TYPE_TV) - tv_step_norm((tvi_handle_t*)(demuxer->priv)); - } break; - case MP_CMD_TV_STEP_CHANNEL_LIST : { - if (file_format == DEMUXER_TYPE_TV) - tv_step_chanlist((tvi_handle_t*)(demuxer->priv)); - } break; -#endif /* USE_TV */ - case MP_CMD_SUB_LOAD: - { - if (sh_video) { - int n = set_of_sub_size; - add_subtitles(cmd->args[0].v.s, sh_video->fps, 0); - if (n != set_of_sub_size) { - if (global_sub_indices[SUB_SOURCE_SUBS] < 0) - global_sub_indices[SUB_SOURCE_SUBS] = global_sub_size; - ++global_sub_size; - } - } - } break; - case MP_CMD_SUB_REMOVE: - { - if (sh_video) { - int v = cmd->args[0].v.i; - sub_data *subd; - if (v < 0) { - for (v = 0; v < set_of_sub_size; ++v) { - subd = set_of_subtitles[v]; - mp_msg(MSGT_CPLAYER, MSGL_STATUS, MSGTR_RemovedSubtitleFile, v + 1, - filename_recode(subd->filename)); - sub_free(subd); - set_of_subtitles[v] = NULL; - } - global_sub_indices[SUB_SOURCE_SUBS] = -1; - global_sub_size -= set_of_sub_size; - set_of_sub_size = 0; - if (set_of_sub_pos >= 0) { - global_sub_pos = -2; - vo_sub_last = vo_sub = NULL; - vo_osd_changed(OSDTYPE_SUBTITLE); - vo_update_osd(sh_video->disp_w, sh_video->disp_h); - mp_input_queue_cmd(mp_input_parse_cmd("sub_select")); - } - } - else if (v < set_of_sub_size) { - subd = set_of_subtitles[v]; - mp_msg(MSGT_CPLAYER, MSGL_STATUS, MSGTR_RemovedSubtitleFile, v + 1, - filename_recode(subd->filename)); - sub_free(subd); - if (set_of_sub_pos == v) { - global_sub_pos = -2; - vo_sub_last = vo_sub = NULL; - vo_osd_changed(OSDTYPE_SUBTITLE); - vo_update_osd(sh_video->disp_w, sh_video->disp_h); - mp_input_queue_cmd(mp_input_parse_cmd("sub_select")); - } - else if (set_of_sub_pos > v) { - --set_of_sub_pos; - --global_sub_pos; - } - while (++v < set_of_sub_size) - set_of_subtitles[v - 1] = set_of_subtitles[v]; - --set_of_sub_size; - --global_sub_size; - if (set_of_sub_size <= 0) - global_sub_indices[SUB_SOURCE_SUBS] = -1; - set_of_subtitles[set_of_sub_size] = NULL; - } - } - } break; - case MP_CMD_GET_SUB_VISIBILITY: - { - if (sh_video) { - mp_msg(MSGT_GLOBAL,MSGL_INFO, "ANS_SUB_VISIBILITY=%d\n", sub_visibility); - } - } break; - case MP_CMD_SCREENSHOT : - if(vo_config_count){ - mp_msg(MSGT_CPLAYER,MSGL_INFO,"sending VFCTRL_SCREENSHOT!\n"); - if(CONTROL_OK!=((vf_instance_t *)sh_video->vfilter)->control(sh_video->vfilter, VFCTRL_SCREENSHOT, &cmd->args[0].v.i)) - video_out->control(VOCTRL_SCREENSHOT, NULL); - } - break; - case MP_CMD_VF_CHANGE_RECTANGLE: - set_rectangle(sh_video, cmd->args[0].v.i, cmd->args[1].v.i); - break; - - case MP_CMD_GET_TIME_LENGTH : { - mp_msg(MSGT_GLOBAL,MSGL_INFO, "ANS_LENGTH=%.2lf\n", demuxer_get_time_length(demuxer)); - } break; - - case MP_CMD_GET_FILENAME : { - mp_msg(MSGT_GLOBAL,MSGL_INFO, "ANS_FILENAME='%s'\n", get_metadata (META_NAME)); - } break; - - case MP_CMD_GET_VIDEO_CODEC : { - char *inf = get_metadata (META_VIDEO_CODEC); - if (!inf) inf = strdup (""); - mp_msg(MSGT_GLOBAL,MSGL_INFO, "ANS_VIDEO_CODEC='%s'\n", inf); - free (inf); - } break; - - case MP_CMD_GET_VIDEO_BITRATE : { - char *inf = get_metadata (META_VIDEO_BITRATE); - if (!inf) inf = strdup (""); - mp_msg(MSGT_GLOBAL,MSGL_INFO, "ANS_VIDEO_BITRATE='%s'\n", inf); - free (inf); - } break; - - case MP_CMD_GET_VIDEO_RESOLUTION : { - char *inf = get_metadata (META_VIDEO_RESOLUTION); - if (!inf) inf = strdup (""); - mp_msg(MSGT_GLOBAL,MSGL_INFO, "ANS_VIDEO_RESOLUTION='%s'\n", inf); - free (inf); - } break; - - case MP_CMD_GET_AUDIO_CODEC : { - char *inf = get_metadata (META_AUDIO_CODEC); - if (!inf) inf = strdup (""); - mp_msg(MSGT_GLOBAL,MSGL_INFO, "ANS_AUDIO_CODEC='%s'\n", inf); - free (inf); - } break; - - case MP_CMD_GET_AUDIO_BITRATE : { - char *inf = get_metadata (META_AUDIO_BITRATE); - if (!inf) inf = strdup (""); - mp_msg(MSGT_GLOBAL,MSGL_INFO, "ANS_AUDIO_BITRATE='%s'\n", inf); - free (inf); - } break; - - case MP_CMD_GET_AUDIO_SAMPLES : { - char *inf = get_metadata (META_AUDIO_SAMPLES); - if (!inf) inf = strdup (""); - mp_msg(MSGT_GLOBAL,MSGL_INFO, "ANS_AUDIO_SAMPLES='%s'\n", inf); - free (inf); - } break; - - case MP_CMD_GET_META_TITLE : { - char *inf = get_metadata (META_INFO_TITLE); - if (!inf) inf = strdup (""); - mp_msg(MSGT_GLOBAL,MSGL_INFO, "ANS_META_TITLE='%s'\n", inf); - free (inf); - } break; - - case MP_CMD_GET_META_ARTIST : { - char *inf = get_metadata (META_INFO_ARTIST); - if (!inf) inf = strdup (""); - mp_msg(MSGT_GLOBAL,MSGL_INFO, "ANS_META_ARTIST='%s'\n", inf); - free (inf); - } break; - - case MP_CMD_GET_META_ALBUM : { - char *inf = get_metadata (META_INFO_ALBUM); - if (!inf) inf = strdup (""); - mp_msg(MSGT_GLOBAL,MSGL_INFO, "ANS_META_ALBUM='%s'\n", inf); - free (inf); - } break; - - case MP_CMD_GET_META_YEAR : { - char *inf = get_metadata (META_INFO_YEAR); - if (!inf) inf = strdup (""); - mp_msg(MSGT_GLOBAL,MSGL_INFO, "ANS_META_YEAR='%s'\n", inf); - free (inf); - } break; - - case MP_CMD_GET_META_COMMENT : { - char *inf = get_metadata (META_INFO_COMMENT); - if (!inf) inf = strdup (""); - mp_msg(MSGT_GLOBAL,MSGL_INFO, "ANS_META_COMMENT='%s'\n", inf); - free (inf); - } break; - - case MP_CMD_GET_META_TRACK : { - char *inf = get_metadata (META_INFO_TRACK); - if (!inf) inf = strdup (""); - mp_msg(MSGT_GLOBAL,MSGL_INFO, "ANS_META_TRACK='%s'\n", inf); - free (inf); - } break; - - case MP_CMD_GET_META_GENRE : { - char *inf = get_metadata (META_INFO_GENRE); - if (!inf) inf = strdup (""); - mp_msg(MSGT_GLOBAL,MSGL_INFO, "ANS_META_GENRE='%s'\n", inf); - free (inf); - } break; - - case MP_CMD_GET_VO_FULLSCREEN : { - if(video_out && vo_config_count) - mp_msg(MSGT_GLOBAL,MSGL_INFO, "ANS_VO_FULLSCREEN=%d\n", vo_fs); - } break; - - case MP_CMD_GET_PERCENT_POS : { - mp_msg(MSGT_GLOBAL,MSGL_INFO, "ANS_PERCENT_POSITION=%d\n", demuxer_get_percent_pos(demuxer)); - } break; - case MP_CMD_GET_TIME_POS : { - float pos = 0; - if (sh_video) - pos = sh_video->pts; - else - if (sh_audio && audio_out) - pos = playing_audio_pts(sh_audio, d_audio, audio_out); - mp_msg(MSGT_GLOBAL, MSGL_INFO, "ANS_TIME_POSITION=%.1f\n", pos); - } break; - case MP_CMD_RUN : { -#ifndef __MINGW32__ - if(!fork()) { - execl("/bin/sh","sh","-c",cmd->args[0].v.s,NULL); - exit(0); - } -#endif - } break; - case MP_CMD_KEYDOWN_EVENTS : { - mplayer_put_key(cmd->args[0].v.i); - } break; - case MP_CMD_SEEK_CHAPTER : { - int seek = cmd->args[0].v.i; - int abs = (cmd->nargs > 1) ? cmd->args[1].v.i : 0; - int chap; - float next_pts = 0; - int num_chapters; - char *chapter_name; - - rel_seek_secs = 0; - abs_seek_pos = 0; - chap = demuxer_seek_chapter(demuxer, seek, abs, &next_pts, &num_chapters, &chapter_name); - if(chap != -1) { - if(next_pts > -1.0) { - abs_seek_pos = 1; - rel_seek_secs = next_pts; - } - if(chapter_name) { - set_osd_msg(OSD_MSG_TEXT, 1, osd_duration, MSGTR_OSDChapter, - chap+1, chapter_name); - free(chapter_name); - } - } else { - if (seek > 0) - rel_seek_secs = 1000000000.; - else - set_osd_msg(OSD_MSG_TEXT, 1, osd_duration, MSGTR_OSDChapter, 0, MSGTR_Unknown); - } - break; - } break; - case MP_CMD_SET_MOUSE_POS: { - int button = -1, pointer_x, pointer_y; - double dx, dy; - pointer_x = cmd->args[0].v.i; - pointer_y = cmd->args[1].v.i; - rescale_input_coordinates(pointer_x, pointer_y, &dx, &dy); -#ifdef USE_DVDNAV - if(stream->type == STREAMTYPE_DVDNAV && dx > 0.0 && dy > 0.0) { - pointer_x = (int) (dx * (double) sh_video->disp_w); - pointer_y = (int) (dy * (double) sh_video->disp_h); - mp_dvdnav_update_mouse_pos(stream, pointer_x, pointer_y, &button); - if(button>0) set_osd_msg(OSD_MSG_TEXT, 1, osd_duration, "Selected button number %d", button); - } -#endif - break; - } -#ifdef USE_DVDNAV - case MP_CMD_DVDNAV: { - int button = -1; - if(stream->type != STREAMTYPE_DVDNAV) break; - - if(mp_dvdnav_handle_input(stream, cmd->args[0].v.i, &button)) { - uninit_player(INITED_ALL-(INITED_STREAM|INITED_INPUT|(fixed_vo ? INITED_VO : 0))); - goto goto_enable_cache; - } else if(button>0) set_osd_msg(OSD_MSG_TEXT, 1, osd_duration, "Selected button number %d", button); - break; - } -#endif - default : { -#ifdef HAVE_NEW_GUI - if ( ( use_gui )&&( cmd->id > MP_CMD_GUI_EVENTS ) ) guiGetEvent( guiIEvent,(char *)cmd->id ); - else -#endif - mp_msg(MSGT_CPLAYER, MSGL_V, "Received unknown cmd %s\n",cmd->name); - } - } - switch (cmd->pausing) { - case 1: // "pausing" - osd_function = OSD_PAUSE; - break; - case 3: // "pausing_toggle" - was_paused = !was_paused; - // fall through - case 2: // "pausing_keep" - if (was_paused) osd_function = OSD_PAUSE; - } - mp_cmd_free(cmd); + brk_cmd = run_command(mpctx, cmd); + mp_cmd_free(cmd); + if (brk_cmd == 2) + goto goto_enable_cache; } } - was_paused = 0; + mpctx->was_paused = 0; if (seek_to_sec) { int a,b; float d; @@ -5455,59 +3451,59 @@ } /* Looping. */ - if(eof==1 && loop_times>=0) { + if(mpctx->eof==1 && loop_times>=0) { int l = loop_times; - play_tree_iter_step(playtree_iter,0,0); + play_tree_iter_step(mpctx->playtree_iter,0,0); loop_times = l; - mp_msg(MSGT_CPLAYER,MSGL_V,"loop_times = %d, eof = %d\n", loop_times,eof); + mp_msg(MSGT_CPLAYER,MSGL_V,"loop_times = %d, eof = %d\n", loop_times,mpctx->eof); if(loop_times>1) loop_times--; else if(loop_times==1) loop_times=-1; play_n_frames=play_n_frames_mf; - eof=0; + mpctx->eof=0; abs_seek_pos=3; rel_seek_secs=0; // seek to start of movie (0%) loop_seek = 1; } if(rel_seek_secs || abs_seek_pos){ current_module="seek"; - if(demux_seek(demuxer,rel_seek_secs,audio_delay,abs_seek_pos)){ + if(demux_seek(mpctx->demuxer,rel_seek_secs,audio_delay,abs_seek_pos)){ // success: /* FIXME there should be real seeking for vobsub */ - if(sh_video) sh_video->pts=d_video->pts; + if(mpctx->sh_video) mpctx->sh_video->pts=mpctx->d_video->pts; if (vo_vobsub) //vobsub_reset(vo_vobsub); - vobsub_seek(vo_vobsub,sh_video->pts); + vobsub_seek(vo_vobsub,mpctx->sh_video->pts); fflush(stdout); - if(sh_video){ + if(mpctx->sh_video){ current_module="seek_video_reset"; - resync_video_stream(sh_video); - if(vo_config_count) video_out->control(VOCTRL_RESET,NULL); - sh_video->num_buffered_pts = 0; - sh_video->last_pts = MP_NOPTS_VALUE; + resync_video_stream(mpctx->sh_video); + if(vo_config_count) mpctx->video_out->control(VOCTRL_RESET,NULL); + mpctx->sh_video->num_buffered_pts = 0; + mpctx->sh_video->last_pts = MP_NOPTS_VALUE; } - if(sh_audio){ + if(mpctx->sh_audio){ current_module="seek_audio_reset"; - audio_out->reset(); // stop audio, throwing away buffered data - sh_audio->a_buffer_len = 0; - sh_audio->a_out_buffer_len = 0; + mpctx->audio_out->reset(); // stop audio, throwing away buffered data + mpctx->sh_audio->a_buffer_len = 0; + mpctx->sh_audio->a_out_buffer_len = 0; } // Set OSD: if(!loop_seek){ if( !edl_decision ) - set_osd_bar(0,"Position",0,100,demuxer_get_percent_pos(demuxer)); + set_osd_bar(0,"Position",0,100,demuxer_get_percent_pos(mpctx->demuxer)); } - if(sh_video) { + if(mpctx->sh_video) { c_total=0; max_pts_correction=0.1; osd_visible=(GetTimerMS() + 1000) | 1; // to revert to PLAY pointer after 1 sec audio_time_usage=0; video_time_usage=0; vout_time_usage=0; drop_frame_cnt=0; - update_subtitles(sh_video, d_dvdsub, 1); + update_subtitles(mpctx->sh_video, mpctx->d_sub, 1); } } /* @@ -5515,7 +3511,7 @@ * and find the next EDL action to take care of. */ -edl_muted = 0; +mpctx->edl_muted = 0; next_edl_record = edl_records; while (next_edl_record) @@ -5524,14 +3520,14 @@ * prior EDL implementation lacks this. */ - if (next_edl_record->start_sec >= sh_video->pts) + if (next_edl_record->start_sec >= mpctx->sh_video->pts) break; - if (next_edl_record->action == EDL_MUTE) edl_muted = !edl_muted; + if (next_edl_record->action == EDL_MUTE) mpctx->edl_muted = !mpctx->edl_muted; next_edl_record = next_edl_record->next; } -if ((user_muted | edl_muted) != mixer.muted) mixer_mute(&mixer); +if ((mpctx->user_muted | mpctx->edl_muted) != mpctx->mixer.muted) mixer_mute(&mpctx->mixer); rel_seek_secs=0; abs_seek_pos=0; @@ -5543,43 +3539,43 @@ #ifdef HAVE_NEW_GUI if(use_gui){ guiEventHandling(); - if(demuxer->file_format==DEMUXER_TYPE_AVI && sh_video && sh_video->video.dwLength>2){ + if(mpctx->demuxer->file_format==DEMUXER_TYPE_AVI && mpctx->sh_video && mpctx->sh_video->video.dwLength>2){ // get pos from frame number / total frames - guiIntfStruct.Position=(float)d_video->pack_no*100.0f/sh_video->video.dwLength; + guiIntfStruct.Position=(float)mpctx->d_video->pack_no*100.0f/mpctx->sh_video->video.dwLength; } else { - off_t len = ( demuxer->movi_end - demuxer->movi_start ); - off_t pos = ( demuxer->file_format == DEMUXER_TYPE_AUDIO?stream->pos:demuxer->filepos ); - guiIntfStruct.Position=(len <= 0? 0.0f : ( pos - demuxer->movi_start ) * 100.0f / len ); - } - if ( sh_video ) guiIntfStruct.TimeSec=sh_video->pts; - else if ( sh_audio ) guiIntfStruct.TimeSec=sh_audio->delay; - guiIntfStruct.LengthInSec=demuxer_get_time_length(demuxer); + off_t len = ( mpctx->demuxer->movi_end - mpctx->demuxer->movi_start ); + off_t pos = ( mpctx->demuxer->file_format == DEMUXER_TYPE_AUDIO?mpctx->stream->pos:mpctx->demuxer->filepos ); + guiIntfStruct.Position=(len <= 0? 0.0f : ( pos - mpctx->demuxer->movi_start ) * 100.0f / len ); + } + if ( mpctx->sh_video ) guiIntfStruct.TimeSec=mpctx->sh_video->pts; + else if ( mpctx->sh_audio ) guiIntfStruct.TimeSec=mpctx->sh_audio->delay; + guiIntfStruct.LengthInSec=demuxer_get_time_length(mpctx->demuxer); guiGetEvent( guiReDraw,NULL ); guiGetEvent( guiSetVolume,NULL ); if(guiIntfStruct.Playing==0) break; // STOP - if(guiIntfStruct.Playing==2) osd_function=OSD_PAUSE; + if(guiIntfStruct.Playing==2) mpctx->osd_function=OSD_PAUSE; if ( guiIntfStruct.DiskChanged || guiIntfStruct.NewPlay ) goto goto_next_file; #ifdef USE_DVDREAD - if ( stream->type == STREAMTYPE_DVD ) + if ( mpctx->stream->type == STREAMTYPE_DVD ) { - dvd_priv_t * dvdp = stream->priv; + dvd_priv_t * dvdp = mpctx->stream->priv; guiIntfStruct.DVD.current_chapter=dvd_chapter_from_cell(dvdp,guiIntfStruct.DVD.current_title-1, dvdp->cur_cell)+1; } #endif } #endif /* HAVE_NEW_GUI */ -} // while(!eof) +} // while(!mpctx->eof) -mp_msg(MSGT_GLOBAL,MSGL_V,"EOF code: %d \n",eof); +mp_msg(MSGT_GLOBAL,MSGL_V,"EOF code: %d \n",mpctx->eof); #ifdef HAS_DVBIN_SUPPORT -if(dvbin_reopen) +if(mpctx->dvbin_reopen) { - eof = 0; + mpctx->eof = 0; uninit_player(INITED_ALL-(INITED_STREAM|INITED_INPUT)); - cache_uninit(stream); - dvbin_reopen = 0; + cache_uninit(mpctx->stream); + mpctx->dvbin_reopen = 0; goto goto_enable_cache; } #endif @@ -5618,17 +3614,17 @@ // time to uninit all, except global stuff: uninit_player(INITED_ALL-(INITED_GUI+INITED_INPUT+(fixed_vo?INITED_VO:0))); - if ( set_of_sub_size > 0 ) + if ( mpctx->set_of_sub_size > 0 ) { current_module="sub_free"; - for (i = 0; i < set_of_sub_size; ++i) { - sub_free( set_of_subtitles[i] ); + for (i = 0; i < mpctx->set_of_sub_size; ++i) { + sub_free( mpctx->set_of_subtitles[i] ); #ifdef USE_ASS - if ( set_of_ass_tracks[i] ) - ass_free_track( set_of_ass_tracks[i] ); + if ( mpctx->set_of_ass_tracks[i] ) + ass_free_track( mpctx->set_of_ass_tracks[i] ); #endif } - set_of_sub_size = 0; + mpctx->set_of_sub_size = 0; } vo_sub_last = vo_sub=NULL; subdata=NULL; @@ -5636,44 +3632,44 @@ ass_track = NULL; #endif -if(eof == PT_NEXT_ENTRY || eof == PT_PREV_ENTRY) { - eof = eof == PT_NEXT_ENTRY ? 1 : -1; - if(play_tree_iter_step(playtree_iter,play_tree_step,0) == PLAY_TREE_ITER_ENTRY) { - eof = 1; +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 { - play_tree_iter_free(playtree_iter); - playtree_iter = NULL; + play_tree_iter_free(mpctx->playtree_iter); + mpctx->playtree_iter = NULL; } - play_tree_step = 1; -} else if (eof == PT_UP_NEXT || eof == PT_UP_PREV) { - eof = eof == PT_UP_NEXT ? 1 : -1; - if ( playtree_iter ) { - if(play_tree_iter_up_step(playtree_iter,eof,0) == PLAY_TREE_ITER_ENTRY) { - eof = 1; + 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; + if ( mpctx->playtree_iter ) { + if(play_tree_iter_up_step(mpctx->playtree_iter,mpctx->eof,0) == PLAY_TREE_ITER_ENTRY) { + mpctx->eof = 1; } else { - play_tree_iter_free(playtree_iter); - playtree_iter = NULL; + play_tree_iter_free(mpctx->playtree_iter); + mpctx->playtree_iter = NULL; } } } else { // NEXT PREV SRC - eof = eof == PT_PREV_SRC ? -1 : 1; + mpctx->eof = mpctx->eof == PT_PREV_SRC ? -1 : 1; } -if(eof == 0) eof = 1; +if(mpctx->eof == 0) mpctx->eof = 1; -while(playtree_iter != NULL) { - filename = play_tree_iter_get_file(playtree_iter,eof); +while(mpctx->playtree_iter != NULL) { + filename = play_tree_iter_get_file(mpctx->playtree_iter,mpctx->eof); if(filename == NULL) { - if( play_tree_iter_step(playtree_iter,eof,0) != PLAY_TREE_ITER_ENTRY) { - play_tree_iter_free(playtree_iter); - playtree_iter = NULL; + if( play_tree_iter_step(mpctx->playtree_iter,mpctx->eof,0) != PLAY_TREE_ITER_ENTRY) { + play_tree_iter_free(mpctx->playtree_iter); + mpctx->playtree_iter = NULL; }; } else break; } #ifdef HAVE_NEW_GUI - if( use_gui && !playtree_iter ) + if( use_gui && !mpctx->playtree_iter ) { #ifdef USE_DVDREAD if ( !guiIntfStruct.DiskChanged ) @@ -5682,9 +3678,9 @@ } #endif -if(use_gui || playtree_iter != NULL || player_idle_mode){ - if (!playtree_iter) filename = NULL; - eof = 0; +if(use_gui || mpctx->playtree_iter != NULL || player_idle_mode){ + if (!mpctx->playtree_iter) filename = NULL; + mpctx->eof = 0; goto play_next_file; }
Hello, On Wed, Feb 21, 2007 at 01:49:25AM +0100, uau wrote:
Author: uau Date: Wed Feb 21 01:49:24 2007 New Revision: 22298
Added: trunk/command.c trunk/command.h trunk/mp_core.h Modified: trunk/Makefile trunk/m_property.c trunk/m_property.h trunk/mplayer.c
Log: Split command/property handling from mplayer.c to a new file command.c. Move some global and static variables under a struct that can be given as a parameter. Add a context argument to the property functions so that they do not have to depend on global/static variables.
To anyone who actually believes in the sense of a cvslog list: svn up -r22297 mplayer.c diff -duwbB mplayer.c command.c | less Might give you back some hope. It's almost readable, despite in some places automated reindent has taken its toll. Greetings, Reimar Döffinger
Hi On Wed, Feb 21, 2007 at 06:29:59PM +0100, Reimar Döffinger wrote:
Hello, On Wed, Feb 21, 2007 at 01:49:25AM +0100, uau wrote:
Author: uau Date: Wed Feb 21 01:49:24 2007 New Revision: 22298
Added: trunk/command.c trunk/command.h trunk/mp_core.h Modified: trunk/Makefile trunk/m_property.c trunk/m_property.h trunk/mplayer.c
Log: Split command/property handling from mplayer.c to a new file command.c. Move some global and static variables under a struct that can be given as a parameter. Add a context argument to the property functions so that they do not have to depend on global/static variables.
To anyone who actually believes in the sense of a cvslog list: svn up -r22297 mplayer.c diff -duwbB mplayer.c command.c | less
Might give you back some hope. It's almost readable, despite in some places automated reindent has taken its toll.
well, adding a new file instead of using proper svn cp and mixing cosmetics and functional changes are svn policy violations so i request reversal of this [...] -- Michael GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB Dictatorship naturally arises out of democracy, and the most aggravated form of tyranny and slavery out of the most extreme liberty. -- Plato
Hi, On Wednesday, 21 February 2007 at 20:05, Michael Niedermayer wrote:
On Wed, Feb 21, 2007 at 06:29:59PM +0100, Reimar Döffinger wrote:
On Wed, Feb 21, 2007 at 01:49:25AM +0100, uau wrote:
Log: Split command/property handling from mplayer.c to a new file command.c. Move some global and static variables under a struct that can be given as a parameter. Add a context argument to the property functions so that they do not have to depend on global/static variables.
To anyone who actually believes in the sense of a cvslog list: svn up -r22297 mplayer.c diff -duwbB mplayer.c command.c | less
Might give you back some hope. It's almost readable, despite in some places automated reindent has taken its toll.
well, adding a new file instead of using proper svn cp and mixing cosmetics and functional changes are svn policy violations so i request reversal of this
Uoti, why haven't you done this? Regards, R. -- MPlayer developer and RPMs maintainer: http://mplayerhq.hu http://rpm.livna.org There should be a science of discontent. People need hard times and oppression to develop psychic muscles. -- from "Collected Sayings of Muad'Dib" by the Princess Irulan
On Friday, 23 February 2007 at 09:12, Dominik 'Rathann' Mierzejewski wrote:
Hi,
On Wednesday, 21 February 2007 at 20:05, Michael Niedermayer wrote:
On Wed, Feb 21, 2007 at 06:29:59PM +0100, Reimar Döffinger wrote:
On Wed, Feb 21, 2007 at 01:49:25AM +0100, uau wrote:
Log: Split command/property handling from mplayer.c to a new file command.c. Move some global and static variables under a struct that can be given as a parameter. Add a context argument to the property functions so that they do not have to depend on global/static variables.
To anyone who actually believes in the sense of a cvslog list: svn up -r22297 mplayer.c diff -duwbB mplayer.c command.c | less
Might give you back some hope. It's almost readable, despite in some places automated reindent has taken its toll.
well, adding a new file instead of using proper svn cp and mixing cosmetics and functional changes are svn policy violations so i request reversal of this
Uoti, why haven't you done this?
Well? If nobody wants to reverse and recommit, I'll try to do it tonight. Regards, R. -- MPlayer developer and RPMs maintainer: http://mplayerhq.hu http://rpm.livna.org There should be a science of discontent. People need hard times and oppression to develop psychic muscles. -- from "Collected Sayings of Muad'Dib" by the Princess Irulan
Hello, On Wed, Feb 21, 2007 at 01:49:25AM +0100, uau wrote:
+static MPContext *mpctx = &(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, +};
Can someone enlighten me on the specifics of this constructs? Esp. if it is valid for the compiler to place this into .rodata or similar, because this is what valgrind gives on my 32 bit system: ==8315== Process terminating with default action of signal 11 (SIGSEGV) ==8315== Bad permissions for mapped region at address 0x85C5898 ==8315== at 0x807FDD8: main (mplayer.c:2233) Greetings, Reimar Döffinger
Reimar Döffinger wrote:
On Wed, Feb 21, 2007 at 01:49:25AM +0100, uau wrote:
+static MPContext *mpctx = &(MPContext){ + .osd_function = OSD_PLAY, ...
Can someone enlighten me on the specifics of this constructs? Esp. if it is valid for the compiler to place this into .rodata or similar,
Compound literals can be read-only, like string literals. HTH Clemens
On Thu, 2007-02-22 at 15:40 +0100, Reimar Döffinger wrote:
Hello, On Wed, Feb 21, 2007 at 01:49:25AM +0100, uau wrote:
+static MPContext *mpctx = &(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, +};
Can someone enlighten me on the specifics of this constructs? Esp. if it is valid for the compiler to place this into .rodata or similar, because this is what valgrind gives on my 32 bit system:
==8315== Process terminating with default action of signal 11 (SIGSEGV) ==8315== Bad permissions for mapped region at address 0x85C5898 ==8315== at 0x807FDD8: main (mplayer.c:2233)
No that is not valid. Looks like it was miscompiled. The C99 standard says (part 6.5.2.5) "String literals, and compound literals with const-qualified types, need not designate dintinct objects". There is nothing const-qualified about that.
Hello, On Thu, Feb 22, 2007 at 06:52:54PM +0200, Uoti Urpala wrote:
On Thu, 2007-02-22 at 15:40 +0100, Reimar Döffinger wrote:
On Wed, Feb 21, 2007 at 01:49:25AM +0100, uau wrote:
+static MPContext *mpctx = &(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, +};
Can someone enlighten me on the specifics of this constructs? Esp. if it is valid for the compiler to place this into .rodata or similar, because this is what valgrind gives on my 32 bit system:
==8315== Process terminating with default action of signal 11 (SIGSEGV) ==8315== Bad permissions for mapped region at address 0x85C5898 ==8315== at 0x807FDD8: main (mplayer.c:2233)
No that is not valid. Looks like it was miscompiled. The C99 standard says (part 6.5.2.5) "String literals, and compound literals with const-qualified types, need not designate dintinct objects". There is nothing const-qualified about that.
Huh? If there is nothing const-qualified about this, the cited part does not say anything at all about this case... Also I'd avoid C99 dependencies if avoidable... And yes, I probably should just read that stuff myself. Greetings, Reimar Döffinger
On Thu, 2007-02-22 at 18:29 +0100, Reimar Döffinger wrote:
No that is not valid. Looks like it was miscompiled. The C99 standard says (part 6.5.2.5) "String literals, and compound literals with const-qualified types, need not designate dintinct objects". There is nothing const-qualified about that.
Huh? If there is nothing const-qualified about this, the cited part does not say anything at all about this case...
The spec doesn't explicitly say "non-const objects must not be in read-only memory", but I think that can be assumed. This part can also be thought to be relevant: 5. If the type name specifies an array of an unknown size, the size is determined by the initializer list as specified in 6.7.8, and the type of the compound literal is that of the completed array type. Otherwise (when the type name specifies an object type), the type of the compound literal is that specified by the type name. In either case, the result is an lvalue. Note "type ... specified by the type name", no magically added "const". Also example 5 is The following three expressions have different meanings: "/tmp/fileXXXXXX" (char []){"/tmp/fileXXXXXX"} (const char []){"/tmp/fileXXXXXX"} The first always has static storage duration and has type array of char, but need not be modifiable; the last two have automatic storage duration when they occur within the body of a function, and the first of these two is modifiable.
On Wednesday 21 February 2007 01:49, uau wrote: [..]
+// Not all functions in mplayer.c take the context as an argument yet +static MPContext *mpctx = &(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, +};
This compiles but does not work with gcc 2.95. Program received signal SIGSEGV, Segmentation fault. [Switching to Thread 16384 (LWP 16224)] 0x08079efb in main (argc=1080797110, argv=0xbf9a2908) at mplayer.c:2335 2335 mpctx->playtree = m_config_parse_mp_command_line(mconfig, argc, argv); 0x08079eef <main+459>: call 0x80a1ca0 <m_config_parse_mp_command_line> 0x08079ef4 <main+464>: mov %eax,%edx 0x08079ef6 <main+466>: mov 0x865f184,%eax 0x08079efb <main+471>: mov %edx,0xc(%eax) It's the assignment that segfaults. It works if you change it to: Index: mplayer.c =================================================================== --- mplayer.c (revision 22402) +++ mplayer.c (working copy) @@ -193,7 +193,7 @@ //**************************************************************************// // Not all functions in mplayer.c take the context as an argument yet -static MPContext *mpctx = &(MPContext){ +static MPContext mpctx_static = { .osd_function = OSD_PLAY, .begin_skip = MP_NOPTS_VALUE, .play_tree_step = 1, @@ -204,6 +204,7 @@ .last_dvb_step = 1, #endif }; +static MPContext *mpctx = &mpctx_static; int fixed_vo=0; --Ivo
participants (7)
-
Clemens Ladisch -
Dominik 'Rathann' Mierzejewski -
Ivo -
Michael Niedermayer -
Reimar Döffinger -
uau -
Uoti Urpala