diff options
author | wm4 <wm4@nowhere> | 2014-04-08 21:10:00 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2014-04-08 21:10:00 +0200 |
commit | a94020e25bc5fc50ac0cea132a4cccb7743e85fa (patch) | |
tree | b18f44436bae70ce7833c4ff5247cc1fdd2793e1 | |
parent | 708f32b74677ae3fac00ecabfbfd866426b06586 (diff) | |
download | mpv-a94020e25bc5fc50ac0cea132a4cccb7743e85fa.tar.bz2 mpv-a94020e25bc5fc50ac0cea132a4cccb7743e85fa.tar.xz |
lua: add API for observing property changes
A low level API was added already earlier, but that was merely a binding
for the raw C API. Add a "proper" one, and document it.
-rw-r--r-- | DOCS/man/en/lua.rst | 22 | ||||
-rw-r--r-- | player/lua.c | 16 | ||||
-rw-r--r-- | player/lua/defaults.lua | 26 |
3 files changed, 60 insertions, 4 deletions
diff --git a/DOCS/man/en/lua.rst b/DOCS/man/en/lua.rst index ac37f1eabb..5b07ebe0ce 100644 --- a/DOCS/man/en/lua.rst +++ b/DOCS/man/en/lua.rst @@ -240,6 +240,28 @@ The ``mp`` module is preloaded, although it can be loaded manually with are equal to the ``fn`` parameter. This uses normal Lua ``==`` comparison, so be careful when dealing with closures. +``mp.observe_property(name, type, fn)`` + Watch a property for changes. If the property ``name`` is changed, then + the function ``fn(name)`` will be called. ``type`` can be ``nil``, or be + set to one of ``none``, ``native``, ``bool``, ``string``, or ``number``. + ``none`` is the same as ``nil``. For all other values, the new value of + the property will be passed as second argument to ``fn``, using + ``mp.get_property_<type>`` to retrieve it. This means if ``type`` is for + 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 + exact behavior depends on timing and other things.) + +``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 ``==`` + comparison, so be careful when dealing with closures. + ``mp.add_timeout(seconds, fn)`` Call the given function fn when the given number of seconds has elapsed. Note that the number of seconds can be fractional. As of now, the timer diff --git a/player/lua.c b/player/lua.c index 6c17bc4d60..e9065d488b 100644 --- a/player/lua.c +++ b/player/lua.c @@ -432,6 +432,11 @@ static int script_wait_event(lua_State *L) lua_pushstring(L, mpv_event_name(event->event_id)); // event name lua_setfield(L, -2, "event"); // event + if (event->reply_userdata) { + lua_pushnumber(L, event->reply_userdata); + lua_setfield(L, -2, "id"); + } + if (event->error < 0) { lua_pushstring(L, mpv_error_string(event->error)); // event err lua_setfield(L, -2, "error"); // event @@ -880,6 +885,8 @@ static int script_get_property_native(lua_State *L) static mpv_format check_property_format(lua_State *L, int arg) { + if (lua_isnil(L, arg)) + return MPV_FORMAT_NONE; const char *fmts[] = {"none", "native", "bool", "string", "number", NULL}; switch (luaL_checkoption(L, arg, "none", fmts)) { case 0: return MPV_FORMAT_NONE; @@ -891,7 +898,8 @@ static mpv_format check_property_format(lua_State *L, int arg) abort(); } -static int script_observe_property(lua_State *L) +// It has a raw_ prefix, because there is a more high level API in defaults.lua. +static int script_raw_observe_property(lua_State *L) { struct script_ctx *ctx = get_ctx(L); uint64_t id = luaL_checknumber(L, 1); @@ -900,7 +908,7 @@ static int script_observe_property(lua_State *L) return check_error(L, mpv_observe_property(ctx->client, id, name, format)); } -static int script_unobserve_property(lua_State *L) +static int script_raw_unobserve_property(lua_State *L) { struct script_ctx *ctx = get_ctx(L); uint64_t id = luaL_checknumber(L, 1); @@ -1063,8 +1071,8 @@ static struct fn_entry fn_list[] = { FN_ENTRY(set_property_bool), FN_ENTRY(set_property_number), FN_ENTRY(set_property_native), - FN_ENTRY(observe_property), - FN_ENTRY(unobserve_property), + FN_ENTRY(raw_observe_property), + FN_ENTRY(raw_unobserve_property), FN_ENTRY(property_list), FN_ENTRY(set_osd_ass), FN_ENTRY(get_osd_resolution), diff --git a/player/lua/defaults.lua b/player/lua/defaults.lua index 512fe0cb54..80630d20b6 100644 --- a/player/lua/defaults.lua +++ b/player/lua/defaults.lua @@ -241,6 +241,31 @@ local function message_dispatch(ev) end end +local property_id = 0 +local properties = {} + +function mp.observe_property(name, t, cb) + local id = property_id + 1 + property_id = id + properties[id] = cb + mp.raw_observe_property(id, name, t) +end + +function mp.unobserve_property(cb) + for prop_id, prop_cb in pairs(properties) do + if cb == prop_cb then + properties[prop_id] = nil + end + end +end + +local function property_change(ev) + local prop = properties[ev.id] + if prop then + prop(ev.name, ev.data) + end +end + -- used by default event loop (mp_event_loop()) to decide when to quit mp.keep_running = true @@ -286,6 +311,7 @@ end mp.register_event("shutdown", function() mp.keep_running = false end) mp.register_event("script-input-dispatch", script_dispatch) mp.register_event("client-message", message_dispatch) +mp.register_event("property-change", property_change) mp.msg = { log = mp.log, |