mirror of
https://github.com/mpv-player/mpv.git
synced 2026-10-26 04:59:30 +08:00
This commit ensures that `input.terminate()` can only close input requests made by the same script, and prevents any in-transit events for old input requests from being processed. Previously, there was no way to guarantee that the input request being terminated was the one intended; the asynchronous nature of the API meant that it was always possible (though unlikely) that another client may have activated its own input request while the termination request was in transit. This commit removes the race condition between different scripts calling `input.terminate()` by sending the script name alongside the termination message. In addition, when a script overwrites one of its own input requests, there may be incoming events still in transit. Some of these events may have a decent chance of calling `input.terminate()` if they are processed (e.g., `submit`). This commit avoids this issue by only processing `closed` requests once a new `input.get()` request is made.
101 lines
3.0 KiB
Lua
101 lines
3.0 KiB
Lua
--[[
|
|
This file is part of mpv.
|
|
|
|
mpv is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
mpv is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with mpv. If not, see <http://www.gnu.org/licenses/>.
|
|
]]
|
|
|
|
local utils = require "mp.utils"
|
|
local input = {}
|
|
|
|
local handle_counter = 0
|
|
local latest_handler_id
|
|
|
|
local function get_non_callbacks(t)
|
|
local non_callbacks = {}
|
|
|
|
for key, value in pairs(t) do
|
|
if type(value) ~= "function" then
|
|
non_callbacks[key] = value
|
|
end
|
|
end
|
|
|
|
return non_callbacks
|
|
end
|
|
|
|
local function register_event_handler(t)
|
|
local handler_id = "input-event/"..handle_counter
|
|
handle_counter = handle_counter + 1
|
|
latest_handler_id = handler_id
|
|
|
|
mp.register_script_message(handler_id, function (type, args)
|
|
-- do not process events (other than closed) for an input that has been overwritten
|
|
if latest_handler_id ~= handler_id and type ~= "closed" then
|
|
return
|
|
end
|
|
|
|
if t[type] then
|
|
local completions, completion_pos, completion_append =
|
|
t[type](unpack(utils.parse_json(args or "") or {}))
|
|
|
|
if type == "complete" and completions then
|
|
mp.commandv("script-message-to", "console", "complete",
|
|
utils.format_json(completions), completion_pos,
|
|
completion_append or "")
|
|
end
|
|
end
|
|
|
|
if type == "closed" then
|
|
mp.unregister_script_message(handler_id)
|
|
end
|
|
end)
|
|
|
|
return handler_id
|
|
end
|
|
|
|
function input.get(t)
|
|
t.has_completions = t.complete ~= nil
|
|
t.client_name = mp.get_script_name()
|
|
t.handler_id = register_event_handler(t)
|
|
|
|
mp.commandv("script-message-to", "console", "get-input",
|
|
utils.format_json(get_non_callbacks(t)))
|
|
end
|
|
|
|
input.select = input.get
|
|
|
|
function input.terminate()
|
|
mp.commandv("script-message-to", "console", "disable", utils.format_json({
|
|
client_name = mp.get_script_name(),
|
|
}))
|
|
end
|
|
|
|
function input.log(message, style, terminal_style)
|
|
mp.commandv("script-message-to", "console", "log", utils.format_json({
|
|
text = message,
|
|
style = style,
|
|
terminal_style = terminal_style,
|
|
}))
|
|
end
|
|
|
|
function input.log_error(message)
|
|
mp.commandv("script-message-to", "console", "log",
|
|
utils.format_json({ text = message, error = true }))
|
|
end
|
|
|
|
function input.set_log(log)
|
|
mp.commandv("script-message-to", "console", "set-log", utils.format_json(log))
|
|
end
|
|
|
|
return input
|