summaryrefslogtreecommitdiffstats
path: root/options/m_config_core.c
diff options
context:
space:
mode:
Diffstat (limited to 'options/m_config_core.c')
-rw-r--r--options/m_config_core.c139
1 files changed, 73 insertions, 66 deletions
diff --git a/options/m_config_core.c b/options/m_config_core.c
index f82b886670..328ec6479f 100644
--- a/options/m_config_core.c
+++ b/options/m_config_core.c
@@ -15,29 +15,29 @@
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <stdlib.h>
-#include <stdio.h>
+#include <assert.h>
#include <errno.h>
+#include <stdatomic.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <strings.h>
-#include <assert.h>
-#include <stdbool.h>
-#include <pthread.h>
-#include "m_config_core.h"
-#include "options/m_option.h"
#include "common/common.h"
#include "common/global.h"
-#include "common/msg.h"
#include "common/msg_control.h"
+#include "common/msg.h"
+#include "m_config_core.h"
#include "misc/dispatch.h"
-#include "osdep/atomic.h"
+#include "options/m_option.h"
+#include "osdep/threads.h"
// For use with m_config_cache.
struct m_config_shadow {
- pthread_mutex_t lock;
+ mp_mutex lock;
// Incremented on every option change.
- mp_atomic_uint64 ts;
+ _Atomic uint64_t ts;
// -- immutable after init
// List of m_sub_options instances.
// Index 0 is the top-level and is always present.
@@ -99,14 +99,19 @@ struct config_cache {
void *wakeup_cb_ctx;
};
+struct force_update {
+ char *name;
+ uint64_t ts;
+};
+
// 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
+ struct force_update **force_update; // tracks opts that are written with force update
+ int force_update_len;
};
-static const union m_option_value default_value = {0};
-
static void add_sub_group(struct m_config_shadow *shadow, const char *name_prefix,
int parent_group_index, int parent_ptr,
const struct m_sub_options *subopts);
@@ -241,7 +246,7 @@ const void *m_config_shadow_get_opt_default(struct m_config_shadow *shadow,
if (subopt->defaults)
return (char *)subopt->defaults + opt->offset;
- return &default_value;
+ return &m_option_value_default;
}
void *m_config_cache_get_opt_data(struct m_config_cache *cache, int32_t id)
@@ -419,14 +424,14 @@ static void shadow_destroy(void *p)
assert(shadow->num_listeners == 0);
talloc_free(shadow->data);
- pthread_mutex_destroy(&shadow->lock);
+ mp_mutex_destroy(&shadow->lock);
}
struct m_config_shadow *m_config_shadow_new(const struct m_sub_options *root)
{
struct m_config_shadow *shadow = talloc_zero(NULL, struct m_config_shadow);
talloc_set_destructor(shadow, shadow_destroy);
- pthread_mutex_init(&shadow->lock, NULL);
+ mp_mutex_init(&shadow->lock);
add_sub_group(shadow, NULL, -1, -1, root);
@@ -568,9 +573,9 @@ struct m_config_cache *m_config_cache_from_shadow(void *ta_parent,
in->shadow = shadow;
in->src = shadow->data;
- pthread_mutex_lock(&shadow->lock);
+ mp_mutex_lock(&shadow->lock);
in->data = allocate_option_data(cache, shadow, group_index, in->src);
- pthread_mutex_unlock(&shadow->lock);
+ mp_mutex_unlock(&shadow->lock);
cache->opts = in->data->gdata[0].udata;
@@ -590,6 +595,34 @@ struct m_config_cache *m_config_cache_alloc(void *ta_parent,
return m_config_cache_from_shadow(ta_parent, global->config, group);
}
+static void append_force_update(struct m_config_cache *cache, struct m_group_data *gdata,
+ const char *opt_name)
+{
+ for (int i = 0; i < gdata->force_update_len; ++i) {
+ if (strcmp(opt_name, gdata->force_update[i]->name) == 0) {
+ gdata->force_update[i]->ts = gdata->ts;
+ return;
+ }
+ }
+ struct force_update *new_update = talloc_zero(cache, struct force_update);
+ new_update->name = talloc_strdup(cache, opt_name);
+ new_update->ts = gdata->ts;
+ MP_TARRAY_APPEND(cache, gdata->force_update, gdata->force_update_len, new_update);
+}
+
+static bool check_force_update(struct m_group_data *gdata, const char *opt_name,
+ uint64_t timestamp)
+{
+ for (int i = 0; i < gdata->force_update_len; ++i) {
+ if ((strcmp(opt_name, gdata->force_update[i]->name) == 0) &&
+ gdata->force_update[i]->ts == timestamp)
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
static void update_next_option(struct m_config_cache *cache, void **p_opt)
{
struct config_cache *in = cache->internal;
@@ -611,16 +644,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 &&
+ check_force_update(gsrc, opt->name, in->ts);
+ 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 "
@@ -677,7 +712,7 @@ bool m_config_cache_update(struct m_config_cache *cache)
if (!cache_check_update(cache))
return false;
- pthread_mutex_lock(&shadow->lock);
+ mp_mutex_lock(&shadow->lock);
bool res = false;
while (1) {
void *p;
@@ -686,7 +721,7 @@ bool m_config_cache_update(struct m_config_cache *cache)
break;
res = true;
}
- pthread_mutex_unlock(&shadow->lock);
+ mp_mutex_unlock(&shadow->lock);
return res;
}
@@ -699,9 +734,9 @@ bool m_config_cache_get_next_changed(struct m_config_cache *cache, void **opt)
if (!cache_check_update(cache) && in->upd_group < 0)
return false;
- pthread_mutex_lock(&shadow->lock);
+ mp_mutex_lock(&shadow->lock);
update_next_option(cache, opt);
- pthread_mutex_unlock(&shadow->lock);
+ mp_mutex_unlock(&shadow->lock);
return !!*opt;
}
@@ -746,13 +781,14 @@ bool m_config_cache_write_opt(struct m_config_cache *cache, void *ptr)
struct m_config_group *g = &shadow->groups[group_idx];
const struct m_option *opt = &g->group->opts[opt_idx];
- pthread_mutex_lock(&shadow->lock);
+ mp_mutex_lock(&shadow->lock);
struct m_group_data *gdst = m_config_gdata(in->data, group_idx);
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);
@@ -765,7 +801,10 @@ bool m_config_cache_write_opt(struct m_config_cache *cache, void *ptr)
}
}
- pthread_mutex_unlock(&shadow->lock);
+ if (opt->force_update)
+ append_force_update(cache, gsrc, opt->name);
+
+ mp_mutex_unlock(&shadow->lock);
return changed;
}
@@ -776,7 +815,7 @@ void m_config_cache_set_wakeup_cb(struct m_config_cache *cache,
struct config_cache *in = cache->internal;
struct m_config_shadow *shadow = in->shadow;
- pthread_mutex_lock(&shadow->lock);
+ mp_mutex_lock(&shadow->lock);
if (in->in_list) {
for (int n = 0; n < shadow->num_listeners; n++) {
if (shadow->listeners[n] == in) {
@@ -798,7 +837,7 @@ void m_config_cache_set_wakeup_cb(struct m_config_cache *cache,
in->wakeup_cb = cb;
in->wakeup_cb_ctx = cb_ctx;
}
- pthread_mutex_unlock(&shadow->lock);
+ mp_mutex_unlock(&shadow->lock);
}
static void dispatch_notify(void *p)
@@ -850,38 +889,6 @@ void *mp_get_config_group(void *ta_parent, struct mpv_global *global,
return cache->opts;
}
-void mp_read_option_raw(struct mpv_global *global, const char *name,
- const struct m_option_type *type, void *dst)
-{
- struct m_config_shadow *shadow = global->config;
-
- int32_t optid = -1;
- while (m_config_shadow_get_next_opt(shadow, &optid)) {
- char buf[M_CONFIG_MAX_OPT_NAME_LEN];
- const char *opt_name =
- m_config_shadow_get_opt_name(shadow, optid, buf, sizeof(buf));
-
- if (strcmp(name, opt_name) == 0) {
- const struct m_option *opt = m_config_shadow_get_opt(shadow, optid);
-
- int group_index, opt_index;
- get_opt_from_id(shadow, optid, &group_index, &opt_index);
-
- struct m_group_data *gdata = m_config_gdata(shadow->data, group_index);
- assert(gdata);
-
- assert(opt->offset >= 0);
- assert(opt->type == type);
-
- memset(dst, 0, opt->type->size);
- m_option_copy(opt, dst, gdata->udata + opt->offset);
- return;
- }
- }
-
- assert(0); // not found
-}
-
static const struct m_config_group *find_group(struct mpv_global *global,
const struct m_option *cfg)
{