summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-04-08 22:06:39 +0200
committerwm4 <wm4@nowhere>2014-04-08 22:06:39 +0200
commit89d400dc21881e63fda20e23b11a88bca6ee49d6 (patch)
tree3d8cbe72f74bb37a0dc4165af99da0a79250ec1a
parentd6022f33d64df9c0226db49bef68197473bfc598 (diff)
downloadmpv-89d400dc21881e63fda20e23b11a88bca6ee49d6.tar.bz2
mpv-89d400dc21881e63fda20e23b11a88bca6ee49d6.tar.xz
client API: avoid redundant property change events if possible
This is done simply by comparing the previous and current values. Do this only if the requested format is not MPV_FORMAT_NONE.
-rw-r--r--DOCS/man/en/lua.rst14
-rw-r--r--libmpv/client.h4
-rw-r--r--player/client.c55
3 files changed, 63 insertions, 10 deletions
diff --git a/DOCS/man/en/lua.rst b/DOCS/man/en/lua.rst
index 5b07ebe0ce..e88f4a9c2c 100644
--- a/DOCS/man/en/lua.rst
+++ b/DOCS/man/en/lua.rst
@@ -250,13 +250,17 @@ The ``mp`` module is preloaded, although it can be loaded manually with
example ``string``, ``fn`` is roughly called as in
``fn(name, mp.get_property_string(name))``.
- Sporadic property change events are possible. This means the change function
- ``fn`` can be called even if the property doesn't actually change. Likewise,
- in some cases the function is not called even if the property changes. If
- possible, change events are coalesced. If a property is changed a bunch of
- times in a row, only the last change triggers the change function. (The
+ If possible, change events are coalesced. If a property is changed a bunch
+ of times in a row, only the last change triggers the change function. (The
exact behavior depends on timing and other things.)
+ In some cases the function is not called even if the property changes.
+ Whether this can happen depends on the property.
+
+ If the ``type`` is ``none`` or ``nil``, sporadic property change events are
+ possible. This means the change function ``fn`` can be called even if the
+ property doesn't actually change.
+
``mp.unobserve_property(fn)``
Undo ``mp.observe_property(..., fn)``. This removes all property handlers
that are equal to the ``fn`` parameter. This uses normal Lua ``==``
diff --git a/libmpv/client.h b/libmpv/client.h
index 35c193f64a..0811935476 100644
--- a/libmpv/client.h
+++ b/libmpv/client.h
@@ -752,6 +752,10 @@ int mpv_get_property_async(mpv_handle *ctx, uint64_t reply_userdata,
* Observing a property that doesn't exist is allowed, although it may still
* cause some sporadic change events.
*
+ * If you set the format parameter to a value other than MPV_FORMAT_NONE, the
+ * API will suppress redundant change events by comparing the raw value against
+ * the previous value.
+ *
* @param reply_userdata This will be used for the mpv_event.reply_userdata
* field for the received MPV_EVENT_PROPERTY_CHANGE
* events. (Also see section about asynchronous calls,
diff --git a/player/client.c b/player/client.c
index f35cb4a659..786eaa81a5 100644
--- a/player/client.c
+++ b/player/client.c
@@ -562,6 +562,46 @@ static bool conv_node_to_format(void *dst, mpv_format dst_fmt, mpv_node *src)
return false;
}
+static bool compare_value(void *a, void *b, mpv_format format)
+{
+ switch (format) {
+ case MPV_FORMAT_NONE:
+ return false;
+ case MPV_FORMAT_STRING:
+ case MPV_FORMAT_OSD_STRING:
+ return strcmp(*(char **)a, *(char **)b) == 0;
+ case MPV_FORMAT_FLAG:
+ return *(int *)a == *(int *)b;
+ case MPV_FORMAT_INT64:
+ return *(int64_t *)a == *(int64_t *)b;
+ case MPV_FORMAT_DOUBLE:
+ return *(double *)a == *(double *)b;
+ case MPV_FORMAT_NODE: {
+ struct mpv_node *a_n = a, *b_n = b;
+ if (a_n->format != b_n->format)
+ return false;
+ return compare_value(&a_n->u, &b_n->u, a_n->format);
+ }
+ case MPV_FORMAT_NODE_ARRAY:
+ case MPV_FORMAT_NODE_MAP:
+ {
+ mpv_node_list *l_a = *(mpv_node_list **)a, *l_b = *(mpv_node_list **)b;
+ if (l_a->num != l_b->num)
+ return false;
+ for (int n = 0; n < l_a->num; n++) {
+ if (!compare_value(&l_a->values[n], &l_b->values[n], MPV_FORMAT_NODE))
+ return false;
+ if (format == MPV_FORMAT_NODE_MAP) {
+ if (strcmp(l_a->keys[n], l_b->keys[n]) != 0)
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+ abort();
+}
+
void mpv_free_node_contents(mpv_node *node)
{
static const struct m_option type = { .type = CONF_TYPE_NODE };
@@ -1104,12 +1144,17 @@ static void update_prop(void *p)
pthread_mutex_lock(&ctx->lock);
ctx->properties_updating--;
prop->updating = false;
- prop->changed = true;
- prop->value_valid = req.status >= 0;
- if (prop->value_valid) {
- m_option_free(type, &prop->value);
- memcpy(&prop->value, &val, type->type->size);
+ bool new_value_valid = req.status >= 0;
+ if (prop->value_valid != new_value_valid) {
+ prop->changed = true;
+ } else if (prop->value_valid && new_value_valid) {
+ if (!compare_value(&prop->value, &val, prop->format))
+ prop->changed = true;
}
+ m_option_free(type, &prop->value);
+ if (new_value_valid)
+ memcpy(&prop->value, &val, type->type->size);
+ prop->value_valid = new_value_valid;
if (prop->dead)
talloc_steal(ctx->cur_event, prop);
wakeup_client(ctx);