1
0
mirror of https://github.com/mpv-player/mpv synced 2024-12-23 23:32:26 +00:00

options: change how option range min/max is handled

Before this commit, option declarations used M_OPT_MIN/M_OPT_MAX (and
some other identifiers based on these) to signal whether an option had
min/max values. Remove these flags, and make it use a range implicitly
on the condition if min<max is true.

This requires care in all cases when only M_OPT_MIN or M_OPT_MAX were
set (instead of both). Generally, the commit replaces all these
instances with using DBL_MAX/DBL_MIN for the "unset" part of the range.

This also happens to fix some cases where you could pass over-large
values to integer options, which were silently truncated, but now cause
an error.

This commit has some higher potential for regressions.
This commit is contained in:
wm4 2020-03-13 16:49:39 +01:00
parent 5d5a7e1953
commit 8d965a1bfb
16 changed files with 142 additions and 119 deletions

View File

@ -361,7 +361,7 @@ const struct mp_user_filter_entry af_rubberband = {
OPT_CHOICE("channels", channels, 0,
({"apart", RubberBandOptionChannelsApart},
{"together", RubberBandOptionChannelsTogether})),
OPT_DOUBLE("pitch-scale", scale, M_OPT_RANGE, .min = 0.01, .max = 100),
OPT_DOUBLE("pitch-scale", scale, 0, .min = 0.01, .max = 100),
{0}
},
},

View File

