mirror of https://github.com/mpv-player/mpv
command: add escape-ass
This adds a command to escape ASS tags to remove code duplication between sub/osd_libass.c, console.lua, osc.lua, stats.lua and any user script that calls mp.create_osd_overlay(). A command is used instead of scripting functions so that all clients can use this and not just use Lua and JS ones. osd_mangle_ass() also interprets osd-sym-cc and osd-ass-cc/{0,1}, but since they use invalid UTF-8 characters there is no risk of escape-ass users using them by accident, like with any OSD message. Always replacing \n with \\N in mangle_ass() even when it is not called by escape-ass doesn't seem to cause any issue, but I made it conditional anyway to avoid changing how all OSD messages are treated unnecessarily.
This commit is contained in:
parent
520849dd48
commit
d6610a5b2f
|
@ -0,0 +1 @@
|
|||
add the `escape-ass` command
|
|
@ -1259,6 +1259,18 @@ Input Commands that are Possibly Subject to Change
|
|||
use the ``mp.create_osd_overlay()`` helper instead of invoking this
|
||||
command directly.
|
||||
|
||||
``escape-ass <text>``
|
||||
Modify ``text`` so that commands and functions that interpret ASS tags,
|
||||
such as ``osd-overlay`` and ``mp.create_osd_overlay``, will display it
|
||||
verbatim, and return it. This can only be used through the client API or
|
||||
from a script using ``mp.command_native``.
|
||||
|
||||
.. admonition:: Example
|
||||
|
||||
``mp.osd_message(mp.command_native({"escape-ass", "foo {bar}"}))``
|
||||
|
||||
This line of Lua prints "foo \\{bar}" on the OSD.
|
||||
|
||||
``script-message [<arg1> [<arg2> [...]]]``
|
||||
Send a message to all clients, and pass it the following list of arguments.
|
||||
What this message means, how many arguments it takes, and what the arguments
|
||||
|
|
|
@ -5582,6 +5582,19 @@ static void cmd_expand_path(void *p)
|
|||
};
|
||||
}
|
||||
|
||||
static void cmd_escape_ass(void *p)
|
||||
{
|
||||
struct mp_cmd_ctx *cmd = p;
|
||||
bstr dst = {0};
|
||||
|
||||
osd_mangle_ass(&dst, cmd->args[0].v.s, true);
|
||||
|
||||
cmd->result = (mpv_node){
|
||||
.format = MPV_FORMAT_STRING,
|
||||
.u.string = dst.len ? (char *)dst.start : talloc_strdup(NULL, ""),
|
||||
};
|
||||
}
|
||||
|
||||
static struct load_action get_load_action(struct MPContext *mpctx, int action_flag)
|
||||
{
|
||||
switch (action_flag) {
|
||||
|
@ -6679,6 +6692,8 @@ const struct mp_cmd_def mp_cmds[] = {
|
|||
.is_noisy = true },
|
||||
{ "expand-path", cmd_expand_path, { {"text", OPT_STRING(v.s)} },
|
||||
.is_noisy = true },
|
||||
{ "escape-ass", cmd_escape_ass, { {"text", OPT_STRING(v.s)} },
|
||||
.is_noisy = true },
|
||||
{ "show-progress", cmd_show_progress, .allow_auto_repeat = true,
|
||||
.is_noisy = true },
|
||||
|
||||
|
|
|
@ -229,19 +229,7 @@ end
|
|||
|
||||
-- Escape a string for verbatim display on the OSD
|
||||
function ass_escape(str)
|
||||
-- There is no escape for '\' in ASS (I think?) but '\' is used verbatim if
|
||||
-- it isn't followed by a recognised character, so add a zero-width
|
||||
-- non-breaking space
|
||||
str = str:gsub('\\', '\\\239\187\191')
|
||||
str = str:gsub('{', '\\{')
|
||||
str = str:gsub('}', '\\}')
|
||||
-- Precede newlines with a ZWNBSP to prevent ASS's weird collapsing of
|
||||
-- consecutive newlines
|
||||
str = str:gsub('\n', '\239\187\191\\N')
|
||||
-- Turn leading spaces into hard spaces to prevent ASS from stripping them
|
||||
str = str:gsub('\\N ', '\\N\\h')
|
||||
str = str:gsub('^ ', '\\h')
|
||||
return str
|
||||
return mp.command_native({'escape-ass', str})
|
||||
end
|
||||
|
||||
-- Takes a list of strings, a max width in characters and
|
||||
|
|
|
@ -129,9 +129,6 @@ local function graph_add_value(graph, value)
|
|||
graph.max = max(graph.max, value)
|
||||
end
|
||||
|
||||
-- "\\<U+2060>" in UTF-8 (U+2060 is WORD-JOINER)
|
||||
local ESC_BACKSLASH = "\\" .. string.char(0xE2, 0x81, 0xA0)
|
||||
|
||||
local function no_ASS(t)
|
||||
if not o.use_ass then
|
||||
return t
|
||||
|
@ -139,16 +136,7 @@ local function no_ASS(t)
|
|||
-- mp.osd_message supports ass-escape using osd-ass-cc/{0|1}
|
||||
return ass_stop .. t .. ass_start
|
||||
else
|
||||
-- mp.set_osd_ass doesn't support ass-escape. roll our own.
|
||||
-- similar to mpv's sub/osd_libass.c:mangle_ass(...), excluding
|
||||
-- space after newlines because no_ASS is not used with multi-line.
|
||||
-- space at the beginning is replaced with "\\h" because it matters
|
||||
-- at the beginning of a line, and we can't know where our output
|
||||
-- ends up. no issue if it ends up at the middle of a line.
|
||||
return tostring(t)
|
||||
:gsub("\\", ESC_BACKSLASH)
|
||||
:gsub("{", "\\{")
|
||||
:gsub("^ ", "\\h")
|
||||
return mp.command_native({"escape-ass", tostring(t)})
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -245,5 +245,6 @@ void osd_set_external(struct osd_state *osd, struct osd_external_ass *ov);
|
|||
void osd_set_external_remove_owner(struct osd_state *osd, void *owner);
|
||||
void osd_get_text_size(struct osd_state *osd, int *out_screen_h, int *out_font_h);
|
||||
void osd_get_function_sym(char *buffer, size_t buffer_size, int osd_function);
|
||||
void osd_mangle_ass(bstr *dst, const char *in, bool replace_newlines);
|
||||
|
||||
#endif /* MPLAYER_SUB_H */
|
||||
|
|
|
@ -193,7 +193,7 @@ void osd_get_function_sym(char *buffer, size_t buffer_size, int osd_function)
|
|||
snprintf(buffer, buffer_size, "\xFF%c", osd_function);
|
||||
}
|
||||
|
||||
static void mangle_ass(bstr *dst, const char *in)
|
||||
void osd_mangle_ass(bstr *dst, const char *in, bool replace_newlines)
|
||||
{
|
||||
const char *start = in;
|
||||
bool escape_ass = true;
|
||||
|
@ -213,6 +213,14 @@ static void mangle_ass(bstr *dst, const char *in)
|
|||
}
|
||||
if (escape_ass && *in == '{')
|
||||
bstr_xappend(NULL, dst, bstr0("\\"));
|
||||
// Replace newlines with \N for escape-ass. This is necessary to apply
|
||||
// ASS tags past newlines and to preserve consecutive newlines with
|
||||
// osd-overlay because update_external() adds a ASS event per line.
|
||||
if (replace_newlines && *in == '\n') {
|
||||
bstr_xappend(NULL, dst, bstr0("\\N"));
|
||||
in += 1;
|
||||
continue;
|
||||
}
|
||||
// Libass will strip leading whitespace
|
||||
if (in[0] == ' ' && (in == start || in[-1] == '\n')) {
|
||||
bstr_xappend(NULL, dst, bstr0("\\h"));
|
||||
|
@ -231,7 +239,7 @@ static ASS_Event *add_osd_ass_event_escaped(ASS_Track *track, const char *style,
|
|||
const char *text)
|
||||
{
|
||||
bstr buf = {0};
|
||||
mangle_ass(&buf, text);
|
||||
osd_mangle_ass(&buf, text, false);
|
||||
ASS_Event *e = add_osd_ass_event(track, style, buf.start);
|
||||
talloc_free(buf.start);
|
||||
return e;
|
||||
|
|
Loading…
Reference in New Issue