diff options
author | wm4 <wm4@nowhere> | 2014-08-02 01:39:28 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2014-08-02 01:53:22 +0200 |
commit | 733bdebcb94e485317e210cfd79ec058b097e12d (patch) | |
tree | bec9b4181e8e9ffdf7d74cabdd12dfad7295f93e /player/command.c | |
parent | 82a223e4e0bf45827c20592aaa7d5690593802ff (diff) | |
download | mpv-733bdebcb94e485317e210cfd79ec058b097e12d.tar.bz2 mpv-733bdebcb94e485317e210cfd79ec058b097e12d.tar.xz |
client API: minor optimizations for property notification
Internally, there are two mechanisms which can trigger property
notification as used with "observed" properties in the client API.
The first mechanism associates events with a group of properties that
are potentially changed by a certain event. mp_event_property_change[]
declares these associations, and maps each event to a set of strings.
When an event happens, the set of strings is matched against the list of
observed properties of each client. Make this more efficient by
comparing bitsets of events instead. This way, only a bit-wise "and" is
needed for each observed property. Even better, we can completely skip
clients which have no observed properties that match.
The second mechanism just updates individual properties explicitly by
name. Optimize this by using the property index instead. It would be
nice if we could reuse the first mechanism for the second one, but
there are too many properties to fit into a 64 bit mask.
(Though the limit on 64 events might get us into trouble later...)
Diffstat (limited to 'player/command.c')
-rw-r--r-- | player/command.c | 47 |
1 files changed, 42 insertions, 5 deletions
diff --git a/player/command.c b/player/command.c index df44df5f69..df59e34714 100644 --- a/player/command.c +++ b/player/command.c @@ -2834,6 +2834,46 @@ static const char *const *const mp_event_property_change[] = { }; #undef E +static int prefix_len(const char *p) +{ + const char *end = strchr(p, '/'); + return end ? end - p : strlen(p); +} + +static bool match_property(const char *a, const char *b) +{ + if (strcmp(a, "*") == 0) + return true; + int len_a = prefix_len(a); + int len_b = prefix_len(b); + return strncmp(a, b, MPMIN(len_a, len_b)) == 0; +} + +// Return a bitset of events which change the property. +uint64_t mp_get_property_event_mask(const char *name) +{ + uint64_t mask = 0; + for (int n = 0; n < MP_ARRAY_SIZE(mp_event_property_change); n++) { + const char *const *const list = mp_event_property_change[n]; + for (int i = 0; list && list[i]; i++) { + if (match_property(list[i], name)) + mask |= 1ULL << n; + } + } + return mask; +} + +// Return an ID for the property. It might not be unique, but is good enough +// for property change handling. Return -1 if property unknown. +int mp_get_property_id(const char *name) +{ + for (int n = 0; mp_properties[n].name; n++) { + if (match_property(mp_properties[n].name, name)) + return n; + } + return -1; +} + static bool is_property_set(int action, void *val) { switch (action) { @@ -3921,13 +3961,10 @@ void mp_notify(struct MPContext *mpctx, int event, void *arg) if (event == MPV_EVENT_START_FILE) ctx->last_seek_pts = MP_NOPTS_VALUE; - if (event < INTERNAL_EVENT_BASE) - mp_client_broadcast_event(mpctx, event, arg); - if (event >= 0 && event < MP_ARRAY_SIZE(mp_event_property_change)) - mp_client_property_change(mpctx, mp_event_property_change[event]); + mp_client_broadcast_event(mpctx, event, arg); } void mp_notify_property(struct MPContext *mpctx, const char *property) { - mp_client_property_change(mpctx, (const char*[]){property, NULL}); + mp_client_property_change(mpctx, property); } |