/****************************************************************************** Copyright (C) 2017 by Hugh Bailey This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ******************************************************************************/ #pragma once /* ---------------------------- */ #include #include #include #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4100) #pragma warning(disable : 4189) #pragma warning(disable : 4244) #pragma warning(disable : 4267) #endif #define SWIG_TYPE_TABLE obslua #include "swig/swigluarun.h" #ifdef _MSC_VER #pragma warning(pop) #endif /* ---------------------------- */ #include #include #include #include "obs-scripting-internal.h" #include "obs-scripting-callback.h" #define do_log(level, format, ...) blog(level, "[Lua] " format, ##__VA_ARGS__) #define warn(format, ...) do_log(LOG_WARNING, format, ##__VA_ARGS__) #define info(format, ...) do_log(LOG_INFO, format, ##__VA_ARGS__) #define debug(format, ...) do_log(LOG_DEBUG, format, ##__VA_ARGS__) /* ------------------------------------------------------------ */ struct obs_lua_script; struct lua_obs_callback; extern THREAD_LOCAL struct lua_obs_callback *current_lua_cb; extern THREAD_LOCAL struct obs_lua_script *current_lua_script; /* ------------------------------------------------------------ */ struct lua_obs_callback; struct obs_lua_script { obs_script_t base; struct dstr dir; struct dstr log_chunk; pthread_mutex_t mutex; lua_State *script; struct script_callback *first_callback; int update; int get_properties; int save; int tick; struct obs_lua_script *next_tick; struct obs_lua_script **p_prev_next_tick; bool defined_sources; }; #define lock_callback() \ struct obs_lua_script *__last_script = current_lua_script; \ struct lua_obs_callback *__last_callback = current_lua_cb; \ current_lua_cb = cb; \ current_lua_script = (struct obs_lua_script *)cb->base.script; \ pthread_mutex_lock(¤t_lua_script->mutex); #define unlock_callback() \ pthread_mutex_unlock(¤t_lua_script->mutex); \ current_lua_script = __last_script; \ current_lua_cb = __last_callback; /* ------------------------------------------------ */ struct lua_obs_callback { struct script_callback base; lua_State *script; int reg_idx; }; static inline struct lua_obs_callback * add_lua_obs_callback_extra(lua_State *script, int stack_idx, size_t extra_size) { struct obs_lua_script *data = current_lua_script; struct lua_obs_callback *cb = add_script_callback(&data->first_callback, (obs_script_t *)data, sizeof(*cb) + extra_size); lua_pushvalue(script, stack_idx); cb->reg_idx = luaL_ref(script, LUA_REGISTRYINDEX); cb->script = script; return cb; } static inline struct lua_obs_callback *add_lua_obs_callback(lua_State *script, int stack_idx) { return add_lua_obs_callback_extra(script, stack_idx, 0); } static inline void *lua_obs_callback_extra_data(struct lua_obs_callback *cb) { return (void *)&cb[1]; } static inline struct obs_lua_script * lua_obs_callback_script(struct lua_obs_callback *cb) { return (struct obs_lua_script *)cb->base.script; } static inline struct lua_obs_callback * find_next_lua_obs_callback(lua_State *script, struct lua_obs_callback *cb, int stack_idx) { struct obs_lua_script *data = current_lua_script; cb = cb ? (struct lua_obs_callback *)cb->base.next : (struct lua_obs_callback *)data->first_callback; while (cb) { lua_rawgeti(script, LUA_REGISTRYINDEX, cb->reg_idx); bool match = lua_rawequal(script, -1, stack_idx); lua_pop(script, 1); if (match) break; cb = (struct lua_obs_callback *)cb->base.next; } return cb; } static inline struct lua_obs_callback *find_lua_obs_callback(lua_State *script, int stack_idx) { return find_next_lua_obs_callback(script, NULL, stack_idx); } static inline void remove_lua_obs_callback(struct lua_obs_callback *cb) { remove_script_callback(&cb->base); luaL_unref(cb->script, LUA_REGISTRYINDEX, cb->reg_idx); } static inline void just_free_lua_obs_callback(struct lua_obs_callback *cb) { just_free_script_callback(&cb->base); } static inline void free_lua_obs_callback(struct lua_obs_callback *cb) { free_script_callback(&cb->base); } /* ------------------------------------------------ */ static int is_ptr(lua_State *script, int idx) { return lua_isuserdata(script, idx) || lua_isnil(script, idx); } static int is_table(lua_State *script, int idx) { return lua_istable(script, idx); } static int is_function(lua_State *script, int idx) { return lua_isfunction(script, idx); } typedef int (*param_cb)(lua_State *script, int idx); static inline bool verify_args1_(lua_State *script, param_cb param1_check, const char *func) { if (lua_gettop(script) != 1) { warn("Wrong number of parameters for %s", func); return false; } if (!param1_check(script, 1)) { warn("Wrong parameter type for parameter %d of %s", 1, func); return false; } return true; } #define verify_args1(script, param1_check) \ verify_args1_(script, param1_check, __FUNCTION__) static inline bool call_func_(lua_State *script, int reg_idx, int args, int rets, const char *func, const char *display_name) { if (reg_idx == LUA_REFNIL) return false; struct obs_lua_script *data = current_lua_script; lua_rawgeti(script, LUA_REGISTRYINDEX, reg_idx); lua_insert(script, -1 - args); if (lua_pcall(script, args, rets, 0) != 0) { script_warn(&data->base, "Failed to call %s for %s: %s", func, display_name, lua_tostring(script, -1)); lua_pop(script, 1); return false; } return true; } bool ls_get_libobs_obj_(lua_State *script, const char *type, int lua_idx, void *libobs_out, const char *id, const char *func, int line); bool ls_push_libobs_obj_(lua_State *script, const char *type, void *libobs_in, bool ownership, const char *id, const char *func, int line); extern void add_lua_source_functions(lua_State *script);