@ -30,6 +30,7 @@
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include <float.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
@ -608,10 +609,10 @@ const struct mp_user_filter_entry af_scaletempo = {
.scale_nominal = 1.0,
},
.options = (const struct m_option[]) {
OPT_FLOAT("scale", scale_nominal, M_OPT_MIN, .min = 0.01),
OPT_FLOAT("stride", ms_stride, M_OPT_MIN, .min = 0.01),
OPT_FLOAT("overlap", percent_overlap, M_OPT_RANGE, .min = 0, .max = 1),
OPT_FLOAT("search", ms_search, M_OPT_MIN, .min = 0),
OPT_FLOAT("scale", scale_nominal, 0, .min = 0.01, .max = DBL_MAX),
OPT_FLOAT("stride", ms_stride, 0, .min = 0.01, .max = DBL_MAX),
OPT_FLOAT("overlap", percent_overlap, 0, .min = 0, .max = 1),
OPT_FLOAT("search", ms_search, 0, .min = 0, .max = DBL_MAX),
OPT_CHOICE("speed", speed_opt, 0,
({"pitch", SCALE_PITCH},
{"tempo", SCALE_TEMPO},

View File

@ -140,7 +140,7 @@ const struct m_sub_options ao_conf = {
OPT_STRING("audio-device", audio_device, UPDATE_AUDIO),
OPT_STRING("audio-client-name", audio_client_name, UPDATE_AUDIO),
OPT_DOUBLE("audio-buffer", audio_buffer,
UPDATE_AUDIO | M_OPT_MIN | M_OPT_MAX, .min = 0, .max = 10),
UPDATE_AUDIO, .min = 0, .max = 10),
{0}
},
.size = sizeof(OPT_BASE_STRUCT),

View File

@ -15,6 +15,7 @@
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include <float.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -114,14 +115,15 @@ const struct m_sub_options demux_conf = {
OPT_CHOICE("cache", enable_cache, 0,
({"no", 0}, {"auto", -1}, {"yes", 1})),
OPT_FLAG("cache-on-disk", disk_cache, 0),
OPT_DOUBLE("demuxer-readahead-secs", min_secs, M_OPT_MIN, .min = 0),
OPT_DOUBLE("demuxer-readahead-secs", min_secs, 0,
.min = 0, .max = DBL_MAX),
// (The MAX_BYTES sizes may not be accurate because the max field is
// of double type.)
OPT_BYTE_SIZE("demuxer-max-bytes", max_bytes, 0, 0, MAX_BYTES),
OPT_BYTE_SIZE("demuxer-max-back-bytes", max_bytes_bw, 0, 0, MAX_BYTES),
OPT_FLAG("demuxer-donate-buffer", donate_fw, 0),
OPT_FLAG("force-seekable", force_seekable, 0),
OPT_DOUBLE("cache-secs", min_secs_cache, M_OPT_MIN, .min = 0,
OPT_DOUBLE("cache-secs", min_secs_cache, 0, .min = 0, .max = DBL_MAX,
.deprecation_message = "will use unlimited time"),
OPT_FLAG("access-references", access_references, 0),
OPT_CHOICE("demuxer-seekable-cache", seekable_cache, 0,
@ -134,8 +136,8 @@ const struct m_sub_options demux_conf = {
1024, ({"auto", -1})),
OPT_INTRANGE("video-backward-batch", back_batch[STREAM_VIDEO], 0, 0, 1024),
OPT_INTRANGE("audio-backward-batch", back_batch[STREAM_AUDIO], 0, 0, 1024),
OPT_DOUBLE("demuxer-backward-playback-step", back_seek_size, M_OPT_MIN,
.min = 0),
OPT_DOUBLE("demuxer-backward-playback-step", back_seek_size, 0,
.min = 0, .max = DBL_MAX),
OPT_STRING("metadata-codepage", meta_cp, 0),
OPT_FLAG("demuxer-force-retry-on-eof", force_retry_eof, 0,
.deprecation_message = "temporary debug option, no replacement"),

View File

@ -20,6 +20,7 @@
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include <float.h>
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
@ -230,10 +231,10 @@ const struct m_sub_options demux_mkv_conf = {
.opts = (const m_option_t[]) {
OPT_CHOICE("subtitle-preroll", subtitle_preroll, 0,
({"no", 0}, {"yes", 1}, {"index", 2})),
OPT_DOUBLE("subtitle-preroll-secs", subtitle_preroll_secs,
M_OPT_MIN, .min = 0),
OPT_DOUBLE("subtitle-preroll-secs-index", subtitle_preroll_secs_index,
M_OPT_MIN, .min = 0),
OPT_DOUBLE("subtitle-preroll-secs", subtitle_preroll_secs, 0,
.min = 0, .max = DBL_MAX),
OPT_DOUBLE("subtitle-preroll-secs-index", subtitle_preroll_secs_index, 0,
.min = 0, .max = DBL_MAX),
OPT_CHOICE("probe-video-duration", probe_duration, 0,
({"no", 0}, {"yes", 1}, {"full", 2})),
OPT_FLAG("probe-start-time", probe_start_time, 0),

View File

@ -15,6 +15,7 @@
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include <float.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
@ -63,9 +64,9 @@ struct dec_queue_opts {
static const struct m_option dec_queue_opts_list[] = {
OPT_FLAG("enable", use_queue, 0),
OPT_DOUBLE("max-secs", max_duration, M_OPT_MIN, .min = 0),
OPT_DOUBLE("max-secs", max_duration, 0, .min = 0, .max = DBL_MAX),
OPT_BYTE_SIZE("max-bytes", max_bytes, 0, 0, (size_t)-1),
OPT_INT64("max-samples", max_samples, M_OPT_MIN, 0, 0),
OPT_INT64("max-samples", max_samples, 0, .min = 0, .max = DBL_MAX),
{0}
};
@ -115,14 +116,14 @@ static int decoder_list_opt(struct mp_log *log, const m_option_t *opt,
const struct m_sub_options dec_wrapper_conf = {
.opts = (const struct m_option[]){
OPT_FLAG("correct-pts", correct_pts, 0),
OPT_DOUBLE("fps", force_fps, CONF_MIN, .min = 0),
OPT_DOUBLE("fps", force_fps, 0, .min = 0, .max = DBL_MAX),
OPT_STRING_VALIDATE("ad", audio_decoders, 0, decoder_list_opt),
OPT_STRING_VALIDATE("vd", video_decoders, 0, decoder_list_opt),
OPT_STRING_VALIDATE("audio-spdif", audio_spdif, 0, decoder_list_opt),
OPT_CHOICE_OR_INT("video-rotate", video_rotate, UPDATE_IMGPAR, 0, 359,
({"no", -1})),
OPT_ASPECT("video-aspect-override", movie_aspect,
UPDATE_IMGPAR | M_OPT_RANGE, .min = -1, .max = 10),
UPDATE_IMGPAR, .min = -1, .max = 10),
OPT_CHOICE("video-aspect-method", aspect_method, UPDATE_IMGPAR,
({"bitstream", 1}, {"container", 2})),
OPT_SUBSTRUCT("vd-queue", vdec_queue_opts, vdec_queue_conf, 0),

View File

@ -74,7 +74,7 @@ const struct m_sub_options resample_conf = {
OPT_INTRANGE("audio-resample-filter-size", filter_size, 0, 0, 32),
OPT_INTRANGE("audio-resample-phase-shift", phase_shift, 0, 0, 30),
OPT_FLAG("audio-resample-linear", linear, 0),
OPT_DOUBLE("audio-resample-cutoff", cutoff, M_OPT_RANGE,
OPT_DOUBLE("audio-resample-cutoff", cutoff, 0,
.min = 0, .max = 1),
OPT_FLAG("audio-normalize-downmix", normalize, 0),
OPT_DOUBLE("audio-resample-max-output-size", max_output_frame_size, 0),

View File

@ -15,6 +15,7 @@
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include <float.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
@ -786,17 +787,17 @@ void m_config_print_option_list(const struct m_config *config, const char *name)
struct m_opt_choice_alternatives *alt = opt->priv;
for (int n = 0; alt[n].name; n++)
MP_INFO(config, " %s", alt[n].name);
if (opt->flags & (M_OPT_MIN | M_OPT_MAX))
if (opt->min < opt->max)
MP_INFO(config, " (or an integer)");
} else {
MP_INFO(config, " %s", opt->type->name);
}
if (opt->flags & (M_OPT_MIN | M_OPT_MAX)) {
if ((opt->type->flags & M_OPT_TYPE_USES_RANGE) && opt->min < opt->max) {
snprintf(min, sizeof(min), "any");
snprintf(max, sizeof(max), "any");
if (opt->flags & M_OPT_MIN)
if (opt->min != DBL_MIN)
snprintf(min, sizeof(min), "%.14g", opt->min);
if (opt->flags & M_OPT_MAX)
if (opt->max != DBL_MAX)
snprintf(max, sizeof(max), "%.14g", opt->max);
MP_INFO(config, " (%s to %s)", min, max);
}

View File

@ -22,6 +22,7 @@
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdarg.h>
@ -52,6 +53,14 @@
const char m_option_path_separator = OPTION_PATH_SEPARATOR;
// For integer types: since min/max are floats and may not be able to represent
// the real min/max, and since opt.min/.max may use +/-INFINITY, some care has
// to be taken. (Also tricky rounding.)
#define OPT_INT_MIN(opt, T, Tm) \
((opt)->min < (opt)->max ? ((opt)->min <= (Tm) ? (Tm) : (T)((opt)->min)) : (Tm))
#define OPT_INT_MAX(opt, T, Tm) \
((opt)->min < (opt)->max ? ((opt)->max >= (Tm) ? (Tm) : (T)((opt)->max)) : (Tm))
char *m_option_strerror(int code)
{
switch (code) {
@ -193,16 +202,19 @@ const m_option_type_t m_option_type_flag = {
#undef VAL
static int clamp_longlong(const m_option_t *opt, void *val)
static int clamp_longlong(const m_option_t *opt, long long i_min, long long i_max,
void *val)
{
long long v = *(long long *)val;
int r = 0;
if ((opt->flags & M_OPT_MAX) && (v > opt->max)) {
v = opt->max;
long long min = OPT_INT_MIN(opt, long long, i_min);
long long max = OPT_INT_MAX(opt, long long, i_max);
if (v > max) {
v = max;
r = M_OPT_OUT_OF_RANGE;
}
if ((opt->flags & M_OPT_MIN) && (v < opt->min)) {
v = opt->min;
if (v < min) {
v = min;
r = M_OPT_OUT_OF_RANGE;
}
*(long long *)val = v;
@ -210,6 +222,7 @@ static int clamp_longlong(const m_option_t *opt, void *val)
}
static int parse_longlong(struct mp_log *log, const m_option_t *opt,
long long i_min, long long i_max,
struct bstr name, struct bstr param, void *dst)
{
if (param.len == 0)
@ -225,15 +238,17 @@ static int parse_longlong(struct mp_log *log, const m_option_t *opt,
return M_OPT_INVALID;
}
if ((opt->flags & M_OPT_MIN) && (tmp_int < opt->min)) {
mp_err(log, "The %.*s option must be >= %d: %.*s\n",
BSTR_P(name), (int) opt->min, BSTR_P(param));
long long min = OPT_INT_MIN(opt, long long, i_min);
if (tmp_int < min) {
mp_err(log, "The %.*s option must be >= %lld: %.*s\n",
BSTR_P(name), min, BSTR_P(param));
return M_OPT_OUT_OF_RANGE;
}
if ((opt->flags & M_OPT_MAX) && (tmp_int > opt->max)) {
mp_err(log, "The %.*s option must be <= %d: %.*s\n",
BSTR_P(name), (int) opt->max, BSTR_P(param));
long long max = OPT_INT_MAX(opt, long long, i_max);
if (tmp_int > max) {
mp_err(log, "The %.*s option must be <= %lld: %.*s\n",
BSTR_P(name), max, BSTR_P(param));
return M_OPT_OUT_OF_RANGE;
}
@ -246,7 +261,7 @@ static int parse_longlong(struct mp_log *log, const m_option_t *opt,
static int clamp_int64(const m_option_t *opt, void *val)
{
long long tmp = *(int64_t *)val;
int r = clamp_longlong(opt, &tmp);
int r = clamp_longlong(opt, INT64_MIN, INT64_MAX, &tmp);
*(int64_t *)val = tmp;
return r;
}
@ -255,7 +270,7 @@ static int parse_int(struct mp_log *log, const m_option_t *opt,
struct bstr name, struct bstr param, void *dst)
{
long long tmp;
int r = parse_longlong(log, opt, name, param, &tmp);
int r = parse_longlong(log, opt, INT_MIN, INT_MAX, name, param, &tmp);
if (r >= 0 && dst)
*(int *)dst = tmp;
return r;
@ -265,7 +280,7 @@ static int parse_int64(struct mp_log *log, const m_option_t *opt,
struct bstr name, struct bstr param, void *dst)
{
long long tmp;
int r = parse_longlong(log, opt, name, param, &tmp);
int r = parse_longlong(log, opt, INT64_MIN, INT64_MAX, name, param, &tmp);
if (r >= 0 && dst)
*(int64_t *)dst = tmp;
return r;
@ -290,8 +305,8 @@ static void add_int64(const m_option_t *opt, void *val, double add, bool wrap)
int64_t nmin = is64 ? INT64_MIN : INT_MIN;
int64_t nmax = is64 ? INT64_MAX : INT_MAX;
int64_t min = (opt->flags & M_OPT_MIN) ? opt->min : nmin;
int64_t max = (opt->flags & M_OPT_MAX) ? opt->max : nmax;
int64_t min = OPT_INT_MIN(opt, int64_t, nmin);
int64_t max = OPT_INT_MAX(opt, int64_t, nmax);
if (v < min)
v = wrap ? max : min;
@ -332,9 +347,9 @@ static int int64_set(const m_option_t *opt, void *dst, struct mpv_node *src)
if (src->format != MPV_FORMAT_INT64)
return M_OPT_UNKNOWN;
int64_t val = src->u.int64;
if ((opt->flags & M_OPT_MIN) && val < opt->min)
if (val < OPT_INT_MIN(opt, int64_t, INT64_MIN))
return M_OPT_OUT_OF_RANGE;
if ((opt->flags & M_OPT_MAX) && val > opt->max)
if (val > OPT_INT_MAX(opt, int64_t, INT64_MAX))
return M_OPT_OUT_OF_RANGE;
*(int64_t *)dst = val;
return 1;
@ -380,6 +395,7 @@ static bool int64_equal(const m_option_t *opt, void *a, void *b)
const m_option_type_t m_option_type_int = {
.name = "Integer",
.flags = M_OPT_TYPE_USES_RANGE,
.size = sizeof(int),
.parse = parse_int,
.print = print_int,
@ -393,6 +409,7 @@ const m_option_type_t m_option_type_int = {
const m_option_type_t m_option_type_int64 = {
.name = "Integer64",
.flags = M_OPT_TYPE_USES_RANGE,
.size = sizeof(int64_t),
.parse = parse_int64,
.print = print_int,
@ -447,15 +464,20 @@ static int parse_byte_size(struct mp_log *log, const m_option_t *opt,
tmp_int *= unit;
if ((opt->flags & M_OPT_MIN) && (tmp_int < opt->min)) {
mp_err(log, "The %.*s option must be >= %d: %.*s\n",
BSTR_P(name), (int) opt->min, BSTR_P(param));
int64_t min = OPT_INT_MIN(opt, int64_t, INT64_MIN);
if (tmp_int < min) {
mp_err(log, "The %.*s option must be >= %"PRId64": %.*s\n",
BSTR_P(name), min, BSTR_P(param));
return M_OPT_OUT_OF_RANGE;
}
if ((opt->flags & M_OPT_MAX) && (tmp_int > opt->max)) {
mp_err(log, "The %.*s option must be <= %d: %.*s\n",
BSTR_P(name), (int) opt->max, BSTR_P(param));
int64_t max = OPT_INT_MAX(opt, int64_t, INT64_MAX);
if (tmp_int > max) {
mp_err(log, "The %.*s option must be <= %"PRId64": %.*s\n",
BSTR_P(name), max, BSTR_P(param));
double x = INT64_MAX;
printf("max: %ld, %f %f %ld %ld %d %d\n", max, x, opt->max, (int64_t)opt->max, (int64_t)x, x > INT64_MAX, x == INT64_MAX);
abort();
return M_OPT_OUT_OF_RANGE;
}
@ -490,6 +512,7 @@ static char *pretty_print_byte_size(const m_option_t *opt, const void *val)
const m_option_type_t m_option_type_byte_size = {
.name = "ByteSize",
.flags = M_OPT_TYPE_USES_RANGE,
.size = sizeof(int64_t),
.parse = parse_byte_size,
.print = print_int,
@ -517,7 +540,7 @@ static void print_choice_values(struct mp_log *log, const struct m_option *opt)
struct m_opt_choice_alternatives *alt = opt->priv;
for ( ; alt->name; alt++)
mp_info(log, " %s\n", alt->name[0] ? alt->name : "(passing nothing)");
if ((opt->flags & M_OPT_MIN) && (opt->flags & M_OPT_MAX))
if (opt->min < opt->max)
mp_info(log, " %g-%g (integer range)\n", opt->min, opt->max);
}
@ -544,9 +567,11 @@ static int parse_choice(struct mp_log *log, const struct m_option *opt,
}
if (param.len == 0)
return M_OPT_MISSING_PARAM;
if ((opt->flags & M_OPT_MIN) && (opt->flags & M_OPT_MAX)) {
if (opt->min < opt->max) {
long long val;
if (parse_longlong(mp_null_log, opt, name, param, &val) == 1) {
if (parse_longlong(mp_null_log, opt, INT_MIN, INT_MAX, name, param,
&val) == 1)
{
if (dst)
*(int *)dst = val;
return 1;
@ -573,7 +598,7 @@ static void choice_get_min_max(const struct m_option *opt, int *min, int *max)
*min = MPMIN(*min, alt->value);
*max = MPMAX(*max, alt->value);
}
if ((opt->flags & M_OPT_MIN) && (opt->flags & M_OPT_MAX)) {
if (opt->min < opt->max) {
*min = MPMIN(*min, opt->min);
*max = MPMAX(*max, opt->max);
}
@ -600,7 +625,7 @@ static void add_choice(const m_option_t *opt, void *val, double add, bool wrap)
if (fabs(add) < 0.5)
return;
if ((opt->flags & M_OPT_MIN) && (opt->flags & M_OPT_MAX)) {
if (opt->min < opt->max) {
int newval = ival + add;
if (ival >= opt->min && ival <= opt->max &&
newval >= opt->min && newval <= opt->max)
@ -655,7 +680,7 @@ static struct m_opt_choice_alternatives *get_choice(const m_option_t *opt,
if (alt->value == v)
return alt;
}
if ((opt->flags & M_OPT_MIN) && (opt->flags & M_OPT_MAX)) {
if (opt->min < opt->max) {
if (v >= opt->min && v <= opt->max) {
*out_val = v;
return NULL;
@ -708,7 +733,7 @@ static char *print_choice(const m_option_t *opt, const void *val)
const struct m_option_type m_option_type_choice = {
.name = "Choice",
.size = sizeof(int),
.flags = M_OPT_TYPE_CHOICE,
.flags = M_OPT_TYPE_CHOICE | M_OPT_TYPE_USES_RANGE,
.parse = parse_choice,
.print = print_choice,
.copy = copy_opt,
@ -850,13 +875,15 @@ static int clamp_double(const m_option_t *opt, void *val)
{
double v = VAL(val);
int r = 0;
if ((opt->flags & M_OPT_MAX) && (v > opt->max)) {
v = opt->max;
r = M_OPT_OUT_OF_RANGE;
}
if ((opt->flags & M_OPT_MIN) && (v < opt->min)) {
v = opt->min;
r = M_OPT_OUT_OF_RANGE;
if (opt->min < opt->max) {
if (v > opt->max) {
v = opt->max;
r = M_OPT_OUT_OF_RANGE;
}
if (v < opt->min) {
v = opt->min;
r = M_OPT_OUT_OF_RANGE;
}
}
// (setting max/min to INFINITY/-INFINITY is allowed)
if (!isfinite(v) && v != opt->max && v != opt->min) {
@ -925,8 +952,8 @@ static void add_double(const m_option_t *opt, void *val, double add, bool wrap)
v = v + add;
double min = (opt->flags & M_OPT_MIN) ? opt->min : -INFINITY;
double max = (opt->flags & M_OPT_MAX) ? opt->max : +INFINITY;
double min = opt->min < opt->max ? opt->min : -INFINITY;
double max = opt->min < opt->max ? opt->max : +INFINITY;
if (v < min)
v = wrap ? max : min;
@ -984,6 +1011,7 @@ static bool double_equal(const m_option_t *opt, void *a, void *b)
const m_option_type_t m_option_type_double = {
// double precision float or ratio (numerator[:/]denominator)
.name = "Double",
.flags = M_OPT_TYPE_USES_RANGE,
.size = sizeof(double),
.parse = parse_double,
.print = print_double,
@ -1059,6 +1087,7 @@ static bool float_equal(const m_option_t *opt, void *a, void *b)
const m_option_type_t m_option_type_float = {
// floating point number or ratio (numerator[:/]denominator)
.name = "Float",
.flags = M_OPT_TYPE_USES_RANGE,
.size = sizeof(float),
.parse = parse_float,
.print = print_float,
@ -1085,7 +1114,7 @@ static int parse_float_aspect(struct mp_log *log, const m_option_t *opt,
const m_option_type_t m_option_type_aspect = {
.name = "Aspect",
.size = sizeof(float),
.flags = M_OPT_TYPE_CHOICE,
.flags = M_OPT_TYPE_CHOICE | M_OPT_TYPE_USES_RANGE,
.parse = parse_float_aspect,
.print = print_float,
.pretty_print = print_float_f3,

View File

@ -18,6 +18,7 @@
#ifndef MPLAYER_M_OPTION_H
#define MPLAYER_M_OPTION_H
#include <float.h>
#include <string.h>
#include <stddef.h>
#include <stdbool.h>
@ -361,13 +362,14 @@ struct m_option {
int offset;
// \brief Mostly useful for numeric types, the \ref M_OPT_MIN flags must
// also be set.
double min;
// \brief Mostly useful for numeric types, the \ref M_OPT_MAX flags must
// also be set.
double max;
// Most numeric types restrict the range to [min, max] if min<max (this
// implies that if min/max are not set, the full range is used). In all
// cases, the actual range is clamped to the type's native range.
// Float types use [DBL_MIN, DBL_MAX], though by setting min or max to
// -/+INFINITY, the range can be extended to INFINITY. (This part is buggy
// for "float".)
// Some types will abuse the min or max field for unrelated things.
double min, max;
// Type dependent data (for all kinds of extended settings).
void *priv;
@ -382,15 +384,6 @@ struct m_option {
char *format_file_size(int64_t size);
// The option has a minimum set in \ref m_option::min.
#define M_OPT_MIN (1 << 0)
// The option has a maximum set in \ref m_option::max.
#define M_OPT_MAX (1 << 1)
// The option has a minimum and maximum in m_option::min and m_option::max.
#define M_OPT_RANGE (M_OPT_MIN | M_OPT_MAX)
// The option is forbidden in config files.
#define M_OPT_NOCFG (1 << 2)
@ -436,9 +429,6 @@ char *format_file_size(int64_t size);
#define M_OPT_OPTIONAL_PARAM (1 << 30)
// These are kept for compatibility with older code.
#define CONF_MIN M_OPT_MIN
#define CONF_MAX M_OPT_MAX
#define CONF_RANGE M_OPT_RANGE
#define CONF_NOCFG M_OPT_NOCFG
#define CONF_PRE_PARSE M_OPT_PRE_PARSE
@ -455,6 +445,9 @@ char *format_file_size(int64_t size);
// might be allowed too). E.g. m_option_type_choice and m_option_type_flag.
#define M_OPT_TYPE_CHOICE (1 << 1)
// When m_option.min/max are set, they denote a value range.
#define M_OPT_TYPE_USES_RANGE (1 << 2)
///////////////////////////// Parser flags /////////////////////////////////
// OptionParserReturn
@ -621,7 +614,7 @@ extern const char m_option_path_separator;
OPT_GENERAL(int64_t, __VA_ARGS__, .type = &m_option_type_int64)
#define OPT_RANGE_(ctype, optname, varname, flags, minval, maxval, ...) \
OPT_GENERAL(ctype, optname, varname, (flags) | CONF_RANGE, \
OPT_GENERAL(ctype, optname, varname, flags, \
.min = minval, .max = maxval, __VA_ARGS__)
#define OPT_INTRANGE(...) \
@ -679,7 +672,7 @@ extern const char m_option_path_separator;
// Union of choices and an int range. The choice values can be included in the
// int range, or be completely separate - both works.
#define OPT_CHOICE_OR_INT_(optname, varname, flags, minval, maxval, choices, ...) \
OPT_GENERAL(int, optname, varname, (flags) | CONF_RANGE, \
OPT_GENERAL(int, optname, varname, flags, \
.min = minval, .max = maxval, \
M_CHOICES(choices), __VA_ARGS__)
#define OPT_CHOICE_OR_INT(...) \

View File

@ -22,6 +22,7 @@
* config for cfgparser
*/
#include <float.h>
#include <stddef.h>
#include <sys/types.h>
#include <limits.h>
@ -118,7 +119,7 @@ static const m_option_t mp_vo_opt_list[] = {
OPT_SIZE_BOX("autofit", autofit, 0),
OPT_SIZE_BOX("autofit-larger", autofit_larger, 0),
OPT_SIZE_BOX("autofit-smaller", autofit_smaller, 0),
OPT_DOUBLE("window-scale", window_scale, CONF_RANGE, .min = 0.001, .max = 100),
OPT_DOUBLE("window-scale", window_scale, 0, .min = 0.001, .max = 100),
OPT_FLAG("window-minimized", window_minimized, 0),
OPT_FLAG("window-maximized", window_maximized, 0),
OPT_FLAG("force-window-position", force_window_position, 0),
@ -149,7 +150,8 @@ static const m_option_t mp_vo_opt_list[] = {
OPT_FLAG("keepaspect-window", keepaspect_window, 0),
OPT_FLAG("hidpi-window-scale", hidpi_window_scale, 0),
OPT_FLAG("native-fs", native_fs, 0),
OPT_DOUBLE("override-display-fps", override_display_fps, M_OPT_MIN, .min = 0),
OPT_DOUBLE("override-display-fps", override_display_fps, 0,
.min = 0, .max = DBL_MAX),
OPT_DOUBLERANGE("video-timing-offset", timing_offset, 0, 0.0, 1.0),
#if HAVE_X11
OPT_CHOICE("x11-netwm", x11_netwm, 0,
@ -454,7 +456,7 @@ static const m_option_t mp_opts[] = {
{"always", 2})),
OPT_FLAG("keep-open-pause", keep_open_pause, 0),
OPT_DOUBLE("image-display-duration", image_display_duration,
M_OPT_RANGE, 0, INFINITY),
0, 0, INFINITY),
OPT_CHOICE("index", index_mode, 0, ({"default", 1}, {"recreate", 0})),
@ -498,7 +500,7 @@ static const m_option_t mp_opts[] = {
OPT_FLAG("prefetch-playlist", prefetch_open, 0),
OPT_FLAG("cache-pause", cache_pause, 0),
OPT_FLAG("cache-pause-initial", cache_pause_initial, 0),
OPT_FLOAT("cache-pause-wait", cache_pause_wait, M_OPT_MIN, .min = 0),
OPT_FLOAT("cache-pause-wait", cache_pause_wait, 0, .min = 0, .max = DBL_MAX),
OPT_DOUBLE("mf-fps", mf_fps, 0),
OPT_STRING("mf-type", mf_type, 0),
@ -515,7 +517,7 @@ static const m_option_t mp_opts[] = {
OPT_INTRANGE("audio-samplerate", force_srate, UPDATE_AUDIO, 0, 16*48000),
OPT_CHANNELS("audio-channels", audio_output_channels, UPDATE_AUDIO),
OPT_AUDIOFORMAT("audio-format", audio_output_format, UPDATE_AUDIO),
OPT_DOUBLE("speed", playback_speed, M_OPT_RANGE, .min = 0.01, .max = 100.0),
OPT_DOUBLE("speed", playback_speed, 0, .min = 0.01, .max = 100.0),
OPT_FLAG("audio-pitch-correction", pitch_correction, 0),
@ -612,7 +614,7 @@ static const m_option_t mp_opts[] = {
OPT_INTRANGE("osd-duration", osd_duration, 0, 0, 3600000),
OPT_FLAG("osd-fractions", osd_fractions, 0),
OPT_DOUBLE("sstep", step_sec, CONF_MIN, 0),
OPT_DOUBLE("sstep", step_sec, 0, .min = 0, .max = DBL_MAX),
OPT_CHOICE("framedrop", frame_dropping, 0,
({"no", 0},
@ -665,12 +667,12 @@ static const m_option_t mp_opts[] = {
{"display-vdrop", VS_DISP_VDROP},
{"display-desync", VS_DISP_NONE},
{"desync", VS_NONE})),
OPT_DOUBLE("video-sync-max-video-change", sync_max_video_change,
M_OPT_MIN, .min = 0),
OPT_DOUBLE("video-sync-max-audio-change", sync_max_audio_change,
M_OPT_MIN | M_OPT_MAX, .min = 0, .max = 1),
OPT_DOUBLE("video-sync-adrop-size", sync_audio_drop_size,
M_OPT_MIN | M_OPT_MAX, .min = 0, .max = 1),
OPT_DOUBLE("video-sync-max-video-change", sync_max_video_change, 0,
.min = 0, .max = DBL_MAX),
OPT_DOUBLE("video-sync-max-audio-change", sync_max_audio_change, 0,
.min = 0, .max = 1),
OPT_DOUBLE("video-sync-adrop-size", sync_audio_drop_size, 0,
.min = 0, .max = 1),
OPT_CHOICE("hr-seek", hr_seek, 0,
({"no", -1}, {"absolute", 0}, {"yes", 1}, {"always", 1},
{"default", 2})),

View File

@ -15,6 +15,7 @@
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include <float.h>
#include <stdlib.h>
#include <inttypes.h>
#include <unistd.h>
@ -737,7 +738,6 @@ static int mp_property_percent_pos(void *ctx, struct m_property *prop,
case M_PROPERTY_GET_TYPE:
*(struct m_option *)arg = (struct m_option){
.type = CONF_TYPE_DOUBLE,
.flags = M_OPT_RANGE,
.min = 0,
.max = 100,
};
@ -856,7 +856,6 @@ static int mp_property_chapter(void *ctx, struct m_property *prop,
case M_PROPERTY_GET_TYPE:
*(struct m_option *)arg = (struct m_option){
.type = CONF_TYPE_INT,
.flags = M_OPT_MIN | M_OPT_MAX,
.min = -1,
.max = num - 1,
};
@ -1048,7 +1047,6 @@ static int mp_property_edition(void *ctx, struct m_property *prop,
if (action == M_PROPERTY_GET_CONSTRICTED_TYPE && demuxer) {
*(struct m_option *)arg = (struct m_option){
.type = CONF_TYPE_INT,
.flags = M_OPT_RANGE,
.min = 0,
.max = demuxer->num_editions - 1,
};
@ -1554,7 +1552,6 @@ static int mp_property_volume(void *ctx, struct m_property *prop,
case M_PROPERTY_GET_CONSTRICTED_TYPE:
*(struct m_option *)arg = (struct m_option){
.type = CONF_TYPE_FLOAT,
.flags = M_OPT_RANGE,
.min = 0,
.max = opts->softvol_max,
};
@ -1593,7 +1590,6 @@ static int mp_property_ao_volume(void *ctx, struct m_property *prop,
case M_PROPERTY_GET_TYPE:
*(struct m_option *)arg = (struct m_option){
.type = CONF_TYPE_FLOAT,
.flags = M_OPT_RANGE,
.min = 0,
.max = 100,
};
@ -2735,7 +2731,6 @@ static int mp_property_playlist_pos_x(void *ctx, struct m_property *prop,
case M_PROPERTY_GET_TYPE: {
struct m_option opt = {
.type = CONF_TYPE_INT,
.flags = CONF_RANGE,
.min = base,
.max = playlist_entry_count(pl) - 1 + base,
};
@ -3127,15 +3122,11 @@ static int mp_property_option_info(void *ctx, struct m_property *prop,
if (def_ptr && opt->type->size > 0)
memcpy(&def, def_ptr, opt->type->size);
bool has_minmax =
opt->type == &m_option_type_int ||
opt->type == &m_option_type_int64 ||
opt->type == &m_option_type_float ||
opt->type == &m_option_type_double;
bool has_minmax = opt->min < opt->max &&
(opt->type->flags & M_OPT_TYPE_USES_RANGE);
char **choices = NULL;
if (opt->type == &m_option_type_choice) {
has_minmax = true;
struct m_opt_choice_alternatives *alt = opt->priv;
int num = 0;
for ( ; alt->name; alt++)
@ -3161,9 +3152,9 @@ static int mp_property_option_info(void *ctx, struct m_property *prop,
{"set-locally", SUB_PROP_FLAG(co->is_set_locally)},
{"default-value", *opt, def},
{"min", SUB_PROP_DOUBLE(opt->min),
.unavailable = !(has_minmax && (opt->flags & M_OPT_MIN))},
.unavailable = !(has_minmax && opt->min != DBL_MIN)},
{"max", SUB_PROP_DOUBLE(opt->max),
.unavailable = !(has_minmax && (opt->flags & M_OPT_MAX))},
.unavailable = !(has_minmax && opt->max != DBL_MAX)},
{"choices", .type = {.type = CONF_TYPE_STRING_LIST},
.value = {.string_list = choices}, .unavailable = !choices},
{0}
@ -3781,15 +3772,15 @@ static void show_property_osd(MPContext *mpctx, const char *name, int osd_mode)
struct m_option prop = {0};
mp_property_do(name, M_PROPERTY_GET_CONSTRICTED_TYPE, &prop, mpctx);
if ((osd_mode & MP_ON_OSD_BAR) && (prop.flags & CONF_RANGE) == CONF_RANGE) {
if (prop.type == CONF_TYPE_INT) {
if ((osd_mode & MP_ON_OSD_BAR)) {
if (prop.type == CONF_TYPE_INT && prop.min < prop.max) {
int n = prop.min;
if (disp.osd_progbar)
n = disp.marker;
int i;
if (mp_property_do(name, M_PROPERTY_GET, &i, mpctx) > 0)
set_osd_bar(mpctx, disp.osd_progbar, prop.min, prop.max, n, i);
} else if (prop.type == CONF_TYPE_FLOAT) {
} else if (prop.type == CONF_TYPE_FLOAT && prop.min < prop.max) {
float n = prop.min;
if (disp.osd_progbar)
n = disp.marker;

View File

@ -62,7 +62,7 @@ const struct m_sub_options stream_lavf_conf = {
OPT_STRING("tls-ca-file", tls_ca_file, M_OPT_FILE),
OPT_STRING("tls-cert-file", tls_cert_file, M_OPT_FILE),
OPT_STRING("tls-key-file", tls_key_file, M_OPT_FILE),
OPT_DOUBLE("network-timeout", timeout, M_OPT_MIN, .min = 0),
OPT_DOUBLE("network-timeout", timeout, 0, .min = 0, .max = DBL_MAX),
OPT_STRING("http-proxy", http_proxy, 0),
{0}
},

View File

@ -15,6 +15,7 @@
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include <float.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
@ -110,7 +111,7 @@ const struct m_sub_options vd_lavc_conf = {
OPT_DISCARD("vd-lavc-skipidct", skip_idct, 0),
OPT_DISCARD("vd-lavc-skipframe", skip_frame, 0),
OPT_DISCARD("vd-lavc-framedrop", framedrop, 0),
OPT_INT("vd-lavc-threads", threads, M_OPT_MIN, .min = 0),
OPT_INT("vd-lavc-threads", threads, 0, .min = 0, .max = DBL_MAX),
OPT_FLAG("vd-lavc-bitexact", bitexact, 0),
OPT_FLAG("vd-lavc-assume-old-x264", old_x264, 0),
OPT_FLAG("vd-lavc-check-hw-profile", check_hw_profile, 0),

View File

@ -98,7 +98,7 @@ const struct vo_driver video_out_null = {
.uninit = uninit,
.priv_size = sizeof(struct priv),
.options = (const struct m_option[]) {
OPT_DOUBLE("fps", cfg_fps, M_OPT_RANGE, .min = 0, .max = 10000),
OPT_DOUBLE("fps", cfg_fps, 0, .min = 0, .max = 10000),
{0},
},
.options_prefix = "vo-null",

View File

@ -17,6 +17,7 @@
* with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include <float.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -897,8 +898,8 @@ const struct vo_driver video_out_xv = {
.cfg_buffers = 2,
},
.options = (const struct m_option[]) {
OPT_INT("port", xv_port, M_OPT_MIN, .min = 0),
OPT_INT("adaptor", cfg_xv_adaptor, M_OPT_MIN, .min = -1),
OPT_INT("port", xv_port, 0, .min = 0, .max = DBL_MAX),
OPT_INT("adaptor", cfg_xv_adaptor, 0, .min = -1, .max = DBL_MAX),
OPT_CHOICE("ck", xv_ck_info.source, 0,
({"use", CK_SRC_USE},
{"set", CK_SRC_SET},