diff options
-rw-r--r-- | options/m_property.c | 108 | ||||
-rw-r--r-- | options/m_property.h | 35 | ||||
-rw-r--r-- | player/command.c | 1105 | ||||
-rw-r--r-- | player/command.h | 2 | ||||
-rw-r--r-- | player/lua.c | 2 |
5 files changed, 687 insertions, 565 deletions
diff --git a/options/m_property.c b/options/m_property.c index 9b3de3cc5d..015313036a 100644 --- a/options/m_property.c +++ b/options/m_property.c @@ -37,10 +37,6 @@ #include "common/msg.h" #include "common/common.h" -const struct m_option_type m_option_type_dummy = { - .name = "Unknown", -}; - struct legacy_prop { const char *old, *new; }; @@ -84,18 +80,28 @@ static bool translate_legacy_property(struct mp_log *log, const char *name, return true; } -static int do_action(const m_option_t *prop_list, const char *name, +static struct m_property *m_property_list_find(const struct m_property *list, + const char *name) +{ + for (int n = 0; list && list[n].name; n++) { + if (strcmp(list[n].name, name) == 0) + return (struct m_property *)&list[n]; + } + return NULL; +} + +static int do_action(const struct m_property *prop_list, const char *name, int action, void *arg, void *ctx) { const char *sep; - const m_option_t *prop; + struct m_property *prop; struct m_property_action_arg ka; if ((sep = strchr(name, '/')) && sep[1]) { int len = sep - name; char base[len + 1]; memcpy(base, name, len); base[len] = 0; - prop = m_option_list_find(prop_list, base); + prop = m_property_list_find(prop_list, base); ka = (struct m_property_action_arg) { .key = sep + 1, .action = action, @@ -104,22 +110,14 @@ static int do_action(const m_option_t *prop_list, const char *name, action = M_PROPERTY_KEY_ACTION; arg = &ka; } else - prop = m_option_list_find(prop_list, name); + prop = m_property_list_find(prop_list, name); if (!prop) return M_PROPERTY_UNKNOWN; - int (*control)(const m_option_t*, int, void*, void*) = prop->p; - int r = control(prop, action, arg, ctx); - if (action == M_PROPERTY_GET_TYPE && r < 0 && - prop->type != &m_option_type_dummy) - { - *(struct m_option *)arg = *prop; - return M_PROPERTY_OK; - } - return r; + return prop->call(ctx, prop, action, arg); } // (as a hack, log can be NULL on read-only paths) -int m_property_do(struct mp_log *log, const m_option_t *prop_list, +int m_property_do(struct mp_log *log, const struct m_property *prop_list, const char *in_name, int action, void *arg, void *ctx) { union m_option_value val = {0}; @@ -259,7 +257,7 @@ static void m_property_unkey(int *action, void **arg) } } -static int m_property_do_bstr(const m_option_t *prop_list, bstr name, +static int m_property_do_bstr(const struct m_property *prop_list, bstr name, int action, void *arg, void *ctx) { char name0[64]; @@ -276,8 +274,8 @@ static void append_str(char **s, int *len, bstr append) *len = *len + append.len; } -static int expand_property(const m_option_t *prop_list, char **ret, int *ret_len, - bstr prop, bool silent_error, void *ctx) +static int expand_property(const struct m_property *prop_list, char **ret, + int *ret_len, bstr prop, bool silent_error, void *ctx) { bool cond_yes = bstr_eatstart0(&prop, "?"); bool cond_no = !cond_yes && bstr_eatstart0(&prop, "!"); @@ -307,7 +305,7 @@ static int expand_property(const m_option_t *prop_list, char **ret, int *ret_len return skip; } -char *m_properties_expand_string(const m_option_t *prop_list, +char *m_properties_expand_string(const struct m_property *prop_list, const char *str0, void *ctx) { char *ret = NULL; @@ -364,67 +362,93 @@ char *m_properties_expand_string(const m_option_t *prop_list, } void m_properties_print_help_list(struct mp_log *log, - const struct m_option* list) + const struct m_property *list) { int count = 0; mp_info(log, "Name\n\n"); for (int i = 0; list[i].name; i++) { - const m_option_t *opt = &list[i]; - mp_info(log, " %s\n", opt->name); + const struct m_property *p = &list[i]; + mp_info(log, " %s\n", p->name); count++; } mp_info(log, "\nTotal: %d properties\n", count); } -int m_property_int_ro(const m_option_t *prop, int action, - void *arg, int var) +int m_property_flag_ro(int action, void* arg, int var) +{ + switch (action) { + case M_PROPERTY_GET: + *(int *)arg = !!var; + return M_PROPERTY_OK; + case M_PROPERTY_GET_TYPE: + *(struct m_option *)arg = (struct m_option){.type = CONF_TYPE_FLAG}; + return M_PROPERTY_OK; + } + return M_PROPERTY_NOT_IMPLEMENTED; +} + +int m_property_int_ro(int action, void *arg, int var) { - if (action == M_PROPERTY_GET) { + switch (action) { + case M_PROPERTY_GET: *(int *)arg = var; return M_PROPERTY_OK; + case M_PROPERTY_GET_TYPE: + *(struct m_option *)arg = (struct m_option){.type = CONF_TYPE_INT}; + return M_PROPERTY_OK; } return M_PROPERTY_NOT_IMPLEMENTED; } -int m_property_int64_ro(const struct m_option* prop, int action, void* arg, - int64_t var) +int m_property_int64_ro(int action, void* arg, int64_t var) { - if (action == M_PROPERTY_GET) { + switch (action) { + case M_PROPERTY_GET: *(int64_t *)arg = var; return M_PROPERTY_OK; + case M_PROPERTY_GET_TYPE: + *(struct m_option *)arg = (struct m_option){.type = CONF_TYPE_INT64}; + return M_PROPERTY_OK; } return M_PROPERTY_NOT_IMPLEMENTED; } -int m_property_float_ro(const m_option_t *prop, int action, - void *arg, float var) +int m_property_float_ro(int action, void *arg, float var) { - if (action == M_PROPERTY_GET) { + switch (action) { + case M_PROPERTY_GET: *(float *)arg = var; return M_PROPERTY_OK; + case M_PROPERTY_GET_TYPE: + *(struct m_option *)arg = (struct m_option){.type = CONF_TYPE_FLOAT}; + return M_PROPERTY_OK; } return M_PROPERTY_NOT_IMPLEMENTED; } -int m_property_double_ro(const m_option_t *prop, int action, - void *arg, double var) +int m_property_double_ro(int action, void *arg, double var) { - if (action == M_PROPERTY_GET) { + switch (action) { + case M_PROPERTY_GET: *(double *)arg = var; return M_PROPERTY_OK; + case M_PROPERTY_GET_TYPE: + *(struct m_option *)arg = (struct m_option){.type = CONF_TYPE_DOUBLE}; + return M_PROPERTY_OK; } return M_PROPERTY_NOT_IMPLEMENTED; } -int m_property_strdup_ro(const struct m_option* prop, int action, void* arg, - const char *var) +int m_property_strdup_ro(int action, void* arg, const char *var) { - if (action == M_PROPERTY_GET) { - if (!var) - return M_PROPERTY_UNAVAILABLE; + switch (action) { + case M_PROPERTY_GET: *(char **)arg = talloc_strdup(NULL, var); return M_PROPERTY_OK; + case M_PROPERTY_GET_TYPE: + *(struct m_option *)arg = (struct m_option){.type = CONF_TYPE_STRING}; + return M_PROPERTY_OK; } return M_PROPERTY_NOT_IMPLEMENTED; } diff --git a/options/m_property.h b/options/m_property.h index 7ba2c5181d..78b3292fba 100644 --- a/options/m_property.h +++ b/options/m_property.h @@ -26,8 +26,6 @@ struct mp_log; -extern const struct m_option_type m_option_type_dummy; - enum mp_property_action { // Get the property type. This defines the fundamental data type read from // or written to the property. @@ -120,11 +118,22 @@ enum mp_property_return { M_PROPERTY_INVALID_FORMAT = -4, }; +struct m_property { + const char *name; + // ctx: opaque caller context, which the property might use + // prop: pointer to this struct + // action: one of enum mp_property_action + // arg: specific to the action + // returns: one of enum mp_property_return + int (*call)(void *ctx, struct m_property *prop, int action, void *arg); + void *priv; +}; + // Access a property. // action: one of m_property_action // ctx: opaque value passed through to property implementation // returns: one of mp_property_return -int m_property_do(struct mp_log *log, const struct m_option* prop_list, +int m_property_do(struct mp_log *log, const struct m_property* prop_list, const char* property_name, int action, void* arg, void *ctx); // Given a path of the form "a/b/c", this function will set *prefix to "a", @@ -135,7 +144,7 @@ bool m_property_split_path(const char *path, bstr *prefix, char **rem); // Print a list of properties. void m_properties_print_help_list(struct mp_log *log, - const struct m_option* list); + const struct m_property *list); // Expand a property string. // This function allows to print strings containing property values. @@ -149,20 +158,16 @@ void m_properties_print_help_list(struct mp_log *log, // STR is recursively expanded using the same rules. // "$$" can be used to escape "$", and "$}" to escape "}". // "$>" disables parsing of "$" for the rest of the string. -char* m_properties_expand_string(const struct m_option* prop_list, +char* m_properties_expand_string(const struct m_property *prop_list, const char *str, void *ctx); // Trivial helpers for implementing properties. -int m_property_int_ro(const struct m_option* prop, int action, void* arg, - int var); -int m_property_int64_ro(const struct m_option* prop, int action, void* arg, - int64_t var); -int m_property_float_ro(const struct m_option* prop, int action, void* arg, - float var); -int m_property_double_ro(const struct m_option* prop, int action, void* arg, - double var); -int m_property_strdup_ro(const struct m_option* prop, int action, void* arg, - const char *var); +int m_property_flag_ro(int action, void* arg, int var); +int m_property_int_ro(int action, void* arg, int var); +int m_property_int64_ro(int action, void* arg, int64_t var); +int m_property_float_ro(int action, void* arg, float var); +int m_property_double_ro(int action, void* arg, double var); +int m_property_strdup_ro(int action, void* arg, const char *var); struct m_sub_property { // Name of the sub-property - this will be prefixed with the parent diff --git a/player/command.c b/player/command.c index 87c91f295e..85823371f3 100644 --- a/player/command.c +++ b/player/command.c @@ -129,11 +129,12 @@ static char *format_delay(double time) return talloc_asprintf(NULL, "%d ms", ROUND(time * 1000)); } -// Property-option bridge. -static int mp_property_generic_option(struct m_option *prop, int action, - void *arg, MPContext *mpctx) +// Property-option bridge. (Maps the property to the option with the same name.) +static int mp_property_generic_option(void *ctx, struct m_property *prop, + int action, void *arg) { - char *optname = prop->priv; + MPContext *mpctx = ctx; + const char *optname = prop->name; struct m_config_option *opt = m_config_get_co(mpctx->mconfig, bstr0(optname)); void *valptr = opt->data; @@ -153,9 +154,10 @@ static int mp_property_generic_option(struct m_option *prop, int action, } /// Playback speed (RW) -static int mp_property_playback_speed(m_option_t *prop, int action, - void *arg, MPContext *mpctx) +static int mp_property_playback_speed(void *ctx, struct m_property *prop, + int action, void *arg) { + MPContext *mpctx = ctx; struct MPOpts *opts = mpctx->opts; double orig_speed = opts->playback_speed; switch (action) { @@ -171,34 +173,36 @@ static int mp_property_playback_speed(m_option_t *prop, int action, *(char **)arg = talloc_asprintf(NULL, "x %6.2f", orig_speed); return M_PROPERTY_OK; } - return mp_property_generic_option(prop, action, arg, mpctx); + return mp_property_generic_option(mpctx, prop, action, arg); } /// filename with path (RO) -static int mp_property_path(m_option_t *prop, int action, void *arg, - MPContext *mpctx) +static int mp_property_path(void *ctx, struct m_property *prop, + int action, void *arg) { + MPContext *mpctx = ctx; if (!mpctx->filename) return M_PROPERTY_UNAVAILABLE; - return m_property_strdup_ro(prop, action, arg, mpctx->filename); + return m_property_strdup_ro(action, arg, mpctx->filename); } -static int mp_property_filename(m_option_t *prop, int action, void *arg, - MPContext *mpctx) +static int mp_property_filename(void *ctx, struct m_property *prop, + int action, void *arg) { + MPContext *mpctx = ctx; if (!mpctx->filename) return M_PROPERTY_UNAVAILABLE; char *filename = talloc_strdup(NULL, mpctx->filename); if (mp_is_url(bstr0(filename))) mp_url_unescape_inplace(filename); char *f = (char *)mp_basename(filename); - int r = m_property_strdup_ro(prop, action, arg, f[0] ? f : filename); + int r = m_property_strdup_ro(action, arg, f[0] ? f : filename); talloc_free(filename); return r; } -static int mp_property_file_size(m_option_t *prop, int action, void *arg, - void *ctx) +static int mp_property_file_size(void *ctx, struct m_property *prop, + int action, void *arg) { MPContext *mpctx = ctx; if (!mpctx->stream) @@ -208,54 +212,51 @@ static int mp_property_file_size(m_option_t *prop, int action, void *arg, if (stream_control(mpctx->stream, STREAM_CTRL_GET_SIZE, &size) != STREAM_OK) return M_PROPERTY_UNAVAILABLE; - switch (action) { - case M_PROPERTY_GET: { - *(int64_t *)arg = size; - return M_PROPERTY_OK; - } - case M_PROPERTY_PRINT: { + if (action == M_PROPERTY_PRINT) { *(char **)arg = format_file_size(size); return M_PROPERTY_OK; } - } - return M_PROPERTY_NOT_IMPLEMENTED; + return m_property_int64_ro(action, arg, size); } -static int mp_property_media_title(m_option_t *prop, int action, void *arg, - MPContext *mpctx) +static int mp_property_media_title(void *ctx, struct m_property *prop, + int action, void *arg) { + MPContext *mpctx = ctx; char *name = NULL; if (mpctx->resolve_result) name = mpctx->resolve_result->title; if (name && name[0]) - return m_property_strdup_ro(prop, action, arg, name); + return m_property_strdup_ro(action, arg, name); if (mpctx->master_demuxer) { name = demux_info_get(mpctx->master_demuxer, "title"); if (name && name[0]) - return m_property_strdup_ro(prop, action, arg, name); + return m_property_strdup_ro(action, arg, name); struct stream *stream = mpctx->master_demuxer->stream; if (stream_control(stream, STREAM_CTRL_GET_DISC_NAME, &name) > 0 && name) { - int r = m_property_strdup_ro(prop, action, arg, name); + int r = m_property_strdup_ro(action, arg, name); talloc_free(name); return r; } } - return mp_property_filename(prop, action, arg, mpctx); + return mp_property_filename(ctx, prop, action, arg); } -static int mp_property_stream_path(m_option_t *prop, int action, void *arg, - MPContext *mpctx) +static int mp_property_stream_path(void *ctx, struct m_property *prop, + int action, void *arg) { + MPContext *mpctx = ctx; struct stream *stream = mpctx->stream; if (!stream || !stream->url) return M_PROPERTY_UNAVAILABLE; - return m_property_strdup_ro(prop, action, arg, stream->url); + return m_property_strdup_ro(action, arg, stream->url); } -static int mp_property_stream_capture(m_option_t *prop, int action, - void *arg, MPContext *mpctx) +static int mp_property_stream_capture(void *ctx, struct m_property *prop, + int action, void *arg) { + MPContext *mpctx = ctx; if (!mpctx->stream) return M_PROPERTY_UNAVAILABLE; @@ -264,52 +265,54 @@ static int mp_property_stream_capture(m_option_t *prop, int action, stream_set_capture_file(mpctx->stream, filename); // fall through to mp_property_generic_option } - return mp_property_generic_option(prop, action, arg, mpctx); + return mp_property_generic_option(mpctx, prop, action, arg); } /// Demuxer name (RO) -static int mp_property_demuxer(m_option_t *prop, int action, void *arg, - MPContext *mpctx) +static int mp_property_demuxer(void *ctx, struct m_property *prop, + int action, void *arg) { + MPContext *mpctx = ctx; struct demuxer *demuxer = mpctx->master_demuxer; if (!demuxer) return M_PROPERTY_UNAVAILABLE; - return m_property_strdup_ro(prop, action, arg, demuxer->desc->name); + return m_property_strdup_ro(action, arg, demuxer->desc->name); } /// Position in the stream (RW) -static int mp_property_stream_pos(m_option_t *prop, int action, void *arg, - MPContext *mpctx) +static int mp_property_stream_pos(void *ctx, struct m_property *prop, + int action, void *arg) { + MPContext *mpctx = ctx; struct stream *stream = mpctx->stream; if (!stream) return M_PROPERTY_UNAVAILABLE; - switch (action) { - case M_PROPERTY_GET: - *(int64_t *) arg = stream_tell(stream); - return M_PROPERTY_OK; - case M_PROPERTY_SET: + if (action == M_PROPERTY_SET) { stream_seek(stream, *(int64_t *) arg); return M_PROPERTY_OK; } - return M_PROPERTY_NOT_IMPLEMENTED; + return m_property_int64_ro(action, arg, stream_tell(stream)); } /// Stream end offset (RO) -static int mp_property_stream_end(m_option_t *prop, int action, void *arg, - MPContext *mpctx) +static int mp_property_stream_end(void *ctx, struct m_property *prop, + int action, void *arg) { - return mp_property_file_size(prop, action, arg, mpctx); + return mp_property_file_size(ctx, prop, action, arg); } // Does some magic to handle "<name>/full" as time formatted with milliseconds. // Assumes prop is the type of the actual property. -static int property_time(m_option_t *prop, int action, void *arg, double time) +static int property_time(int action, void *arg, double time) { + const struct m_option time_type = {.type = CONF_TYPE_TIME}; switch (action) { case M_PROPERTY_GET: *(double *)arg = time; return M_PROPERTY_OK; + case M_PROPERTY_GET_TYPE: + *(struct m_option *)arg = time_type; + return M_PROPERTY_OK; case M_PROPERTY_KEY_ACTION: { struct m_property_action_arg *ka = arg; @@ -324,7 +327,7 @@ static int property_time(m_option_t *prop, int action, void *arg, double time) *(char **)ka->arg = mp_format_time(time, true); return M_PROPERTY_OK; case M_PROPERTY_GET_TYPE: - *(struct m_option *)ka->arg = *prop; + *(struct m_option *)ka->arg = time_type; return M_PROPERTY_OK; } } @@ -333,9 +336,10 @@ static int property_time(m_option_t *prop, int action, void *arg, double time) } /// Current stream position in seconds (RO) -static int mp_property_stream_time_pos(m_option_t *prop, int action, - void *arg, MPContext *mpctx) +static int mp_property_stream_time_pos(void *ctx, struct m_property *prop, + int action, void *arg) { + MPContext *mpctx = ctx; struct demuxer *demuxer = mpctx->demuxer; if (!demuxer) return M_PROPERTY_UNAVAILABLE; @@ -343,57 +347,62 @@ static int mp_property_stream_time_pos(m_option_t *prop, int action, if (pts == MP_NOPTS_VALUE) return M_PROPERTY_UNAVAILABLE; - return property_time(prop, action, arg, pts); + return property_time(action, arg, pts); } /// Media length in seconds (RO) -static int mp_property_length(m_option_t *prop, int action, void *arg, - MPContext *mpctx) +static int mp_property_length(void *ctx, struct m_property *prop, + int action, void *arg) { + MPContext *mpctx = ctx; double len; if (!(int) (len = get_time_length(mpctx))) return M_PROPERTY_UNAVAILABLE; - return property_time(prop, action, arg, len); + return property_time(action, arg, len); } -static int mp_property_avsync(m_option_t *prop, int action, void *arg, - MPContext *mpctx) +static int mp_property_avsync(void *ctx, struct m_property *prop, + int action, void *arg) { + MPContext *mpctx = ctx; if (!mpctx->d_audio || !mpctx->d_video) return M_PROPERTY_UNAVAILABLE; if (mpctx->last_av_difference == MP_NOPTS_VALUE) return M_PROPERTY_UNAVAILABLE; - return m_property_double_ro(prop, action, arg, mpctx->last_av_difference); + return m_property_double_ro(action, arg, mpctx->last_av_difference); } -static int mp_property_total_avsync_change(m_option_t *prop, int action, void *arg, - MPContext *mpctx) +static int mp_property_total_avsync_change(void *ctx, struct m_property *prop, + int action, void *arg) { + MPContext *mpctx = ctx; if (!mpctx->d_audio || !mpctx->d_video) return M_PROPERTY_UNAVAILABLE; if (mpctx->total_avsync_change == MP_NOPTS_VALUE) return M_PROPERTY_UNAVAILABLE; - return m_property_double_ro(prop, action, arg, mpctx->total_avsync_change); + return m_property_double_ro(action, arg, mpctx->total_avsync_change); } /// Late frames -static int mp_property_drop_frame_cnt(m_option_t *prop, int action, void *arg, - MPContext *mpctx) +static int mp_property_drop_frame_cnt(void *ctx, struct m_property *prop, + int action, void *arg) { + MPContext *mpctx = ctx; if (!mpctx->d_video) return M_PROPERTY_UNAVAILABLE; - return m_property_int_ro(prop, action, arg, mpctx->drop_frame_cnt); + return m_property_int_ro(action, arg, mpctx->drop_frame_cnt); } /// Current position in percent (RW) -static int mp_property_percent_pos(m_option_t *prop, int action, - void *arg, MPContext *mpctx) +static int mp_property_percent_pos(void *ctx, struct m_property *prop, + int action, void *arg) { + MPContext *mpctx = ctx; if (!mpctx->num_sources) return M_PROPERTY_UNAVAILABLE; @@ -410,6 +419,14 @@ static int mp_property_percent_pos(m_option_t *prop, int action, *(double *)arg = pos; return M_PROPERTY_OK; } + case M_PROPERTY_GET_TYPE: + *(struct m_option *)arg = (struct m_option){ + .type = CONF_TYPE_DOUBLE, + .flags = M_OPT_RANGE, + .min = 0, + .max = 100, + }; + return M_PROPERTY_OK; case M_PROPERTY_PRINT: *(char **)arg = talloc_asprintf(NULL, "%d", get_percent_pos(mpctx)); return M_PROPERTY_OK; @@ -417,19 +434,21 @@ static int mp_property_percent_pos(m_option_t *prop, int action, return M_PROPERTY_NOT_IMPLEMENTED; } -static int mp_property_time_start(m_option_t *prop, int action, void *arg, - MPContext *mpctx) +static int mp_property_time_start(void *ctx, struct m_property *prop, + int action, void *arg) { + MPContext *mpctx = ctx; double start = get_start_time(mpctx); if (start < 0) return M_PROPERTY_UNAVAILABLE; - return property_time(prop, action, arg, start); + return property_time(action, arg, start); } /// Current position in seconds (RW) -static int mp_property_time_pos(m_option_t *prop, int action, - void *arg, MPContext *mpctx) +static int mp_property_time_pos(void *ctx, struct m_property *prop, + int action, void *arg) { + MPContext *mpctx = ctx; if (!mpctx->num_sources) return M_PROPERTY_UNAVAILABLE; @@ -437,7 +456,7 @@ static int mp_property_time_pos(m_option_t *prop, int action, queue_seek(mpctx, MPSEEK_ABSOLUTE, *(double *)arg, 0, true); return M_PROPERTY_OK; } - return property_time(prop, action, arg, get_current_time(mpctx)); + return property_time(action, arg, get_current_time(mpctx)); } static bool time_remaining(MPContext *mpctx, double *remaining) @@ -451,31 +470,33 @@ static bool time_remaining(MPContext *mpctx, double *remaining) return len > 0; } -static int mp_property_remaining(m_option_t *prop, int action, - void *arg, MPContext *mpctx) +static int mp_property_remaining(void *ctx, struct m_property *prop, + int action, void *arg) { double remaining; - if (!time_remaining(mpctx, &remaining)) + if (!time_remaining(ctx, &remaining)) return M_PROPERTY_UNAVAILABLE; - return property_time(prop, action, arg, remaining); + return property_time(action, arg, remaining); } -static int mp_property_playtime_remaining(m_option_t *prop, int action, - void *arg, MPContext *mpctx) +static int mp_property_playtime_remaining(void *ctx, struct m_property *prop, + int action, void *arg) { + MPContext *mpctx = ctx; double remaining; if (!time_remaining(mpctx, &remaining)) return M_PROPERTY_UNAVAILABLE; double speed = mpctx->opts->playback_speed; - return property_time(prop, action, arg, remaining / speed); + return property_time(action, arg, remaining / speed); } /// Current BD/DVD title (RW) -static int mp_property_disc_title(m_option_t *prop, int action, void *arg, - MPContext *mpctx) +static int mp_property_disc_title(void *ctx, struct m_property *prop, + int action, void *arg) { + MPContext *mpctx = ctx; struct demuxer *demuxer = mpctx->master_demuxer; if (!demuxer || !demuxer->stream) return M_PROPERTY_UNAVAILABLE; @@ -487,29 +508,37 @@ static int mp_property_disc_title(m_option_t *prop, int action, void *arg, return M_PROPERTY_UNAVAILABLE; *(int*)arg = title; return M_PROPERTY_OK; + case M_PROPERTY_GET_TYPE: + *(struct m_option *)arg = (struct m_option){ + .type = CONF_TYPE_INT, + .flags = M_OPT_MIN, + .min = -1, + }; + return M_PROPERTY_OK; case M_PROPERTY_SET: title = *(int*)arg; if (stream_control(stream, STREAM_CTRL_SET_CURRENT_TITLE, &title) <= 0) return M_PROPERTY_NOT_IMPLEMENTED; return M_PROPERTY_OK; - default: - return M_PROPERTY_NOT_IMPLEMENTED; } + return M_PROPERTY_NOT_IMPLEMENTED; } -static int mp_property_disc_menu(m_option_t *prop, int action, void *arg, - MPContext *mpctx) +static int mp_property_disc_menu(void *ctx, struct m_property *prop, + int action, void *arg) { + MPContext *mpctx = ctx; int state = mp_nav_in_menu(mpctx); if (state < 0) return M_PROPERTY_UNAVAILABLE; - return m_property_int_ro(prop, action, arg, !!state); + return m_property_flag_ro(action, arg, !!state); } /// Current chapter (RW) -static int mp_property_chapter(m_option_t *prop, int action, void *arg, - MPContext *mpctx) +static int mp_property_chapter(void *ctx, struct m_property *prop, + int action, void *arg) { + MPContext *mpctx = ctx; int chapter = get_current_chapter(mpctx); if (chapter < -1) return M_PROPERTY_UNAVAILABLE; @@ -518,6 +547,14 @@ static int mp_property_chapter(m_option_t *prop, int action, void *arg, case M_PROPERTY_GET: *(int *) arg = chapter; return M_PROPERTY_OK; + 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 = get_chapter_count(mpctx) - 1, + }; + return M_PROPERTY_OK; case M_PROPERTY_PRINT: { *(char **) arg = chapter_display_name(mpctx, chapter); return M_PROPERTY_OK; @@ -571,9 +608,10 @@ static int get_chapter_entry(int item, int action, void *arg, void *ctx) return r; } -static int mp_property_list_chapters(m_option_t *prop, int action, void *arg, - MPContext *mpctx) +static int mp_property_list_chapters(void *ctx, struct m_property *prop, + int action, void *arg) { + MPContext *mpctx = ctx; int count = get_chapter_count(mpctx); if (action == M_PROPERTY_PRINT) { int cur = mpctx->num_sources ? get_current_chapter(mpctx) : -1; @@ -603,9 +641,10 @@ static int mp_property_list_chapters(m_option_t *prop, int action, void *arg, return m_property_read_list(action, arg, count, get_chapter_entry, mpctx); } -static int mp_property_edition(m_option_t *prop, int action, void *arg, - MPContext *mpctx) +static int mp_property_edition(void *ctx, struct m_property *prop, + int action, void *arg) { + MPContext *mpctx = ctx; struct MPOpts *opts = mpctx->opts; struct demuxer *demuxer = mpctx->master_demuxer; if (!demuxer) @@ -661,9 +700,10 @@ static int get_edition_entry(int item, int action, void *arg, void *ctx) return m_property_read_sub(props, action, arg); } -static int property_list_editions(m_option_t *prop, int action, void *arg, - MPContext *mpctx) +static int property_list_editions(void *ctx, struct m_property *prop, + int action, void *arg) { + MPContext *mpctx = ctx; struct demuxer *demuxer = mpctx->master_demuxer; if (!demuxer) return M_PROPERTY_UNAVAILABLE; @@ -721,9 +761,10 @@ static struct mp_resolve_src *find_source(struct mp_resolve_result *res, return res->srcs[src]; } -static int mp_property_quvi_format(m_option_t *prop, int action, void *arg, - MPContext *mpctx) +static int mp_property_quvi_format(void *ctx, struct m_property *prop, + int action, void *arg) { + MPContext *mpctx = ctx; struct MPOpts *opts = mpctx->opts; struct mp_resolve_result *res = mpctx->resolve_result; if (!res || !res->num_srcs) @@ -766,49 +807,53 @@ static int mp_property_quvi_format(m_option_t *prop, int action, void *arg, } } char *fmt = res->srcs[pos]->encid; - return mp_property_quvi_format(prop, M_PROPERTY_SET, &fmt, mpctx); + return mp_property_quvi_format(mpctx, prop, M_PROPERTY_SET, &fmt); } } - return mp_property_generic_option(prop, action, arg, mpctx); + return mp_property_generic_option(mpctx, prop, action, arg); } /// Number of titles in BD/DVD -static int mp_property_disc_titles(m_option_t *prop, int action, void *arg, - MPContext *mpctx) +static int mp_property_disc_titles(void *ctx, struct m_property *prop, + int action, void *arg) { + MPContext *mpctx = ctx; struct demuxer *demuxer = mpctx->master_demuxer; unsigned int num_titles; if (!demuxer || stream_control(demuxer->stream, STREAM_CTRL_GET_NUM_TITLES, &num_titles) < 1) return M_PROPERTY_UNAVAILABLE; - return m_property_int_ro(prop, action, arg, num_titles); + return m_property_int_ro(action, arg, num_titles); } /// Number of chapters in file -static int mp_property_chapters(m_option_t *prop, int action, void *arg, - MPContext *mpctx) +static int mp_property_chapters(void *ctx, struct m_property *prop, + int action, void *arg) { + MPContext *mpctx = ctx; if (!mpctx->num_sources) return M_PROPERTY_UNAVAILABLE; int count = get_chapter_count(mpctx); - return m_property_int_ro(prop, action, arg, count); + return m_property_int_ro(action, arg, count); } -static int mp_property_editions(m_option_t *prop, int action, void *arg, - MPContext *mpctx) +static int mp_property_editions(void *ctx, struct m_property *prop, + int action, void *arg) { + MPContext *mpctx = ctx; struct demuxer *demuxer = mpctx->master_demuxer; if (!demuxer) return M_PROPERTY_UNAVAILABLE; if (demuxer->num_editions <= 0) return M_PROPERTY_UNAVAILABLE; - return m_property_int_ro(prop, action, arg, demuxer->num_editions); + return m_property_int_ro(action, arg, demuxer->num_editions); } /// Current dvd angle (RW) -static int mp_property_angle(m_option_t *prop, int action, void *arg, - MPContext *mpctx) +static int mp_property_angle(void *ctx, struct m_property *prop, + int action, void *arg) { + MPContext *mpctx = ctx; struct demuxer *demuxer = mpctx->master_demuxer; int angle = -1; int angles; @@ -866,8 +911,7 @@ static int get_tag_entry(int item, int action, void *arg, void *ctx) return m_property_read_sub(props, action, arg); } -static int tag_property(m_option_t *prop, int action, void *arg, - struct mp_tags *tags) +static int tag_property(int action, void *arg, struct mp_tags *tags) { switch (action) { case M_PROPERTY_GET: { @@ -935,30 +979,33 @@ static int tag_property(m_option_t *prop, int action, void *arg, } /// Demuxer meta data -static int mp_property_metadata(m_option_t *prop, int action, void *arg, - MPContext *mpctx) +static int mp_property_metadata(void *ctx, struct m_property *prop, + int action, void *arg) { + MPContext *mpctx = ctx; struct demuxer *demuxer = mpctx->master_demuxer; if (!demuxer) return M_PROPERTY_UNAVAILABLE; - return tag_property(prop, action, arg, demuxer->metadata); + return tag_property(action, arg, demuxer->metadata); } -static int mp_property_chapter_metadata(m_option_t *prop, int action, void *arg, - MPContext *mpctx) +static int mp_property_chapter_metadata(void *ctx, struct m_property *prop, + int action, void *arg) { + MPContext *mpctx = ctx; struct demuxer *demuxer = mpctx->master_demuxer; int chapter = get_current_chapter(mpctx); if (!demuxer || chapter < 0 || chapter >= demuxer->num_chapters) return M_PROPERTY_UNAVAILABLE; - return tag_property(prop, action, arg, demuxer->chapters[chapter].metadata); + return tag_property(action, arg, demuxer->chapters[chapter].meta |