diff --git a/DOCS/man/input.rst b/DOCS/man/input.rst index 0f6ec9430e..94e1f2fd27 100644 --- a/DOCS/man/input.rst +++ b/DOCS/man/input.rst @@ -2533,6 +2533,28 @@ Property list ``current-ao`` Current audio output driver (name as used with ``--ao``). +``shared-script-properties`` (RW) + This is a key/value map of arbitrary strings shared between scripts for + general use. The player itself does not use any data in it (although some + builtin scripts may). The property is not preserved across player restarts. + + This is very primitive, inefficient, and annoying to use. It's a makeshift + solution which could go away any time (for example, when a better solution + becomes available). This is also why this property has an annoying name. You + should avoid using it, unless you absolutely have to. + + Lua scripting has helpers starting with ``utils.shared_script_property_``. + They are undocumented because you should not use this property. If you still + think you must, you should use the helpers instead of the property directly. + + You are supposed to use the ``change-list`` command to modify the contents. + Reading, modifying, and writing the property manually could data loss if two + scripts update different keys at the same time due to lack of + synchronization. The Lua helpers take care of this. + + (There is no way to ensure synchronization if two scripts try to update the + same key at the same time.) + ``working-directory`` Return the working directory of the mpv process. Can be useful for JSON IPC users, because the command line player usually works with relative paths. diff --git a/player/command.c b/player/command.c index 8576e36da7..32e4e3dfea 100644 --- a/player/command.c +++ b/player/command.c @@ -102,6 +102,12 @@ struct command_ctx { struct ao_hotplug *hotplug; struct mp_cmd_ctx *cache_dump_cmd; // in progress cache dumping + + char **script_props; +}; + +static const struct m_option script_props_type = { + .type = &m_option_type_keyvalue_list }; struct overlay { @@ -3217,6 +3223,27 @@ static int mp_property_bindings(void *ctx, struct m_property *prop, return M_PROPERTY_NOT_IMPLEMENTED; } + +static int mp_property_script_props(void *ctx, struct m_property *prop, + int action, void *arg) +{ + MPContext *mpctx = ctx; + struct command_ctx *cmd = mpctx->command_ctx; + switch (action) { + case M_PROPERTY_GET_TYPE: + *(struct m_option *)arg = script_props_type; + return M_PROPERTY_OK; + case M_PROPERTY_GET: + m_option_copy(&script_props_type, arg, &cmd->script_props); + return M_PROPERTY_OK; + case M_PROPERTY_SET: + m_option_copy(&script_props_type, &cmd->script_props, arg); + mp_notify_property(mpctx, prop->name); + return M_PROPERTY_OK; + } + return M_PROPERTY_NOT_IMPLEMENTED; +} + // Redirect a property name to another #define M_PROPERTY_ALIAS(name, real_property) \ {(name), mp_property_alias, .priv = (real_property)} @@ -3391,6 +3418,8 @@ static const struct m_property mp_properties_base[] = { {"command-list", mp_property_commands}, {"input-bindings", mp_property_bindings}, + {"shared-script-properties", mp_property_script_props}, + M_PROPERTY_ALIAS("video", "vid"), M_PROPERTY_ALIAS("audio", "aid"), M_PROPERTY_ALIAS("sub", "sid"), @@ -5856,6 +5885,8 @@ void command_uninit(struct MPContext *mpctx) overlay_uninit(mpctx); ao_hotplug_destroy(ctx->hotplug); + m_option_free(&script_props_type, &ctx->script_props); + talloc_free(mpctx->command_ctx); mpctx->command_ctx = NULL; } diff --git a/player/lua/defaults.lua b/player/lua/defaults.lua index f2983e8dc3..29e513f4ea 100644 --- a/player/lua/defaults.lua +++ b/player/lua/defaults.lua @@ -676,4 +676,28 @@ function mp_utils.subprocess_detached(t) mp.commandv("run", unpack(t.args)) end +function mp_utils.shared_script_property_set(name, value) + if value ~= nil then + -- no such thing as change-list with mpv_node, so build a string value + mp.commandv("change-list", "shared-script-properties", "append", + name .. "=" .. value) + else + mp.commandv("change-list", "shared-script-properties", "remove", name) + end +end + +function mp_utils.shared_script_property_get(name) + local map = mp.get_property_native("shared-script-properties") + return map and map[name] +end + +-- cb(name, value) on change and on init +function mp_utils.shared_script_property_observe(name, cb) + -- it's _very_ wasteful to observe the mpv core "super" property for every + -- shared sub-property, but then again you shouldn't use this + mp.observe_property("shared-script-properties", "native", function(_, val) + cb(name, val and val[name]) + end) +end + return {}