Add initial Lua scripting support
This is preliminary. There are still tons of issues, and any aspect
of scripting may change in the future. I decided to merge this
(preliminary) work now because it makes it easier to develop it, not
because it's done. lua.rst is clear enough about it (plus some
sarcasm).
This requires linking to Lua. Lua has no official pkg-config file, but
there are distribution specific .pc files, all with different names.
Adding a non-pkg-config based configure test was considered, but we'd
rather not.
One major complication is that libquvi links against Lua too, and if
the Lua version is different from mpv's, you will get a crash as soon
as libquvi uses Lua. (libquvi by design always runs when a file is
opened.) I would consider this the problem of distros and whoever
builds mpv, but to make things easier for users, we add a terrible
runtime test to the configure script, which probes whether libquvi
will crash. This is disabled when cross-compiling, but in that case
we hope the user knows what he is doing.
2013-09-26 00:41:14 +02:00
|
|
|
#include <assert.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include <lua.h>
|
|
|
|
#include <lualib.h>
|
|
|
|
#include <lauxlib.h>
|
|
|
|
|
|
|
|
#include "talloc.h"
|
|
|
|
|
2013-12-17 02:39:45 +01:00
|
|
|
#include "common/common.h"
|
2013-12-17 02:02:25 +01:00
|
|
|
#include "options/m_property.h"
|
2013-12-17 02:39:45 +01:00
|
|
|
#include "common/msg.h"
|
lua: allow scripts to snoop messages
Adds the following Lua function to enable message events:
mp.enable_messages(size, level)
size is the maximum number of messages the ringbuffer consists of. level
is the minimum log level for a message to be added to the ringbuffer,
and uses the same values as the mp.log() function. (Actually not yet,
but this will be fixed in the following commit.)
The messages will be delivered via the mp_event() in the user script,
using "message" as event name. The event argument is a table with the
following fields:
level: log level of the message (string as in mp.log())
prefix: string identifying the module of origin
text: contents of the message
As of currently, the message text will contain newline characters. A
message can consist of several lines. It is also possible that a
message doesn't end with a newline, and a caller can use multiple
messages to "build" a line. Most messages will contain exactly 1 line
ending with a single newline character, though.
If the message buffer overflows (messages are not read quickly enough),
new messages are lost until the queued up messages are read. At the
point of the overflow, a special overflow message is inserted. It will
have prefix set to "overflow", and the message text is set to "".
Care should be taken not to print any messages from the message event
handler. This would lead to an infinite loop (the event handler would be
called again after returning, because a new message is available). This
includes mp.log() and all mp.msg.* functions. Keep in mind that the Lua
print() function is mapped to mp.msg.info().
2014-01-16 21:34:58 +01:00
|
|
|
#include "common/msg_control.h"
|
2013-12-17 02:02:25 +01:00
|
|
|
#include "options/m_option.h"
|
2013-12-17 01:23:09 +01:00
|
|
|
#include "input/input.h"
|
2013-12-17 02:02:25 +01:00
|
|
|
#include "options/path.h"
|
2013-12-17 02:39:45 +01:00
|
|
|
#include "bstr/bstr.h"
|
2013-10-29 21:35:29 +01:00
|
|
|
#include "osdep/timer.h"
|
2013-11-24 12:58:06 +01:00
|
|
|
#include "sub/osd.h"
|
2013-12-17 01:08:53 +01:00
|
|
|
#include "core.h"
|
Add initial Lua scripting support
This is preliminary. There are still tons of issues, and any aspect
of scripting may change in the future. I decided to merge this
(preliminary) work now because it makes it easier to develop it, not
because it's done. lua.rst is clear enough about it (plus some
sarcasm).
This requires linking to Lua. Lua has no official pkg-config file, but
there are distribution specific .pc files, all with different names.
Adding a non-pkg-config based configure test was considered, but we'd
rather not.
One major complication is that libquvi links against Lua too, and if
the Lua version is different from mpv's, you will get a crash as soon
as libquvi uses Lua. (libquvi by design always runs when a file is
opened.) I would consider this the problem of distros and whoever
builds mpv, but to make things easier for users, we add a terrible
runtime test to the configure script, which probes whether libquvi
will crash. This is disabled when cross-compiling, but in that case
we hope the user knows what he is doing.
2013-09-26 00:41:14 +02:00
|
|
|
#include "command.h"
|
2013-12-17 01:15:48 +01:00
|
|
|
#include "lua.h"
|
Add initial Lua scripting support
This is preliminary. There are still tons of issues, and any aspect
of scripting may change in the future. I decided to merge this
(preliminary) work now because it makes it easier to develop it, not
because it's done. lua.rst is clear enough about it (plus some
sarcasm).
This requires linking to Lua. Lua has no official pkg-config file, but
there are distribution specific .pc files, all with different names.
Adding a non-pkg-config based configure test was considered, but we'd
rather not.
One major complication is that libquvi links against Lua too, and if
the Lua version is different from mpv's, you will get a crash as soon
as libquvi uses Lua. (libquvi by design always runs when a file is
opened.) I would consider this the problem of distros and whoever
builds mpv, but to make things easier for users, we add a terrible
runtime test to the configure script, which probes whether libquvi
will crash. This is disabled when cross-compiling, but in that case
we hope the user knows what he is doing.
2013-09-26 00:41:14 +02:00
|
|
|
|
|
|
|
// List of builtin modules and their contents as strings.
|
2013-12-17 00:53:22 +01:00
|
|
|
// All these are generated from player/lua/*.lua
|
Add initial Lua scripting support
This is preliminary. There are still tons of issues, and any aspect
of scripting may change in the future. I decided to merge this
(preliminary) work now because it makes it easier to develop it, not
because it's done. lua.rst is clear enough about it (plus some
sarcasm).
This requires linking to Lua. Lua has no official pkg-config file, but
there are distribution specific .pc files, all with different names.
Adding a non-pkg-config based configure test was considered, but we'd
rather not.
One major complication is that libquvi links against Lua too, and if
the Lua version is different from mpv's, you will get a crash as soon
as libquvi uses Lua. (libquvi by design always runs when a file is
opened.) I would consider this the problem of distros and whoever
builds mpv, but to make things easier for users, we add a terrible
runtime test to the configure script, which probes whether libquvi
will crash. This is disabled when cross-compiling, but in that case
we hope the user knows what he is doing.
2013-09-26 00:41:14 +02:00
|
|
|
static const char *builtin_lua_scripts[][2] = {
|
|
|
|
{"mp.defaults",
|
2013-12-17 00:53:22 +01:00
|
|
|
# include "player/lua/defaults.inc"
|
Add initial Lua scripting support
This is preliminary. There are still tons of issues, and any aspect
of scripting may change in the future. I decided to merge this
(preliminary) work now because it makes it easier to develop it, not
because it's done. lua.rst is clear enough about it (plus some
sarcasm).
This requires linking to Lua. Lua has no official pkg-config file, but
there are distribution specific .pc files, all with different names.
Adding a non-pkg-config based configure test was considered, but we'd
rather not.
One major complication is that libquvi links against Lua too, and if
the Lua version is different from mpv's, you will get a crash as soon
as libquvi uses Lua. (libquvi by design always runs when a file is
opened.) I would consider this the problem of distros and whoever
builds mpv, but to make things easier for users, we add a terrible
runtime test to the configure script, which probes whether libquvi
will crash. This is disabled when cross-compiling, but in that case
we hope the user knows what he is doing.
2013-09-26 00:41:14 +02:00
|
|
|
},
|
|
|
|
{"mp.assdraw",
|
2013-12-17 00:53:22 +01:00
|
|
|
# include "player/lua/assdraw.inc"
|
2013-09-26 00:56:41 +02:00
|
|
|
},
|
|
|
|
{"@osc",
|
2013-12-17 00:53:22 +01:00
|
|
|
# include "player/lua/osc.inc"
|
Add initial Lua scripting support
This is preliminary. There are still tons of issues, and any aspect
of scripting may change in the future. I decided to merge this
(preliminary) work now because it makes it easier to develop it, not
because it's done. lua.rst is clear enough about it (plus some
sarcasm).
This requires linking to Lua. Lua has no official pkg-config file, but
there are distribution specific .pc files, all with different names.
Adding a non-pkg-config based configure test was considered, but we'd
rather not.
One major complication is that libquvi links against Lua too, and if
the Lua version is different from mpv's, you will get a crash as soon
as libquvi uses Lua. (libquvi by design always runs when a file is
opened.) I would consider this the problem of distros and whoever
builds mpv, but to make things easier for users, we add a terrible
runtime test to the configure script, which probes whether libquvi
will crash. This is disabled when cross-compiling, but in that case
we hope the user knows what he is doing.
2013-09-26 00:41:14 +02:00
|
|
|
},
|
|
|
|
{0}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Represents a loaded script. Each has its own Lua state.
|
|
|
|
struct script_ctx {
|
|
|
|
const char *name;
|
|
|
|
lua_State *state;
|
lua: allow scripts to snoop messages
Adds the following Lua function to enable message events:
mp.enable_messages(size, level)
size is the maximum number of messages the ringbuffer consists of. level
is the minimum log level for a message to be added to the ringbuffer,
and uses the same values as the mp.log() function. (Actually not yet,
but this will be fixed in the following commit.)
The messages will be delivered via the mp_event() in the user script,
using "message" as event name. The event argument is a table with the
following fields:
level: log level of the message (string as in mp.log())
prefix: string identifying the module of origin
text: contents of the message
As of currently, the message text will contain newline characters. A
message can consist of several lines. It is also possible that a
message doesn't end with a newline, and a caller can use multiple
messages to "build" a line. Most messages will contain exactly 1 line
ending with a single newline character, though.
If the message buffer overflows (messages are not read quickly enough),
new messages are lost until the queued up messages are read. At the
point of the overflow, a special overflow message is inserted. It will
have prefix set to "overflow", and the message text is set to "".
Care should be taken not to print any messages from the message event
handler. This would lead to an infinite loop (the event handler would be
called again after returning, because a new message is available). This
includes mp.log() and all mp.msg.* functions. Keep in mind that the Lua
print() function is mapped to mp.msg.info().
2014-01-16 21:34:58 +01:00
|
|
|
struct mp_log_buffer *messages;
|
Add initial Lua scripting support
This is preliminary. There are still tons of issues, and any aspect
of scripting may change in the future. I decided to merge this
(preliminary) work now because it makes it easier to develop it, not
because it's done. lua.rst is clear enough about it (plus some
sarcasm).
This requires linking to Lua. Lua has no official pkg-config file, but
there are distribution specific .pc files, all with different names.
Adding a non-pkg-config based configure test was considered, but we'd
rather not.
One major complication is that libquvi links against Lua too, and if
the Lua version is different from mpv's, you will get a crash as soon
as libquvi uses Lua. (libquvi by design always runs when a file is
opened.) I would consider this the problem of distros and whoever
builds mpv, but to make things easier for users, we add a terrible
runtime test to the configure script, which probes whether libquvi
will crash. This is disabled when cross-compiling, but in that case
we hope the user knows what he is doing.
2013-09-26 00:41:14 +02:00
|
|
|
struct mp_log *log;
|
|
|
|
struct MPContext *mpctx;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct lua_ctx {
|
|
|
|
struct script_ctx **scripts;
|
|
|
|
int num_scripts;
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct script_ctx *find_script(struct lua_ctx *lctx, const char *name)
|
|
|
|
{
|
|
|
|
for (int n = 0; n < lctx->num_scripts; n++) {
|
|
|
|
if (strcmp(lctx->scripts[n]->name, name) == 0)
|
|
|
|
return lctx->scripts[n];
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct script_ctx *get_ctx(lua_State *L)
|
|
|
|
{
|
|
|
|
lua_getfield(L, LUA_REGISTRYINDEX, "ctx");
|
|
|
|
struct script_ctx *ctx = lua_touserdata(L, -1);
|
|
|
|
lua_pop(L, 1);
|
|
|
|
assert(ctx);
|
|
|
|
return ctx;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct MPContext *get_mpctx(lua_State *L)
|
|
|
|
{
|
|
|
|
return get_ctx(L)->mpctx;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int wrap_cpcall(lua_State *L)
|
|
|
|
{
|
|
|
|
lua_CFunction fn = lua_touserdata(L, -1);
|
|
|
|
lua_pop(L, 1);
|
|
|
|
return fn(L);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Call the given function fn under a Lua error handler (similar to lua_cpcall).
|
|
|
|
// Pass the given number of args from the Lua stack to fn.
|
|
|
|
// Returns 0 (and empty stack) on success.
|
|
|
|
// Returns LUA_ERR[RUN|MEM|ERR] otherwise, with the error value on the stack.
|
|
|
|
static int mp_cpcall(lua_State *L, lua_CFunction fn, int args)
|
|
|
|
{
|
|
|
|
// Don't use lua_pushcfunction() - it allocates memory on Lua 5.1.
|
|
|
|
// Instead, emulate C closures by making wrap_cpcall call fn.
|
|
|
|
lua_pushlightuserdata(L, fn); // args... fn
|
|
|
|
// Will always succeed if mp_lua_init() set it up correctly.
|
|
|
|
lua_getfield(L, LUA_REGISTRYINDEX, "wrap_cpcall"); // args... fn wrap_cpcall
|
|
|
|
lua_insert(L, -(args + 2)); // wrap_cpcall args... fn
|
|
|
|
return lua_pcall(L, args + 1, 0, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void report_error(lua_State *L)
|
|
|
|
{
|
2013-12-19 21:28:55 +01:00
|
|
|
struct MPContext *mpctx = get_mpctx(L);
|
Add initial Lua scripting support
This is preliminary. There are still tons of issues, and any aspect
of scripting may change in the future. I decided to merge this
(preliminary) work now because it makes it easier to develop it, not
because it's done. lua.rst is clear enough about it (plus some
sarcasm).
This requires linking to Lua. Lua has no official pkg-config file, but
there are distribution specific .pc files, all with different names.
Adding a non-pkg-config based configure test was considered, but we'd
rather not.
One major complication is that libquvi links against Lua too, and if
the Lua version is different from mpv's, you will get a crash as soon
as libquvi uses Lua. (libquvi by design always runs when a file is
opened.) I would consider this the problem of distros and whoever
builds mpv, but to make things easier for users, we add a terrible
runtime test to the configure script, which probes whether libquvi
will crash. This is disabled when cross-compiling, but in that case
we hope the user knows what he is doing.
2013-09-26 00:41:14 +02:00
|
|
|
const char *err = lua_tostring(L, -1);
|
2013-12-19 21:28:55 +01:00
|
|
|
MP_WARN(mpctx, "Error: %s\n", err ? err : "[unknown]");
|
Add initial Lua scripting support
This is preliminary. There are still tons of issues, and any aspect
of scripting may change in the future. I decided to merge this
(preliminary) work now because it makes it easier to develop it, not
because it's done. lua.rst is clear enough about it (plus some
sarcasm).
This requires linking to Lua. Lua has no official pkg-config file, but
there are distribution specific .pc files, all with different names.
Adding a non-pkg-config based configure test was considered, but we'd
rather not.
One major complication is that libquvi links against Lua too, and if
the Lua version is different from mpv's, you will get a crash as soon
as libquvi uses Lua. (libquvi by design always runs when a file is
opened.) I would consider this the problem of distros and whoever
builds mpv, but to make things easier for users, we add a terrible
runtime test to the configure script, which probes whether libquvi
will crash. This is disabled when cross-compiling, but in that case
we hope the user knows what he is doing.
2013-09-26 00:41:14 +02:00
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void add_functions(struct script_ctx *ctx);
|
|
|
|
|
|
|
|
static char *script_name_from_filename(void *talloc_ctx, struct lua_ctx *lctx,
|
|
|
|
const char *fname)
|
|
|
|
{
|
|
|
|
fname = mp_basename(fname);
|
|
|
|
if (fname[0] == '@')
|
|
|
|
fname += 1;
|
|
|
|
char *name = talloc_strdup(talloc_ctx, fname);
|
|
|
|
// Drop .lua extension
|
|
|
|
char *dot = strrchr(name, '.');
|
|
|
|
if (dot)
|
|
|
|
*dot = '\0';
|
|
|
|
// Turn it into a safe identifier - this is used with e.g. dispatching
|
|
|
|
// input via: "send scriptname ..."
|
|
|
|
for (int n = 0; name[n]; n++) {
|
|
|
|
char c = name[n];
|
|
|
|
if (!(c >= 'A' && c <= 'Z') && !(c >= 'a' && c <= 'z') &&
|
|
|
|
!(c >= '0' && c <= '9'))
|
|
|
|
name[n] = '_';
|
|
|
|
}
|
|
|
|
// Make unique (stupid but simple)
|
|
|
|
while (find_script(lctx, name))
|
|
|
|
name = talloc_strdup_append(name, "_");
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int load_file(struct script_ctx *ctx, const char *fname)
|
|
|
|
{
|
|
|
|
int r = 0;
|
|
|
|
lua_State *L = ctx->state;
|
|
|
|
if (luaL_loadfile(L, fname) || lua_pcall(L, 0, 0, 0)) {
|
|
|
|
report_error(L);
|
|
|
|
r = -1;
|
|
|
|
}
|
|
|
|
assert(lua_gettop(L) == 0);
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int load_builtin(lua_State *L)
|
|
|
|
{
|
|
|
|
const char *name = luaL_checkstring(L, 1);
|
|
|
|
for (int n = 0; builtin_lua_scripts[n][0]; n++) {
|
|
|
|
if (strcmp(name, builtin_lua_scripts[n][0]) == 0) {
|
|
|
|
if (luaL_loadstring(L, builtin_lua_scripts[n][1]))
|
|
|
|
lua_error(L);
|
|
|
|
lua_call(L, 0, 1);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Execute "require " .. name
|
|
|
|
static bool require(lua_State *L, const char *name)
|
|
|
|
{
|
|
|
|
char buf[80];
|
|
|
|
// Lazy, but better than calling the "require" function manually
|
|
|
|
snprintf(buf, sizeof(buf), "require '%s'", name);
|
|
|
|
if (luaL_loadstring(L, buf) || lua_pcall(L, 0, 0, 0)) {
|
|
|
|
report_error(L);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void mp_lua_load_script(struct MPContext *mpctx, const char *fname)
|
|
|
|
{
|
|
|
|
struct lua_ctx *lctx = mpctx->lua_ctx;
|
|
|
|
struct script_ctx *ctx = talloc_ptrtype(NULL, ctx);
|
|
|
|
*ctx = (struct script_ctx) {
|
|
|
|
.mpctx = mpctx,
|
|
|
|
.name = script_name_from_filename(ctx, lctx, fname),
|
|
|
|
};
|
|
|
|
char *log_name = talloc_asprintf(ctx, "lua/%s", ctx->name);
|
|
|
|
ctx->log = mp_log_new(ctx, mpctx->log, log_name);
|
|
|
|
|
|
|
|
lua_State *L = ctx->state = luaL_newstate();
|
|
|
|
if (!L)
|
|
|
|
goto error_out;
|
|
|
|
|
|
|
|
// used by get_ctx()
|
|
|
|
lua_pushlightuserdata(L, ctx); // ctx
|
|
|
|
lua_setfield(L, LUA_REGISTRYINDEX, "ctx"); // -
|
|
|
|
|
|
|
|
lua_pushcfunction(L, wrap_cpcall); // closure
|
|
|
|
lua_setfield(L, LUA_REGISTRYINDEX, "wrap_cpcall"); // -
|
|
|
|
|
|
|
|
luaL_openlibs(L);
|
|
|
|
|
|
|
|
lua_newtable(L); // mp
|
|
|
|
lua_pushvalue(L, -1); // mp mp
|
|
|
|
lua_setglobal(L, "mp"); // mp
|
|
|
|
|
|
|
|
add_functions(ctx); // mp
|
|
|
|
|
|
|
|
lua_pushstring(L, ctx->name); // mp name
|
|
|
|
lua_setfield(L, -2, "script_name"); // mp
|
|
|
|
|
|
|
|
lua_pop(L, 1); // -
|
|
|
|
|
|
|
|
// Add a preloader for each builtin Lua module
|
|
|
|
lua_getglobal(L, "package"); // package
|
|
|
|
assert(lua_type(L, -1) == LUA_TTABLE);
|
|
|
|
lua_getfield(L, -1, "preload"); // package preload
|
|
|
|
assert(lua_type(L, -1) == LUA_TTABLE);
|
|
|
|
for (int n = 0; builtin_lua_scripts[n][0]; n++) {
|
|
|
|
lua_pushcfunction(L, load_builtin); // package preload load_builtin
|
|
|
|
lua_setfield(L, -2, builtin_lua_scripts[n][0]);
|
|
|
|
}
|
|
|
|
lua_pop(L, 2); // -
|
|
|
|
|
|
|
|
assert(lua_gettop(L) == 0);
|
|
|
|
|
|
|
|
if (!require(L, "mp.defaults")) {
|
|
|
|
report_error(L);
|
|
|
|
goto error_out;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(lua_gettop(L) == 0);
|
|
|
|
|
|
|
|
if (fname[0] == '@') {
|
|
|
|
if (!require(L, fname))
|
|
|
|
goto error_out;
|
|
|
|
} else {
|
|
|
|
if (load_file(ctx, fname) < 0)
|
|
|
|
goto error_out;
|
|
|
|
}
|
|
|
|
|
|
|
|
MP_TARRAY_APPEND(lctx, lctx->scripts, lctx->num_scripts, ctx);
|
|
|
|
return;
|
|
|
|
|
|
|
|
error_out:
|
|
|
|
if (ctx->state)
|
|
|
|
lua_close(ctx->state);
|
|
|
|
talloc_free(ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void kill_script(struct script_ctx *ctx)
|
|
|
|
{
|
|
|
|
if (!ctx)
|
|
|
|
return;
|
|
|
|
struct lua_ctx *lctx = ctx->mpctx->lua_ctx;
|
lua: allow scripts to snoop messages
Adds the following Lua function to enable message events:
mp.enable_messages(size, level)
size is the maximum number of messages the ringbuffer consists of. level
is the minimum log level for a message to be added to the ringbuffer,
and uses the same values as the mp.log() function. (Actually not yet,
but this will be fixed in the following commit.)
The messages will be delivered via the mp_event() in the user script,
using "message" as event name. The event argument is a table with the
following fields:
level: log level of the message (string as in mp.log())
prefix: string identifying the module of origin
text: contents of the message
As of currently, the message text will contain newline characters. A
message can consist of several lines. It is also possible that a
message doesn't end with a newline, and a caller can use multiple
messages to "build" a line. Most messages will contain exactly 1 line
ending with a single newline character, though.
If the message buffer overflows (messages are not read quickly enough),
new messages are lost until the queued up messages are read. At the
point of the overflow, a special overflow message is inserted. It will
have prefix set to "overflow", and the message text is set to "".
Care should be taken not to print any messages from the message event
handler. This would lead to an infinite loop (the event handler would be
called again after returning, because a new message is available). This
includes mp.log() and all mp.msg.* functions. Keep in mind that the Lua
print() function is mapped to mp.msg.info().
2014-01-16 21:34:58 +01:00
|
|
|
if (ctx->messages)
|
|
|
|
mp_msg_log_buffer_destroy(ctx->messages);
|
Add initial Lua scripting support
This is preliminary. There are still tons of issues, and any aspect
of scripting may change in the future. I decided to merge this
(preliminary) work now because it makes it easier to develop it, not
because it's done. lua.rst is clear enough about it (plus some
sarcasm).
This requires linking to Lua. Lua has no official pkg-config file, but
there are distribution specific .pc files, all with different names.
Adding a non-pkg-config based configure test was considered, but we'd
rather not.
One major complication is that libquvi links against Lua too, and if
the Lua version is different from mpv's, you will get a crash as soon
as libquvi uses Lua. (libquvi by design always runs when a file is
opened.) I would consider this the problem of distros and whoever
builds mpv, but to make things easier for users, we add a terrible
runtime test to the configure script, which probes whether libquvi
will crash. This is disabled when cross-compiling, but in that case
we hope the user knows what he is doing.
2013-09-26 00:41:14 +02:00
|
|
|
lua_close(ctx->state);
|
|
|
|
for (int n = 0; n < lctx->num_scripts; n++) {
|
|
|
|
if (lctx->scripts[n] == ctx) {
|
|
|
|
MP_TARRAY_REMOVE_AT(lctx->scripts, lctx->num_scripts, n);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
talloc_free(ctx);
|
|
|
|
}
|
|
|
|
|
lua: allow scripts to snoop messages
Adds the following Lua function to enable message events:
mp.enable_messages(size, level)
size is the maximum number of messages the ringbuffer consists of. level
is the minimum log level for a message to be added to the ringbuffer,
and uses the same values as the mp.log() function. (Actually not yet,
but this will be fixed in the following commit.)
The messages will be delivered via the mp_event() in the user script,
using "message" as event name. The event argument is a table with the
following fields:
level: log level of the message (string as in mp.log())
prefix: string identifying the module of origin
text: contents of the message
As of currently, the message text will contain newline characters. A
message can consist of several lines. It is also possible that a
message doesn't end with a newline, and a caller can use multiple
messages to "build" a line. Most messages will contain exactly 1 line
ending with a single newline character, though.
If the message buffer overflows (messages are not read quickly enough),
new messages are lost until the queued up messages are read. At the
point of the overflow, a special overflow message is inserted. It will
have prefix set to "overflow", and the message text is set to "".
Care should be taken not to print any messages from the message event
handler. This would lead to an infinite loop (the event handler would be
called again after returning, because a new message is available). This
includes mp.log() and all mp.msg.* functions. Keep in mind that the Lua
print() function is mapped to mp.msg.info().
2014-01-16 21:34:58 +01:00
|
|
|
static int check_loglevel(lua_State *L, int arg)
|
|
|
|
{
|
|
|
|
const char *level = luaL_checkstring(L, arg);
|
2014-01-16 21:37:29 +01:00
|
|
|
for (int n = 0; n < MSGL_MAX; n++) {
|
|
|
|
if (mp_log_levels[n] && strcasecmp(mp_log_levels[n], level) == 0)
|
lua: allow scripts to snoop messages
Adds the following Lua function to enable message events:
mp.enable_messages(size, level)
size is the maximum number of messages the ringbuffer consists of. level
is the minimum log level for a message to be added to the ringbuffer,
and uses the same values as the mp.log() function. (Actually not yet,
but this will be fixed in the following commit.)
The messages will be delivered via the mp_event() in the user script,
using "message" as event name. The event argument is a table with the
following fields:
level: log level of the message (string as in mp.log())
prefix: string identifying the module of origin
text: contents of the message
As of currently, the message text will contain newline characters. A
message can consist of several lines. It is also possible that a
message doesn't end with a newline, and a caller can use multiple
messages to "build" a line. Most messages will contain exactly 1 line
ending with a single newline character, though.
If the message buffer overflows (messages are not read quickly enough),
new messages are lost until the queued up messages are read. At the
point of the overflow, a special overflow message is inserted. It will
have prefix set to "overflow", and the message text is set to "".
Care should be taken not to print any messages from the message event
handler. This would lead to an infinite loop (the event handler would be
called again after returning, because a new message is available). This
includes mp.log() and all mp.msg.* functions. Keep in mind that the Lua
print() function is mapped to mp.msg.info().
2014-01-16 21:34:58 +01:00
|
|
|
return n;
|
|
|
|
}
|
|
|
|
luaL_error(L, "Invalid log level '%s'", level);
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
Add initial Lua scripting support
This is preliminary. There are still tons of issues, and any aspect
of scripting may change in the future. I decided to merge this
(preliminary) work now because it makes it easier to develop it, not
because it's done. lua.rst is clear enough about it (plus some
sarcasm).
This requires linking to Lua. Lua has no official pkg-config file, but
there are distribution specific .pc files, all with different names.
Adding a non-pkg-config based configure test was considered, but we'd
rather not.
One major complication is that libquvi links against Lua too, and if
the Lua version is different from mpv's, you will get a crash as soon
as libquvi uses Lua. (libquvi by design always runs when a file is
opened.) I would consider this the problem of distros and whoever
builds mpv, but to make things easier for users, we add a terrible
runtime test to the configure script, which probes whether libquvi
will crash. This is disabled when cross-compiling, but in that case
we hope the user knows what he is doing.
2013-09-26 00:41:14 +02:00
|
|
|
static int script_log(lua_State *L)
|
|
|
|
{
|
|
|
|
struct script_ctx *ctx = get_ctx(L);
|
|
|
|
|
lua: allow scripts to snoop messages
Adds the following Lua function to enable message events:
mp.enable_messages(size, level)
size is the maximum number of messages the ringbuffer consists of. level
is the minimum log level for a message to be added to the ringbuffer,
and uses the same values as the mp.log() function. (Actually not yet,
but this will be fixed in the following commit.)
The messages will be delivered via the mp_event() in the user script,
using "message" as event name. The event argument is a table with the
following fields:
level: log level of the message (string as in mp.log())
prefix: string identifying the module of origin
text: contents of the message
As of currently, the message text will contain newline characters. A
message can consist of several lines. It is also possible that a
message doesn't end with a newline, and a caller can use multiple
messages to "build" a line. Most messages will contain exactly 1 line
ending with a single newline character, though.
If the message buffer overflows (messages are not read quickly enough),
new messages are lost until the queued up messages are read. At the
point of the overflow, a special overflow message is inserted. It will
have prefix set to "overflow", and the message text is set to "".
Care should be taken not to print any messages from the message event
handler. This would lead to an infinite loop (the event handler would be
called again after returning, because a new message is available). This
includes mp.log() and all mp.msg.* functions. Keep in mind that the Lua
print() function is mapped to mp.msg.info().
2014-01-16 21:34:58 +01:00
|
|
|
int msgl = check_loglevel(L, 1);
|
Add initial Lua scripting support
This is preliminary. There are still tons of issues, and any aspect
of scripting may change in the future. I decided to merge this
(preliminary) work now because it makes it easier to develop it, not
because it's done. lua.rst is clear enough about it (plus some
sarcasm).
This requires linking to Lua. Lua has no official pkg-config file, but
there are distribution specific .pc files, all with different names.
Adding a non-pkg-config based configure test was considered, but we'd
rather not.
One major complication is that libquvi links against Lua too, and if
the Lua version is different from mpv's, you will get a crash as soon
as libquvi uses Lua. (libquvi by design always runs when a file is
opened.) I would consider this the problem of distros and whoever
builds mpv, but to make things easier for users, we add a terrible
runtime test to the configure script, which probes whether libquvi
will crash. This is disabled when cross-compiling, but in that case
we hope the user knows what he is doing.
2013-09-26 00:41:14 +02:00
|
|
|
|
|
|
|
int last = lua_gettop(L);
|
|
|
|
lua_getglobal(L, "tostring"); // args... tostring
|
|
|
|
for (int i = 2; i <= last; i++) {
|
|
|
|
lua_pushvalue(L, -1); // args... tostring tostring
|
|
|
|
lua_pushvalue(L, i); // args... tostring tostring args[i]
|
|
|
|
lua_call(L, 1, 1); // args... tostring str
|
|
|
|
const char *s = lua_tostring(L, -1);
|
|
|
|
if (s == NULL)
|
|
|
|
return luaL_error(L, "Invalid argument");
|
2013-12-21 21:49:13 +01:00
|
|
|
mp_msg(ctx->log, msgl, "%s%s", s, i > 0 ? " " : "");
|
Add initial Lua scripting support
This is preliminary. There are still tons of issues, and any aspect
of scripting may change in the future. I decided to merge this
(preliminary) work now because it makes it easier to develop it, not
because it's done. lua.rst is clear enough about it (plus some
sarcasm).
This requires linking to Lua. Lua has no official pkg-config file, but
there are distribution specific .pc files, all with different names.
Adding a non-pkg-config based configure test was considered, but we'd
rather not.
One major complication is that libquvi links against Lua too, and if
the Lua version is different from mpv's, you will get a crash as soon
as libquvi uses Lua. (libquvi by design always runs when a file is
opened.) I would consider this the problem of distros and whoever
builds mpv, but to make things easier for users, we add a terrible
runtime test to the configure script, which probes whether libquvi
will crash. This is disabled when cross-compiling, but in that case
we hope the user knows what he is doing.
2013-09-26 00:41:14 +02:00
|
|
|
lua_pop(L, 1); // args... tostring
|
|
|
|
}
|
2013-12-21 21:49:13 +01:00
|
|
|
mp_msg(ctx->log, msgl, "\n");
|
Add initial Lua scripting support
This is preliminary. There are still tons of issues, and any aspect
of scripting may change in the future. I decided to merge this
(preliminary) work now because it makes it easier to develop it, not
because it's done. lua.rst is clear enough about it (plus some
sarcasm).
This requires linking to Lua. Lua has no official pkg-config file, but
there are distribution specific .pc files, all with different names.
Adding a non-pkg-config based configure test was considered, but we'd
rather not.
One major complication is that libquvi links against Lua too, and if
the Lua version is different from mpv's, you will get a crash as soon
as libquvi uses Lua. (libquvi by design always runs when a file is
opened.) I would consider this the problem of distros and whoever
builds mpv, but to make things easier for users, we add a terrible
runtime test to the configure script, which probes whether libquvi
will crash. This is disabled when cross-compiling, but in that case
we hope the user knows what he is doing.
2013-09-26 00:41:14 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int script_find_config_file(lua_State *L)
|
|
|
|
{
|
2013-12-21 20:45:19 +01:00
|
|
|
struct MPContext *mpctx = get_mpctx(L);
|
Add initial Lua scripting support
This is preliminary. There are still tons of issues, and any aspect
of scripting may change in the future. I decided to merge this
(preliminary) work now because it makes it easier to develop it, not
because it's done. lua.rst is clear enough about it (plus some
sarcasm).
This requires linking to Lua. Lua has no official pkg-config file, but
there are distribution specific .pc files, all with different names.
Adding a non-pkg-config based configure test was considered, but we'd
rather not.
One major complication is that libquvi links against Lua too, and if
the Lua version is different from mpv's, you will get a crash as soon
as libquvi uses Lua. (libquvi by design always runs when a file is
opened.) I would consider this the problem of distros and whoever
builds mpv, but to make things easier for users, we add a terrible
runtime test to the configure script, which probes whether libquvi
will crash. This is disabled when cross-compiling, but in that case
we hope the user knows what he is doing.
2013-09-26 00:41:14 +02:00
|
|
|
const char *s = luaL_checkstring(L, 1);
|
2013-12-21 20:45:19 +01:00
|
|
|
char *path = mp_find_user_config_file(NULL, mpctx->global, s);
|
Add initial Lua scripting support
This is preliminary. There are still tons of issues, and any aspect
of scripting may change in the future. I decided to merge this
(preliminary) work now because it makes it easier to develop it, not
because it's done. lua.rst is clear enough about it (plus some
sarcasm).
This requires linking to Lua. Lua has no official pkg-config file, but
there are distribution specific .pc files, all with different names.
Adding a non-pkg-config based configure test was considered, but we'd
rather not.
One major complication is that libquvi links against Lua too, and if
the Lua version is different from mpv's, you will get a crash as soon
as libquvi uses Lua. (libquvi by design always runs when a file is
opened.) I would consider this the problem of distros and whoever
builds mpv, but to make things easier for users, we add a terrible
runtime test to the configure script, which probes whether libquvi
will crash. This is disabled when cross-compiling, but in that case
we hope the user knows what he is doing.
2013-09-26 00:41:14 +02:00
|
|
|
if (path) {
|
|
|
|
lua_pushstring(L, path);
|
|
|
|
} else {
|
|
|
|
lua_pushnil(L);
|
|
|
|
}
|
|
|
|
talloc_free(path);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int run_event(lua_State *L)
|
|
|
|
{
|
|
|
|
lua_getglobal(L, "mp_event"); // name arg mp_event
|
|
|
|
if (lua_isnil(L, -1))
|
|
|
|
return 0;
|
|
|
|
lua_insert(L, -3); // mp_event name arg
|
|
|
|
lua_call(L, 2, 0);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
lua: allow scripts to snoop messages
Adds the following Lua function to enable message events:
mp.enable_messages(size, level)
size is the maximum number of messages the ringbuffer consists of. level
is the minimum log level for a message to be added to the ringbuffer,
and uses the same values as the mp.log() function. (Actually not yet,
but this will be fixed in the following commit.)
The messages will be delivered via the mp_event() in the user script,
using "message" as event name. The event argument is a table with the
following fields:
level: log level of the message (string as in mp.log())
prefix: string identifying the module of origin
text: contents of the message
As of currently, the message text will contain newline characters. A
message can consist of several lines. It is also possible that a
message doesn't end with a newline, and a caller can use multiple
messages to "build" a line. Most messages will contain exactly 1 line
ending with a single newline character, though.
If the message buffer overflows (messages are not read quickly enough),
new messages are lost until the queued up messages are read. At the
point of the overflow, a special overflow message is inserted. It will
have prefix set to "overflow", and the message text is set to "".
Care should be taken not to print any messages from the message event
handler. This would lead to an infinite loop (the event handler would be
called again after returning, because a new message is available). This
includes mp.log() and all mp.msg.* functions. Keep in mind that the Lua
print() function is mapped to mp.msg.info().
2014-01-16 21:34:58 +01:00
|
|
|
static void poll_messages(struct script_ctx *ctx)
|
|
|
|
{
|
|
|
|
lua_State *L = ctx->state;
|
|
|
|
|
|
|
|
if (!ctx->messages)
|
|
|
|
return;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
struct mp_log_buffer_entry *msg = mp_msg_log_buffer_read(ctx->messages);
|
|
|
|
if (!msg)
|
|
|
|
break;
|
|
|
|
|
|
|
|
lua_pushstring(L, "message"); // msg
|
|
|
|
lua_newtable(L); // msg t
|
|
|
|
lua_pushstring(L, msg->prefix); // msg t s
|
|
|
|
lua_setfield(L, -2, "prefix"); // msg t
|
|
|
|
lua_pushstring(L, mp_log_levels[msg->level]); // msg t s
|
|
|
|
lua_setfield(L, -2, "level"); // msg t
|
|
|
|
lua_pushstring(L, msg->text); // msg t s
|
|
|
|
lua_setfield(L, -2, "text"); // msg t
|
|
|
|
|
|
|
|
if (mp_cpcall(L, run_event, 2) != 0)
|
|
|
|
report_error(L);
|
|
|
|
|
|
|
|
talloc_free(msg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Add initial Lua scripting support
This is preliminary. There are still tons of issues, and any aspect
of scripting may change in the future. I decided to merge this
(preliminary) work now because it makes it easier to develop it, not
because it's done. lua.rst is clear enough about it (plus some
sarcasm).
This requires linking to Lua. Lua has no official pkg-config file, but
there are distribution specific .pc files, all with different names.
Adding a non-pkg-config based configure test was considered, but we'd
rather not.
One major complication is that libquvi links against Lua too, and if
the Lua version is different from mpv's, you will get a crash as soon
as libquvi uses Lua. (libquvi by design always runs when a file is
opened.) I would consider this the problem of distros and whoever
builds mpv, but to make things easier for users, we add a terrible
runtime test to the configure script, which probes whether libquvi
will crash. This is disabled when cross-compiling, but in that case
we hope the user knows what he is doing.
2013-09-26 00:41:14 +02:00
|
|
|
void mp_lua_event(struct MPContext *mpctx, const char *name, const char *arg)
|
|
|
|
{
|
|
|
|
// There is no proper subscription mechanism yet, so all scripts get it.
|
|
|
|
struct lua_ctx *lctx = mpctx->lua_ctx;
|
|
|
|
for (int n = 0; n < lctx->num_scripts; n++) {
|
|
|
|
struct script_ctx *ctx = lctx->scripts[n];
|
|
|
|
lua_State *L = ctx->state;
|
|
|
|
lua_pushstring(L, name);
|
|
|
|
if (arg) {
|
|
|
|
lua_pushstring(L, arg);
|
|
|
|
} else {
|
|
|
|
lua_pushnil(L);
|
|
|
|
}
|
|
|
|
if (mp_cpcall(L, run_event, 2) != 0)
|
|
|
|
report_error(L);
|
lua: allow scripts to snoop messages
Adds the following Lua function to enable message events:
mp.enable_messages(size, level)
size is the maximum number of messages the ringbuffer consists of. level
is the minimum log level for a message to be added to the ringbuffer,
and uses the same values as the mp.log() function. (Actually not yet,
but this will be fixed in the following commit.)
The messages will be delivered via the mp_event() in the user script,
using "message" as event name. The event argument is a table with the
following fields:
level: log level of the message (string as in mp.log())
prefix: string identifying the module of origin
text: contents of the message
As of currently, the message text will contain newline characters. A
message can consist of several lines. It is also possible that a
message doesn't end with a newline, and a caller can use multiple
messages to "build" a line. Most messages will contain exactly 1 line
ending with a single newline character, though.
If the message buffer overflows (messages are not read quickly enough),
new messages are lost until the queued up messages are read. At the
point of the overflow, a special overflow message is inserted. It will
have prefix set to "overflow", and the message text is set to "".
Care should be taken not to print any messages from the message event
handler. This would lead to an infinite loop (the event handler would be
called again after returning, because a new message is available). This
includes mp.log() and all mp.msg.* functions. Keep in mind that the Lua
print() function is mapped to mp.msg.info().
2014-01-16 21:34:58 +01:00
|
|
|
poll_messages(ctx);
|
Add initial Lua scripting support
This is preliminary. There are still tons of issues, and any aspect
of scripting may change in the future. I decided to merge this
(preliminary) work now because it makes it easier to develop it, not
because it's done. lua.rst is clear enough about it (plus some
sarcasm).
This requires linking to Lua. Lua has no official pkg-config file, but
there are distribution specific .pc files, all with different names.
Adding a non-pkg-config based configure test was considered, but we'd
rather not.
One major complication is that libquvi links against Lua too, and if
the Lua version is different from mpv's, you will get a crash as soon
as libquvi uses Lua. (libquvi by design always runs when a file is
opened.) I would consider this the problem of distros and whoever
builds mpv, but to make things easier for users, we add a terrible
runtime test to the configure script, which probes whether libquvi
will crash. This is disabled when cross-compiling, but in that case
we hope the user knows what he is doing.
2013-09-26 00:41:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
lua: allow scripts to snoop messages
Adds the following Lua function to enable message events:
mp.enable_messages(size, level)
size is the maximum number of messages the ringbuffer consists of. level
is the minimum log level for a message to be added to the ringbuffer,
and uses the same values as the mp.log() function. (Actually not yet,
but this will be fixed in the following commit.)
The messages will be delivered via the mp_event() in the user script,
using "message" as event name. The event argument is a table with the
following fields:
level: log level of the message (string as in mp.log())
prefix: string identifying the module of origin
text: contents of the message
As of currently, the message text will contain newline characters. A
message can consist of several lines. It is also possible that a
message doesn't end with a newline, and a caller can use multiple
messages to "build" a line. Most messages will contain exactly 1 line
ending with a single newline character, though.
If the message buffer overflows (messages are not read quickly enough),
new messages are lost until the queued up messages are read. At the
point of the overflow, a special overflow message is inserted. It will
have prefix set to "overflow", and the message text is set to "".
Care should be taken not to print any messages from the message event
handler. This would lead to an infinite loop (the event handler would be
called again after returning, because a new message is available). This
includes mp.log() and all mp.msg.* functions. Keep in mind that the Lua
print() function is mapped to mp.msg.info().
2014-01-16 21:34:58 +01:00
|
|
|
static int script_enable_messages(lua_State *L)
|
|
|
|
{
|
|
|
|
struct script_ctx *ctx = get_ctx(L);
|
|
|
|
if (ctx->messages)
|
|
|
|
luaL_error(L, "messages already enabled");
|
|
|
|
|
|
|
|
int size = luaL_checkinteger(L, 1);
|
|
|
|
int level = check_loglevel(L, 2);
|
|
|
|
if (size < 2 || size > 100000)
|
|
|
|
luaL_error(L, "size argument out of range");
|
|
|
|
ctx->messages = mp_msg_log_buffer_new(ctx->mpctx->global, size, level);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Add initial Lua scripting support
This is preliminary. There are still tons of issues, and any aspect
of scripting may change in the future. I decided to merge this
(preliminary) work now because it makes it easier to develop it, not
because it's done. lua.rst is clear enough about it (plus some
sarcasm).
This requires linking to Lua. Lua has no official pkg-config file, but
there are distribution specific .pc files, all with different names.
Adding a non-pkg-config based configure test was considered, but we'd
rather not.
One major complication is that libquvi links against Lua too, and if
the Lua version is different from mpv's, you will get a crash as soon
as libquvi uses Lua. (libquvi by design always runs when a file is
opened.) I would consider this the problem of distros and whoever
builds mpv, but to make things easier for users, we add a terrible
runtime test to the configure script, which probes whether libquvi
will crash. This is disabled when cross-compiling, but in that case
we hope the user knows what he is doing.
2013-09-26 00:41:14 +02:00
|
|
|
static int run_script_dispatch(lua_State *L)
|
|
|
|
{
|
|
|
|
int id = lua_tointeger(L, 1);
|
|
|
|
const char *event = lua_tostring(L, 2);
|
|
|
|
lua_getglobal(L, "mp_script_dispatch");
|
|
|
|
if (lua_isnil(L, -1))
|
|
|
|
return 0;
|
|
|
|
lua_pushinteger(L, id);
|
|
|
|
lua_pushstring(L, event);
|
|
|
|
lua_call(L, 2, 0);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void mp_lua_script_dispatch(struct MPContext *mpctx, char *script_name,
|
|
|
|
int id, char *event)
|
|
|
|
{
|
|
|
|
struct script_ctx *ctx = find_script(mpctx->lua_ctx, script_name);
|
|
|
|
if (!ctx) {
|
2013-12-19 21:28:55 +01:00
|
|
|
MP_VERBOSE(mpctx, "Can't find script '%s' when handling input.\n",
|
|
|
|
script_name);
|
Add initial Lua scripting support
This is preliminary. There are still tons of issues, and any aspect
of scripting may change in the future. I decided to merge this
(preliminary) work now because it makes it easier to develop it, not
because it's done. lua.rst is clear enough about it (plus some
sarcasm).
This requires linking to Lua. Lua has no official pkg-config file, but
there are distribution specific .pc files, all with different names.
Adding a non-pkg-config based configure test was considered, but we'd
rather not.
One major complication is that libquvi links against Lua too, and if
the Lua version is different from mpv's, you will get a crash as soon
as libquvi uses Lua. (libquvi by design always runs when a file is
opened.) I would consider this the problem of distros and whoever
builds mpv, but to make things easier for users, we add a terrible
runtime test to the configure script, which probes whether libquvi
will crash. This is disabled when cross-compiling, but in that case
we hope the user knows what he is doing.
2013-09-26 00:41:14 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
lua_State *L = ctx->state;
|
|
|
|
lua_pushinteger(L, id);
|
|
|
|
lua_pushstring(L, event);
|
|
|
|
if (mp_cpcall(L, run_script_dispatch, 2) != 0)
|
|
|
|
report_error(L);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int script_send_command(lua_State *L)
|
|
|
|
{
|
|
|
|
struct MPContext *mpctx = get_mpctx(L);
|
|
|
|
const char *s = luaL_checkstring(L, 1);
|
|
|
|
|
2013-09-27 15:30:59 +02:00
|
|
|
mp_cmd_t *cmd = mp_input_parse_cmd(mpctx->input, bstr0((char*)s), "<lua>");
|
Add initial Lua scripting support
This is preliminary. There are still tons of issues, and any aspect
of scripting may change in the future. I decided to merge this
(preliminary) work now because it makes it easier to develop it, not
because it's done. lua.rst is clear enough about it (plus some
sarcasm).
This requires linking to Lua. Lua has no official pkg-config file, but
there are distribution specific .pc files, all with different names.
Adding a non-pkg-config based configure test was considered, but we'd
rather not.
One major complication is that libquvi links against Lua too, and if
the Lua version is different from mpv's, you will get a crash as soon
as libquvi uses Lua. (libquvi by design always runs when a file is
opened.) I would consider this the problem of distros and whoever
builds mpv, but to make things easier for users, we add a terrible
runtime test to the configure script, which probes whether libquvi
will crash. This is disabled when cross-compiling, but in that case
we hope the user knows what he is doing.
2013-09-26 00:41:14 +02:00
|
|
|
if (!cmd)
|
|
|
|
luaL_error(L, "error parsing command");
|
|
|
|
mp_input_queue_cmd(mpctx->input, cmd);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-12-20 18:01:04 +01:00
|
|
|
static int script_send_commandv(lua_State *L)
|
|
|
|
{
|
|
|
|
struct script_ctx *ctx = get_ctx(L);
|
|
|
|
int num = lua_gettop(L);
|
|
|
|
bstr args[50];
|
|
|
|
if (num > MP_ARRAY_SIZE(args))
|
|
|
|
luaL_error(L, "too many arguments");
|
|
|
|
for (int n = 1; n <= num; n++) {
|
|
|
|
size_t len;
|
|
|
|
const char *s = lua_tolstring(L, n, &len);
|
|
|
|
if (!s)
|
|
|
|
luaL_error(L, "argument %d is not a string", n);
|
|
|
|
args[n - 1] = (bstr){(char *)s, len};
|
|
|
|
}
|
|
|
|
mp_cmd_t *cmd = mp_input_parse_cmd_bstrv(ctx->log, 0, num, args, "<lua>");
|
|
|
|
if (!cmd)
|
|
|
|
luaL_error(L, "error parsing command");
|
|
|
|
mp_input_queue_cmd(ctx->mpctx->input, cmd);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Add initial Lua scripting support
This is preliminary. There are still tons of issues, and any aspect
of scripting may change in the future. I decided to merge this
(preliminary) work now because it makes it easier to develop it, not
because it's done. lua.rst is clear enough about it (plus some
sarcasm).
This requires linking to Lua. Lua has no official pkg-config file, but
there are distribution specific .pc files, all with different names.
Adding a non-pkg-config based configure test was considered, but we'd
rather not.
One major complication is that libquvi links against Lua too, and if
the Lua version is different from mpv's, you will get a crash as soon
as libquvi uses Lua. (libquvi by design always runs when a file is
opened.) I would consider this the problem of distros and whoever
builds mpv, but to make things easier for users, we add a terrible
runtime test to the configure script, which probes whether libquvi
will crash. This is disabled when cross-compiling, but in that case
we hope the user knows what he is doing.
2013-09-26 00:41:14 +02:00
|
|
|
static int script_property_list(lua_State *L)
|
|
|
|
{
|
|
|
|
const struct m_option *props = mp_get_property_list();
|
|
|
|
lua_newtable(L);
|
|
|
|
for (int i = 0; props[i].name; i++) {
|
|
|
|
lua_pushinteger(L, i + 1);
|
|
|
|
lua_pushstring(L, props[i].name);
|
|
|
|
lua_settable(L, -3);
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int script_property_string(lua_State *L)
|
|
|
|
{
|
|
|
|
struct MPContext *mpctx = get_mpctx(L);
|
|
|
|
const char *name = luaL_checkstring(L, 1);
|
|
|
|
int type = lua_tointeger(L, lua_upvalueindex(1))
|
|
|
|
? M_PROPERTY_PRINT : M_PROPERTY_GET_STRING;
|
|
|
|
|
|
|
|
char *result = NULL;
|
2013-12-21 18:18:31 +01:00
|
|
|
if (mp_property_do(name, type, &result, mpctx) >= 0 && result) {
|
Add initial Lua scripting support
This is preliminary. There are still tons of issues, and any aspect
of scripting may change in the future. I decided to merge this
(preliminary) work now because it makes it easier to develop it, not
because it's done. lua.rst is clear enough about it (plus some
sarcasm).
This requires linking to Lua. Lua has no official pkg-config file, but
there are distribution specific .pc files, all with different names.
Adding a non-pkg-config based configure test was considered, but we'd
rather not.
One major complication is that libquvi links against Lua too, and if
the Lua version is different from mpv's, you will get a crash as soon
as libquvi uses Lua. (libquvi by design always runs when a file is
opened.) I would consider this the problem of distros and whoever
builds mpv, but to make things easier for users, we add a terrible
runtime test to the configure script, which probes whether libquvi
will crash. This is disabled when cross-compiling, but in that case
we hope the user knows what he is doing.
2013-09-26 00:41:14 +02:00
|
|
|
lua_pushstring(L, result);
|
|
|
|
talloc_free(result);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (type == M_PROPERTY_PRINT) {
|
|
|
|
lua_pushstring(L, "");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int script_set_osd_ass(lua_State *L)
|
|
|
|
{
|
|
|
|
struct MPContext *mpctx = get_mpctx(L);
|
|
|
|
int res_x = luaL_checkinteger(L, 1);
|
|
|
|
int res_y = luaL_checkinteger(L, 2);
|
|
|
|
const char *text = luaL_checkstring(L, 3);
|
|
|
|
if (!mpctx->osd->external ||
|
|
|
|
strcmp(mpctx->osd->external, text) != 0 ||
|
|
|
|
mpctx->osd->external_res_x != res_x ||
|
|
|
|
mpctx->osd->external_res_y != res_y)
|
|
|
|
{
|
|
|
|
talloc_free(mpctx->osd->external);
|
|
|
|
mpctx->osd->external = talloc_strdup(mpctx->osd, text);
|
|
|
|
mpctx->osd->external_res_x = res_x;
|
|
|
|
mpctx->osd->external_res_y = res_y;
|
|
|
|
osd_changed(mpctx->osd, OSDTYPE_EXTERNAL);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int script_get_osd_resolution(lua_State *L)
|
|
|
|
{
|
|
|
|
struct MPContext *mpctx = get_mpctx(L);
|
|
|
|
int w, h;
|
|
|
|
osd_object_get_resolution(mpctx->osd, mpctx->osd->objs[OSDTYPE_EXTERNAL],
|
|
|
|
&w, &h);
|
|
|
|
lua_pushnumber(L, w);
|
|
|
|
lua_pushnumber(L, h);
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int script_get_screen_size(lua_State *L)
|
|
|
|
{
|
|
|
|
struct MPContext *mpctx = get_mpctx(L);
|
|
|
|
struct osd_object *obj = mpctx->osd->objs[OSDTYPE_EXTERNAL];
|
|
|
|
double aspect = 1.0 * obj->vo_res.w / MPMAX(obj->vo_res.h, 1) /
|
|
|
|
obj->vo_res.display_par;
|
|
|
|
lua_pushnumber(L, obj->vo_res.w);
|
|
|
|
lua_pushnumber(L, obj->vo_res.h);
|
|
|
|
lua_pushnumber(L, aspect);
|
|
|
|
return 3;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int script_get_mouse_pos(lua_State *L)
|
|
|
|
{
|
|
|
|
struct MPContext *mpctx = get_mpctx(L);
|
2013-09-27 15:39:28 +02:00
|
|
|
int px, py;
|
|
|
|
mp_input_get_mouse_pos(mpctx->input, &px, &py);
|
Add initial Lua scripting support
This is preliminary. There are still tons of issues, and any aspect
of scripting may change in the future. I decided to merge this
(preliminary) work now because it makes it easier to develop it, not
because it's done. lua.rst is clear enough about it (plus some
sarcasm).
This requires linking to Lua. Lua has no official pkg-config file, but
there are distribution specific .pc files, all with different names.
Adding a non-pkg-config based configure test was considered, but we'd
rather not.
One major complication is that libquvi links against Lua too, and if
the Lua version is different from mpv's, you will get a crash as soon
as libquvi uses Lua. (libquvi by design always runs when a file is
opened.) I would consider this the problem of distros and whoever
builds mpv, but to make things easier for users, we add a terrible
runtime test to the configure script, which probes whether libquvi
will crash. This is disabled when cross-compiling, but in that case
we hope the user knows what he is doing.
2013-09-26 00:41:14 +02:00
|
|
|
double sw, sh;
|
|
|
|
osd_object_get_scale_factor(mpctx->osd, mpctx->osd->objs[OSDTYPE_EXTERNAL],
|
|
|
|
&sw, &sh);
|
|
|
|
lua_pushnumber(L, px * sw);
|
|
|
|
lua_pushnumber(L, py * sh);
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int script_get_timer(lua_State *L)
|
|
|
|
{
|
|
|
|
lua_pushnumber(L, mp_time_sec());
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int script_get_chapter_list(lua_State *L)
|
|
|
|
{
|
|
|
|
struct MPContext *mpctx = get_mpctx(L);
|
|
|
|
lua_newtable(L); // list
|
|
|
|
int num = get_chapter_count(mpctx);
|
|
|
|
for (int n = 0; n < num; n++) {
|
|
|
|
double time = chapter_start_time(mpctx, n);
|
|
|
|
char *name = chapter_display_name(mpctx, n);
|
|
|
|
lua_newtable(L); // list ch
|
|
|
|
lua_pushnumber(L, time); // list ch time
|
|
|
|
lua_setfield(L, -2, "time"); // list ch
|
|
|
|
lua_pushstring(L, name); // list ch name
|
|
|
|
lua_setfield(L, -2, "name"); // list ch
|
|
|
|
lua_pushinteger(L, n + 1); // list ch n1
|
|
|
|
lua_insert(L, -2); // list n1 ch
|
|
|
|
lua_settable(L, -3); // list
|
|
|
|
talloc_free(name);
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *stream_type(enum stream_type t)
|
|
|
|
{
|
|
|
|
switch (t) {
|
|
|
|
case STREAM_VIDEO: return "video";
|
|
|
|
case STREAM_AUDIO: return "audio";
|
|
|
|
case STREAM_SUB: return "sub";
|
|
|
|
default: return "unknown";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int script_get_track_list(lua_State *L)
|
|
|
|
{
|
|
|
|
struct MPContext *mpctx = get_mpctx(L);
|
|
|
|
lua_newtable(L); // list
|
|
|
|
for (int n = 0; n < mpctx->num_tracks; n++) {
|
|
|
|
struct track *track = mpctx->tracks[n];
|
|
|
|
lua_newtable(L); // list track
|
|
|
|
|
|
|
|
lua_pushstring(L, stream_type(track->type));
|
|
|
|
lua_setfield(L, -2, "type");
|
|
|
|
lua_pushinteger(L, track->user_tid);
|
|
|
|
lua_setfield(L, -2, "id");
|
|
|
|
lua_pushboolean(L, track->default_track);
|
|
|
|
lua_setfield(L, -2, "default");
|
|
|
|
lua_pushboolean(L, track->attached_picture);
|
|
|
|
lua_setfield(L, -2, "attached_picture");
|
|
|
|
if (track->lang) {
|
|
|
|
lua_pushstring(L, track->lang);
|
|
|
|
lua_setfield(L, -2, "language");
|
|
|
|
}
|
|
|
|
if (track->title) {
|
|
|
|
lua_pushstring(L, track->title);
|
|
|
|
lua_setfield(L, -2, "title");
|
|
|
|
}
|
|
|
|
lua_pushboolean(L, track->is_external);
|
|
|
|
lua_setfield(L, -2, "external");
|
|
|
|
if (track->external_filename) {
|
|
|
|
lua_pushstring(L, track->external_filename);
|
|
|
|
lua_setfield(L, -2, "external_filename");
|
|
|
|
}
|
|
|
|
lua_pushboolean(L, track->auto_loaded);
|
|
|
|
lua_setfield(L, -2, "auto_loaded");
|
|
|
|
|
|
|
|
lua_pushinteger(L, n + 1); // list track n1
|
|
|
|
lua_insert(L, -2); // list n1 track
|
|
|
|
lua_settable(L, -3); // list
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int script_input_define_section(lua_State *L)
|
|
|
|
{
|
|
|
|
struct MPContext *mpctx = get_mpctx(L);
|
|
|
|
char *section = (char *)luaL_checkstring(L, 1);
|
|
|
|
char *contents = (char *)luaL_checkstring(L, 2);
|
|
|
|
mp_input_define_section(mpctx->input, section, "<script>", contents, true);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int script_input_enable_section(lua_State *L)
|
|
|
|
{
|
|
|
|
struct MPContext *mpctx = get_mpctx(L);
|
|
|
|
char *section = (char *)luaL_checkstring(L, 1);
|
|
|
|
char *sflags = (char *)luaL_optstring(L, 2, "");
|
|
|
|
bstr bflags = bstr0(sflags);
|
|
|
|
int flags = 0;
|
|
|
|
while (bflags.len) {
|
|
|
|
bstr val;
|
|
|
|
bstr_split_tok(bflags, "|", &val, &bflags);
|
|
|
|
if (bstr_equals0(val, "allow-hide-cursor")) {
|
|
|
|
flags |= MP_INPUT_ALLOW_HIDE_CURSOR;
|
|
|
|
} else if (bstr_equals0(val, "allow-vo-dragging")) {
|
|
|
|
flags |= MP_INPUT_ALLOW_VO_DRAGGING;
|
|
|
|
} else if (bstr_equals0(val, "exclusive")) {
|
|
|
|
flags |= MP_INPUT_EXCLUSIVE;
|
|
|
|
} else {
|
|
|
|
luaL_error(L, "invalid flag: '%.*s'", BSTR_P(val));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mp_input_enable_section(mpctx->input, section, flags);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int script_input_disable_section(lua_State *L)
|
|
|
|
{
|
|
|
|
struct MPContext *mpctx = get_mpctx(L);
|
|
|
|
char *section = (char *)luaL_checkstring(L, 1);
|
|
|
|
mp_input_disable_section(mpctx->input, section);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int script_input_set_section_mouse_area(lua_State *L)
|
|
|
|
{
|
|
|
|
struct MPContext *mpctx = get_mpctx(L);
|
|
|
|
|
|
|
|
double sw, sh;
|
|
|
|
struct osd_object *obj = mpctx->osd->objs[OSDTYPE_EXTERNAL];
|
|
|
|
osd_object_get_scale_factor(mpctx->osd, obj, &sw, &sh);
|
|
|
|
|
|
|
|
char *section = (char *)luaL_checkstring(L, 1);
|
|
|
|
int x0 = luaL_checkinteger(L, 2) / sw;
|
|
|
|
int y0 = luaL_checkinteger(L, 3) / sh;
|
|
|
|
int x1 = luaL_checkinteger(L, 4) / sw;
|
|
|
|
int y1 = luaL_checkinteger(L, 5) / sh;
|
|
|
|
mp_input_set_section_mouse_area(mpctx->input, section, x0, y0, x1, y1);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int script_format_time(lua_State *L)
|
|
|
|
{
|
|
|
|
double t = luaL_checknumber(L, 1);
|
|
|
|
const char *fmt = luaL_optstring(L, 2, "%H:%M:%S");
|
|
|
|
char *r = mp_format_time_fmt(fmt, t);
|
|
|
|
if (!r)
|
|
|
|
luaL_error(L, "Invalid time format string '%s'", fmt);
|
|
|
|
lua_pushstring(L, r);
|
|
|
|
talloc_free(r);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct fn_entry {
|
|
|
|
const char *name;
|
|
|
|
int (*fn)(lua_State *L);
|
|
|
|
};
|
|
|
|
|
|
|
|
#define FN_ENTRY(name) {#name, script_ ## name}
|
|
|
|
|
|
|
|
static struct fn_entry fn_list[] = {
|
|
|
|
FN_ENTRY(log),
|
|
|
|
FN_ENTRY(find_config_file),
|
|
|
|
FN_ENTRY(send_command),
|
2013-12-20 18:01:04 +01:00
|
|
|
FN_ENTRY(send_commandv),
|
Add initial Lua scripting support
This is preliminary. There are still tons of issues, and any aspect
of scripting may change in the future. I decided to merge this
(preliminary) work now because it makes it easier to develop it, not
because it's done. lua.rst is clear enough about it (plus some
sarcasm).
This requires linking to Lua. Lua has no official pkg-config file, but
there are distribution specific .pc files, all with different names.
Adding a non-pkg-config based configure test was considered, but we'd
rather not.
One major complication is that libquvi links against Lua too, and if
the Lua version is different from mpv's, you will get a crash as soon
as libquvi uses Lua. (libquvi by design always runs when a file is
opened.) I would consider this the problem of distros and whoever
builds mpv, but to make things easier for users, we add a terrible
runtime test to the configure script, which probes whether libquvi
will crash. This is disabled when cross-compiling, but in that case
we hope the user knows what he is doing.
2013-09-26 00:41:14 +02:00
|
|
|
FN_ENTRY(property_list),
|
|
|
|
FN_ENTRY(set_osd_ass),
|
|
|
|
FN_ENTRY(get_osd_resolution),
|
|
|
|
FN_ENTRY(get_screen_size),
|
|
|
|
FN_ENTRY(get_mouse_pos),
|
|
|
|
FN_ENTRY(get_timer),
|
|
|
|
FN_ENTRY(get_chapter_list),
|
|
|
|
FN_ENTRY(get_track_list),
|
|
|
|
FN_ENTRY(input_define_section),
|
|
|
|
FN_ENTRY(input_enable_section),
|
|
|
|
FN_ENTRY(input_disable_section),
|
|
|
|
FN_ENTRY(input_set_section_mouse_area),
|
|
|
|
FN_ENTRY(format_time),
|
lua: allow scripts to snoop messages
Adds the following Lua function to enable message events:
mp.enable_messages(size, level)
size is the maximum number of messages the ringbuffer consists of. level
is the minimum log level for a message to be added to the ringbuffer,
and uses the same values as the mp.log() function. (Actually not yet,
but this will be fixed in the following commit.)
The messages will be delivered via the mp_event() in the user script,
using "message" as event name. The event argument is a table with the
following fields:
level: log level of the message (string as in mp.log())
prefix: string identifying the module of origin
text: contents of the message
As of currently, the message text will contain newline characters. A
message can consist of several lines. It is also possible that a
message doesn't end with a newline, and a caller can use multiple
messages to "build" a line. Most messages will contain exactly 1 line
ending with a single newline character, though.
If the message buffer overflows (messages are not read quickly enough),
new messages are lost until the queued up messages are read. At the
point of the overflow, a special overflow message is inserted. It will
have prefix set to "overflow", and the message text is set to "".
Care should be taken not to print any messages from the message event
handler. This would lead to an infinite loop (the event handler would be
called again after returning, because a new message is available). This
includes mp.log() and all mp.msg.* functions. Keep in mind that the Lua
print() function is mapped to mp.msg.info().
2014-01-16 21:34:58 +01:00
|
|
|
FN_ENTRY(enable_messages),
|
Add initial Lua scripting support
This is preliminary. There are still tons of issues, and any aspect
of scripting may change in the future. I decided to merge this
(preliminary) work now because it makes it easier to develop it, not
because it's done. lua.rst is clear enough about it (plus some
sarcasm).
This requires linking to Lua. Lua has no official pkg-config file, but
there are distribution specific .pc files, all with different names.
Adding a non-pkg-config based configure test was considered, but we'd
rather not.
One major complication is that libquvi links against Lua too, and if
the Lua version is different from mpv's, you will get a crash as soon
as libquvi uses Lua. (libquvi by design always runs when a file is
opened.) I would consider this the problem of distros and whoever
builds mpv, but to make things easier for users, we add a terrible
runtime test to the configure script, which probes whether libquvi
will crash. This is disabled when cross-compiling, but in that case
we hope the user knows what he is doing.
2013-09-26 00:41:14 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
// On stack: mp table
|
|
|
|
static void add_functions(struct script_ctx *ctx)
|
|
|
|
{
|
|
|
|
lua_State *L = ctx->state;
|
|
|
|
|
|
|
|
for (int n = 0; n < MP_ARRAY_SIZE(fn_list); n++) {
|
|
|
|
lua_pushcfunction(L, fn_list[n].fn);
|
|
|
|
lua_setfield(L, -2, fn_list[n].name);
|
|
|
|
}
|
|
|
|
|
|
|
|
lua_pushinteger(L, 0);
|
|
|
|
lua_pushcclosure(L, script_property_string, 1);
|
|
|
|
lua_setfield(L, -2, "property_get");
|
|
|
|
|
|
|
|
lua_pushinteger(L, 1);
|
|
|
|
lua_pushcclosure(L, script_property_string, 1);
|
|
|
|
lua_setfield(L, -2, "property_get_string");
|
|
|
|
}
|
|
|
|
|
|
|
|
void mp_lua_init(struct MPContext *mpctx)
|
|
|
|
{
|
|
|
|
mpctx->lua_ctx = talloc_zero(NULL, struct lua_ctx);
|
|
|
|
// Load scripts from options
|
2013-09-26 00:56:41 +02:00
|
|
|
if (mpctx->opts->lua_load_osc)
|
|
|
|
mp_lua_load_script(mpctx, "@osc");
|
Add initial Lua scripting support
This is preliminary. There are still tons of issues, and any aspect
of scripting may change in the future. I decided to merge this
(preliminary) work now because it makes it easier to develop it, not
because it's done. lua.rst is clear enough about it (plus some
sarcasm).
This requires linking to Lua. Lua has no official pkg-config file, but
there are distribution specific .pc files, all with different names.
Adding a non-pkg-config based configure test was considered, but we'd
rather not.
One major complication is that libquvi links against Lua too, and if
the Lua version is different from mpv's, you will get a crash as soon
as libquvi uses Lua. (libquvi by design always runs when a file is
opened.) I would consider this the problem of distros and whoever
builds mpv, but to make things easier for users, we add a terrible
runtime test to the configure script, which probes whether libquvi
will crash. This is disabled when cross-compiling, but in that case
we hope the user knows what he is doing.
2013-09-26 00:41:14 +02:00
|
|
|
char **files = mpctx->opts->lua_files;
|
|
|
|
for (int n = 0; files && files[n]; n++) {
|
|
|
|
if (files[n][0])
|
|
|
|
mp_lua_load_script(mpctx, files[n]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void mp_lua_uninit(struct MPContext *mpctx)
|
|
|
|
{
|
|
|
|
if (mpctx->lua_ctx) {
|
|
|
|
while (mpctx->lua_ctx->num_scripts)
|
|
|
|
kill_script(mpctx->lua_ctx->scripts[0]);
|
|
|
|
talloc_free(mpctx->lua_ctx);
|
|
|
|
mpctx->lua_ctx = NULL;
|
|
|
|
}
|
|
|
|
}
|