diff options
author | wm4 <wm4@nowhere> | 2012-11-05 17:02:04 +0100 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2012-11-12 20:06:14 +0100 |
commit | d4bdd0473d6f43132257c9fb3848d829755167a3 (patch) | |
tree | 8021c2f7da1841393c8c832105e20cd527826d6c /core/m_property.c | |
parent | bd48deba77bd5582c5829d6fe73a7d2571088aba (diff) | |
download | mpv-d4bdd0473d6f43132257c9fb3848d829755167a3.tar.bz2 mpv-d4bdd0473d6f43132257c9fb3848d829755167a3.tar.xz |
Rename directories, move files (step 1 of 2) (does not compile)
Tis drops the silly lib prefixes, and attempts to organize the tree in
a more logical way. Make the top-level directory less cluttered as
well.
Renames the following directories:
libaf -> audio/filter
libao2 -> audio/out
libvo -> video/out
libmpdemux -> demux
Split libmpcodecs:
vf* -> video/filter
vd*, dec_video.* -> video/decode
mp_image*, img_format*, ... -> video/
ad*, dec_audio.* -> audio/decode
libaf/format.* is moved to audio/ - this is similar to how mp_image.*
is located in video/.
Move most top-level .c/.h files to core. (talloc.c/.h is left on top-
level, because it's external.) Park some of the more annoying files
in compat/. Some of these are relicts from the time mplayer used
ffmpeg internals.
sub/ is not split, because it's too much of a mess (subtitle code is
mixed with OSD display and rendering).
Maybe the organization of core is not ideal: it mixes playback core
(like mplayer.c) and utility helpers (like bstr.c/h). Should the need
arise, the playback core will be moved somewhere else, while core
contains all helper and common code.
Diffstat (limited to 'core/m_property.c')
-rw-r--r-- | core/m_property.c | 365 |
1 files changed, 365 insertions, 0 deletions
diff --git a/core/m_property.c b/core/m_property.c new file mode 100644 index 0000000000..f97bb366a4 --- /dev/null +++ b/core/m_property.c @@ -0,0 +1,365 @@ +/* + * This file is part of MPlayer. + * + * MPlayer is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * MPlayer is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with MPlayer; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/// \file +/// \ingroup Properties + +#include "config.h" + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <inttypes.h> +#include <assert.h> + +#include <libavutil/common.h> + +#include "talloc.h" +#include "m_option.h" +#include "m_property.h" +#include "mp_msg.h" +#include "mpcommon.h" + +const struct m_option_type m_option_type_dummy = { + .name = "Unknown", +}; + +struct legacy_prop { + const char *old, *new; +}; +static const struct legacy_prop legacy_props[] = { + {"switch_video", "video"}, + {"switch_audio", "audio"}, + {"switch_program", "program"}, + {"framedropping", "framedrop"}, + {"osdlevel", "osd-level"}, + {0} +}; + +static bool translate_legacy_property(const char *name, char *buffer, + size_t buffer_size) +{ + if (strlen(name) + 1 > buffer_size) + return false; + + const char *old_name = name; + + for (int n = 0; legacy_props[n].new; n++) { + if (strcmp(name, legacy_props[n].old) == 0) { + name = legacy_props[n].new; + break; + } + } + + snprintf(buffer, buffer_size, "%s", name); + + // Old names used "_" instead of "-" + for (int n = 0; buffer[n]; n++) { + if (buffer[n] == '_') + buffer[n] = '-'; + } + + if (strcmp(old_name, buffer) != 0) { + mp_msg(MSGT_CPLAYER, MSGL_V, "Warning: property '%s' is deprecated, " + "replaced with '%s'. Fix your input.conf!\n", old_name, buffer); + } + + return true; +} + +static int do_action(const m_option_t *prop_list, const char *name, + int action, void *arg, void *ctx) +{ + const char *sep; + const m_option_t *prop; + 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); + struct m_property_action_arg ka = { + .key = sep + 1, + .action = action, + .arg = arg, + }; + action = M_PROPERTY_KEY_ACTION; + arg = &ka; + } else + prop = m_option_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; +} + +int m_property_do(const m_option_t *prop_list, const char *in_name, + int action, void *arg, void *ctx) +{ + union m_option_value val = {0}; + int r; + + char name[64]; + if (!translate_legacy_property(in_name, name, sizeof(name))) + return M_PROPERTY_UNKNOWN; + + struct m_option opt = {0}; + r = do_action(prop_list, name, M_PROPERTY_GET_TYPE, &opt, ctx); + if (r <= 0) + return r; + assert(opt.type); + + switch (action) { + case M_PROPERTY_PRINT: { + if ((r = do_action(prop_list, name, M_PROPERTY_PRINT, arg, ctx)) >= 0) + return r; + // Fallback to m_option + if ((r = do_action(prop_list, name, M_PROPERTY_GET, &val, ctx)) <= 0) + return r; + char *str = m_option_pretty_print(&opt, &val); + m_option_free(&opt, &val); + *(char **)arg = str; + return str != NULL; + } + case M_PROPERTY_GET_STRING: { + if ((r = do_action(prop_list, name, M_PROPERTY_GET, &val, ctx)) <= 0) + return r; + char *str = m_option_print(&opt, &val); + m_option_free(&opt, &val); + *(char **)arg = str; + return str != NULL; + } + case M_PROPERTY_SET_STRING: { + // (reject 0 return value: success, but empty string with flag) + if (m_option_parse(&opt, bstr0(name), bstr0(arg), &val) <= 0) + return M_PROPERTY_ERROR; + r = do_action(prop_list, name, M_PROPERTY_SET, &val, ctx); + m_option_free(&opt, &val); + return r; + } + case M_PROPERTY_SWITCH: { + struct m_property_switch_arg *sarg = arg; + if ((r = do_action(prop_list, name, M_PROPERTY_SWITCH, arg, ctx)) != + M_PROPERTY_NOT_IMPLEMENTED) + return r; + // Fallback to m_option + if (!opt.type->add) + return M_PROPERTY_NOT_IMPLEMENTED; + if ((r = do_action(prop_list, name, M_PROPERTY_GET, &val, ctx)) <= 0) + return r; + opt.type->add(&opt, &val, sarg->inc, sarg->wrap); + r = do_action(prop_list, name, M_PROPERTY_SET, &val, ctx); + m_option_free(&opt, &val); + return r; + } + case M_PROPERTY_SET: { + if (!opt.type->clamp) { + mp_msg(MSGT_CPLAYER, MSGL_WARN, "Property '%s' without clamp().\n", + name); + } else { + m_option_copy(&opt, &val, arg); + r = opt.type->clamp(&opt, arg); + m_option_free(&opt, &val); + if (r != 0) { + mp_msg(MSGT_CPLAYER, MSGL_ERR, + "Property '%s': invalid value.\n", name); + return M_PROPERTY_ERROR; + } + } + return do_action(prop_list, name, M_PROPERTY_SET, arg, ctx); + } + default: + return do_action(prop_list, name, action, arg, ctx); + } +} + +static int m_property_do_bstr(const m_option_t *prop_list, bstr name, + int action, void *arg, void *ctx) +{ + char name0[64]; + if (name.len >= sizeof(name0)) + return M_PROPERTY_UNKNOWN; + snprintf(name0, sizeof(name0), "%.*s", BSTR_P(name)); + return m_property_do(prop_list, name0, action, arg, ctx); +} + +static void append_str(char **s, int *len, bstr append) +{ + MP_TARRAY_GROW(NULL, *s, *len + append.len); + memcpy(*s + *len, append.start, append.len); + *len = *len + append.len; +} + +char *m_properties_expand_string(const m_option_t *prop_list, char *str0, + void *ctx) +{ + char *ret = NULL; + int ret_len = 0; + bool skip = false; + int level = 0, skip_level = 0; + bstr str = bstr0(str0); + + while (str.len) { + if (level > 0 && bstr_eatstart0(&str, "}")) { + if (skip && level <= skip_level) + skip = false; + level--; + } else if (bstr_startswith0(str, "${") && bstr_find0(str, "}") >= 0) { + str = bstr_cut(str, 2); + level++; + + // Assume ":" and "}" can't be part of the property name + // => if ":" comes before "}", it must be for the fallback + int term_pos = bstrcspn(str, ":}"); + bstr name = bstr_splice(str, 0, term_pos < 0 ? str.len : term_pos); + str = bstr_cut(str, term_pos); + bool have_fallback = bstr_eatstart0(&str, ":"); + + if (!skip) { + bool cond_yes = bstr_eatstart0(&name, "?"); + bool cond_no = !cond_yes && bstr_eatstart0(&name, "!"); + bool raw = bstr_eatstart0(&name, "="); + int method = (raw || cond_yes || cond_no) + ? M_PROPERTY_GET_STRING : M_PROPERTY_PRINT; + + char *s = NULL; + int r = m_property_do_bstr(prop_list, name, method, &s, ctx); + if (cond_yes || cond_no) { + skip = (!!s != cond_yes); + } else { + skip = !!s; + char *append = s; + if (!s && !have_fallback && !raw) { + append = r == M_PROPERTY_UNAVAILABLE + ? "(unavailable)" : "(error)"; + } + append_str(&ret, &ret_len, bstr0(append)); + } + talloc_free(s); + if (skip) + skip_level = level; + } + } else if (level == 0 && bstr_eatstart0(&str, "$>")) { + append_str(&ret, &ret_len, str); + break; + } else { + char c; + + // Other combinations, e.g. "$x", are added verbatim + if (bstr_eatstart0(&str, "$$")) { + c = '$'; + } else if (bstr_eatstart0(&str, "$}")) { + c = '}'; + } else { + c = str.start[0]; + str = bstr_cut(str, 1); + } + + if (!skip) + MP_TARRAY_APPEND(NULL, ret, ret_len, c); + } + } + + MP_TARRAY_APPEND(NULL, ret, ret_len, '\0'); + return ret; +} + +void m_properties_print_help_list(const m_option_t *list) +{ + char min[50], max[50]; + int i, count = 0; + + mp_tmsg(MSGT_CFGPARSER, MSGL_INFO, + "\n Name Type Min Max\n\n"); + for (i = 0; list[i].name; i++) { + const m_option_t *opt = &list[i]; + if (opt->flags & M_OPT_MIN) + sprintf(min, "%-8.0f", opt->min); + else + strcpy(min, "No"); + if (opt->flags & M_OPT_MAX) + sprintf(max, "%-8.0f", opt->max); + else + strcpy(max, "No"); + mp_msg(MSGT_CFGPARSER, MSGL_INFO, + " %-20.20s %-15.15s %-10.10s %-10.10s\n", + opt->name, + opt->type->name, + min, + max); + count++; + } + mp_tmsg(MSGT_CFGPARSER, MSGL_INFO, "\nTotal: %d properties\n", count); +} + +int m_property_int_ro(const m_option_t *prop, int action, + void *arg, int var) +{ + if (action == M_PROPERTY_GET) { + *(int *)arg = var; + 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) +{ + if (action == M_PROPERTY_GET) { + *(int64_t *)arg = var; + 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) +{ + if (action == M_PROPERTY_GET) { + *(float *)arg = var; + 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) +{ + if (action == M_PROPERTY_GET) { + *(double *)arg = var; + 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) +{ + if (action == M_PROPERTY_GET) { + *(char **)arg = talloc_strdup(NULL, var); + return M_PROPERTY_OK; + } + return M_PROPERTY_NOT_IMPLEMENTED; +} |