From 51503a05778290edc0bb77276b67d33ca0e10783 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 15 Nov 2012 18:49:17 +0100 Subject: options: rename -ss and -endpos, allow relative times Rename the -ss option to -start, and -endpos to -length. Add a -end option. The -end option always specifies an absolute end time, as opposed to -endpos/-length. All these options (--start, --end, --length) now accept relative times. Percent positions (e.g. "--start=30%") are interpreted as fractions of the file duration. Negative times (e.g. "--start=-1:00) are interpreted relative to the end of the file. Chapters (e.g. "--start=#3") yield the chapter's time position. The chapter support might be able to replace --chapter completely, but for now I am not sure how well this works out with e.g. DVDs and BDs, and a separate --chapter option is useful interface-wise. --- core/cfg-mplayer.h | 7 +++--- core/m_option.c | 63 +++++++++++++++++++--------------------------- core/m_option.h | 22 +++++++++------- core/mplayer.c | 68 +++++++++++++++++++++++++++++++++++--------------- core/options.h | 6 ++++- core/playlist_parser.c | 2 +- 6 files changed, 96 insertions(+), 72 deletions(-) (limited to 'core') diff --git a/core/cfg-mplayer.h b/core/cfg-mplayer.h index 776798aaad..b6e947be5f 100644 --- a/core/cfg-mplayer.h +++ b/core/cfg-mplayer.h @@ -376,14 +376,13 @@ const m_option_t common_opts[] = { // seek to byte/seconds position {"sb", &seek_to_byte, CONF_TYPE_INT64, CONF_MIN, 0, 0, NULL}, - OPT_TIME("ss", seek_to_sec, 0), + OPT_REL_TIME("start", play_start, 0), + OPT_REL_TIME("end", play_end, 0), + OPT_REL_TIME("length", play_length, 0), // start paused OPT_FLAG_ON("pause", start_paused, 0), - // stop at given position - {"endpos", &end_at, CONF_TYPE_TIME_SIZE, 0, 0, 0, NULL}, - // AVI specific: force non-interleaved mode {"avi-ni", &force_ni, CONF_TYPE_FLAG, 0, 0, 1, NULL}, diff --git a/core/m_option.c b/core/m_option.c index f64b4deb20..693c95cf96 100644 --- a/core/m_option.c +++ b/core/m_option.c @@ -1248,60 +1248,49 @@ const m_option_type_t m_option_type_time = { }; -// Time or size (-endpos) +// Relative time -static int parse_time_size(const m_option_t *opt, struct bstr name, - struct bstr param, void *dst) +static int parse_rel_time(const m_option_t *opt, struct bstr name, + struct bstr param, void *dst) { - m_time_size_t ts; - char unit[4]; - double end_at; + struct m_rel_time t = {0}; if (param.len == 0) return M_OPT_MISSING_PARAM; - ts.pos = 0; - /* End at size parsing */ - if (bstr_sscanf(param, "%lf%3s", &end_at, unit) == 2) { - ts.type = END_AT_SIZE; - if (!strcasecmp(unit, "b")) - ; - else if (!strcasecmp(unit, "kb")) - end_at *= 1024; - else if (!strcasecmp(unit, "mb")) - end_at *= 1024 * 1024; - else if (!strcasecmp(unit, "gb")) - end_at *= 1024 * 1024 * 1024; - else - ts.type = END_AT_NONE; - - if (ts.type == END_AT_SIZE) { - ts.pos = end_at; + // Percent pos + double percent; + if (bstr_sscanf(param, "%lf%%", &percent) == 1) { + if (percent >= 0 && percent <= 100) { + t.type = REL_TIME_PERCENT; + t.pos = percent; goto out; } } - /* End at time parsing. This has to be last because the parsing accepts - * even a number followed by garbage */ - if (!parse_timestring(param, &end_at, 0)) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, - "Option %.*s: invalid time or size: '%.*s'\n", - BSTR_P(name), BSTR_P(param)); - return M_OPT_INVALID; + double sign = bstr_eatstart0(¶m, "-") ? -1 : +1; + double time; + if (parse_timestring(param, &time, 0)) { + t.type = sign ? REL_TIME_NEGATIVE : REL_TIME_ABSOLUTE; + t.pos = time; + goto out; } - ts.type = END_AT_TIME; - ts.pos = end_at; + mp_msg(MSGT_CFGPARSER, MSGL_ERR, + "Option %.*s: invalid time or size: '%.*s'\n", + BSTR_P(name), BSTR_P(param)); + return M_OPT_INVALID; + out: if (dst) - *(m_time_size_t *)dst = ts; + *(struct m_rel_time *)dst = t; return 1; } -const m_option_type_t m_option_type_time_size = { - .name = "Time or size", - .size = sizeof(m_time_size_t), - .parse = parse_time_size, +const m_option_type_t m_option_type_rel_time = { + .name = "Relative time or percent position", + .size = sizeof(struct m_rel_time), + .parse = parse_rel_time, .copy = copy_opt, }; diff --git a/core/m_option.h b/core/m_option.h index 7fec11895a..d7041f9cf4 100644 --- a/core/m_option.h +++ b/core/m_option.h @@ -44,7 +44,7 @@ extern const m_option_type_t m_option_type_double; extern const m_option_type_t m_option_type_string; extern const m_option_type_t m_option_type_string_list; extern const m_option_type_t m_option_type_time; -extern const m_option_type_t m_option_type_time_size; +extern const m_option_type_t m_option_type_rel_time; extern const m_option_type_t m_option_type_choice; extern const m_option_type_t m_option_type_print; @@ -58,13 +58,17 @@ extern const m_option_type_t m_option_type_afmt; // Callback used by m_option_type_print_func options. typedef int (*m_opt_func_full_t)(const m_option_t *, const char *, const char *); -#define END_AT_NONE 0 -#define END_AT_TIME 1 -#define END_AT_SIZE 2 -typedef struct { +enum m_rel_time_type { + REL_TIME_NONE, + REL_TIME_ABSOLUTE, + REL_TIME_NEGATIVE, + REL_TIME_PERCENT, +}; + +struct m_rel_time { double pos; - int type; -} m_time_size_t; + enum m_rel_time_type type; +}; // Extra definition needed for \ref m_option_type_obj_settings_list options. typedef struct { @@ -174,7 +178,6 @@ struct m_sub_options { #define CONF_TYPE_CUSTOM_URL (&m_option_type_custom_url) #define CONF_TYPE_OBJ_PARAMS (&m_option_type_obj_params) #define CONF_TYPE_TIME (&m_option_type_time) -#define CONF_TYPE_TIME_SIZE (&m_option_type_time_size) #define CONF_TYPE_CHOICE (&m_option_type_choice) // Possible option values. Code is allowed to access option data without going @@ -193,7 +196,7 @@ union m_option_value { m_span_t span; m_obj_settings_t *obj_settings_list; double time; - m_time_size_t time_size; + struct m_rel_time rel_time; }; //////////////////////////////////////////////////////////////////////////// @@ -506,6 +509,7 @@ static inline void m_option_free(const m_option_t *opt, void *dst) #define OPT_CHOICE_OR_INT(...) OPT_CHOICE_OR_INT_(__VA_ARGS__, .type = &m_option_type_choice) #define OPT_CHOICE_OR_INT_(optname, varname, flags, minval, maxval, choices, ...) OPT_GENERAL(optname, varname, (flags) | CONF_RANGE, .min = minval, .max = maxval, M_CHOICES(choices), __VA_ARGS__) #define OPT_TIME(...) OPT_GENERAL(__VA_ARGS__, .type = &m_option_type_time) +#define OPT_REL_TIME(...) OPT_GENERAL(__VA_ARGS__, .type = &m_option_type_rel_time) #define OPT_TRACKCHOICE(name, var) OPT_CHOICE_OR_INT(name, var, 0, 0, 8190, ({"no", -2}, {"auto", -1})) diff --git a/core/mplayer.c b/core/mplayer.c index 2923d15374..3d38330c0a 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -165,7 +165,7 @@ static const char help_text[] = _( "Usage: mpv [options] [url|path/]filename\n" "\n" "Basic options: (complete list in the man page)\n" -" --ss= seek to given (seconds or hh:mm:ss) position\n" +" --start=