diff --git a/options/m_config_core.c b/options/m_config_core.c index 08a76eb76d..0cd51ceb41 100644 --- a/options/m_config_core.c +++ b/options/m_config_core.c @@ -101,8 +101,10 @@ struct config_cache { // Per m_config_data state for each m_config_group. struct m_group_data { - char *udata; // pointer to group user option struct - uint64_t ts; // timestamp of the data copy + char *udata; // pointer to group user option struct + uint64_t ts; // timestamp of the data copy + char **force_updates; // track if any opt in group was written with force_update + int force_updates_len; }; static void add_sub_group(struct m_config_shadow *shadow, const char *name_prefix, @@ -588,6 +590,27 @@ struct m_config_cache *m_config_cache_alloc(void *ta_parent, return m_config_cache_from_shadow(ta_parent, global->config, group); } +static void clear_force_update_list(struct m_group_data *gsrc) +{ + int index = 0; + while (index < gsrc->force_updates_len) { + TA_FREEP(&gsrc->force_updates[index]); + ++index; + } + gsrc->force_updates_len = 0; +} + +static bool check_force_update_list(struct m_group_data *gsrc, const char *opt_name) +{ + int index = 0; + while (index < gsrc->force_updates_len) { + if (strcmp(opt_name, gsrc->force_updates[index]) == 0) + return true; + ++index; + } + return false; +} + static void update_next_option(struct m_config_cache *cache, void **p_opt) { struct config_cache *in = cache->internal; @@ -609,16 +632,18 @@ static void update_next_option(struct m_config_cache *cache, void **p_opt) while (opts && opts[in->upd_opt].name) { const struct m_option *opt = &opts[in->upd_opt]; + void *dsrc = gsrc->udata + opt->offset; + void *ddst = gdst->udata + opt->offset; if (opt->offset >= 0 && opt->type->size) { - void *dsrc = gsrc->udata + opt->offset; - void *ddst = gdst->udata + opt->offset; - - if (!m_option_equal(opt, ddst, dsrc)) { + bool opt_equal = m_option_equal(opt, ddst, dsrc); + bool force_update = opt->force_update && gsrc->force_updates_len && + check_force_update_list(gsrc, opt->name); + if (!opt_equal || force_update) { uint64_t ch = get_opt_change_mask(dst->shadow, in->upd_group, dst->group_index, opt); - if (cache->debug) { + if (cache->debug && !opt_equal) { char *vdst = m_option_print(opt, ddst); char *vsrc = m_option_print(opt, dsrc); mp_warn(cache->debug, "Option '%s' changed from " @@ -641,6 +666,8 @@ static void update_next_option(struct m_config_cache *cache, void **p_opt) } gdst->ts = gsrc->ts; + } else { + clear_force_update_list(gsrc); } in->upd_group++; @@ -750,7 +777,8 @@ bool m_config_cache_write_opt(struct m_config_cache *cache, void *ptr) struct m_group_data *gsrc = m_config_gdata(in->src, group_idx); assert(gdst && gsrc); - bool changed = !m_option_equal(opt, gsrc->udata + opt->offset, ptr); + bool changed = !m_option_equal(opt, gsrc->udata + opt->offset, ptr) || + opt->force_update; if (changed) { m_option_copy(opt, gsrc->udata + opt->offset, ptr); @@ -763,6 +791,11 @@ bool m_config_cache_write_opt(struct m_config_cache *cache, void *ptr) } } + if (opt->force_update) { + MP_TARRAY_APPEND(shadow, gsrc->force_updates, gsrc->force_updates_len, + talloc_strdup(shadow, opt->name)); + } + mp_mutex_unlock(&shadow->lock); return changed; diff --git a/options/m_option.h b/options/m_option.h index 530c0a3d50..4c3385876c 100644 --- a/options/m_option.h +++ b/options/m_option.h @@ -384,6 +384,9 @@ struct m_option { // See \ref OptionFlags. unsigned int flags; + // Always force an option update even if the written value does not change. + bool force_update; + int offset; // Most numeric types restrict the range to [min, max] if min