Something went wrong. Try again.
🎥 Command line media player
Something went wrong. Try again.
C
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141#include <stdio.h>#include <sys/types.h>
#include <mujs.h>
#include "common/common.h"#include "common/msg.h"#include "misc/bstr.h"#include "options/options.h"#include "sd.h"
// p_NAME are protected functions (never throw) which interact with the JS VM.// return 0 on successful interaction, not-0 on (caught) js-error.// on error: stack is the same as on entry + an error value
// js: global[n] = new RegExp(str, flags)static int p_regcomp(js_State *J, int n, const char *str, int flags){ if (js_try(J)) return 1;
js_pushnumber(J, n); // n js_newregexp(J, str, flags); // n regex js_setglobal(J, js_tostring(J, -2)); // n (and global[n] is the regex) js_pop(J, 1);
js_endtry(J); return 0;}
// js: found = global[n].test(text)static int p_regexec(js_State *J, int n, const char *text, int *found){ if (js_try(J)) return 1;
js_pushnumber(J, n); // n js_getglobal(J, js_tostring(J, -1)); // n global[n] js_getproperty(J, -1, "test"); // n global[n] global[n].test js_rot2(J); // n global[n].test global[n] (n, test(), and its `this') js_pushstring(J, text); // n global[n].test global[n] text js_call(J, 1); // n test-result *found = js_toboolean(J, -1); js_pop(J, 2); // the result and n
js_endtry(J); return 0;}
// protected. caller should pop the error after using the result string.static const char *get_err(js_State *J){ return js_trystring(J, -1, "unknown error");}
struct priv { js_State *J; int num_regexes; int offset;};
static void destruct_priv(void *p){ js_freestate(((struct priv *)p)->J);}
static bool jsre_init(struct sd_filter *ft){ if (strcmp(ft->codec, "ass") != 0) return false;
if (!ft->opts->rf_enable) return false;
if (!(ft->opts->jsre_items && ft->opts->jsre_items[0])) return false;
struct priv *p = talloc_zero(ft, struct priv); ft->priv = p;
p->J = js_newstate(0, 0, JS_STRICT); if (!p->J) { MP_ERR(ft, "jsre: VM init error\n"); return false; } talloc_set_destructor(p, destruct_priv);
for (int n = 0; ft->opts->jsre_items[n]; n++) { char *item = ft->opts->jsre_items[n];
int err = p_regcomp(p->J, p->num_regexes, item, JS_REGEXP_I | JS_REGEXP_M); if (err) { MP_ERR(ft, "jsre: %s -- '%s'\n", get_err(p->J), item); js_pop(p->J, 1); continue; }
p->num_regexes += 1; }
if (!p->num_regexes) return false;
p->offset = sd_ass_fmt_offset(ft->event_format); return true;}
static struct demux_packet *jsre_filter(struct sd_filter *ft, struct demux_packet *pkt){ struct priv *p = ft->priv; char *text = bstrto0(NULL, sd_ass_pkt_text(ft, pkt, p->offset)); bool drop = false;
if (ft->opts->rf_plain) sd_ass_to_plaintext(&text, text);
for (int n = 0; n < p->num_regexes; n++) { int found, err = p_regexec(p->J, n, text, &found); if (err == 0 && found) { int level = ft->opts->rf_warn ? MSGL_WARN : MSGL_V; MP_MSG(ft, level, "jsre: regex %d => drop: '%s'\n", n, text); drop = true; break; } else if (err) { MP_WARN(ft, "jsre: test regex %d: %s.\n", n, get_err(p->J)); js_pop(p->J, 1); } }
talloc_free(text); return drop ? NULL : pkt;}
const struct sd_filter_functions sd_filter_jsre = { .init = jsre_init, .filter = jsre_filter,};