diff options
-rw-r--r-- | DOCS/man/en/changes.rst | 4 | ||||
-rw-r--r-- | DOCS/man/en/options.rst | 12 | ||||
-rw-r--r-- | cfg-mplayer.h | 11 | ||||
-rw-r--r-- | command.c | 460 | ||||
-rw-r--r-- | m_config.c | 4 | ||||
-rw-r--r-- | m_config.h | 3 | ||||
-rw-r--r-- | m_property.c | 71 | ||||
-rw-r--r-- | m_property.h | 41 |
8 files changed, 242 insertions, 364 deletions
diff --git a/DOCS/man/en/changes.rst b/DOCS/man/en/changes.rst index ec08c7eac2..11b7242d1a 100644 --- a/DOCS/man/en/changes.rst +++ b/DOCS/man/en/changes.rst @@ -97,6 +97,10 @@ Command line switches -loop 0 --loop=inf -hardframedrop --framedrop=hard -osdlevel --osd-level + -delay --audio-delay + -subdelay --sub-delay + -subpos --sub-pos + -forcedsubsonly --sub-forced-only =================================== =================================== input.conf and slave commands diff --git a/DOCS/man/en/options.rst b/DOCS/man/en/options.rst index da7ed79e03..342626d5d2 100644 --- a/DOCS/man/en/options.rst +++ b/DOCS/man/en/options.rst @@ -472,7 +472,7 @@ will stay hidden. Supported by video output drivers which use X11 or OS X Cocoa. ---delay=<sec> +--audio-delay=<sec> audio delay in seconds (positive or negative float value). Negative values delay the audio, and positive values delay the video. @@ -624,7 +624,7 @@ there is a change in video parameters, video stream or file. This used to be the default behavior. Currently only affects X11 VOs. ---forcedsubsonly +--sub-forced-only Display only forced subtitles for the DVD subtitle stream selected by e.g. ``--slang``. @@ -659,6 +659,7 @@ Specifies the character set that will be passed to FriBiDi when decoding non-UTF-8 subtitles (default: ISO8859-8). +--fullscreen --fs Fullscreen playback (centers movie, and paints black bands around it). @@ -1312,9 +1313,6 @@ controls how much of the image is cropped. May not work with all video output drivers. - *NOTE*: Values between -1 and 0 are allowed as well, but highly - experimental and may crash or worse. Use at your own risk! - --panscanrange=<-19.0-99.0> (experimental) Change the range of the pan-and-scan functionality (default: 1). Positive @@ -1894,7 +1892,7 @@ - ``--subcp=enca:pl:cp1250`` guess the encoding for Polish, fall back on cp1250. ---subdelay=<sec> +--sub-delay=<sec> Delays subtitles by <sec> seconds. Can be negative. --subfile=<filename> @@ -1941,7 +1939,7 @@ *NOTE*: <rate> > movie fps speeds the subtitles up for frame-based subtitle files and slows them down for time-based ones. ---subpos=<0-100> +--sub-pos=<0-100> Specify the position of subtitles on the screen. The value is the vertical position of the subtitle in % of the screen height. Can be useful with ``--vf=expand``. diff --git a/cfg-mplayer.h b/cfg-mplayer.h index dd90df21d6..db99b1da28 100644 --- a/cfg-mplayer.h +++ b/cfg-mplayer.h @@ -459,7 +459,7 @@ const m_option_t common_opts[] = { OPT_FLOATRANGE("speed", playback_speed, 0, 0.01, 100.0), // set a-v distance - {"delay", &audio_delay, CONF_TYPE_FLOAT, CONF_RANGE, -100.0, 100.0, NULL}, + {"audio-delay", &audio_delay, CONF_TYPE_FLOAT, CONF_RANGE, -100.0, 100.0, NULL}, // ignore header-specified delay (dwStart) {"ignore-start", &ignore_start, CONF_TYPE_FLAG, 0, 0, 1, NULL}, @@ -512,12 +512,12 @@ const m_option_t common_opts[] = { OPT_STRINGLIST("sub", sub_name, 0), OPT_PATHLIST("sub-paths", sub_paths, 0), {"subcp", &sub_cp, CONF_TYPE_STRING, 0, 0, 0, NULL}, - {"subdelay", &sub_delay, CONF_TYPE_FLOAT, 0, 0.0, 10.0, NULL}, + {"sub-delay", &sub_delay, CONF_TYPE_FLOAT, 0, 0.0, 10.0, NULL}, {"subfps", &sub_fps, CONF_TYPE_FLOAT, 0, 0.0, 10.0, NULL}, OPT_MAKE_FLAGS("autosub", sub_auto, 0), {"unicode", &sub_unicode, CONF_TYPE_FLAG, 0, 0, 1, NULL}, {"utf8", &sub_utf8, CONF_TYPE_FLAG, 0, 0, 1, NULL}, - {"forcedsubsonly", &forced_subs_only, CONF_TYPE_FLAG, 0, 0, 1, NULL}, + {"sub-forced-only", &forced_subs_only, CONF_TYPE_FLAG, 0, 0, 1, NULL}, // specify IFO file for VOBSUB subtitle {"ifo", &spudec_ifo, CONF_TYPE_STRING, 0, 0, 0, NULL}, // enable Closed Captioning display @@ -529,7 +529,7 @@ const m_option_t common_opts[] = { {"font", &font_name, CONF_TYPE_STRING, 0, 0, 0, NULL}, {"subfont", &sub_font_name, CONF_TYPE_STRING, 0, 0, 0, NULL}, {"ffactor", &font_factor, CONF_TYPE_FLOAT, CONF_RANGE, 0.0, 10.0, NULL}, - {"subpos", &sub_pos, CONF_TYPE_INT, CONF_RANGE, 0, 100, NULL}, + {"sub-pos", &sub_pos, CONF_TYPE_INT, CONF_RANGE, 0, 100, NULL}, {"subwidth", &sub_width_p, CONF_TYPE_INT, CONF_RANGE, 10, 100, NULL}, {"spualign", &spu_alignment, CONF_TYPE_INT, CONF_RANGE, -1, 2, NULL}, {"spuaa", &spu_aamode, CONF_TYPE_INT, CONF_RANGE, 0, 31, NULL}, @@ -618,6 +618,7 @@ const m_option_t mplayer_opts[]={ // video mode switching: (x11,xv,dga) OPT_MAKE_FLAGS("vm", vidmode, 0), // start in fullscreen mode: + OPT_MAKE_FLAGS("fullscreen", fullscreen, CONF_GLOBAL), OPT_MAKE_FLAGS("fs", fullscreen, CONF_GLOBAL), // set fullscreen switch method (workaround for buggy WMs) {"fsmode-dontuse", &vo_fsmode, CONF_TYPE_INT, CONF_RANGE, 0, 31, NULL}, @@ -628,7 +629,7 @@ const m_option_t mplayer_opts[]={ {"double", &vo_doublebuffering, CONF_TYPE_FLAG, 0, 0, 1, NULL}, // wait for v-sync (gl) {"vsync", &vo_vsync, CONF_TYPE_FLAG, 0, 0, 1, NULL}, - {"panscan", &vo_panscan, CONF_TYPE_FLOAT, CONF_RANGE, -1.0, 1.0, NULL}, + {"panscan", &vo_panscan, CONF_TYPE_FLOAT, CONF_RANGE, 0, 1.0, NULL}, OPT_FLOATRANGE("panscanrange", vo_panscanrange, 0, -19.0, 99.0), OPT_CHOICE("colormatrix", requested_colorspace, 0, ({"auto", MP_CSP_AUTO}, @@ -114,23 +114,24 @@ static void rescale_input_coordinates(struct MPContext *mpctx, int ix, int iy, vo->dheight, vo_fs); } +// Property-option bridge. static int mp_property_generic_option(struct m_option *prop, int action, void *arg, MPContext *mpctx) { char *optname = prop->priv; - const struct m_option *opt = m_config_get_option(mpctx->mconfig, - bstr0(optname)); - void *valptr = m_option_get_ptr(opt, &mpctx->opts); + struct m_config_option *opt = m_config_get_co(mpctx->mconfig, + bstr0(optname)); + void *valptr = opt->data; switch (action) { case M_PROPERTY_GET_TYPE: - *(const struct m_option **)arg = opt; + *(const struct m_option **)arg = opt->opt; return M_PROPERTY_OK; case M_PROPERTY_GET: - m_option_copy(opt, arg, valptr); + m_option_copy(opt->opt, arg, valptr); return M_PROPERTY_OK; case M_PROPERTY_SET: - m_option_copy(opt, valptr, arg); + m_option_copy(opt->opt, valptr, arg); return M_PROPERTY_OK; } return M_PROPERTY_NOT_IMPLEMENTED; @@ -141,36 +142,42 @@ static int mp_property_playback_speed(m_option_t *prop, int action, void *arg, MPContext *mpctx) { struct MPOpts *opts = &mpctx->opts; - double orig_speed = opts->playback_speed; - switch (action) { - case M_PROPERTY_SET: + if (action == M_PROPERTY_SET) { + double orig_speed = opts->playback_speed; opts->playback_speed = *(float *) arg; // Adjust time until next frame flip for nosound mode mpctx->time_frame *= orig_speed / opts->playback_speed; reinit_audio_chain(mpctx); return M_PROPERTY_OK; } - return m_property_float_range(prop, action, arg, &opts->playback_speed); + return mp_property_generic_option(prop, action, arg, mpctx); } /// 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, mpctx->filename); + if (action == M_PROPERTY_GET) { + *(char **)arg = talloc_strdup(NULL, mpctx->filename); + return M_PROPERTY_OK; + } + return M_PROPERTY_NOT_IMPLEMENTED; } /// filename without path (RO) static int mp_property_filename(m_option_t *prop, int action, void *arg, MPContext *mpctx) { - char *f; if (!mpctx->filename) return M_PROPERTY_UNAVAILABLE; - f = (char *)mp_basename(mpctx->filename); - if (!*f) - f = mpctx->filename; - return m_property_string_ro(prop, action, arg, f); + if (action == M_PROPERTY_GET) { + char *f = (char *)mp_basename(mpctx->filename); + if (!*f) + f = mpctx->filename; + *(char **)arg = talloc_strdup(NULL, f); + return M_PROPERTY_OK; + } + return M_PROPERTY_NOT_IMPLEMENTED; } /// Demuxer name (RO) @@ -180,7 +187,11 @@ static int mp_property_demuxer(m_option_t *prop, int action, void *arg, struct demuxer *demuxer = mpctx->master_demuxer; if (!demuxer) return M_PROPERTY_UNAVAILABLE; - return m_property_string_ro(prop, action, arg, (char *)demuxer->desc->name); + if (action == M_PROPERTY_GET) { + *(char **)arg = talloc_strdup(NULL, demuxer->desc->name); + return M_PROPERTY_OK; + } + return M_PROPERTY_NOT_IMPLEMENTED; } /// Position in the stream (RW) @@ -277,21 +288,19 @@ static int mp_property_length(m_option_t *prop, int action, void *arg, static int mp_property_percent_pos(m_option_t *prop, int action, void *arg, MPContext *mpctx) { - int pos; - if (!mpctx->num_sources) return M_PROPERTY_UNAVAILABLE; switch (action) { - case M_PROPERTY_SET: - pos = *(int *)arg; - break; - default: - return m_property_int_ro(prop, action, arg, get_percent_pos(mpctx)); + case M_PROPERTY_SET: ; + int pos = *(int *)arg; + queue_seek(mpctx, MPSEEK_FACTOR, pos / 100.0, 0); + return M_PROPERTY_OK; + case M_PROPERTY_GET: + *(int *)arg = get_percent_pos(mpctx); + return M_PROPERTY_OK; } - - queue_seek(mpctx, MPSEEK_FACTOR, pos / 100.0, 0); - return M_PROPERTY_OK; + return M_PROPERTY_NOT_IMPLEMENTED; } /// Current position in seconds (RW) @@ -305,8 +314,11 @@ static int mp_property_time_pos(m_option_t *prop, int action, case M_PROPERTY_SET: queue_seek(mpctx, MPSEEK_ABSOLUTE, *(double *)arg, 0); return M_PROPERTY_OK; + case M_PROPERTY_GET: + *(double *)arg = get_current_time(mpctx); + return M_PROPERTY_OK; } - return m_property_double_ro(prop, action, arg, get_current_time(mpctx)); + return M_PROPERTY_NOT_IMPLEMENTED; } /// Current chapter (RW) @@ -314,7 +326,6 @@ static int mp_property_chapter(m_option_t *prop, int action, void *arg, MPContext *mpctx) { struct MPOpts *opts = &mpctx->opts; - int step_all; char *chapter_name = NULL; int chapter = get_current_chapter(mpctx); @@ -332,30 +343,27 @@ static int mp_property_chapter(m_option_t *prop, int action, void *arg, *(char **) arg = chapter_name; return M_PROPERTY_OK; } - case M_PROPERTY_SET: - step_all = *(int *)arg - chapter; + case M_PROPERTY_SET: ; + int step_all = *(int *)arg - chapter; chapter += step_all; - break; - default: - return M_PROPERTY_NOT_IMPLEMENTED; + double next_pts = 0; + queue_seek(mpctx, MPSEEK_NONE, 0, 0); + chapter = seek_chapter(mpctx, chapter, &next_pts); + if (chapter >= 0) { + if (next_pts > -1.0) + queue_seek(mpctx, MPSEEK_ABSOLUTE, next_pts, 0); + chapter_name = chapter_display_name(mpctx, chapter); + set_osd_tmsg(mpctx, OSD_MSG_TEXT, 1, opts->osd_duration, + "Chapter: %s", chapter_name); + } else if (step_all > 0) + mpctx->stop_play = PT_NEXT_ENTRY; + else + set_osd_tmsg(mpctx, OSD_MSG_TEXT, 1, opts->osd_duration, + "Chapter: (%d) %s", 0, mp_gtext("unknown")); + talloc_free(chapter_name); + return M_PROPERTY_OK; } - - double next_pts = 0; - queue_seek(mpctx, MPSEEK_NONE, 0, 0); - chapter = seek_chapter(mpctx, chapter, &next_pts); - if (chapter >= 0) { - if (next_pts > -1.0) - queue_seek(mpctx, MPSEEK_ABSOLUTE, next_pts, 0); - chapter_name = chapter_display_name(mpctx, chapter); - set_osd_tmsg(mpctx, OSD_MSG_TEXT, 1, opts->osd_duration, - "Chapter: %s", chapter_name); - } else if (step_all > 0) - mpctx->stop_play = PT_NEXT_ENTRY; - else - set_osd_tmsg(mpctx, OSD_MSG_TEXT, 1, opts->osd_duration, - "Chapter: (%d) %s", 0, mp_gtext("unknown")); - talloc_free(chapter_name); - return M_PROPERTY_OK; + return M_PROPERTY_NOT_IMPLEMENTED; } static int mp_property_edition(m_option_t *prop, int action, void *arg, @@ -372,8 +380,8 @@ static int mp_property_edition(m_option_t *prop, int action, void *arg, switch (action) { case M_PROPERTY_GET: - case M_PROPERTY_PRINT: - return m_property_int_ro(prop, action, arg, edition); + *(int *)arg = edition; + return M_PROPERTY_OK; case M_PROPERTY_SET: edition = *(int *)arg; break; @@ -457,26 +465,22 @@ static int mp_property_angle(m_option_t *prop, int action, void *arg, return M_PROPERTY_OK; } case M_PROPERTY_SET: - angle = *(int *)arg; - break; + angle = demuxer_set_angle(demuxer, *(int *)arg); + if (angle >= 0) { + struct sh_video *sh_video = demuxer->video->sh; + if (sh_video) + resync_video_stream(sh_video); + + struct sh_audio *sh_audio = demuxer->audio->sh; + if (sh_audio) + resync_audio_stream(sh_audio); + } + return M_PROPERTY_OK; case M_PROPERTY_SWITCH: // NOTE: should cycle return M_PROPERTY_NOT_IMPLEMENTED; - default: - return M_PROPERTY_NOT_IMPLEMENTED; - } - angle = demuxer_set_angle(demuxer, angle); - if (angle >= 0) { - struct sh_video *sh_video = demuxer->video->sh; - if (sh_video) - resync_video_stream(sh_video); - - struct sh_audio *sh_audio = demuxer->audio->sh; - if (sh_audio) - resync_audio_stream(sh_audio); } - - return M_PROPERTY_OK; + return M_PROPERTY_NOT_IMPLEMENTED; } /// Demuxer meta data @@ -495,16 +499,19 @@ static int mp_property_metadata(m_option_t *prop, int action, void *arg, }; switch (action) { - case M_PROPERTY_GET: - *(char ***)arg = demuxer->info; + case M_PROPERTY_GET: { + char **slist = NULL; + m_option_copy(prop, &slist, &demuxer->info); + *(char ***)arg = slist; return M_PROPERTY_OK; + } case M_PROPERTY_KEY_ACTION: ka = arg; if (!(meta = demux_info_get(demuxer, ka->key))) return M_PROPERTY_UNKNOWN; switch (ka->action) { case M_PROPERTY_GET: - *(char **)ka->arg = meta; + *(char **)ka->arg = talloc_strdup(NULL, meta); return M_PROPERTY_OK; case M_PROPERTY_GET_TYPE: *(const m_option_t **)ka->arg = &key_type; @@ -527,9 +534,11 @@ static int mp_property_pause(m_option_t *prop, int action, void *arg, unpause_player(mpctx); } return M_PROPERTY_OK; - default: - return m_property_flag(prop, action, arg, &mpctx->paused); + case M_PROPERTY_GET: + *(int *)arg = mpctx->paused; + return M_PROPERTY_OK; } + return M_PROPERTY_NOT_IMPLEMENTED; } @@ -545,19 +554,6 @@ static int mp_property_volume(m_option_t *prop, int action, void *arg, case M_PROPERTY_GET: mixer_getbothvolume(&mpctx->mixer, arg); return M_PROPERTY_OK; - case M_PROPERTY_PRINT: { - float vol; - mixer_getbothvolume(&mpctx->mixer, &vol); - return m_property_float_range(prop, action, arg, &vol); - } - case M_PROPERTY_SWITCH: - case M_PROPERTY_SET: - break; - default: - return M_PROPERTY_NOT_IMPLEMENTED; - } - - switch (action) { case M_PROPERTY_SET: mixer_setvolume(&mpctx->mixer, *(float *) arg, *(float *) arg); return M_PROPERTY_OK; @@ -583,10 +579,11 @@ static int mp_property_mute(m_option_t *prop, int action, void *arg, case M_PROPERTY_SET: mixer_setmute(&mpctx->mixer, *(int *) arg); return M_PROPERTY_OK; - default: - return m_property_flag_ro(prop, action, arg, - mixer_getmute(&mpctx->mixer)); + case M_PROPERTY_GET: + *(int *)arg = mixer_getmute(&mpctx->mixer); + return M_PROPERTY_OK; } + return M_PROPERTY_NOT_IMPLEMENTED; } /// Audio delay (RW) @@ -599,19 +596,11 @@ static int mp_property_audio_delay(m_option_t *prop, int action, case M_PROPERTY_PRINT: *(char **)arg = format_delay(audio_delay); return M_PROPERTY_OK; - case M_PROPERTY_SET: { - int ret; - float delay = audio_delay; - ret = m_property_float_range(prop, action, arg, &audio_delay); - if (ret != M_PROPERTY_OK) - return ret; - if (mpctx->sh_audio) - mpctx->delay -= audio_delay - delay; - } + case M_PROPERTY_SET: + mpctx->delay -= audio_delay - *(float *)arg; return M_PROPERTY_OK; - default: - return m_property_float_range(prop, action, arg, &audio_delay); } + return M_PROPERTY_NOT_IMPLEMENTED; } /// Audio codec tag (RO) @@ -629,8 +618,11 @@ static int mp_property_audio_codec(m_option_t *prop, int action, { if (!mpctx->sh_audio || !mpctx->sh_audio->codec) return M_PROPERTY_UNAVAILABLE; - return m_property_string_ro(prop, action, arg, - mpctx->sh_audio->codec->name); + if (action == M_PROPERTY_GET) { + *(char **)arg = talloc_strdup(NULL, mpctx->sh_audio->codec->name); + return M_PROPERTY_OK; + } + return M_PROPERTY_NOT_IMPLEMENTED; } /// Audio bitrate (RO) @@ -643,8 +635,11 @@ static int mp_property_audio_bitrate(m_option_t *prop, int action, case M_PROPERTY_PRINT: *(char **)arg = format_bitrate(mpctx->sh_audio->i_bps); return M_PROPERTY_OK; + case M_PROPERTY_GET: + *(int *)arg = mpctx->sh_audio->i_bps; + return M_PROPERTY_OK; } - return m_property_int_ro(prop, action, arg, mpctx->sh_audio->i_bps); + return M_PROPERTY_NOT_IMPLEMENTED; } /// Samplerate (RO) @@ -658,8 +653,11 @@ static int mp_property_samplerate(m_option_t *prop, int action, void *arg, *(char **)arg = talloc_asprintf(NULL, "%d kHz", mpctx->sh_audio->samplerate / 1000); return M_PROPERTY_OK; + case M_PROPERTY_GET: + *(int *)arg = mpctx->sh_audio->samplerate; + return M_PROPERTY_OK; } - return m_property_int_ro(prop, action, arg, mpctx->sh_audio->samplerate); + return M_PROPERTY_NOT_IMPLEMENTED; } /// Number of channels (RO) @@ -682,8 +680,11 @@ static int mp_property_channels(m_option_t *prop, int action, void *arg, mpctx->sh_audio->channels); } return M_PROPERTY_OK; + case M_PROPERTY_GET: + *(int *)arg = mpctx->sh_audio->channels; + return M_PROPERTY_OK; } - return m_property_int_ro(prop, action, arg, mpctx->sh_audio->channels); + return M_PROPERTY_NOT_IMPLEMENTED; } /// Balance (RW) @@ -824,10 +825,8 @@ static int mp_property_program(m_option_t *prop, int action, void *arg, mp_property_do("audio", M_PROPERTY_SET, &prog.aid, mpctx); mp_property_do("video", M_PROPERTY_SET, &prog.vid, mpctx); return M_PROPERTY_OK; - - default: - return M_PROPERTY_NOT_IMPLEMENTED; } + return M_PROPERTY_NOT_IMPLEMENTED; } @@ -839,17 +838,15 @@ static int mp_property_fullscreen(m_option_t *prop, int action, void *arg, if (!mpctx->video_out) return M_PROPERTY_UNAVAILABLE; - switch (action) { - case M_PROPERTY_SET: + if (action == M_PROPERTY_SET) { if (vo_fs == !!*(int *) arg) return M_PROPERTY_OK; if (mpctx->video_out->config_ok) vo_control(mpctx->video_out, VOCTRL_FULLSCREEN, 0); mpctx->opts.fullscreen = vo_fs; return M_PROPERTY_OK; - default: - return m_property_flag(prop, action, arg, &vo_fs); } + return mp_property_generic_option(prop, action, arg, mpctx); } static int mp_property_deinterlace(m_option_t *prop, int action, @@ -867,20 +864,16 @@ static int mp_property_deinterlace(m_option_t *prop, int action, vf->control(vf, VFCTRL_SET_DEINTERLACE, arg); return M_PROPERTY_OK; } - int value = 0; - vf->control(vf, VFCTRL_GET_DEINTERLACE, &value); - return m_property_flag_ro(prop, action, arg, value); + return M_PROPERTY_NOT_IMPLEMENTED; } static int colormatrix_property_helper(m_option_t *prop, int action, void *arg, MPContext *mpctx) { int r = mp_property_generic_option(prop, action, arg, mpctx); - switch (action) { - case M_PROPERTY_SET: + if (action == M_PROPERTY_SET) { if (mpctx->sh_video) set_video_colorspace(mpctx->sh_video); - break; } return r; } @@ -889,8 +882,7 @@ static int mp_property_colormatrix(m_option_t *prop, int action, void *arg, MPContext *mpctx) { struct MPOpts *opts = &mpctx->opts; - switch (action) { - case M_PROPERTY_PRINT: ; + if (action == M_PROPERTY_PRINT) { struct mp_csp_details actual = { .format = -1 }; char *req_csp = mp_csp_names[opts->requested_colorspace]; char *real_csp = NULL; @@ -916,9 +908,8 @@ static int mp_property_colormatrix(m_option_t *prop, int action, void *arg, req_csp, real_csp); *(char **)arg = res; return M_PROPERTY_OK; - default:; - return colormatrix_property_helper(prop, action, arg, mpctx); } + return colormatrix_property_helper(prop, action, arg, mpctx); } static int levels_property_helper(int offset, m_option_t *prop, int action, @@ -929,8 +920,7 @@ static int levels_property_helper(int offset, m_option_t *prop, int action, bstr0(optname)); int *valptr = (int *)m_option_get_ptr(opt, &mpctx->opts); - switch (action) { - case M_PROPERTY_PRINT: ; + if (action == M_PROPERTY_PRINT) { struct mp_csp_details actual = {0}; int actual_level = -1; char *req_level = m_option_print(opt, valptr); @@ -956,9 +946,8 @@ static int levels_property_helper(int offset, m_option_t *prop, int action, talloc_free(real_level); *(char **)arg = res; return M_PROPERTY_OK; - default:; - return colormatrix_property_helper(prop, action, arg, mpctx); } + return colormatrix_property_helper(prop, action, arg, mpctx); } static int mp_property_colormatrix_input_range(m_option_t *prop, int action, @@ -984,14 +973,10 @@ static int mp_property_panscan(m_option_t *prop, int action, void *arg, || vo_control(mpctx->video_out, VOCTRL_GET_PANSCAN, NULL) != VO_TRUE) return M_PROPERTY_UNAVAILABLE; - switch (action) { - case M_PROPERTY_SET: - vo_panscan = *(float *) arg; + int r = mp_property_generic_option(prop, action, arg, mpctx); + if (action == M_PROPERTY_SET) vo_control(mpctx->video_out, VOCTRL_SET_PANSCAN, NULL); - return M_PROPERTY_OK; - default: - return m_property_float_range(prop, action, arg, &vo_panscan); - } + return r; } /// Helper to set vo flags. @@ -1004,16 +989,14 @@ static int mp_property_vo_flag(m_option_t *prop, int action, void *arg, if (!mpctx->video_out) return M_PROPERTY_UNAVAILABLE; - switch (action) { - case M_PROPERTY_SET: + if (action == M_PROPERTY_SET) { if (*vo_var == !!*(int *) arg) return M_PROPERTY_OK; if (mpctx->video_out->config_ok) vo_control(mpctx->video_out, vo_ctrl, 0); return M_PROPERTY_OK; - default: - return m_property_flag(prop, action, arg, vo_var); } + return mp_property_generic_option(prop, action, arg, mpctx); } /// Window always on top (RW) @@ -1078,7 +1061,7 @@ static int mp_property_gamma(m_option_t *prop, int action, void *arg, } break; default: - return M_PROPERTY_NOT_IMPLEMENTED; + return mp_property_generic_option(prop, action, arg, mpctx); } #ifdef CONFIG_TV @@ -1097,7 +1080,7 @@ static int mp_property_gamma(m_option_t *prop, int action, void *arg, static int mp_property_vsync(m_option_t *prop, int action, void *arg, MPContext *mpctx) { - return m_property_flag(prop, action, arg, &vo_vsync); + return mp_property_generic_option(prop, action, arg, mpctx); } /// Video codec tag (RO) @@ -1131,8 +1114,11 @@ static int mp_property_video_format(m_option_t *prop, int action, } *(char **)arg = meta; return M_PROPERTY_OK; + case M_PROPERTY_GET: + *(int *)arg = mpctx->sh_video->format; + return M_PROPERTY_OK; } - return m_property_int_ro(prop, action, arg, mpctx->sh_video->format); + return M_PROPERTY_NOT_IMPLEMENTED; } /// Video codec name (RO) @@ -1141,8 +1127,11 @@ static int mp_property_video_codec(m_option_t *prop, int action, { if (!mpctx->sh_video || !mpctx->sh_video->codec) return M_PROPERTY_UNAVAILABLE; - return m_property_string_ro(prop, action, arg, - mpctx->sh_video->codec->name); + if (action == M_PROPERTY_GET) { + *(char **)arg = talloc_strdup(NULL, mpctx->sh_video->codec->name); + return M_PROPERTY_OK; + } + return M_PROPERTY_NOT_IMPLEMENTED; } @@ -1152,8 +1141,7 @@ static int mp_property_video_bitrate(m_option_t *prop, int action, { if (!mpctx->sh_video) return M_PROPERTY_UNAVAILABLE; - switch (action) { - case M_PROPERTY_PRINT: + if (action == M_PROPERTY_PRINT) { *(char **)arg = format_bitrate(mpctx->sh_video->i_bps); return M_PROPERTY_OK; } @@ -1196,17 +1184,17 @@ static int mp_property_aspect(m_option_t *prop, int action, void *arg, return m_property_float_ro(prop, action, arg, mpctx->sh_video->aspect); } - -/// Text subtitle position (RW) -static int mp_property_sub_pos(m_option_t *prop, int action, void *arg, +// For subtitle related properties using the generic option bridge. +// - Fail as unavailable if no video is active +// - Trigger OSD state update when property is set +static int property_sub_helper(m_option_t *prop, int action, void *arg, MPContext *mpctx) { - switch (action) { - case M_PROPERTY_SET: + if (!mpctx->sh_video) + return M_PROPERTY_UNAVAILABLE; + if (action == M_PROPERTY_SET) vo_osd_changed(OSDTYPE_SUBTITLE); - default: - return m_property_int_range(prop, action, arg, &sub_pos); - } + return mp_property_generic_option(prop, action, arg, mpctx); } /// Selected subtitles (RW) @@ -1227,7 +1215,7 @@ static int mp_property_sub_delay(m_option_t *prop, int action, void *arg, *(char **)arg = format_delay(sub_delay); return M_PROPERTY_OK; } - return m_property_float_range(prop, action, arg, &sub_delay); + return mp_property_generic_option(prop, action, arg, mpctx); } /// Subtitle visibility (RW) @@ -1241,48 +1229,18 @@ static int mp_property_sub_visibility(m_option_t *prop, int action, switch (action) { case M_PROPERTY_SET: + opts->sub_visibility = *(int *)arg; vo_osd_changed(OSDTYPE_SUBTITLE); if (vo_spudec) vo_osd_changed(OSDTYPE_SPU); - default: - return m_property_flag(prop, action, arg, &opts->sub_visibility); - } -} - -#ifdef CONFIG_ASS -/// Use margins for libass subtitles (RW) -static int mp_property_ass_use_margins(m_option_t *prop, int action, - void *arg, MPContext *mpctx) -{ - struct MPOpts *opts = &mpctx->opts; - if (!mpctx->sh_video) - return M_PROPERTY_UNAVAILABLE; - - switch (action) { - case M_PROPERTY_SET: - vo_osd_changed(OSDTYPE_SUBTITLE); - default: - return m_property_flag(prop, action, arg, &opts->ass_use_margins); - } -} - -static int mp_property_ass_vsfilter_aspect_compat(m_option_t *prop, int action, - void *arg, MPContext *mpctx) -{ - if (!mpctx->sh_video) - return M_PROPERTY_UNAVAILABLE; - - switch (action) { - case M_PROPERTY_SET: - vo_osd_changed(OSDTYPE_SUBTITLE); - default: - return m_property_flag(prop, action, arg, - &mpctx->opts.ass_vsfilter_aspect_compat); + return M_PROPERTY_OK; + case M_PROPERTY_GET: + *(int *)arg = opts->sub_visibility; + return M_PROPERTY_OK; } + return M_PROPERTY_NOT_IMPLEMENTED; } -#endif - /// Show only forced subtitles (RW) static int mp_property_sub_forced_only(m_option_t *prop, int action, void *arg, MPContext *mpctx) @@ -1290,15 +1248,12 @@ static int mp_property_sub_forced_only(m_option_t *prop, int action, if (!vo_spudec) return M_PROPERTY_UNAVAILABLE; - switch (action) { - case M_PROPERTY_SET: - m_property_flag(prop, action, arg, &forced_subs_only); + if (action == M_PROPERTY_SET) { + forced_subs_only = *(int *)arg; 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); } - + return mp_property_generic_option(prop, action, arg, mpctx); } /// Subtitle scale (RW) @@ -1307,20 +1262,19 @@ static int mp_property_sub_scale(m_option_t *prop, int action, void *arg, { struct MPOpts *opts = &mpctx->opts; + float *pscale = opts->ass_enabled + ? &opts->ass_font_scale : &text_font_scale_factor; + switch (action) { case M_PROPERTY_SET: - if (opts->ass_enabled) - opts->ass_font_scale = *(float *) arg; - else - text_font_scale_factor = *(float *) arg; + *pscale = *(float *) arg; vo_osd_resized(); return M_PROPERTY_OK; - default: - if (opts->ass_enabled) - return m_property_float_ro(prop, action, arg, opts->ass_font_scale); - else - return m_property_float_ro(prop, action, arg, text_font_scale_factor); + case M_PROPERTY_GET: + *(float *)arg = *pscale; + return M_PROPERTY_OK; } + return M_PROPERTY_NOT_IMPLEMENTED; } @@ -1352,17 +1306,25 @@ static int mp_property_tv_color(m_option_t *prop, int action, void *arg, #endif +// Use option-to-property-bridge. (The property and option have the same names.) +#define M_OPTION_PROPERTY(name) \ + {(name), mp_property_generic_option, &m_option_type_choice, 0, 0, 0, (name)} + +// OPTION_PROPERTY(), but with a custom property handler. The custom handler +// must let unknown operations fall back to mp_property_generic_option(). +#define M_OPTION_PROPERTY_CUSTOM(name, handler) \ + {(name), (handler), &m_option_type_choice, 0, 0, 0, (name)} +#define M_OPTION_PROPERTY_CUSTOM_(name, handler, ...) \ + {(name), (handler), &m_option_type_choice, 0, 0, 0, (name), __VA_ARGS__} + /// All properties available in MPlayer. /** \ingroup Properties */ static const m_option_t mp_properties[] = { // General - { "osd-level", mp_property_generic_option, &m_option_type_choice, - 0, 0, 0, "osd-level" }, - { "loop", mp_property_generic_option, &m_option_type_choice, - 0, 0, 0, "loop" }, - { "speed", mp_property_playback_speed, CONF_TYPE_FLOAT, - M_OPT_RANGE, 0.01, 100.0, NULL }, + M_OPTION_PROPERTY("osd-level"), + M_OPTION_PROPERTY("loop"), + M_OPTION_PROPERTY_CUSTOM("speed", mp_property_playback_speed), { "filename", mp_property_filename, CONF_TYPE_STRING, 0, 0, 0, NULL }, { "path", mp_property_path, CONF_TYPE_STRING, @@ -1400,18 +1362,15 @@ static const m_option_t mp_properties[] = { 0, 0, 0, NULL }, { "pause", mp_property_pause, CONF_TYPE_FLAG, M_OPT_RANGE, 0, 1, NULL }, - { "pts-association-mode", mp_property_generic_option, &m_option_type_choice, - 0, 0, 0, "pts-association-mode" }, - { "hr-seek", mp_property_generic_option, &m_option_type_choice, - 0, 0, 0, "hr-seek" }, + M_OPTION_PROPERTY("pts-association-mode"), + M_OPTION_PROPERTY("hr-seek"), // 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 }, + M_OPTION_PROPERTY_CUSTOM("audio-delay", mp_property_audio_delay), { "audio-format", mp_property_audio_format, CONF_TYPE_INT, 0, 0, 0, NULL }, { "audio-codec", mp_property_audio_codec, CONF_TYPE_STRING, @@ -1428,38 +1387,30 @@ static const m_option_t mp_properties[] = { M_OPT_RANGE, -1, 1, NULL }, // Video - { "fullscreen", mp_property_fullscreen, CONF_TYPE_FLAG, - M_OPT_RANGE, 0, 1, NULL }, + M_OPTION_PROPERTY_CUSTOM("fullscreen", mp_property_fullscreen), { "deinterlace", mp_property_deinterlace, CONF_TYPE_FLAG, M_OPT_RANGE, 0, 1, NULL }, - { "colormatrix", mp_property_colormatrix, &m_option_type_choice, - 0, 0, 0, "colormatrix" }, - { "colormatrix-input-range", mp_property_colormatrix_input_range, &m_option_type_choice, - 0, 0, 0, "colormatrix-input-range" }, - { "colormatrix-output-range", mp_property_colormatrix_output_range, &m_option_type_choice, - 0, 0, 0, "colormatrix-output-range" }, - { "ontop", m |