summaryrefslogtreecommitdiffstats
path: root/player
diff options
context:
space:
mode:
Diffstat (limited to 'player')
-rw-r--r--player/command.c57
-rw-r--r--player/command.h1
-rw-r--r--player/core.h1
-rw-r--r--player/loadfile.c2
-rw-r--r--player/lua.c337
-rw-r--r--player/lua.h4
-rw-r--r--player/lua/defaults.lua47
-rw-r--r--player/lua/osc.lua11
-rw-r--r--player/main.c3
-rw-r--r--player/playloop.c3
10 files changed, 242 insertions, 224 deletions
diff --git a/player/command.c b/player/command.c
index 2d0f7c0d9a..ada0aef16e 100644
--- a/player/command.c
+++ b/player/command.c
@@ -78,8 +78,6 @@
#include "lua.h"
struct command_ctx {
- int events;
-
double last_seek_time;
double last_seek_pts;
@@ -3119,14 +3117,20 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd)
cmd->args[1].v.s, msg_osd);
break;
- case MP_CMD_SCRIPT_DISPATCH:
- if (mpctx->lua_ctx) {
-#if HAVE_LUA
- mp_lua_script_dispatch(mpctx, cmd->args[0].v.s, cmd->args[1].v.i,
- cmd->key_up_follows ? "keyup_follows" : "press");
-#endif
+ case MP_CMD_SCRIPT_DISPATCH: {
+ mpv_event_script_input_dispatch *event = talloc_ptrtype(NULL, event);
+ *event = (mpv_event_script_input_dispatch){
+ .arg0 = cmd->args[1].v.i,
+ .type = cmd->key_up_follows ? "keyup_follows" : "press",
+ };
+ if (mp_client_send_event(mpctx, cmd->args[0].v.s,
+ MPV_EVENT_SCRIPT_INPUT_DISPATCH, event) < 0)
+ {
+ MP_VERBOSE(mpctx, "Can't find script '%s' when handling input.\n",
+ cmd->args[0].v.s);
}
break;
+ }
#if HAVE_SYS_MMAN_H
case MP_CMD_OVERLAY_ADD:
@@ -3182,45 +3186,8 @@ void command_init(struct MPContext *mpctx)
void mp_notify(struct MPContext *mpctx, int event, void *arg)
{
struct command_ctx *ctx = mpctx->command_ctx;
- ctx->events |= 1u << event;
if (event == MPV_EVENT_START_FILE)
ctx->last_seek_pts = MP_NOPTS_VALUE;
mp_client_broadcast_event(mpctx, event, arg);
}
-
-static void handle_script_event(struct MPContext *mpctx, const char *name,
- const char *arg)
-{
-#if HAVE_LUA
- mp_lua_event(mpctx, name, arg);
-#endif
-}
-
-void mp_flush_events(struct MPContext *mpctx)
-{
- struct command_ctx *ctx = mpctx->command_ctx;
-
- ctx->events |= (1u << MPV_EVENT_TICK);
-
- for (int n = 0; n < 16; n++) {
- int event = n;
- unsigned mask = 1 << event;
- if (ctx->events & mask) {
- // The event handler could set event flags again; in this case let
- // the next mp_flush_events() call handle it to avoid infinite loops.
- ctx->events &= ~mask;
- const char *name = NULL;
- switch (event) {
- case MPV_EVENT_TICK: name = "tick"; break;
- case MPV_EVENT_TRACKS_CHANGED: name = "track-layout"; break;
- case MPV_EVENT_PLAYBACK_START: name = "playback-start"; break;
- case MPV_EVENT_START_FILE: name = "start"; break;
- case MPV_EVENT_END_FILE: name = "end"; break;
- default: ;
- }
- if (name)
- handle_script_event(mpctx, name, "");
- }
- }
-}
diff --git a/player/command.h b/player/command.h
index 8047fd747a..61fe1ffad0 100644
--- a/player/command.h
+++ b/player/command.h
@@ -35,6 +35,5 @@ int mp_property_do(const char* name, int action, void* val,
const struct m_option *mp_get_property_list(void);
void mp_notify(struct MPContext *mpctx, int event, void *arg);
-void mp_flush_events(struct MPContext *mpctx);
#endif /* MPLAYER_COMMAND_H */
diff --git a/player/core.h b/player/core.h
index d39ac64dab..10c2f1886d 100644
--- a/player/core.h
+++ b/player/core.h
@@ -339,7 +339,6 @@ typedef struct MPContext {
struct screenshot_ctx *screenshot_ctx;
struct command_ctx *command_ctx;
struct encode_lavc_context *encode_lavc_ctx;
- struct lua_ctx *lua_ctx;
struct mp_nav_state *nav_state;
} MPContext;
diff --git a/player/loadfile.c b/player/loadfile.c
index b289ef4922..94a0274297 100644
--- a/player/loadfile.c
+++ b/player/loadfile.c
@@ -1052,7 +1052,6 @@ static void play_current_file(struct MPContext *mpctx)
mpctx->initialized_flags |= INITIALIZED_PLAYBACK;
mp_notify(mpctx, MPV_EVENT_START_FILE, NULL);
- mp_flush_events(mpctx);
mpctx->stop_play = 0;
mpctx->filename = NULL;
@@ -1411,7 +1410,6 @@ terminate_playback: // don't jump here after ao/vo/getch initialization!
mp_notify(mpctx, MPV_EVENT_TRACKS_CHANGED, NULL);
mp_notify(mpctx, MPV_EVENT_END_FILE, NULL);
- mp_flush_events(mpctx);
}
// Determine the next file to play. Note that if this function returns non-NULL,
diff --git a/player/lua.c b/player/lua.c
index 79bf61b713..68b8c40ab0 100644
--- a/player/lua.c
+++ b/player/lua.c
@@ -16,9 +16,12 @@
#include "options/path.h"
#include "bstr/bstr.h"
#include "osdep/timer.h"
+#include "osdep/threads.h"
#include "sub/osd.h"
#include "core.h"
#include "command.h"
+#include "client.h"
+#include "libmpv/client.h"
#include "lua.h"
// List of builtin modules and their contents as strings.
@@ -40,25 +43,12 @@ static const char *builtin_lua_scripts[][2] = {
struct script_ctx {
const char *name;
lua_State *state;
- struct mp_log_buffer *messages;
struct mp_log *log;
+ struct mpv_handle *client;
struct MPContext *mpctx;
+ int suspended;
};
-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");
@@ -103,10 +93,29 @@ static void report_error(lua_State *L)
lua_pop(L, 1);
}
+// Check client API error code:
+// if err >= 0, return 0.
+// if err < 0, raise the error as Lua error.
+static int check_error(lua_State *L, int err)
+{
+ if (err >= 0)
+ return 0;
+ luaL_error(L, "mpv API error: %s", mpv_error_string(err));
+ abort();
+}
+
+static int run_event_loop(lua_State *L)
+{
+ lua_getglobal(L, "mp_event_loop");
+ if (lua_isnil(L, -1))
+ luaL_error(L, "no event loop function\n");
+ lua_call(L, 0, 0);
+ return 0;
+}
+
static void add_functions(struct script_ctx *ctx);
-static char *script_name_from_filename(void *talloc_ctx, struct lua_ctx *lctx,
- const char *fname)
+static char *script_name_from_filename(void *talloc_ctx, const char *fname)
{
fname = mp_basename(fname);
if (fname[0] == '@')
@@ -124,10 +133,7 @@ static char *script_name_from_filename(void *talloc_ctx, struct lua_ctx *lctx,
!(c >= '0' && c <= '9'))
name[n] = '_';
}
- // Make unique (stupid but simple)
- while (find_script(lctx, name))
- name = talloc_strdup_append(name, "_");
- return name;
+ return talloc_asprintf(talloc_ctx, "lua/%s", name);
}
static int load_file(struct script_ctx *ctx, const char *fname)
@@ -171,16 +177,28 @@ static bool require(lua_State *L, const char *name)
return true;
}
-static void mp_lua_load_script(struct MPContext *mpctx, const char *fname)
+struct thread_arg {
+ struct MPContext *mpctx;
+ mpv_handle *client;
+ const char *fname;
+};
+
+static void *lua_thread(void *p)
{
- struct lua_ctx *lctx = mpctx->lua_ctx;
+ pthread_detach(pthread_self());
+
+ struct thread_arg *arg = p;
+ struct MPContext *mpctx = arg->mpctx;
+ const char *fname = arg->fname;
+ mpv_handle *client = arg->client;
+
struct script_ctx *ctx = talloc_ptrtype(NULL, ctx);
*ctx = (struct script_ctx) {
.mpctx = mpctx,
- .name = script_name_from_filename(ctx, lctx, fname),
+ .client = client,
+ .name = mpv_client_name(client),
+ .log = mp_client_get_log(client),
};
- 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)
@@ -234,30 +252,43 @@ static void mp_lua_load_script(struct MPContext *mpctx, const char *fname)
goto error_out;
}
- MP_TARRAY_APPEND(lctx, lctx->scripts, lctx->num_scripts, ctx);
- return;
+ // Call the script's event loop runs until the script terminates and unloads.
+ if (mp_cpcall(L, run_event_loop, 0) != 0)
+ report_error(L);
error_out:
+ if (ctx->suspended)
+ mpv_resume(ctx->client);
if (ctx->state)
lua_close(ctx->state);
+ mpv_destroy(ctx->client);
talloc_free(ctx);
+ talloc_free(arg);
+ return NULL;
}
-static void kill_script(struct script_ctx *ctx)
+static void mp_lua_load_script(struct MPContext *mpctx, const char *fname)
{
- if (!ctx)
+ struct thread_arg *arg = talloc_ptrtype(NULL, arg);
+ char *name = script_name_from_filename(arg, fname);
+ *arg = (struct thread_arg){
+ .mpctx = mpctx,
+ .fname = talloc_strdup(arg, fname),
+ // Create the client before creating the thread; otherwise a race
+ // condition could happen, where MPContext is destroyed while the
+ // thread tries to create the client.
+ .client = mp_new_client(mpctx->clients, name),
+ };
+ if (!arg->client) {
+ talloc_free(arg);
return;
- struct lua_ctx *lctx = ctx->mpctx->lua_ctx;
- if (ctx->messages)
- mp_msg_log_buffer_destroy(ctx->messages);
- 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);
+
+ pthread_t thread;
+ if (pthread_create(&thread, NULL, lua_thread, arg))
+ talloc_free(arg);
+
+ return;
}
static int check_loglevel(lua_State *L, int arg)
@@ -308,139 +339,130 @@ static int script_find_config_file(lua_State *L)
return 1;
}
-static int run_event(lua_State *L)
+static int script_suspend(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);
+ struct script_ctx *ctx = get_ctx(L);
+ if (!ctx->suspended)
+ mpv_suspend(ctx->client);
+ ctx->suspended++;
return 0;
}
-static void poll_messages(struct script_ctx *ctx)
+static int script_resume(lua_State *L)
{
- lua_State *L = ctx->state;
+ struct script_ctx *ctx = get_ctx(L);
+ static const char *modes[] = {"normal", "all", NULL};
+ if (luaL_checkoption(L, 1, "normal", modes) == 1) {
+ if (ctx->suspended)
+ mpv_resume(ctx->client);
+ ctx->suspended = 0;
+ } else {
+ if (ctx->suspended < 1)
+ luaL_error(L, "trying to resume, but core is not suspended");
+ ctx->suspended--;
+ if (!ctx->suspended)
+ mpv_resume(ctx->client);
+ }
+ return 0;
+}
- if (!ctx->messages)
- return;
+static int script_wait_event(lua_State *L)
+{
+ struct script_ctx *ctx = get_ctx(L);
- while (1) {
- struct mp_log_buffer_entry *msg = mp_msg_log_buffer_read(ctx->messages);
- if (!msg)
- break;
+ double timeout = luaL_optnumber(L, 1, 1e20);
+
+ // This will almost surely lead to a deadlock. (Polling is still ok.)
+ if (ctx->suspended && timeout > 0)
+ luaL_error(L, "attempting to wait while core is suspended");
+
+ mpv_event *event = mpv_wait_event(ctx->client, timeout);
- 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
+ lua_newtable(L); // event
+ lua_pushstring(L, mpv_event_name(event->event_id)); // event name
+ lua_setfield(L, -2, "event"); // event
- if (mp_cpcall(L, run_event, 2) != 0)
- report_error(L);
+ if (event->error < 0) {
+ lua_pushstring(L, mpv_error_string(event->error)); // event err
+ lua_setfield(L, -2, "error"); // event
+ }
- talloc_free(msg);
+ switch (event->event_id) {
+ case MPV_EVENT_LOG_MESSAGE: {
+ mpv_event_log_message *msg = event->data;
+
+ lua_pushstring(L, msg->prefix); // event s
+ lua_setfield(L, -2, "prefix"); // event
+ lua_pushstring(L, msg->level); // event s
+ lua_setfield(L, -2, "level"); // event
+ lua_pushstring(L, msg->text); // event s
+ lua_setfield(L, -2, "text"); // event
+ break;
+ }
+ case MPV_EVENT_SCRIPT_INPUT_DISPATCH: {
+ mpv_event_script_input_dispatch *msg = event->data;
+
+ lua_pushinteger(L, msg->arg0); // event i
+ lua_setfield(L, -2, "arg0"); // event
+ lua_pushstring(L, msg->type); // event s
+ lua_setfield(L, -2, "type"); // event
+ break;
+ }
+ default: ;
}
+
+ return 1;
}
-void mp_lua_event(struct MPContext *mpctx, const char *name, const char *arg)
+static int script_request_event(lua_State *L)
{
- // 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);
+ struct script_ctx *ctx = get_ctx(L);
+ const char *event = luaL_checkstring(L, 1);
+ bool enable = lua_toboolean(L, 2);
+ // brute force event name -> id; stops working for events > assumed max
+ int event_id = -1;
+ for (int n = 0; n < 256; n++) {
+ const char *name = mpv_event_name(n);
+ if (name && strcmp(name, event) == 0) {
+ event_id = n;
+ break;
}
- if (mp_cpcall(L, run_event, 2) != 0)
- report_error(L);
- poll_messages(ctx);
}
+ lua_pushboolean(L, mpv_request_event(ctx->client, event_id, enable) >= 0);
+ return 1;
}
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;
-}
-
-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) {
- MP_VERBOSE(mpctx, "Can't find script '%s' when handling input.\n",
- script_name);
- 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);
+ check_loglevel(L, 1);
+ const char *level = luaL_checkstring(L, 1);
+ return check_error(L, mpv_request_log_messages(ctx->client, level));
}
static int script_send_command(lua_State *L)
{
- struct MPContext *mpctx = get_mpctx(L);
+ struct script_ctx *ctx = get_ctx(L);
const char *s = luaL_checkstring(L, 1);
- mp_cmd_t *cmd = mp_input_parse_cmd(mpctx->input, bstr0((char*)s), "<lua>");
- if (!cmd)
- luaL_error(L, "error parsing command");
- mp_input_queue_cmd(mpctx->input, cmd);
-
- return 0;
+ return check_error(L, mpv_command_string(ctx->client, s));
}
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))
+ const char *args[50];
+ if (num + 1 > 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);
+ const char *s = lua_tostring(L, n);
if (!s)
luaL_error(L, "argument %d is not a string", n);
- args[n - 1] = (bstr){(char *)s, len};
+ args[n - 1] = s;
}
- 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;
+ args[num] = NULL;
+ return check_error(L, mpv_command(ctx->client, args));
}
static int script_property_list(lua_State *L)
@@ -457,18 +479,24 @@ static int script_property_list(lua_State *L)
static int script_property_string(lua_State *L)
{
- struct MPContext *mpctx = get_mpctx(L);
+ struct script_ctx *ctx = get_ctx(L);
const char *name = luaL_checkstring(L, 1);
int type = lua_tointeger(L, lua_upvalueindex(1))
- ? M_PROPERTY_PRINT : M_PROPERTY_GET_STRING;
+ ? MPV_FORMAT_OSD_STRING : MPV_FORMAT_STRING;
char *result = NULL;
- if (mp_property_do(name, type, &result, mpctx) >= 0 && result) {
+ int err = mpv_get_property(ctx->client, name, type, &result);
+ if (err >= 0) {
lua_pushstring(L, result);
talloc_free(result);
return 1;
}
- if (type == M_PROPERTY_PRINT) {
+ // out of convenience, property access errors are not hard errors
+ if (err != MPV_ERROR_PROPERTY_NOT_FOUND &&
+ err != MPV_ERROR_PROPERTY_ERROR &&
+ err != MPV_ERROR_PROPERTY_UNAVAILABLE)
+ check_error(L, err);
+ if (type == MPV_FORMAT_OSD_STRING) {
lua_pushstring(L, "");
return 1;
}
@@ -528,6 +556,7 @@ static int script_get_timer(lua_State *L)
static int script_get_chapter_list(lua_State *L)
{
struct MPContext *mpctx = get_mpctx(L);
+ mp_dispatch_lock(mpctx->dispatch);
lua_newtable(L); // list
int num = get_chapter_count(mpctx);
for (int n = 0; n < num; n++) {
@@ -543,6 +572,7 @@ static int script_get_chapter_list(lua_State *L)
lua_settable(L, -3); // list
talloc_free(name);
}
+ mp_dispatch_unlock(mpctx->dispatch);
return 1;
}
@@ -559,6 +589,7 @@ static const char *stream_type(enum stream_type t)
static int script_get_track_list(lua_State *L)
{
struct MPContext *mpctx = get_mpctx(L);
+ mp_dispatch_lock(mpctx->dispatch);
lua_newtable(L); // list
for (int n = 0; n < mpctx->num_tracks; n++) {
struct track *track = mpctx->tracks[n];
@@ -593,6 +624,7 @@ static int script_get_track_list(lua_State *L)
lua_insert(L, -2); // list n1 track
lua_settable(L, -3); // list
}
+ mp_dispatch_unlock(mpctx->dispatch);
return 1;
}
@@ -668,16 +700,24 @@ static int script_format_time(lua_State *L)
static int script_getopt(lua_State *L)
{
struct MPContext *mpctx = get_mpctx(L);
+
+ mp_dispatch_lock(mpctx->dispatch);
+
char **opts = mpctx->opts->lua_opts;
const char *name = luaL_checkstring(L, 1);
+ int r = 0;
for (int n = 0; opts && opts[n] && opts[n + 1]; n++) {
if (strcmp(opts[n], name) == 0) {
lua_pushstring(L, opts[n + 1]);
- return 1;
+ r = 1;
+ break;
}
}
- return 0;
+
+ mp_dispatch_unlock(mpctx->dispatch);
+
+ return r;
}
struct fn_entry {
@@ -689,6 +729,10 @@ struct fn_entry {
static struct fn_entry fn_list[] = {
FN_ENTRY(log),
+ FN_ENTRY(suspend),
+ FN_ENTRY(resume),
+ FN_ENTRY(wait_event),
+ FN_ENTRY(request_event),
FN_ENTRY(find_config_file),
FN_ENTRY(send_command),
FN_ENTRY(send_commandv),
@@ -730,7 +774,6 @@ static void add_functions(struct script_ctx *ctx)
void mp_lua_init(struct MPContext *mpctx)
{
- mpctx->lua_ctx = talloc_zero(NULL, struct lua_ctx);
// Load scripts from options
if (mpctx->opts->lua_load_osc)
mp_lua_load_script(mpctx, "@osc");
@@ -740,13 +783,3 @@ void mp_lua_init(struct MPContext *mpctx)
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;
- }
-}
diff --git a/player/lua.h b/player/lua.h
index 050548e2d2..cb4a7f95ec 100644
--- a/player/lua.h
+++ b/player/lua.h
@@ -6,9 +6,5 @@
struct MPContext;
void mp_lua_init(struct MPContext *mpctx);
-void mp_lua_uninit(struct MPContext *mpctx);
-void mp_lua_event(struct MPContext *mpctx, const char *name, const char *arg);
-void mp_lua_script_dispatch(struct MPContext *mpctx, char *script_name,
- int id, char *event);
#endif
diff --git a/player/lua/defaults.lua b/player/lua/defaults.lua
index 4b5e5e6126..7dca478252 100644
--- a/player/lua/defaults.lua
+++ b/player/lua/defaults.lua
@@ -52,18 +52,31 @@ function mp.set_mouse_area(x0, y0, x1, y1, section)
mp.input_set_section_mouse_area(section or default_section, x0, y0, x1, y1)
end
--- called by C on script_dispatch input command
-function mp_script_dispatch(id, event)
- local cb = callbacks[id]
+local function script_dispatch(event)
+ local cb = callbacks[event.arg0]
if cb then
- if event == "press" and cb.press then
+ if event.type == "press" and cb.press then
cb.press()
- elseif event == "keyup_follows" and cb.before_press then
+ elseif event.type == "keyup_follows" and cb.before_press then
cb.before_press()
end
end
end
+-- used by default event loop (mp_event_loop()) to decide when to quit
+mp.keep_running = true
+
+local event_handlers = {}
+
+function mp.register_event(name, cb)
+ event_handlers[name] = cb
+ mp.request_event(name, true)
+end
+
+-- default handlers
+mp.register_event("shutdown", function() mp.keep_running = false end)
+mp.register_event("script-input-dispatch", script_dispatch)
+
mp.msg = {
log = mp.log,
fatal = function(...) return mp.log("fatal", ...) end,
@@ -79,4 +92,28 @@ _G.print = mp.msg.info
package.loaded["mp"] = mp
package.loaded["mp.msg"] = mp.msg
+_G.mp_event_loop = function()
+ wait = 0
+ while mp.keep_running do
+ -- Drop all locks - important especially if an error happened while
+ -- locked, and the error was handled, but the lock not dropped.
+ if wait > 0 then
+ mp.resume("all")
+ end
+ local e = mp.wait_event(wait)
+ if e.event == "none" then
+ wait = 1e20
+ else
+ -- Empty the event queue while suspended; otherwise, each
+ -- event will keep us waiting until the core suspends again.
+ mp.suspend()
+ wait = 0
+ local handler = event_handlers[e.event]
+ if handler then
+ handler(e)
+ end
+ end
+ end
+end
+
return {}
diff --git a/player/lua/osc.lua b/player/lua/osc.lua
index cf6ce3449e..d19bfd7d78 100644
--- a/player/lua/osc.lua
+++ b/player/lua/osc.lua
@@ -1257,14 +1257,9 @@ function tick()
end
end
-function mp_event(name, arg)
- if name == "tick" then
- tick()
- elseif name == "start" or name == "track-layout" then
- request_init()
- elseif name == "end" then
- end
-end
+mp.register_event("tick", tick)
+mp.register_event("start-file", request_init)
+mp.register_event("tracks-changed", request_init)
-- mouse show/hide bindings
mp.set_key_bindings({
diff --git a/player/main.c b/player/main.c
index c455a0641c..4493d8aeb5 100644
--- a/player/main.c
+++ b/player/main.c
@@ -139,9 +139,6 @@ void mp_destroy(struct MPContext *mpctx)
mpctx->encode_lavc_ctx = NULL;
-#if HAVE_LUA
- mp_lua_uninit(mpctx);
-#endif
shutdown_clients(mpctx);
command_uninit(mpctx);
diff --git a/player/playloop.c b/player/playloop.c
index d97fedccbc..57d5281240 100644
--- a/player/playloop.c
+++ b/player/playloop.c
@@ -747,8 +747,6 @@ static void handle_cursor_autohide(struct MPContext *mpctx)
static void handle_input_and_seek_coalesce(struct MPContext *mpctx)
{
- mp_flush_events(mpctx);
-
mp_cmd_t *cmd;
while ((cmd = mp_input_get_cmd(mpctx->input, 0, 1)) != NULL) {
mp_dispatch_queue_process(mpctx->dispatch, 0);
@@ -1340,7 +1338,6 @@ void idle_loop(struct MPContext *mpctx)
if (cmd)
run_command(mpctx, cmd);
mp_cmd_free(cmd);
- mp_flush_events(mpctx);
mp_dispatch_queue_process(mpctx->dispatch, 0);
if (mpctx->opts->use_terminal)
getch2_poll();