mirror of
https://github.com/obsproject/obs-studio.git
synced 2024-09-20 04:42:18 +02:00
deps/obs-scripting: Add scripting support
Allows Lua/Python scripting support.
This commit is contained in:
parent
fd9e5d45a3
commit
9eabfdbf1e
3
.gitignore
vendored
3
.gitignore
vendored
@ -45,6 +45,9 @@ install-sh
|
|||||||
Makefile.in
|
Makefile.in
|
||||||
Makefile
|
Makefile
|
||||||
|
|
||||||
|
#python
|
||||||
|
__pycache__
|
||||||
|
|
||||||
#sphinx
|
#sphinx
|
||||||
/docs/sphinx/_build/*
|
/docs/sphinx/_build/*
|
||||||
!/docs/sphinx/_build/.gitignore
|
!/docs/sphinx/_build/.gitignore
|
||||||
|
@ -20,6 +20,7 @@ if(WIN32)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/")
|
||||||
|
set(ENABLE_SCRIPTING OFF CACHE BOOL "" FORCE)
|
||||||
|
|
||||||
include(ObsHelpers)
|
include(ObsHelpers)
|
||||||
include(ObsCpack)
|
include(ObsCpack)
|
||||||
|
1
deps/CMakeLists.txt
vendored
1
deps/CMakeLists.txt
vendored
@ -12,6 +12,7 @@ endif()
|
|||||||
|
|
||||||
add_subdirectory(media-playback)
|
add_subdirectory(media-playback)
|
||||||
add_subdirectory(file-updater)
|
add_subdirectory(file-updater)
|
||||||
|
add_subdirectory(obs-scripting)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
add_subdirectory(blake2)
|
add_subdirectory(blake2)
|
||||||
|
173
deps/obs-scripting/CMakeLists.txt
vendored
Normal file
173
deps/obs-scripting/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
cmake_minimum_required(VERSION 2.8)
|
||||||
|
project(obs-scripting)
|
||||||
|
|
||||||
|
if(MSVC)
|
||||||
|
set(obs-scripting_PLATFORM_DEPS
|
||||||
|
w32-pthreads)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_package(Luajit QUIET)
|
||||||
|
find_package(PythonLibs QUIET 3.4)
|
||||||
|
find_package(SWIG QUIET 2)
|
||||||
|
|
||||||
|
set(COMPILE_PYTHON FALSE CACHE BOOL "" FORCE)
|
||||||
|
set(COMPILE_LUA FALSE CACHE BOOL "" FORCE)
|
||||||
|
|
||||||
|
if(NOT SWIG_FOUND)
|
||||||
|
message(STATUS "Scripting: SWIG not found; scripting disabled")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT PYTHONLIBS_FOUND AND NOT LUAJIT_FOUND)
|
||||||
|
message(STATUS "Scripting: Neither Python 3 nor Luajit was found; scripting plugin disabled")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT LUAJIT_FOUND)
|
||||||
|
message(STATUS "Scripting: Luajit not found; Luajit support disabled")
|
||||||
|
else()
|
||||||
|
message(STATUS "Scripting: Luajit supported")
|
||||||
|
set(COMPILE_LUA TRUE CACHE BOOL "" FORCE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT PYTHONLIBS_FOUND)
|
||||||
|
message(STATUS "Scripting: Python 3 not found; Python support disabled")
|
||||||
|
set(PYTHON_FOUND FALSE)
|
||||||
|
set(PYTHONLIBS_FOUND FALSE)
|
||||||
|
else()
|
||||||
|
message(STATUS "Scripting: Python 3 supported")
|
||||||
|
set(PYTHON_FOUND TRUE)
|
||||||
|
set(COMPILE_PYTHON TRUE CACHE BOOL "" FORCE)
|
||||||
|
|
||||||
|
get_filename_component(PYTHON_LIB "${PYTHON_LIBRARIES}" NAME)
|
||||||
|
string(REGEX REPLACE "\\.[^.]*$" "" PYTHON_LIB ${PYTHON_LIB})
|
||||||
|
if(WIN32)
|
||||||
|
string(REGEX REPLACE "_d" "" PYTHON_LIB "${PYTHON_LIB}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(ENABLE_SCRIPTING ON CACHE BOOL "" FORCE)
|
||||||
|
|
||||||
|
if(UI_ENABLED)
|
||||||
|
set(EXTRA_LIBS obs-frontend-api)
|
||||||
|
include_directories(SYSTEM "${CMAKE_SOURCE_DIR}/UI/obs-frontend-api")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
configure_file(
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/obs-scripting-config.h.in"
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/obs-scripting-config.h")
|
||||||
|
|
||||||
|
include(${SWIG_USE_FILE})
|
||||||
|
|
||||||
|
include_directories(${CMAKE_SOURCE_DIR}/libobs)
|
||||||
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
|
if(PYTHONLIBS_FOUND)
|
||||||
|
include_directories(${PYTHON_INCLUDE_DIR})
|
||||||
|
|
||||||
|
set(obs-scripting-python_SOURCES
|
||||||
|
obs-scripting-python.c
|
||||||
|
)
|
||||||
|
set(obs-scripting-python_HEADERS
|
||||||
|
obs-scripting-python.h
|
||||||
|
obs-scripting-python-import.h
|
||||||
|
)
|
||||||
|
|
||||||
|
if(UI_ENABLED)
|
||||||
|
set(obs-scripting-python_SOURCES
|
||||||
|
${obs-scripting-python_SOURCES}
|
||||||
|
obs-scripting-python-frontend.c
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
if(WIN32 OR APPLE)
|
||||||
|
set(obs-scripting-python_SOURCES
|
||||||
|
${obs-scripting-python_SOURCES}
|
||||||
|
obs-scripting-python-import.c
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
set(EXTRA_LIBS ${EXTRA_LIBS} ${PYTHON_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(LUAJIT_FOUND)
|
||||||
|
include_directories(${LUAJIT_INCLUDE_DIR})
|
||||||
|
|
||||||
|
set(obs-scripting-lua_SOURCES
|
||||||
|
obs-scripting-lua.c
|
||||||
|
obs-scripting-lua-source.c
|
||||||
|
)
|
||||||
|
set(obs-scripting-lua_HEADERS
|
||||||
|
obs-scripting-lua.h
|
||||||
|
)
|
||||||
|
if(UI_ENABLED)
|
||||||
|
set(obs-scripting-lua_SOURCES
|
||||||
|
${obs-scripting-lua_SOURCES}
|
||||||
|
obs-scripting-lua-frontend.c
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(obs-scripting_SOURCES
|
||||||
|
obs-scripting.c
|
||||||
|
obs-scripting-logging.c
|
||||||
|
cstrcache.cpp
|
||||||
|
)
|
||||||
|
set(obs-scripting_HEADERS
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/obs-scripting-config.h
|
||||||
|
obs-scripting.h
|
||||||
|
obs-scripting-callback.h
|
||||||
|
cstrcache.h
|
||||||
|
)
|
||||||
|
|
||||||
|
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/swig)
|
||||||
|
|
||||||
|
if(PYTHONLIBS_FOUND)
|
||||||
|
set(SWIG_PY_RUNTIME swig/swigpyrun.h)
|
||||||
|
add_custom_command(OUTPUT ${SWIG_PY_RUNTIME}
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
PRE_BUILD
|
||||||
|
COMMAND ${SWIG_EXECUTABLE} -python -external-runtime ${SWIG_PY_RUNTIME}
|
||||||
|
COMMENT "Scripting plugin: Building Python SWIG interface header"
|
||||||
|
)
|
||||||
|
set_source_files_properties(${SWIG_PY_RUNTIME} PROPERTIES GENERATED TRUE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(LUAJIT_FOUND)
|
||||||
|
set(SWIG_LUA_RUNTIME swig/swigluarun.h)
|
||||||
|
add_custom_command(OUTPUT ${SWIG_LUA_RUNTIME}
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
PRE_BUILD
|
||||||
|
COMMAND ${SWIG_EXECUTABLE} -lua -external-runtime ${SWIG_LUA_RUNTIME}
|
||||||
|
COMMENT "Scripting: Building Lua SWIG interface header"
|
||||||
|
)
|
||||||
|
set_source_files_properties(${SWIG_LUA_RUNTIME} PROPERTIES GENERATED TRUE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_library(obs-scripting SHARED
|
||||||
|
${obs-scripting_SOURCES}
|
||||||
|
${obs-scripting_HEADERS}
|
||||||
|
${obs-scripting-python_SOURCES}
|
||||||
|
${obs-scripting-python_HEADERS}
|
||||||
|
${obs-scripting-lua_SOURCES}
|
||||||
|
${obs-scripting-lua_HEADERS}
|
||||||
|
${SWIG_PY_RUNTIME}
|
||||||
|
${SWIG_LUA_RUNTIME}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(obs-scripting
|
||||||
|
libobs
|
||||||
|
${LUAJIT_LIBRARIES}
|
||||||
|
${EXTRA_LIBS}
|
||||||
|
${obs-scripting_PLATFORM_DEPS}
|
||||||
|
)
|
||||||
|
|
||||||
|
if(PYTHONLIBS_FOUND)
|
||||||
|
add_subdirectory(obspython)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(LUAJIT_FOUND)
|
||||||
|
add_subdirectory(obslua)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
install_obs_core(obs-scripting)
|
28
deps/obs-scripting/cstrcache.cpp
vendored
Normal file
28
deps/obs-scripting/cstrcache.cpp
vendored
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#include <unordered_map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "cstrcache.h"
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
struct const_string_table {
|
||||||
|
unordered_map<string, string> strings;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct const_string_table table;
|
||||||
|
|
||||||
|
const char *cstrcache_get(const char *str)
|
||||||
|
{
|
||||||
|
if (!str || !*str)
|
||||||
|
return "";
|
||||||
|
|
||||||
|
auto &strings = table.strings;
|
||||||
|
auto pair = strings.find(str);
|
||||||
|
|
||||||
|
if (pair == strings.end()) {
|
||||||
|
strings[str] = str;
|
||||||
|
pair = strings.find(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pair->second.c_str();
|
||||||
|
}
|
13
deps/obs-scripting/cstrcache.h
vendored
Normal file
13
deps/obs-scripting/cstrcache.h
vendored
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
/* simple constant string cache table using STL unordered_map as storage */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern const char *cstrcache_get(const char *str);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
91
deps/obs-scripting/obs-scripting-callback.h
vendored
Normal file
91
deps/obs-scripting/obs-scripting-callback.h
vendored
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
Copyright (C) 2017 by Hugh Bailey <jim@obsproject.com>
|
||||||
|
|
||||||
|
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 <http://www.gnu.org/licenses/>.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <callback/calldata.h>
|
||||||
|
#include <util/threading.h>
|
||||||
|
#include <util/bmem.h>
|
||||||
|
#include "obs-scripting-internal.h"
|
||||||
|
|
||||||
|
extern pthread_mutex_t detach_mutex;
|
||||||
|
extern struct script_callback *detached_callbacks;
|
||||||
|
|
||||||
|
struct script_callback {
|
||||||
|
struct script_callback *next;
|
||||||
|
struct script_callback **p_prev_next;
|
||||||
|
|
||||||
|
void (*on_remove)(void *p_cb);
|
||||||
|
obs_script_t *script;
|
||||||
|
calldata_t extra;
|
||||||
|
|
||||||
|
bool removed;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void *add_script_callback(
|
||||||
|
struct script_callback **first,
|
||||||
|
obs_script_t *script,
|
||||||
|
size_t extra_size)
|
||||||
|
{
|
||||||
|
struct script_callback *cb = bzalloc(sizeof(*cb) + extra_size);
|
||||||
|
cb->script = script;
|
||||||
|
|
||||||
|
struct script_callback *next = *first;
|
||||||
|
cb->next = next;
|
||||||
|
cb->p_prev_next = first;
|
||||||
|
if (next) next->p_prev_next = &cb->next;
|
||||||
|
*first = cb;
|
||||||
|
|
||||||
|
return cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void remove_script_callback(struct script_callback *cb)
|
||||||
|
{
|
||||||
|
cb->removed = true;
|
||||||
|
|
||||||
|
struct script_callback *next = cb->next;
|
||||||
|
if (next) next->p_prev_next = cb->p_prev_next;
|
||||||
|
*cb->p_prev_next = cb->next;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&detach_mutex);
|
||||||
|
next = detached_callbacks;
|
||||||
|
cb->next = next;
|
||||||
|
if (next) next->p_prev_next = &cb->next;
|
||||||
|
cb->p_prev_next = &detached_callbacks;
|
||||||
|
detached_callbacks = cb;
|
||||||
|
pthread_mutex_unlock(&detach_mutex);
|
||||||
|
|
||||||
|
if (cb->on_remove)
|
||||||
|
cb->on_remove(cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void just_free_script_callback(struct script_callback *cb)
|
||||||
|
{
|
||||||
|
calldata_free(&cb->extra);
|
||||||
|
bfree(cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void free_script_callback(struct script_callback *cb)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&detach_mutex);
|
||||||
|
struct script_callback *next = cb->next;
|
||||||
|
if (next) next->p_prev_next = cb->p_prev_next;
|
||||||
|
*cb->p_prev_next = cb->next;
|
||||||
|
pthread_mutex_unlock(&detach_mutex);
|
||||||
|
|
||||||
|
just_free_script_callback(cb);
|
||||||
|
}
|
22
deps/obs-scripting/obs-scripting-config.h.in
vendored
Normal file
22
deps/obs-scripting/obs-scripting-config.h.in
vendored
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef TRUE
|
||||||
|
#define TRUE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ON
|
||||||
|
#define ON 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FALSE
|
||||||
|
#define FALSE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef OFF
|
||||||
|
#define OFF 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PYTHON_LIB "@PYTHON_LIB@"
|
||||||
|
#define COMPILE_LUA @LUAJIT_FOUND@
|
||||||
|
#define COMPILE_PYTHON @PYTHON_FOUND@
|
||||||
|
#define UI_ENABLED @UI_ENABLED@
|
51
deps/obs-scripting/obs-scripting-internal.h
vendored
Normal file
51
deps/obs-scripting/obs-scripting-internal.h
vendored
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
Copyright (C) 2017 by Hugh Bailey <jim@obsproject.com>
|
||||||
|
|
||||||
|
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 <http://www.gnu.org/licenses/>.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <util/dstr.h>
|
||||||
|
#include <callback/calldata.h>
|
||||||
|
#include "obs-scripting.h"
|
||||||
|
|
||||||
|
struct obs_script {
|
||||||
|
enum obs_script_lang type;
|
||||||
|
bool loaded;
|
||||||
|
|
||||||
|
obs_data_t *settings;
|
||||||
|
|
||||||
|
struct dstr path;
|
||||||
|
struct dstr file;
|
||||||
|
struct dstr desc;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct script_callback;
|
||||||
|
typedef void (*defer_call_cb)(void *param);
|
||||||
|
|
||||||
|
extern void defer_call_post(defer_call_cb call, void *cb);
|
||||||
|
|
||||||
|
extern void script_log(obs_script_t *script, int level, const char *format, ...);
|
||||||
|
extern void script_log_va(obs_script_t *script, int level, const char *format,
|
||||||
|
va_list args);
|
||||||
|
|
||||||
|
#define script_error(script, format, ...) \
|
||||||
|
script_log(script, LOG_ERROR, format, ##__VA_ARGS__)
|
||||||
|
#define script_warn(script, format, ...) \
|
||||||
|
script_log(script, LOG_WARNING, format, ##__VA_ARGS__)
|
||||||
|
#define script_info(script, format, ...) \
|
||||||
|
script_log(script, LOG_INFO, format, ##__VA_ARGS__)
|
||||||
|
#define script_debug(script, format, ...) \
|
||||||
|
script_log(script, LOG_DEBUG, format, ##__VA_ARGS__)
|
59
deps/obs-scripting/obs-scripting-logging.c
vendored
Normal file
59
deps/obs-scripting/obs-scripting-logging.c
vendored
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
Copyright (C) 2017 by Hugh Bailey <jim@obsproject.com>
|
||||||
|
|
||||||
|
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 <http://www.gnu.org/licenses/>.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "obs-scripting-internal.h"
|
||||||
|
#include <util/platform.h>
|
||||||
|
|
||||||
|
static scripting_log_handler_t callback = NULL;
|
||||||
|
static void *param = NULL;
|
||||||
|
|
||||||
|
void script_log_va(obs_script_t *script, int level, const char *format,
|
||||||
|
va_list args)
|
||||||
|
{
|
||||||
|
char msg[2048];
|
||||||
|
const char *lang = "(Unknown)";
|
||||||
|
size_t start_len;
|
||||||
|
|
||||||
|
switch (script->type) {
|
||||||
|
case OBS_SCRIPT_LANG_UNKNOWN: lang = "(Unknown language)"; break;
|
||||||
|
case OBS_SCRIPT_LANG_LUA: lang = "Lua"; break;
|
||||||
|
case OBS_SCRIPT_LANG_PYTHON: lang = "Python"; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
start_len = snprintf(msg, sizeof(msg), "[%s: %s] ",
|
||||||
|
lang, script->file.array);
|
||||||
|
vsnprintf(msg + start_len, sizeof(msg) - start_len, format, args);
|
||||||
|
|
||||||
|
if (callback)
|
||||||
|
callback(param, script, level, msg + start_len);
|
||||||
|
blog(level, "%s", msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void script_log(obs_script_t *script, int level, const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
script_log_va(script, level, format, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void obs_scripting_set_log_callback(scripting_log_handler_t handler,
|
||||||
|
void *log_param)
|
||||||
|
{
|
||||||
|
callback = handler;
|
||||||
|
param = log_param;
|
||||||
|
}
|
315
deps/obs-scripting/obs-scripting-lua-frontend.c
vendored
Normal file
315
deps/obs-scripting/obs-scripting-lua-frontend.c
vendored
Normal file
@ -0,0 +1,315 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
Copyright (C) 2017 by Hugh Bailey <jim@obsproject.com>
|
||||||
|
|
||||||
|
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 <http://www.gnu.org/licenses/>.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include <obs-module.h>
|
||||||
|
#include <obs-frontend-api.h>
|
||||||
|
|
||||||
|
#include "obs-scripting-lua.h"
|
||||||
|
|
||||||
|
#define ls_get_libobs_obj(type, lua_index, obs_obj) \
|
||||||
|
ls_get_libobs_obj_(script, #type " *", lua_index, obs_obj, \
|
||||||
|
NULL, __FUNCTION__, __LINE__)
|
||||||
|
#define ls_push_libobs_obj(type, obs_obj, ownership) \
|
||||||
|
ls_push_libobs_obj_(script, #type " *", obs_obj, ownership, \
|
||||||
|
NULL, __FUNCTION__, __LINE__)
|
||||||
|
#define call_func(func, args, rets) \
|
||||||
|
call_func_(script, cb->reg_idx, args, rets, #func, "frontend API")
|
||||||
|
|
||||||
|
/* ----------------------------------- */
|
||||||
|
|
||||||
|
static int get_scene_names(lua_State *script)
|
||||||
|
{
|
||||||
|
char **names = obs_frontend_get_scene_names();
|
||||||
|
char **name = names;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
lua_newtable(script);
|
||||||
|
|
||||||
|
while (name && *name) {
|
||||||
|
lua_pushstring(script, *name);
|
||||||
|
lua_rawseti(script, -2, i++);
|
||||||
|
name++;
|
||||||
|
}
|
||||||
|
|
||||||
|
bfree(names);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_scenes(lua_State *script)
|
||||||
|
{
|
||||||
|
struct obs_frontend_source_list list = {0};
|
||||||
|
obs_frontend_get_scenes(&list);
|
||||||
|
|
||||||
|
lua_createtable(script, (int)list.sources.num, 0);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < list.sources.num; i++) {
|
||||||
|
obs_source_t *source = list.sources.array[i];
|
||||||
|
ls_push_libobs_obj(obs_source_t, source, false);
|
||||||
|
lua_rawseti(script, -2, (int)i++);
|
||||||
|
}
|
||||||
|
|
||||||
|
da_free(list.sources);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_current_scene(lua_State *script)
|
||||||
|
{
|
||||||
|
obs_source_t *source = obs_frontend_get_current_scene();
|
||||||
|
ls_push_libobs_obj(obs_source_t, source, false);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_current_scene(lua_State *script)
|
||||||
|
{
|
||||||
|
obs_source_t *source = NULL;
|
||||||
|
ls_get_libobs_obj(obs_source_t, 1, &source);
|
||||||
|
obs_frontend_set_current_scene(source);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_transitions(lua_State *script)
|
||||||
|
{
|
||||||
|
struct obs_frontend_source_list list = {0};
|
||||||
|
obs_frontend_get_transitions(&list);
|
||||||
|
|
||||||
|
lua_createtable(script, (int)list.sources.num, 0);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < list.sources.num; i++) {
|
||||||
|
obs_source_t *source = list.sources.array[i];
|
||||||
|
ls_push_libobs_obj(obs_source_t, source, false);
|
||||||
|
lua_rawseti(script, -2, (int)i++);
|
||||||
|
}
|
||||||
|
|
||||||
|
da_free(list.sources);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_current_transition(lua_State *script)
|
||||||
|
{
|
||||||
|
obs_source_t *source = obs_frontend_get_current_transition();
|
||||||
|
ls_push_libobs_obj(obs_source_t, source, false);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_current_transition(lua_State *script)
|
||||||
|
{
|
||||||
|
obs_source_t *source = NULL;
|
||||||
|
ls_get_libobs_obj(obs_source_t, 1, &source);
|
||||||
|
obs_frontend_set_current_transition(source);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_scene_collections(lua_State *script)
|
||||||
|
{
|
||||||
|
char **names = obs_frontend_get_scene_collections();
|
||||||
|
char **name = names;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
lua_newtable(script);
|
||||||
|
|
||||||
|
while (name && *name) {
|
||||||
|
lua_pushstring(script, *name);
|
||||||
|
lua_rawseti(script, -2, i++);
|
||||||
|
name++;
|
||||||
|
}
|
||||||
|
|
||||||
|
bfree(names);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_current_scene_collection(lua_State *script)
|
||||||
|
{
|
||||||
|
char *name = obs_frontend_get_current_scene_collection();
|
||||||
|
lua_pushstring(script, name);
|
||||||
|
bfree(name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_current_scene_collection(lua_State *script)
|
||||||
|
{
|
||||||
|
if (lua_isstring(script, 1)) {
|
||||||
|
const char *name = lua_tostring(script, 1);
|
||||||
|
obs_frontend_set_current_scene_collection(name);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_profiles(lua_State *script)
|
||||||
|
{
|
||||||
|
char **names = obs_frontend_get_profiles();
|
||||||
|
char **name = names;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
lua_newtable(script);
|
||||||
|
|
||||||
|
while (name && *name) {
|
||||||
|
lua_pushstring(script, *name);
|
||||||
|
lua_rawseti(script, -2, i++);
|
||||||
|
name++;
|
||||||
|
}
|
||||||
|
|
||||||
|
bfree(names);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_current_profile(lua_State *script)
|
||||||
|
{
|
||||||
|
char *name = obs_frontend_get_current_profile();
|
||||||
|
lua_pushstring(script, name);
|
||||||
|
bfree(name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_current_profile(lua_State *script)
|
||||||
|
{
|
||||||
|
if (lua_isstring(script, 1)) {
|
||||||
|
const char *name = lua_tostring(script, 1);
|
||||||
|
obs_frontend_set_current_profile(name);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------- */
|
||||||
|
|
||||||
|
static void frontend_event_callback(enum obs_frontend_event event, void *priv)
|
||||||
|
{
|
||||||
|
struct lua_obs_callback *cb = priv;
|
||||||
|
lua_State *script = cb->script;
|
||||||
|
|
||||||
|
if (cb->base.removed) {
|
||||||
|
obs_frontend_remove_event_callback(frontend_event_callback, cb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock_callback();
|
||||||
|
|
||||||
|
lua_pushinteger(script, (int)event);
|
||||||
|
call_func(frontend_event_callback, 1, 0);
|
||||||
|
|
||||||
|
unlock_callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int remove_event_callback(lua_State *script)
|
||||||
|
{
|
||||||
|
if (!verify_args1(script, is_function))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
struct lua_obs_callback *cb = find_lua_obs_callback(script, 1);
|
||||||
|
if (cb) {
|
||||||
|
remove_lua_obs_callback(cb);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_event_callback_defer(void *cb)
|
||||||
|
{
|
||||||
|
obs_frontend_add_event_callback(frontend_event_callback, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int add_event_callback(lua_State *script)
|
||||||
|
{
|
||||||
|
if (!verify_args1(script, is_function))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
struct lua_obs_callback *cb = add_lua_obs_callback(script, 1);
|
||||||
|
defer_call_post(add_event_callback_defer, cb);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------- */
|
||||||
|
|
||||||
|
static void frontend_save_callback(obs_data_t *save_data, bool saving,
|
||||||
|
void *priv)
|
||||||
|
{
|
||||||
|
struct lua_obs_callback *cb = priv;
|
||||||
|
lua_State *script = cb->script;
|
||||||
|
|
||||||
|
if (cb->base.removed) {
|
||||||
|
obs_frontend_remove_save_callback(frontend_save_callback, cb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock_callback();
|
||||||
|
|
||||||
|
ls_push_libobs_obj(obs_data_t, save_data, false);
|
||||||
|
lua_pushboolean(script, saving);
|
||||||
|
call_func(frontend_save_callback, 2, 0);
|
||||||
|
|
||||||
|
unlock_callback();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int remove_save_callback(lua_State *script)
|
||||||
|
{
|
||||||
|
if (!verify_args1(script, is_function))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
struct lua_obs_callback *cb = find_lua_obs_callback(script, 1);
|
||||||
|
if (cb) {
|
||||||
|
remove_lua_obs_callback(cb);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_save_callback_defer(void *cb)
|
||||||
|
{
|
||||||
|
obs_frontend_add_save_callback(frontend_save_callback, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int add_save_callback(lua_State *script)
|
||||||
|
{
|
||||||
|
if (!verify_args1(script, is_function))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
struct lua_obs_callback *cb = add_lua_obs_callback(script, 1);
|
||||||
|
defer_call_post(add_save_callback_defer, cb);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------- */
|
||||||
|
|
||||||
|
void add_lua_frontend_funcs(lua_State *script)
|
||||||
|
{
|
||||||
|
lua_getglobal(script, "obslua");
|
||||||
|
|
||||||
|
#define add_func(name) \
|
||||||
|
do { \
|
||||||
|
lua_pushstring(script, "obs_frontend_" #name); \
|
||||||
|
lua_pushcfunction(script, name); \
|
||||||
|
lua_rawset(script, -3); \
|
||||||
|
} while (false)
|
||||||
|
|
||||||
|
add_func(get_scene_names);
|
||||||
|
add_func(get_scenes);
|
||||||
|
add_func(get_current_scene);
|
||||||
|
add_func(set_current_scene);
|
||||||
|
add_func(get_transitions);
|
||||||
|
add_func(get_current_transition);
|
||||||
|
add_func(set_current_transition);
|
||||||
|
add_func(get_scene_collections);
|
||||||
|
add_func(get_current_scene_collection);
|
||||||
|
add_func(set_current_scene_collection);
|
||||||
|
add_func(get_profiles);
|
||||||
|
add_func(get_current_profile);
|
||||||
|
add_func(set_current_profile);
|
||||||
|
add_func(remove_event_callback);
|
||||||
|
add_func(add_event_callback);
|
||||||
|
add_func(remove_save_callback);
|
||||||
|
add_func(add_save_callback);
|
||||||
|
#undef add_func
|
||||||
|
|
||||||
|
lua_pop(script, 1);
|
||||||
|
}
|
762
deps/obs-scripting/obs-scripting-lua-source.c
vendored
Normal file
762
deps/obs-scripting/obs-scripting-lua-source.c
vendored
Normal file
@ -0,0 +1,762 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
Copyright (C) 2017 by Hugh Bailey <jim@obsproject.com>
|
||||||
|
|
||||||
|
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 <http://www.gnu.org/licenses/>.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "obs-scripting-lua.h"
|
||||||
|
#include "cstrcache.h"
|
||||||
|
|
||||||
|
#include <obs-module.h>
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
|
||||||
|
static inline const char *get_table_string_(lua_State *script, int idx,
|
||||||
|
const char *name, const char *func)
|
||||||
|
{
|
||||||
|
const char *str = "";
|
||||||
|
|
||||||
|
lua_pushstring(script, name);
|
||||||
|
lua_gettable(script, idx - 1);
|
||||||
|
if (!lua_isstring(script, -1))
|
||||||
|
warn("%s: no item '%s' of type %s", func, name, "string");
|
||||||
|
else
|
||||||
|
str = cstrcache_get(lua_tostring(script, -1));
|
||||||
|
lua_pop(script, 1);
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int get_table_int_(lua_State *script, int idx,
|
||||||
|
const char *name, const char *func)
|
||||||
|
{
|
||||||
|
int val = 0;
|
||||||
|
|
||||||
|
lua_pushstring(script, name);
|
||||||
|
lua_gettable(script, idx - 1);
|
||||||
|
val = (int)lua_tointeger(script, -1);
|
||||||
|
lua_pop(script, 1);
|
||||||
|
|
||||||
|
UNUSED_PARAMETER(func);
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void get_callback_from_table_(lua_State *script, int idx,
|
||||||
|
const char *name, int *p_reg_idx, const char *func)
|
||||||
|
{
|
||||||
|
*p_reg_idx = LUA_REFNIL;
|
||||||
|
|
||||||
|
lua_pushstring(script, name);
|
||||||
|
lua_gettable(script, idx - 1);
|
||||||
|
if (!lua_isfunction(script, -1)) {
|
||||||
|
if (!lua_isnil(script, -1)) {
|
||||||
|
warn("%s: item '%s' is not a function", func, name);
|
||||||
|
}
|
||||||
|
lua_pop(script, 1);
|
||||||
|
} else {
|
||||||
|
*p_reg_idx = luaL_ref(script, LUA_REGISTRYINDEX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define get_table_string(script, idx, name) \
|
||||||
|
get_table_string_(script, idx, name, __FUNCTION__)
|
||||||
|
#define get_table_int(script, idx, name) \
|
||||||
|
get_table_int_(script, idx, name, __FUNCTION__)
|
||||||
|
#define get_callback_from_table(script, idx, name, p_reg_idx) \
|
||||||
|
get_callback_from_table_(script, idx, name, p_reg_idx, __FUNCTION__)
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
swig_type_info *info = SWIG_TypeQuery(script, type);
|
||||||
|
if (info == NULL) {
|
||||||
|
warn("%s:%d: SWIG could not find type: %s%s%s",
|
||||||
|
func,
|
||||||
|
line,
|
||||||
|
id ? id : "",
|
||||||
|
id ? "::" : "",
|
||||||
|
type);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = SWIG_ConvertPtr(script, lua_idx, libobs_out, info, 0);
|
||||||
|
if (!SWIG_IsOK(ret)) {
|
||||||
|
warn("%s:%d: SWIG failed to convert lua object to obs "
|
||||||
|
"object: %s%s%s",
|
||||||
|
func,
|
||||||
|
line,
|
||||||
|
id ? id : "",
|
||||||
|
id ? "::" : "",
|
||||||
|
type);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ls_get_libobs_obj(type, lua_index, obs_obj) \
|
||||||
|
ls_get_libobs_obj_(ls->script, #type " *", lua_index, obs_obj, \
|
||||||
|
ls->id, __FUNCTION__, __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)
|
||||||
|
{
|
||||||
|
swig_type_info *info = SWIG_TypeQuery(script, type);
|
||||||
|
if (info == NULL) {
|
||||||
|
warn("%s:%d: SWIG could not find type: %s%s%s",
|
||||||
|
func,
|
||||||
|
line,
|
||||||
|
id ? id : "",
|
||||||
|
id ? "::" : "",
|
||||||
|
type);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SWIG_NewPointerObj(script, libobs_in, info, (int)ownership);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ls_push_libobs_obj(type, obs_obj, ownership) \
|
||||||
|
ls_push_libobs_obj_(ls->script, #type " *", obs_obj, ownership, \
|
||||||
|
ls->id, __FUNCTION__, __LINE__)
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
|
||||||
|
struct obs_lua_data;
|
||||||
|
|
||||||
|
struct obs_lua_source {
|
||||||
|
struct obs_lua_script *data;
|
||||||
|
|
||||||
|
lua_State * script;
|
||||||
|
const char *id;
|
||||||
|
const char *display_name;
|
||||||
|
int func_create;
|
||||||
|
int func_destroy;
|
||||||
|
int func_get_width;
|
||||||
|
int func_get_height;
|
||||||
|
int func_get_defaults;
|
||||||
|
int func_get_properties;
|
||||||
|
int func_update;
|
||||||
|
int func_activate;
|
||||||
|
int func_deactivate;
|
||||||
|
int func_show;
|
||||||
|
int func_hide;
|
||||||
|
int func_video_tick;
|
||||||
|
int func_video_render;
|
||||||
|
int func_save;
|
||||||
|
int func_load;
|
||||||
|
|
||||||
|
pthread_mutex_t definition_mutex;
|
||||||
|
struct obs_lua_data *first_source;
|
||||||
|
|
||||||
|
struct obs_lua_source *next;
|
||||||
|
struct obs_lua_source **p_prev_next;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern pthread_mutex_t lua_source_def_mutex;
|
||||||
|
struct obs_lua_source *first_source_def = NULL;
|
||||||
|
|
||||||
|
struct obs_lua_data {
|
||||||
|
obs_source_t * source;
|
||||||
|
struct obs_lua_source *ls;
|
||||||
|
int lua_data_ref;
|
||||||
|
|
||||||
|
struct obs_lua_data *next;
|
||||||
|
struct obs_lua_data **p_prev_next;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define call_func(name, args, rets) \
|
||||||
|
call_func_(ls->script, ls->func_ ## name, args, rets, #name, \
|
||||||
|
ls->display_name)
|
||||||
|
#define have_func(name) \
|
||||||
|
(ls->func_ ## name != LUA_REFNIL)
|
||||||
|
#define ls_push_data() \
|
||||||
|
lua_rawgeti(ls->script, LUA_REGISTRYINDEX, ld->lua_data_ref)
|
||||||
|
#define ls_pop(count) \
|
||||||
|
lua_pop(ls->script, count)
|
||||||
|
#define lock_script() \
|
||||||
|
struct obs_lua_script *__data = ls->data; \
|
||||||
|
struct obs_lua_script *__prev_script = current_lua_script; \
|
||||||
|
current_lua_script = __data; \
|
||||||
|
pthread_mutex_lock(&__data->mutex);
|
||||||
|
#define unlock_script() \
|
||||||
|
pthread_mutex_unlock(&__data->mutex); \
|
||||||
|
current_lua_script = __prev_script;
|
||||||
|
|
||||||
|
static const char *obs_lua_source_get_name(void *type_data)
|
||||||
|
{
|
||||||
|
struct obs_lua_source *ls = type_data;
|
||||||
|
return ls->display_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void *obs_lua_source_create(obs_data_t *settings, obs_source_t *source)
|
||||||
|
{
|
||||||
|
struct obs_lua_source *ls = obs_source_get_type_data(source);
|
||||||
|
struct obs_lua_data *data = NULL;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&ls->definition_mutex);
|
||||||
|
if (!ls->script)
|
||||||
|
goto fail;
|
||||||
|
if (!have_func(create))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
lock_script();
|
||||||
|
|
||||||
|
ls_push_libobs_obj(obs_data_t, settings, false);
|
||||||
|
ls_push_libobs_obj(obs_source_t, source, false);
|
||||||
|
call_func(create, 2, 1);
|
||||||
|
|
||||||
|
int lua_data_ref = luaL_ref(ls->script, LUA_REGISTRYINDEX);
|
||||||
|
if (lua_data_ref != LUA_REFNIL) {
|
||||||
|
data = bmalloc(sizeof(*data));
|
||||||
|
data->source = source;
|
||||||
|
data->ls = ls;
|
||||||
|
data->lua_data_ref = lua_data_ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
unlock_script();
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
struct obs_lua_data *next = ls->first_source;
|
||||||
|
data->next = next;
|
||||||
|
data->p_prev_next = &ls->first_source;
|
||||||
|
if (next) next->p_prev_next = &data->next;
|
||||||
|
ls->first_source = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
fail:
|
||||||
|
pthread_mutex_unlock(&ls->definition_mutex);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void call_destroy(struct obs_lua_data *ld)
|
||||||
|
{
|
||||||
|
struct obs_lua_source *ls = ld->ls;
|
||||||
|
|
||||||
|
ls_push_data();
|
||||||
|
call_func(destroy, 1, 0);
|
||||||
|
luaL_unref(ls->script, LUA_REGISTRYINDEX, ld->lua_data_ref);
|
||||||
|
ld->lua_data_ref = LUA_REFNIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void obs_lua_source_destroy(void *data)
|
||||||
|
{
|
||||||
|
struct obs_lua_data * ld = data;
|
||||||
|
struct obs_lua_source *ls = ld->ls;
|
||||||
|
struct obs_lua_data * next;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&ls->definition_mutex);
|
||||||
|
if (!ls->script)
|
||||||
|
goto fail;
|
||||||
|
if (!have_func(destroy))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
lock_script();
|
||||||
|
call_destroy(ld);
|
||||||
|
unlock_script();
|
||||||
|
|
||||||
|
fail:
|
||||||
|
next = ld->next;
|
||||||
|
*ld->p_prev_next = next;
|
||||||
|
if (next) next->p_prev_next = ld->p_prev_next;
|
||||||
|
|
||||||
|
bfree(data);
|
||||||
|
pthread_mutex_unlock(&ls->definition_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t obs_lua_source_get_width(void *data)
|
||||||
|
{
|
||||||
|
struct obs_lua_data * ld = data;
|
||||||
|
struct obs_lua_source *ls = ld->ls;
|
||||||
|
uint32_t width = 0;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&ls->definition_mutex);
|
||||||
|
if (!ls->script)
|
||||||
|
goto fail;
|
||||||
|
if (!have_func(get_width))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
lock_script();
|
||||||
|
|
||||||
|
ls_push_data();
|
||||||
|
if (call_func(get_width, 1, 1)) {
|
||||||
|
width = (uint32_t)lua_tointeger(ls->script, -1);
|
||||||
|
ls_pop(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
unlock_script();
|
||||||
|
|
||||||
|
fail:
|
||||||
|
pthread_mutex_unlock(&ls->definition_mutex);
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t obs_lua_source_get_height(void *data)
|
||||||
|
{
|
||||||
|
struct obs_lua_data * ld = data;
|
||||||
|
struct obs_lua_source *ls = ld->ls;
|
||||||
|
uint32_t height = 0;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&ls->definition_mutex);
|
||||||
|
if (!ls->script)
|
||||||
|
goto fail;
|
||||||
|
if (!have_func(get_height))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
lock_script();
|
||||||
|
|
||||||
|
ls_push_data();
|
||||||
|
if (call_func(get_height, 1, 1)) {
|
||||||
|
height = (uint32_t)lua_tointeger(ls->script, -1);
|
||||||
|
ls_pop(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
unlock_script();
|
||||||
|
|
||||||
|
fail:
|
||||||
|
pthread_mutex_unlock(&ls->definition_mutex);
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void obs_lua_source_get_defaults(void *type_data, obs_data_t *settings)
|
||||||
|
{
|
||||||
|
struct obs_lua_source *ls = type_data;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&ls->definition_mutex);
|
||||||
|
if (!ls->script)
|
||||||
|
goto fail;
|
||||||
|
if (!have_func(get_defaults))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
lock_script();
|
||||||
|
|
||||||
|
ls_push_libobs_obj(obs_data_t, settings, false);
|
||||||
|
call_func(get_defaults, 1, 0);
|
||||||
|
|
||||||
|
unlock_script();
|
||||||
|
|
||||||
|
fail:
|
||||||
|
pthread_mutex_unlock(&ls->definition_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static obs_properties_t *obs_lua_source_get_properties(void *data)
|
||||||
|
{
|
||||||
|
struct obs_lua_data * ld = data;
|
||||||
|
struct obs_lua_source *ls = ld->ls;
|
||||||
|
obs_properties_t * props = NULL;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&ls->definition_mutex);
|
||||||
|
if (!ls->script)
|
||||||
|
goto fail;
|
||||||
|
if (!have_func(get_properties))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
lock_script();
|
||||||
|
|
||||||
|
ls_push_data();
|
||||||
|
if (call_func(get_properties, 1, 1)) {
|
||||||
|
ls_get_libobs_obj(obs_properties_t, -1, &props);
|
||||||
|
ls_pop(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
unlock_script();
|
||||||
|
|
||||||
|
fail:
|
||||||
|
pthread_mutex_unlock(&ls->definition_mutex);
|
||||||
|
return props;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void obs_lua_source_update(void *data, obs_data_t *settings)
|
||||||
|
{
|
||||||
|
struct obs_lua_data * ld = data;
|
||||||
|
struct obs_lua_source *ls = ld->ls;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&ls->definition_mutex);
|
||||||
|
if (!ls->script)
|
||||||
|
goto fail;
|
||||||
|
if (!have_func(update))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
lock_script();
|
||||||
|
|
||||||
|
ls_push_data();
|
||||||
|
ls_push_libobs_obj(obs_data_t, settings, false);
|
||||||
|
call_func(update, 2, 0);
|
||||||
|
|
||||||
|
unlock_script();
|
||||||
|
|
||||||
|
fail:
|
||||||
|
pthread_mutex_unlock(&ls->definition_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEFINE_VOID_DATA_CALLBACK(name) \
|
||||||
|
static void obs_lua_source_ ## name(void *data) \
|
||||||
|
{ \
|
||||||
|
struct obs_lua_data * ld = data; \
|
||||||
|
struct obs_lua_source *ls = ld->ls; \
|
||||||
|
if (!have_func(name)) \
|
||||||
|
return; \
|
||||||
|
lock_script(); \
|
||||||
|
ls_push_data(); \
|
||||||
|
call_func(name, 1, 0); \
|
||||||
|
unlock_script(); \
|
||||||
|
}
|
||||||
|
DEFINE_VOID_DATA_CALLBACK(activate)
|
||||||
|
DEFINE_VOID_DATA_CALLBACK(deactivate)
|
||||||
|
DEFINE_VOID_DATA_CALLBACK(show)
|
||||||
|
DEFINE_VOID_DATA_CALLBACK(hide)
|
||||||
|
#undef DEFINE_VOID_DATA_CALLBACK
|
||||||
|
|
||||||
|
static void obs_lua_source_video_tick(void *data, float seconds)
|
||||||
|
{
|
||||||
|
struct obs_lua_data * ld = data;
|
||||||
|
struct obs_lua_source *ls = ld->ls;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&ls->definition_mutex);
|
||||||
|
if (!ls->script)
|
||||||
|
goto fail;
|
||||||
|
if (!have_func(video_tick))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
lock_script();
|
||||||
|
|
||||||
|
ls_push_data();
|
||||||
|
lua_pushnumber(ls->script, (double)seconds);
|
||||||
|
call_func(video_tick, 2, 0);
|
||||||
|
|
||||||
|
unlock_script();
|
||||||
|
|
||||||
|
fail:
|
||||||
|
pthread_mutex_unlock(&ls->definition_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void obs_lua_source_video_render(void *data, gs_effect_t *effect)
|
||||||
|
{
|
||||||
|
struct obs_lua_data * ld = data;
|
||||||
|
struct obs_lua_source *ls = ld->ls;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&ls->definition_mutex);
|
||||||
|
if (!ls->script)
|
||||||
|
goto fail;
|
||||||
|
if (!have_func(video_render))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
lock_script();
|
||||||
|
|
||||||
|
ls_push_data();
|
||||||
|
ls_push_libobs_obj(gs_effect_t, effect, false);
|
||||||
|
call_func(video_render, 2, 0);
|
||||||
|
|
||||||
|
unlock_script();
|
||||||
|
|
||||||
|
fail:
|
||||||
|
pthread_mutex_unlock(&ls->definition_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void obs_lua_source_save(void *data, obs_data_t *settings)
|
||||||
|
{
|
||||||
|
struct obs_lua_data * ld = data;
|
||||||
|
struct obs_lua_source *ls = ld->ls;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&ls->definition_mutex);
|
||||||
|
if (!ls->script)
|
||||||
|
goto fail;
|
||||||
|
if (!have_func(save))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
lock_script();
|
||||||
|
|
||||||
|
ls_push_data();
|
||||||
|
ls_push_libobs_obj(obs_data_t, settings, false);
|
||||||
|
call_func(save, 2, 0);
|
||||||
|
|
||||||
|
unlock_script();
|
||||||
|
|
||||||
|
fail:
|
||||||
|
pthread_mutex_unlock(&ls->definition_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void obs_lua_source_load(void *data, obs_data_t *settings)
|
||||||
|
{
|
||||||
|
struct obs_lua_data * ld = data;
|
||||||
|
struct obs_lua_source *ls = ld->ls;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&ls->definition_mutex);
|
||||||
|
if (!ls->script)
|
||||||
|
goto fail;
|
||||||
|
if (!have_func(load))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
lock_script();
|
||||||
|
|
||||||
|
ls_push_data();
|
||||||
|
ls_push_libobs_obj(obs_data_t, settings, false);
|
||||||
|
call_func(load, 2, 0);
|
||||||
|
|
||||||
|
unlock_script();
|
||||||
|
|
||||||
|
fail:
|
||||||
|
pthread_mutex_unlock(&ls->definition_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void source_type_unload(struct obs_lua_source *ls)
|
||||||
|
{
|
||||||
|
#define unref(name) \
|
||||||
|
luaL_unref(ls->script, LUA_REGISTRYINDEX, name); \
|
||||||
|
name = LUA_REFNIL
|
||||||
|
|
||||||
|
unref(ls->func_create);
|
||||||
|
unref(ls->func_destroy);
|
||||||
|
unref(ls->func_get_width);
|
||||||
|
unref(ls->func_get_height);
|
||||||
|
unref(ls->func_get_defaults);
|
||||||
|
unref(ls->func_get_properties);
|
||||||
|
unref(ls->func_update);
|
||||||
|
unref(ls->func_activate);
|
||||||
|
unref(ls->func_deactivate);
|
||||||
|
unref(ls->func_show);
|
||||||
|
unref(ls->func_hide);
|
||||||
|
unref(ls->func_video_tick);
|
||||||
|
unref(ls->func_video_render);
|
||||||
|
unref(ls->func_save);
|
||||||
|
unref(ls->func_load);
|
||||||
|
#undef unref
|
||||||
|
}
|
||||||
|
|
||||||
|
static void obs_lua_source_free_type_data(void *type_data)
|
||||||
|
{
|
||||||
|
struct obs_lua_source *ls = type_data;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&ls->definition_mutex);
|
||||||
|
|
||||||
|
if (ls->script) {
|
||||||
|
lock_script();
|
||||||
|
source_type_unload(ls);
|
||||||
|
unlock_script();
|
||||||
|
ls->script = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&ls->definition_mutex);
|
||||||
|
pthread_mutex_destroy(&ls->definition_mutex);
|
||||||
|
bfree(ls);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT void obs_enable_source_type(const char *name, bool enable);
|
||||||
|
|
||||||
|
static inline struct obs_lua_source *find_existing(const char *id)
|
||||||
|
{
|
||||||
|
struct obs_lua_source *existing = NULL;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&lua_source_def_mutex);
|
||||||
|
struct obs_lua_source *ls = first_source_def;
|
||||||
|
while (ls) {
|
||||||
|
/* can compare pointers here due to string table */
|
||||||
|
if (ls->id == id) {
|
||||||
|
existing = ls;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ls = ls->next;
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&lua_source_def_mutex);
|
||||||
|
|
||||||
|
return existing;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int obs_lua_register_source(lua_State *script)
|
||||||
|
{
|
||||||
|
struct obs_lua_source ls = {0};
|
||||||
|
struct obs_lua_source *existing = NULL;
|
||||||
|
struct obs_lua_source *v = NULL;
|
||||||
|
struct obs_source_info info = {0};
|
||||||
|
const char *id;
|
||||||
|
|
||||||
|
if (!verify_args1(script, is_table))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
id = get_table_string(script, -1, "id");
|
||||||
|
if (!id || !*id)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
/* redefinition */
|
||||||
|
existing = find_existing(id);
|
||||||
|
if (existing) {
|
||||||
|
if (existing->script) {
|
||||||
|
existing = NULL;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_lock(&existing->definition_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
v = existing ? existing : &ls;
|
||||||
|
|
||||||
|
v->script = script;
|
||||||
|
v->id = id;
|
||||||
|
|
||||||
|
info.id = v->id;
|
||||||
|
info.type = (enum obs_source_type)get_table_int(script, -1, "type");
|
||||||
|
|
||||||
|
info.output_flags = get_table_int(script, -1, "output_flags");
|
||||||
|
|
||||||
|
lua_pushstring(script, "get_name");
|
||||||
|
lua_gettable(script, -2);
|
||||||
|
if (lua_pcall(script, 0, 1, 0) == 0) {
|
||||||
|
v->display_name = cstrcache_get(lua_tostring(script, -1));
|
||||||
|
lua_pop(script, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!v->display_name ||
|
||||||
|
!*v->display_name ||
|
||||||
|
!*info.id ||
|
||||||
|
!info.output_flags)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
#define get_callback(val) \
|
||||||
|
do { \
|
||||||
|
get_callback_from_table(script, -1, #val, &v->func_ ## val); \
|
||||||
|
info.val = obs_lua_source_ ## val; \
|
||||||
|
} while (false)
|
||||||
|
|
||||||
|
get_callback(create);
|
||||||
|
get_callback(destroy);
|
||||||
|
get_callback(get_width);
|
||||||
|
get_callback(get_height);
|
||||||
|
get_callback(get_properties);
|
||||||
|
get_callback(update);
|
||||||
|
get_callback(activate);
|
||||||
|
get_callback(deactivate);
|
||||||
|
get_callback(show);
|
||||||
|
get_callback(hide);
|
||||||
|
get_callback(video_tick);
|
||||||
|
get_callback(video_render);
|
||||||
|
get_callback(save);
|
||||||
|
get_callback(load);
|
||||||
|
#undef get_callback
|
||||||
|
|
||||||
|
get_callback_from_table(script, -1, "get_defaults",
|
||||||
|
&v->func_get_defaults);
|
||||||
|
|
||||||
|
if (!existing) {
|
||||||
|
ls.data = current_lua_script;
|
||||||
|
|
||||||
|
pthread_mutex_init(&ls.definition_mutex, NULL);
|
||||||
|
info.type_data = bmemdup(&ls, sizeof(ls));
|
||||||
|
info.free_type_data = obs_lua_source_free_type_data;
|
||||||
|
info.get_name = obs_lua_source_get_name;
|
||||||
|
info.get_defaults2 = obs_lua_source_get_defaults;
|
||||||
|
obs_register_source(&info);
|
||||||
|
|
||||||
|
pthread_mutex_lock(&lua_source_def_mutex);
|
||||||
|
v = info.type_data;
|
||||||
|
|
||||||
|
struct obs_lua_source *next = first_source_def;
|
||||||
|
v->next = next;
|
||||||
|
if (next) next->p_prev_next = &v->next;
|
||||||
|
v->p_prev_next = &first_source_def;
|
||||||
|
first_source_def = v;
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&lua_source_def_mutex);
|
||||||
|
} else {
|
||||||
|
existing->script = script;
|
||||||
|
existing->data = current_lua_script;
|
||||||
|
obs_enable_source_type(id, true);
|
||||||
|
|
||||||
|
struct obs_lua_data *ld = v->first_source;
|
||||||
|
while (ld) {
|
||||||
|
struct obs_lua_source *ls = v;
|
||||||
|
|
||||||
|
if (have_func(create)) {
|
||||||
|
obs_source_t *source = ld->source;
|
||||||
|
obs_data_t *settings = obs_source_get_settings(
|
||||||
|
source);
|
||||||
|
|
||||||
|
ls_push_libobs_obj(obs_data_t, settings, false);
|
||||||
|
ls_push_libobs_obj(obs_source_t, source, false);
|
||||||
|
call_func(create, 2, 1);
|
||||||
|
|
||||||
|
ld->lua_data_ref = luaL_ref(ls->script,
|
||||||
|
LUA_REGISTRYINDEX);
|
||||||
|
obs_data_release(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
ld = ld->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (existing) {
|
||||||
|
pthread_mutex_unlock(&existing->definition_mutex);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========================================================================= */
|
||||||
|
|
||||||
|
void add_lua_source_functions(lua_State *script)
|
||||||
|
{
|
||||||
|
lua_getglobal(script, "obslua");
|
||||||
|
|
||||||
|
lua_pushstring(script, "obs_register_source");
|
||||||
|
lua_pushcfunction(script, obs_lua_register_source);
|
||||||
|
lua_rawset(script, -3);
|
||||||
|
|
||||||
|
lua_pop(script, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void undef_source_type(struct obs_lua_script *data,
|
||||||
|
struct obs_lua_source *ls)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&ls->definition_mutex);
|
||||||
|
pthread_mutex_lock(&data->mutex);
|
||||||
|
|
||||||
|
obs_enable_source_type(ls->id, false);
|
||||||
|
|
||||||
|
struct obs_lua_data *ld = ls->first_source;
|
||||||
|
while (ld) {
|
||||||
|
call_destroy(ld);
|
||||||
|
ld = ld->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
source_type_unload(ls);
|
||||||
|
ls->script = NULL;
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&data->mutex);
|
||||||
|
pthread_mutex_unlock(&ls->definition_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void undef_lua_script_sources(struct obs_lua_script *data)
|
||||||
|
{
|
||||||
|
pthread_mutex_lock(&lua_source_def_mutex);
|
||||||
|
|
||||||
|
struct obs_lua_source *def = first_source_def;
|
||||||
|
while (def) {
|
||||||
|
if (def->script == data->script)
|
||||||
|
undef_source_type(data, def);
|
||||||
|
def = def->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&lua_source_def_mutex);
|
||||||
|
}
|
1287
deps/obs-scripting/obs-scripting-lua.c
vendored
Normal file
1287
deps/obs-scripting/obs-scripting-lua.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
262
deps/obs-scripting/obs-scripting-lua.h
vendored
Normal file
262
deps/obs-scripting/obs-scripting-lua.h
vendored
Normal file
@ -0,0 +1,262 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
Copyright (C) 2017 by Hugh Bailey <jim@obsproject.com>
|
||||||
|
|
||||||
|
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 <http://www.gnu.org/licenses/>.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/* ---------------------------- */
|
||||||
|
|
||||||
|
#include <lua.h>
|
||||||
|
#include <lualib.h>
|
||||||
|
#include <lauxlib.h>
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#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 <util/threading.h>
|
||||||
|
#include <util/base.h>
|
||||||
|
#include <util/bmem.h>
|
||||||
|
|
||||||
|
#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);
|
361
deps/obs-scripting/obs-scripting-python-frontend.c
vendored
Normal file
361
deps/obs-scripting/obs-scripting-python-frontend.c
vendored
Normal file
@ -0,0 +1,361 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
Copyright (C) 2017 by Hugh Bailey <jim@obsproject.com>
|
||||||
|
|
||||||
|
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 <http://www.gnu.org/licenses/>.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include <obs-module.h>
|
||||||
|
#include <obs-frontend-api.h>
|
||||||
|
|
||||||
|
#include "obs-scripting-python.h"
|
||||||
|
|
||||||
|
#define libobs_to_py(type, obs_obj, ownership, py_obj) \
|
||||||
|
libobs_to_py_(#type " *", obs_obj, ownership, py_obj, \
|
||||||
|
NULL, __func__, __LINE__)
|
||||||
|
#define py_to_libobs(type, py_obj, libobs_out) \
|
||||||
|
py_to_libobs_(#type " *", py_obj, libobs_out, \
|
||||||
|
NULL, __func__, __LINE__)
|
||||||
|
|
||||||
|
/* ----------------------------------- */
|
||||||
|
|
||||||
|
static PyObject *get_scene_names(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
char **names = obs_frontend_get_scene_names();
|
||||||
|
char **name = names;
|
||||||
|
|
||||||
|
PyObject *list = PyList_New(0);
|
||||||
|
|
||||||
|
while (name && *name) {
|
||||||
|
PyObject *py_name = PyUnicode_FromString(*name);
|
||||||
|
if (py_name) {
|
||||||
|
PyList_Append(list, py_name);
|
||||||
|
Py_DECREF(py_name);
|
||||||
|
}
|
||||||
|
name++;
|
||||||
|
}
|
||||||
|
|
||||||
|
UNUSED_PARAMETER(self);
|
||||||
|
UNUSED_PARAMETER(args);
|
||||||
|
|
||||||
|
bfree(names);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *get_scenes(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
struct obs_frontend_source_list list = {0};
|
||||||
|
obs_frontend_get_scenes(&list);
|
||||||
|
|
||||||
|
PyObject *ret = PyList_New(0);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < list.sources.num; i++) {
|
||||||
|
obs_source_t *source = list.sources.array[i];
|
||||||
|
PyObject *py_source;
|
||||||
|
|
||||||
|
if (libobs_to_py(obs_source_t, source, false, &py_source)) {
|
||||||
|
PyList_Append(ret, py_source);
|
||||||
|
Py_DECREF(py_source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UNUSED_PARAMETER(self);
|
||||||
|
UNUSED_PARAMETER(args);
|
||||||
|
|
||||||
|
da_free(list.sources);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *get_current_scene(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
obs_source_t *source = obs_frontend_get_current_scene();
|
||||||
|
|
||||||
|
PyObject *py_source;
|
||||||
|
if (!libobs_to_py(obs_source_t, source, false, &py_source)) {
|
||||||
|
obs_source_release(source);
|
||||||
|
return python_none();
|
||||||
|
}
|
||||||
|
|
||||||
|
UNUSED_PARAMETER(self);
|
||||||
|
UNUSED_PARAMETER(args);
|
||||||
|
return py_source;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *set_current_scene(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
PyObject *py_source;
|
||||||
|
obs_source_t *source = NULL;
|
||||||
|
|
||||||
|
if (!parse_args(args, "O", &py_source))
|
||||||
|
return python_none();
|
||||||
|
if (!py_to_libobs(obs_source_t, py_source, &source))
|
||||||
|
return python_none();
|
||||||
|
|
||||||
|
UNUSED_PARAMETER(self);
|
||||||
|
|
||||||
|
obs_frontend_set_current_scene(source);
|
||||||
|
return python_none();
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *get_transitions(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
struct obs_frontend_source_list list = {0};
|
||||||
|
obs_frontend_get_transitions(&list);
|
||||||
|
|
||||||
|
PyObject *ret = PyList_New(0);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < list.sources.num; i++) {
|
||||||
|
obs_source_t *source = list.sources.array[i];
|
||||||
|
PyObject *py_source;
|
||||||
|
|
||||||
|
if (libobs_to_py(obs_source_t, source, false, &py_source)) {
|
||||||
|
PyList_Append(ret, py_source);
|
||||||
|
Py_DECREF(py_source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UNUSED_PARAMETER(self);
|
||||||
|
UNUSED_PARAMETER(args);
|
||||||
|
|
||||||
|
da_free(list.sources);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *get_current_transition(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
obs_source_t *source = obs_frontend_get_current_transition();
|
||||||
|
|
||||||
|
PyObject *py_source;
|
||||||
|
if (!libobs_to_py(obs_source_t, source, false, &py_source)) {
|
||||||
|
obs_source_release(source);
|
||||||
|
return python_none();
|
||||||
|
}
|
||||||
|
|
||||||
|
UNUSED_PARAMETER(self);
|
||||||
|
UNUSED_PARAMETER(args);
|
||||||
|
return py_source;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *set_current_transition(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
PyObject *py_source;
|
||||||
|
obs_source_t *source = NULL;
|
||||||
|
|
||||||
|
if (!parse_args(args, "O", &py_source))
|
||||||
|
return python_none();
|
||||||
|
if (!py_to_libobs(obs_source_t, py_source, &source))
|
||||||
|
return python_none();
|
||||||
|
|
||||||
|
UNUSED_PARAMETER(self);
|
||||||
|
|
||||||
|
obs_frontend_set_current_transition(source);
|
||||||
|
return python_none();
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *get_scene_collections(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
char **names = obs_frontend_get_scene_collections();
|
||||||
|
char **name = names;
|
||||||
|
|
||||||
|
PyObject *list = PyList_New(0);
|
||||||
|
|
||||||
|
while (name && *name) {
|
||||||
|
PyObject *py_name = PyUnicode_FromString(*name);
|
||||||
|
if (py_name) {
|
||||||
|
PyList_Append(list, py_name);
|
||||||
|
Py_DECREF(py_name);
|
||||||
|
}
|
||||||
|
name++;
|
||||||
|
}
|
||||||
|
|
||||||
|
UNUSED_PARAMETER(self);
|
||||||
|
UNUSED_PARAMETER(args);
|
||||||
|
|
||||||
|
bfree(names);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *get_current_scene_collection(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
char *name = obs_frontend_get_current_scene_collection();
|
||||||
|
PyObject *ret = PyUnicode_FromString(name);
|
||||||
|
bfree(name);
|
||||||
|
|
||||||
|
UNUSED_PARAMETER(self);
|
||||||
|
UNUSED_PARAMETER(args);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *set_current_scene_collection(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
if (!parse_args(args, "s", &name))
|
||||||
|
return python_none();
|
||||||
|
|
||||||
|
UNUSED_PARAMETER(self);
|
||||||
|
|
||||||
|
obs_frontend_set_current_scene_collection(name);
|
||||||
|
return python_none();
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *get_profiles(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
char **names = obs_frontend_get_profiles();
|
||||||
|
char **name = names;
|
||||||
|
|
||||||
|
PyObject *list = PyList_New(0);
|
||||||
|
|
||||||
|
while (name && *name) {
|
||||||
|
PyObject *py_name = PyUnicode_FromString(*name);
|
||||||
|
if (py_name) {
|
||||||
|
PyList_Append(list, py_name);
|
||||||
|
Py_DECREF(py_name);
|
||||||
|
}
|
||||||
|
name++;
|
||||||
|
}
|
||||||
|
|
||||||
|
UNUSED_PARAMETER(self);
|
||||||
|
UNUSED_PARAMETER(args);
|
||||||
|
|
||||||
|
bfree(names);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *get_current_profile(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
char *name = obs_frontend_get_current_profile();
|
||||||
|
PyObject *ret = PyUnicode_FromString(name);
|
||||||
|
bfree(name);
|
||||||
|
|
||||||
|
UNUSED_PARAMETER(self);
|
||||||
|
UNUSED_PARAMETER(args);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *set_current_profile(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
const char *name;
|
||||||
|
if (!parse_args(args, "s", &name))
|
||||||
|
return python_none();
|
||||||
|
|
||||||
|
UNUSED_PARAMETER(self);
|
||||||
|
|
||||||
|
obs_frontend_set_current_profile(name);
|
||||||
|
return python_none();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------- */
|
||||||
|
|
||||||
|
static void frontend_save_callback(obs_data_t *save_data, bool saving,
|
||||||
|
void *priv)
|
||||||
|
{
|
||||||
|
struct python_obs_callback *cb = priv;
|
||||||
|
|
||||||
|
if (cb->base.removed) {
|
||||||
|
obs_frontend_remove_save_callback(frontend_save_callback, cb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock_python();
|
||||||
|
|
||||||
|
PyObject *py_save_data;
|
||||||
|
|
||||||
|
if (libobs_to_py(obs_data_t, save_data, false, &py_save_data)) {
|
||||||
|
PyObject *args = Py_BuildValue("(Op)", py_save_data, saving);
|
||||||
|
|
||||||
|
struct python_obs_callback *last_cb = cur_python_cb;
|
||||||
|
cur_python_cb = cb;
|
||||||
|
cur_python_script = (struct obs_python_script *)cb->base.script;
|
||||||
|
|
||||||
|
PyObject *py_ret = PyObject_CallObject(cb->func, args);
|
||||||
|
Py_XDECREF(py_ret);
|
||||||
|
py_error();
|
||||||
|
|
||||||
|
cur_python_script = NULL;
|
||||||
|
cur_python_cb = last_cb;
|
||||||
|
|
||||||
|
Py_XDECREF(args);
|
||||||
|
Py_XDECREF(py_save_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
unlock_python();
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *remove_save_callback(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
struct obs_python_script *script = cur_python_script;
|
||||||
|
PyObject *py_cb = NULL;
|
||||||
|
|
||||||
|
UNUSED_PARAMETER(self);
|
||||||
|
|
||||||
|
if (!parse_args(args, "O", &py_cb))
|
||||||
|
return python_none();
|
||||||
|
if (!py_cb || !PyFunction_Check(py_cb))
|
||||||
|
return python_none();
|
||||||
|
|
||||||
|
struct python_obs_callback *cb = find_python_obs_callback(script, py_cb);
|
||||||
|
if (cb) remove_python_obs_callback(cb);
|
||||||
|
return python_none();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_save_callback_defer(void *cb)
|
||||||
|
{
|
||||||
|
obs_frontend_add_save_callback(frontend_save_callback, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *add_save_callback(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
struct obs_python_script *script = cur_python_script;
|
||||||
|
PyObject *py_cb = NULL;
|
||||||
|
|
||||||
|
UNUSED_PARAMETER(self);
|
||||||
|
|
||||||
|
if (!parse_args(args, "O", &py_cb))
|
||||||
|
return python_none();
|
||||||
|
if (!py_cb || !PyFunction_Check(py_cb))
|
||||||
|
return python_none();
|
||||||
|
|
||||||
|
struct python_obs_callback *cb = add_python_obs_callback(script, py_cb);
|
||||||
|
defer_call_post(add_save_callback_defer, cb);
|
||||||
|
return python_none();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------- */
|
||||||
|
|
||||||
|
void add_python_frontend_funcs(PyObject *module)
|
||||||
|
{
|
||||||
|
static PyMethodDef funcs[] = {
|
||||||
|
#define DEF_FUNC(c) {"obs_frontend_" #c, c, METH_VARARGS, NULL}
|
||||||
|
|
||||||
|
DEF_FUNC(get_scene_names),
|
||||||
|
DEF_FUNC(get_scenes),
|
||||||
|
DEF_FUNC(get_current_scene),
|
||||||
|
DEF_FUNC(set_current_scene),
|
||||||
|
DEF_FUNC(get_transitions),
|
||||||
|
DEF_FUNC(get_current_transition),
|
||||||
|
DEF_FUNC(set_current_transition),
|
||||||
|
DEF_FUNC(get_scene_collections),
|
||||||
|
DEF_FUNC(get_current_scene_collection),
|
||||||
|
DEF_FUNC(set_current_scene_collection),
|
||||||
|
DEF_FUNC(get_profiles),
|
||||||
|
DEF_FUNC(get_current_profile),
|
||||||
|
DEF_FUNC(set_current_profile),
|
||||||
|
DEF_FUNC(remove_save_callback),
|
||||||
|
DEF_FUNC(add_save_callback),
|
||||||
|
|
||||||
|
#undef DEF_FUNC
|
||||||
|
{0}
|
||||||
|
};
|
||||||
|
|
||||||
|
add_functions_to_py_module(module, funcs);
|
||||||
|
}
|
149
deps/obs-scripting/obs-scripting-python-import.c
vendored
Normal file
149
deps/obs-scripting/obs-scripting-python-import.c
vendored
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
Copyright (C) 2017 by Hugh Bailey <jim@obsproject.com>
|
||||||
|
|
||||||
|
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 <http://www.gnu.org/licenses/>.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include <util/dstr.h>
|
||||||
|
#include <util/platform.h>
|
||||||
|
|
||||||
|
#define NO_REDEFS
|
||||||
|
#include "obs-scripting-python-import.h"
|
||||||
|
#include "obs-scripting-config.h"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(disable : 4152)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define SO_EXT ".dll"
|
||||||
|
#elif __APPLE__
|
||||||
|
#define SO_EXT ".dylib"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool import_python(const char *python_path)
|
||||||
|
{
|
||||||
|
struct dstr lib_path;
|
||||||
|
bool success = false;
|
||||||
|
void *lib;
|
||||||
|
|
||||||
|
if (!python_path)
|
||||||
|
python_path = "";
|
||||||
|
|
||||||
|
dstr_init_copy(&lib_path, python_path);
|
||||||
|
dstr_replace(&lib_path, "\\", "/");
|
||||||
|
if (!dstr_is_empty(&lib_path)) {
|
||||||
|
dstr_cat(&lib_path, "/");
|
||||||
|
}
|
||||||
|
dstr_cat(&lib_path, PYTHON_LIB SO_EXT);
|
||||||
|
|
||||||
|
lib = os_dlopen(lib_path.array);
|
||||||
|
if (!lib) {
|
||||||
|
blog(LOG_WARNING, "[Python] Could not load library: %s",
|
||||||
|
lib_path.array);
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define IMPORT_FUNC(x) \
|
||||||
|
do { \
|
||||||
|
Import_##x = os_dlsym(lib, #x); \
|
||||||
|
if (!Import_##x) { \
|
||||||
|
blog(LOG_WARNING, "[Python] Failed to import: %s", \
|
||||||
|
#x); \
|
||||||
|
goto fail; \
|
||||||
|
} \
|
||||||
|
} while (false)
|
||||||
|
|
||||||
|
IMPORT_FUNC(PyType_Ready);
|
||||||
|
IMPORT_FUNC(PyObject_GenericGetAttr);
|
||||||
|
IMPORT_FUNC(PyObject_IsTrue);
|
||||||
|
IMPORT_FUNC(Py_DecRef);
|
||||||
|
IMPORT_FUNC(PyObject_Malloc);
|
||||||
|
IMPORT_FUNC(PyObject_Free);
|
||||||
|
IMPORT_FUNC(PyObject_Init);
|
||||||
|
IMPORT_FUNC(PyUnicode_FromFormat);
|
||||||
|
IMPORT_FUNC(PyUnicode_Concat);
|
||||||
|
IMPORT_FUNC(PyLong_FromVoidPtr);
|
||||||
|
IMPORT_FUNC(PyBool_FromLong);
|
||||||
|
IMPORT_FUNC(PyGILState_Ensure);
|
||||||
|
IMPORT_FUNC(PyGILState_GetThisThreadState);
|
||||||
|
IMPORT_FUNC(PyErr_SetString);
|
||||||
|
IMPORT_FUNC(PyErr_Occurred);
|
||||||
|
IMPORT_FUNC(PyErr_Fetch);
|
||||||
|
IMPORT_FUNC(PyErr_Restore);
|
||||||
|
IMPORT_FUNC(PyErr_WriteUnraisable);
|
||||||
|
IMPORT_FUNC(PyArg_UnpackTuple);
|
||||||
|
IMPORT_FUNC(Py_BuildValue);
|
||||||
|
IMPORT_FUNC(PyRun_SimpleStringFlags);
|
||||||
|
IMPORT_FUNC(PyErr_Print);
|
||||||
|
IMPORT_FUNC(Py_SetPythonHome);
|
||||||
|
IMPORT_FUNC(Py_Initialize);
|
||||||
|
IMPORT_FUNC(Py_Finalize);
|
||||||
|
IMPORT_FUNC(Py_IsInitialized);
|
||||||
|
IMPORT_FUNC(PyEval_InitThreads);
|
||||||
|
IMPORT_FUNC(PyEval_ThreadsInitialized);
|
||||||
|
IMPORT_FUNC(PyEval_ReleaseThread);
|
||||||
|
IMPORT_FUNC(PySys_SetArgv);
|
||||||
|
IMPORT_FUNC(PyImport_ImportModule);
|
||||||
|
IMPORT_FUNC(PyObject_CallFunctionObjArgs);
|
||||||
|
IMPORT_FUNC(_Py_NotImplementedStruct);
|
||||||
|
IMPORT_FUNC(PyExc_TypeError);
|
||||||
|
IMPORT_FUNC(PyExc_RuntimeError);
|
||||||
|
IMPORT_FUNC(PyObject_GetAttr);
|
||||||
|
IMPORT_FUNC(PyUnicode_FromString);
|
||||||
|
IMPORT_FUNC(PyDict_GetItemString);
|
||||||
|
IMPORT_FUNC(PyDict_SetItemString);
|
||||||
|
IMPORT_FUNC(PyCFunction_NewEx);
|
||||||
|
IMPORT_FUNC(PyModule_GetDict);
|
||||||
|
IMPORT_FUNC(PyModule_GetNameObject);
|
||||||
|
IMPORT_FUNC(PyModule_AddObject);
|
||||||
|
IMPORT_FUNC(PyModule_AddStringConstant);
|
||||||
|
IMPORT_FUNC(PyImport_Import);
|
||||||
|
IMPORT_FUNC(PyObject_CallObject);
|
||||||
|
IMPORT_FUNC(_Py_FalseStruct);
|
||||||
|
IMPORT_FUNC(_Py_TrueStruct);
|
||||||
|
IMPORT_FUNC(PyGILState_Release);
|
||||||
|
IMPORT_FUNC(PyList_Append);
|
||||||
|
IMPORT_FUNC(PySys_GetObject);
|
||||||
|
IMPORT_FUNC(PyImport_ReloadModule);
|
||||||
|
IMPORT_FUNC(PyObject_GetAttrString);
|
||||||
|
IMPORT_FUNC(PyCapsule_New);
|
||||||
|
IMPORT_FUNC(PyCapsule_GetPointer);
|
||||||
|
IMPORT_FUNC(PyArg_ParseTuple);
|
||||||
|
IMPORT_FUNC(PyFunction_Type);
|
||||||
|
IMPORT_FUNC(PyObject_SetAttr);
|
||||||
|
IMPORT_FUNC(_PyObject_New);
|
||||||
|
IMPORT_FUNC(PyCapsule_Import);
|
||||||
|
IMPORT_FUNC(PyErr_Clear);
|
||||||
|
IMPORT_FUNC(PyObject_Call);
|
||||||
|
IMPORT_FUNC(PyList_New);
|
||||||
|
IMPORT_FUNC(PyList_Size);
|
||||||
|
IMPORT_FUNC(PyList_GetItem);
|
||||||
|
IMPORT_FUNC(PyUnicode_AsUTF8String);
|
||||||
|
IMPORT_FUNC(PyLong_FromUnsignedLongLong);
|
||||||
|
IMPORT_FUNC(PyArg_VaParse);
|
||||||
|
IMPORT_FUNC(_Py_NoneStruct);
|
||||||
|
|
||||||
|
#undef IMPORT_FUNC
|
||||||
|
|
||||||
|
success = true;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
if (!success && lib)
|
||||||
|
os_dlclose(lib);
|
||||||
|
|
||||||
|
dstr_free(&lib_path);
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
198
deps/obs-scripting/obs-scripting-python-import.h
vendored
Normal file
198
deps/obs-scripting/obs-scripting-python-import.h
vendored
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
Copyright (C) 2017 by Hugh Bailey <jim@obsproject.com>
|
||||||
|
|
||||||
|
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 <http://www.gnu.org/licenses/>.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <util/c99defs.h>
|
||||||
|
|
||||||
|
#if defined(_WIN32) || defined(__APPLE__)
|
||||||
|
#define RUNTIME_LINK 1
|
||||||
|
#define Py_NO_ENABLE_SHARED
|
||||||
|
#else
|
||||||
|
#define RUNTIME_LINK 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4115)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN32) && defined(_DEBUG)
|
||||||
|
# undef _DEBUG
|
||||||
|
# include <Python.h>
|
||||||
|
# define _DEBUG
|
||||||
|
#else
|
||||||
|
# include <Python.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if RUNTIME_LINK
|
||||||
|
|
||||||
|
#ifdef NO_REDEFS
|
||||||
|
#define PY_EXTERN
|
||||||
|
#else
|
||||||
|
#define PY_EXTERN extern
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PY_EXTERN int (*Import_PyType_Ready)(PyTypeObject *);
|
||||||
|
PY_EXTERN PyObject *(*Import_PyObject_GenericGetAttr)(PyObject *, PyObject *);
|
||||||
|
PY_EXTERN int (*Import_PyObject_IsTrue)(PyObject *);
|
||||||
|
PY_EXTERN void (*Import_Py_DecRef)(PyObject *);
|
||||||
|
PY_EXTERN void *(*Import_PyObject_Malloc)(size_t size);
|
||||||
|
PY_EXTERN void (*Import_PyObject_Free)(void *ptr);
|
||||||
|
PY_EXTERN PyObject *(*Import_PyObject_Init)(PyObject *, PyTypeObject *);
|
||||||
|
PY_EXTERN PyObject *(*Import_PyUnicode_FromFormat)(const char *format, ...);
|
||||||
|
PY_EXTERN PyObject *(*Import_PyUnicode_Concat)(PyObject *left, PyObject *right);
|
||||||
|
PY_EXTERN PyObject *(*Import_PyLong_FromVoidPtr)(void *);
|
||||||
|
PY_EXTERN PyObject *(*Import_PyBool_FromLong)(long);
|
||||||
|
PY_EXTERN PyGILState_STATE (*Import_PyGILState_Ensure)(void);
|
||||||
|
PY_EXTERN PyThreadState *(*Import_PyGILState_GetThisThreadState)(void);
|
||||||
|
PY_EXTERN void (*Import_PyErr_SetString)(PyObject *exception, const char *string);
|
||||||
|
PY_EXTERN PyObject *(*Import_PyErr_Occurred)(void);
|
||||||
|
PY_EXTERN void (*Import_PyErr_Fetch)(PyObject **, PyObject **, PyObject **);
|
||||||
|
PY_EXTERN void (*Import_PyErr_Restore)(PyObject *, PyObject *, PyObject *);
|
||||||
|
PY_EXTERN void (*Import_PyErr_WriteUnraisable)(PyObject *);
|
||||||
|
PY_EXTERN int (*Import_PyArg_UnpackTuple)(PyObject *, const char *, Py_ssize_t, Py_ssize_t, ...);
|
||||||
|
PY_EXTERN PyObject *(*Import_Py_BuildValue)(const char *, ...);
|
||||||
|
PY_EXTERN int (*Import_PyRun_SimpleStringFlags)(const char *, PyCompilerFlags *);
|
||||||
|
PY_EXTERN void (*Import_PyErr_Print)(void);
|
||||||
|
PY_EXTERN void (*Import_Py_SetPythonHome)(wchar_t *);
|
||||||
|
PY_EXTERN void (*Import_Py_Initialize)(void);
|
||||||
|
PY_EXTERN void (*Import_Py_Finalize)(void);
|
||||||
|
PY_EXTERN int (*Import_Py_IsInitialized)(void);
|
||||||
|
PY_EXTERN void (*Import_PyEval_InitThreads)(void);
|
||||||
|
PY_EXTERN int (*Import_PyEval_ThreadsInitialized)(void);
|
||||||
|
PY_EXTERN void (*Import_PyEval_ReleaseThread)(PyThreadState *tstate);
|
||||||
|
PY_EXTERN void (*Import_PySys_SetArgv)(int, wchar_t **);
|
||||||
|
PY_EXTERN PyObject *(*Import_PyImport_ImportModule)(const char *name);
|
||||||
|
PY_EXTERN PyObject *(*Import_PyObject_CallFunctionObjArgs)(PyObject *callable, ...);
|
||||||
|
PY_EXTERN PyObject (*Import__Py_NotImplementedStruct);
|
||||||
|
PY_EXTERN PyObject *(*Import_PyExc_TypeError);
|
||||||
|
PY_EXTERN PyObject *(*Import_PyExc_RuntimeError);
|
||||||
|
PY_EXTERN PyObject *(*Import_PyObject_GetAttr)(PyObject *, PyObject *);
|
||||||
|
PY_EXTERN PyObject *(*Import_PyUnicode_FromString)(const char *u);
|
||||||
|
PY_EXTERN PyObject *(*Import_PyDict_GetItemString)(PyObject *dp, const char *key);
|
||||||
|
PY_EXTERN int (*Import_PyDict_SetItemString)(PyObject *dp, const char *key, PyObject *item);
|
||||||
|
PY_EXTERN PyObject *(*Import_PyCFunction_NewEx)(PyMethodDef *, PyObject *, PyObject *);
|
||||||
|
PY_EXTERN PyObject *(*Import_PyModule_GetDict)(PyObject *);
|
||||||
|
PY_EXTERN PyObject *(*Import_PyModule_GetNameObject)(PyObject *);
|
||||||
|
PY_EXTERN int (*Import_PyModule_AddObject)(PyObject *, const char *, PyObject *);
|
||||||
|
PY_EXTERN int (*Import_PyModule_AddStringConstant)(PyObject *, const char *, const char *);
|
||||||
|
PY_EXTERN PyObject *(*Import_PyImport_Import)(PyObject *name);
|
||||||
|
PY_EXTERN PyObject *(*Import_PyObject_CallObject)(PyObject *callable_object, PyObject *args);
|
||||||
|
PY_EXTERN struct _longobject (*Import__Py_FalseStruct);
|
||||||
|
PY_EXTERN struct _longobject (*Import__Py_TrueStruct);
|
||||||
|
PY_EXTERN void (*Import_PyGILState_Release)(PyGILState_STATE);
|
||||||
|
PY_EXTERN int (*Import_PyList_Append)(PyObject *, PyObject *);
|
||||||
|
PY_EXTERN PyObject *(*Import_PySys_GetObject)(const char *);
|
||||||
|
PY_EXTERN PyObject *(*Import_PyImport_ReloadModule)(PyObject *m);
|
||||||
|
PY_EXTERN PyObject *(*Import_PyObject_GetAttrString)(PyObject *, const char *);
|
||||||
|
PY_EXTERN PyObject *(*Import_PyCapsule_New)(void *pointer, const char *name, PyCapsule_Destructor destructor);
|
||||||
|
PY_EXTERN void *(*Import_PyCapsule_GetPointer)(PyObject *capsule, const char *name);
|
||||||
|
PY_EXTERN int (*Import_PyArg_ParseTuple)(PyObject *, const char *, ...);
|
||||||
|
PY_EXTERN PyTypeObject (*Import_PyFunction_Type);
|
||||||
|
PY_EXTERN int (*Import_PyObject_SetAttr)(PyObject *, PyObject *, PyObject *);
|
||||||
|
PY_EXTERN PyObject *(*Import__PyObject_New)(PyTypeObject *);
|
||||||
|
PY_EXTERN void *(*Import_PyCapsule_Import)(const char *name, int no_block);
|
||||||
|
PY_EXTERN void (*Import_PyErr_Clear)(void);
|
||||||
|
PY_EXTERN PyObject *(*Import_PyObject_Call)(PyObject *callable_object, PyObject *args, PyObject *kwargs);
|
||||||
|
PY_EXTERN PyObject *(*Import_PyList_New)(Py_ssize_t size);
|
||||||
|
PY_EXTERN Py_ssize_t (*Import_PyList_Size)(PyObject *);
|
||||||
|
PY_EXTERN PyObject *(*Import_PyList_GetItem)(PyObject *, Py_ssize_t);
|
||||||
|
PY_EXTERN PyObject *(*Import_PyUnicode_AsUTF8String)(PyObject *unicode);
|
||||||
|
PY_EXTERN PyObject *(*Import_PyLong_FromUnsignedLongLong)(unsigned long long);
|
||||||
|
PY_EXTERN int (*Import_PyArg_VaParse)(PyObject *, const char *, va_list);
|
||||||
|
PY_EXTERN PyObject (*Import__Py_NoneStruct);
|
||||||
|
|
||||||
|
extern bool import_python(const char *python_path);
|
||||||
|
|
||||||
|
# ifndef NO_REDEFS
|
||||||
|
# define PyType_Ready Import_PyType_Ready
|
||||||
|
# define PyObject_GenericGetAttr Import_PyObject_GenericGetAttr
|
||||||
|
# define PyObject_IsTrue Import_PyObject_IsTrue
|
||||||
|
# define Py_DecRef Import_Py_DecRef
|
||||||
|
# define PyObject_Malloc Import_PyObject_Malloc
|
||||||
|
# define PyObject_Free Import_PyObject_Free
|
||||||
|
# define PyObject_Init Import_PyObject_Init
|
||||||
|
# define PyUnicode_FromFormat Import_PyUnicode_FromFormat
|
||||||
|
# define PyUnicode_Concat Import_PyUnicode_Concat
|
||||||
|
# define PyLong_FromVoidPtr Import_PyLong_FromVoidPtr
|
||||||
|
# define PyBool_FromLong Import_PyBool_FromLong
|
||||||
|
# define PyGILState_Ensure Import_PyGILState_Ensure
|
||||||
|
# define PyGILState_GetThisThreadState Import_PyGILState_GetThisThreadState
|
||||||
|
# define PyErr_SetString Import_PyErr_SetString
|
||||||
|
# define PyErr_Occurred Import_PyErr_Occurred
|
||||||
|
# define PyErr_Fetch Import_PyErr_Fetch
|
||||||
|
# define PyErr_Restore Import_PyErr_Restore
|
||||||
|
# define PyErr_WriteUnraisable Import_PyErr_WriteUnraisable
|
||||||
|
# define PyArg_UnpackTuple Import_PyArg_UnpackTuple
|
||||||
|
# define Py_BuildValue Import_Py_BuildValue
|
||||||
|
# define PyRun_SimpleStringFlags Import_PyRun_SimpleStringFlags
|
||||||
|
# define PyErr_Print Import_PyErr_Print
|
||||||
|
# define Py_SetPythonHome Import_Py_SetPythonHome
|
||||||
|
# define Py_Initialize Import_Py_Initialize
|
||||||
|
# define Py_Finalize Import_Py_Finalize
|
||||||
|
# define Py_IsInitialized Import_Py_IsInitialized
|
||||||
|
# define PyEval_InitThreads Import_PyEval_InitThreads
|
||||||
|
# define PyEval_ThreadsInitialized Import_PyEval_ThreadsInitialized
|
||||||
|
# define PyEval_ReleaseThread Import_PyEval_ReleaseThread
|
||||||
|
# define PySys_SetArgv Import_PySys_SetArgv
|
||||||
|
# define PyImport_ImportModule Import_PyImport_ImportModule
|
||||||
|
# define PyObject_CallFunctionObjArgs Import_PyObject_CallFunctionObjArgs
|
||||||
|
# define _Py_NotImplementedStruct (*Import__Py_NotImplementedStruct)
|
||||||
|
# define PyExc_TypeError (*Import_PyExc_TypeError)
|
||||||
|
# define PyExc_RuntimeError (*Import_PyExc_RuntimeError)
|
||||||
|
# define PyObject_GetAttr Import_PyObject_GetAttr
|
||||||
|
# define PyUnicode_FromString Import_PyUnicode_FromString
|
||||||
|
# define PyDict_GetItemString Import_PyDict_GetItemString
|
||||||
|
# define PyDict_SetItemString Import_PyDict_SetItemString
|
||||||
|
# define PyCFunction_NewEx Import_PyCFunction_NewEx
|
||||||
|
# define PyModule_GetDict Import_PyModule_GetDict
|
||||||
|
# define PyModule_GetNameObject Import_PyModule_GetNameObject
|
||||||
|
# define PyModule_AddObject Import_PyModule_AddObject
|
||||||
|
# define PyModule_AddStringConstant Import_PyModule_AddStringConstant
|
||||||
|
# define PyImport_Import Import_PyImport_Import
|
||||||
|
# define PyObject_CallObject Import_PyObject_CallObject
|
||||||
|
# define _Py_FalseStruct (*Import__Py_FalseStruct)
|
||||||
|
# define _Py_TrueStruct (*Import__Py_TrueStruct)
|
||||||
|
# define PyGILState_Release Import_PyGILState_Release
|
||||||
|
# define PyList_Append Import_PyList_Append
|
||||||
|
# define PySys_GetObject Import_PySys_GetObject
|
||||||
|
# define PyImport_ReloadModule Import_PyImport_ReloadModule
|
||||||
|
# define PyObject_GetAttrString Import_PyObject_GetAttrString
|
||||||
|
# define PyCapsule_New Import_PyCapsule_New
|
||||||
|
# define PyCapsule_GetPointer Import_PyCapsule_GetPointer
|
||||||
|
# define PyArg_ParseTuple Import_PyArg_ParseTuple
|
||||||
|
# define PyFunction_Type (*Import_PyFunction_Type)
|
||||||
|
# define PyObject_SetAttr Import_PyObject_SetAttr
|
||||||
|
# define _PyObject_New Import__PyObject_New
|
||||||
|
# define PyCapsule_Import Import_PyCapsule_Import
|
||||||
|
# define PyErr_Clear Import_PyErr_Clear
|
||||||
|
# define PyObject_Call Import_PyObject_Call
|
||||||
|
# define PyList_New Import_PyList_New
|
||||||
|
# define PyList_Size Import_PyList_Size
|
||||||
|
# define PyList_GetItem Import_PyList_GetItem
|
||||||
|
# define PyUnicode_AsUTF8String Import_PyUnicode_AsUTF8String
|
||||||
|
# define PyLong_FromUnsignedLongLong Import_PyLong_FromUnsignedLongLong
|
||||||
|
# define PyArg_VaParse Import_PyArg_VaParse
|
||||||
|
# define _Py_NoneStruct (*Import__Py_NoneStruct)
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#endif
|
1705
deps/obs-scripting/obs-scripting-python.c
vendored
Normal file
1705
deps/obs-scripting/obs-scripting-python.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
244
deps/obs-scripting/obs-scripting-python.h
vendored
Normal file
244
deps/obs-scripting/obs-scripting-python.h
vendored
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
Copyright (C) 2015 by Andrew Skinner <obs@theandyroid.com>
|
||||||
|
Copyright (C) 2017 by Hugh Bailey <jim@obsproject.com>
|
||||||
|
|
||||||
|
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 <http://www.gnu.org/licenses/>.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/* ---------------------------- */
|
||||||
|
|
||||||
|
#define SWIG_TYPE_TABLE obspython
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 4100)
|
||||||
|
#pragma warning(disable : 4115)
|
||||||
|
#pragma warning(disable : 4204)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "obs-scripting-python-import.h"
|
||||||
|
|
||||||
|
#include <structmember.h>
|
||||||
|
#include "swig/swigpyrun.h"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ---------------------------- */
|
||||||
|
|
||||||
|
#include "obs-scripting-internal.h"
|
||||||
|
#include "obs-scripting-callback.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define __func__ __FUNCTION__
|
||||||
|
#else
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <callback/calldata.h>
|
||||||
|
#include <util/threading.h>
|
||||||
|
#include <util/base.h>
|
||||||
|
|
||||||
|
#define do_log(level, format, ...) \
|
||||||
|
blog(level, "[Python] " 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 python_obs_callback;
|
||||||
|
|
||||||
|
struct obs_python_script {
|
||||||
|
obs_script_t base;
|
||||||
|
|
||||||
|
struct dstr dir;
|
||||||
|
struct dstr name;
|
||||||
|
|
||||||
|
PyObject *module;
|
||||||
|
|
||||||
|
PyObject *save;
|
||||||
|
PyObject *update;
|
||||||
|
PyObject *get_properties;
|
||||||
|
|
||||||
|
struct script_callback *first_callback;
|
||||||
|
|
||||||
|
PyObject *tick;
|
||||||
|
struct obs_python_script *next_tick;
|
||||||
|
struct obs_python_script **p_prev_next_tick;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
|
||||||
|
struct python_obs_callback {
|
||||||
|
struct script_callback base;
|
||||||
|
|
||||||
|
PyObject *func;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct python_obs_callback *add_python_obs_callback_extra(
|
||||||
|
struct obs_python_script *script,
|
||||||
|
PyObject *func,
|
||||||
|
size_t extra_size)
|
||||||
|
{
|
||||||
|
struct python_obs_callback *cb = add_script_callback(
|
||||||
|
&script->first_callback,
|
||||||
|
(obs_script_t *)script,
|
||||||
|
sizeof(*cb) + extra_size);
|
||||||
|
|
||||||
|
Py_XINCREF(func);
|
||||||
|
cb->func = func;
|
||||||
|
return cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct python_obs_callback *add_python_obs_callback(
|
||||||
|
struct obs_python_script *script,
|
||||||
|
PyObject *func)
|
||||||
|
{
|
||||||
|
return add_python_obs_callback_extra(script, func, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void *python_obs_callback_extra_data(
|
||||||
|
struct python_obs_callback *cb)
|
||||||
|
{
|
||||||
|
return (void*)&cb[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct obs_python_script *python_obs_callback_script(
|
||||||
|
struct python_obs_callback *cb)
|
||||||
|
{
|
||||||
|
return (struct obs_python_script *)cb->base.script;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct python_obs_callback *find_next_python_obs_callback(
|
||||||
|
struct obs_python_script *script,
|
||||||
|
struct python_obs_callback *cb, PyObject *func)
|
||||||
|
{
|
||||||
|
cb = cb ? (struct python_obs_callback *)cb->base.next
|
||||||
|
: (struct python_obs_callback *)script->first_callback;
|
||||||
|
|
||||||
|
while (cb) {
|
||||||
|
if (cb->func == func)
|
||||||
|
break;
|
||||||
|
cb = (struct python_obs_callback *)cb->base.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline struct python_obs_callback *find_python_obs_callback(
|
||||||
|
struct obs_python_script *script,
|
||||||
|
PyObject *func)
|
||||||
|
{
|
||||||
|
return find_next_python_obs_callback(script, NULL, func);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void remove_python_obs_callback(struct python_obs_callback *cb)
|
||||||
|
{
|
||||||
|
remove_script_callback(&cb->base);
|
||||||
|
|
||||||
|
Py_XDECREF(cb->func);
|
||||||
|
cb->func = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void just_free_python_obs_callback(struct python_obs_callback *cb)
|
||||||
|
{
|
||||||
|
just_free_script_callback(&cb->base);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void free_python_obs_callback(struct python_obs_callback *cb)
|
||||||
|
{
|
||||||
|
free_script_callback(&cb->base);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
|
||||||
|
static int parse_args_(PyObject *args, const char *func, const char *format, ...)
|
||||||
|
{
|
||||||
|
char new_format[128];
|
||||||
|
va_list va_args;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
snprintf(new_format, sizeof(new_format), "%s:%s", format, func);
|
||||||
|
|
||||||
|
va_start(va_args, format);
|
||||||
|
ret = PyArg_VaParse(args, new_format, va_args);
|
||||||
|
va_end(va_args);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define parse_args(args, format, ...) \
|
||||||
|
parse_args_(args, __FUNCTION__, format, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
static inline bool py_error_(const char *func, int line)
|
||||||
|
{
|
||||||
|
if (PyErr_Occurred()) {
|
||||||
|
warn("Python failure in %s:%d:", func, line);
|
||||||
|
PyErr_Print();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define py_error() py_error_(__FUNCTION__, __LINE__)
|
||||||
|
|
||||||
|
#define lock_python() \
|
||||||
|
PyGILState_STATE gstate = PyGILState_Ensure()
|
||||||
|
#define unlock_python() \
|
||||||
|
PyGILState_Release(gstate)
|
||||||
|
|
||||||
|
struct py_source;
|
||||||
|
typedef struct py_source py_source_t;
|
||||||
|
|
||||||
|
extern PyObject* py_libobs;
|
||||||
|
extern struct python_obs_callback *cur_python_cb;
|
||||||
|
extern struct obs_python_script *cur_python_script;
|
||||||
|
|
||||||
|
extern void py_to_obs_source_info(py_source_t *py_info);
|
||||||
|
extern PyObject *py_obs_register_source(PyObject *self, PyObject *args);
|
||||||
|
extern PyObject *py_obs_get_script_config_path(PyObject *self, PyObject *args);
|
||||||
|
extern void add_functions_to_py_module(PyObject *module,
|
||||||
|
PyMethodDef *method_list);
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------ */
|
||||||
|
/* Warning: the following functions expect python to be locked! */
|
||||||
|
|
||||||
|
extern bool py_to_libobs_(const char *type,
|
||||||
|
PyObject * py_in,
|
||||||
|
void * libobs_out,
|
||||||
|
const char *id,
|
||||||
|
const char *func,
|
||||||
|
int line);
|
||||||
|
|
||||||
|
extern bool libobs_to_py_(const char *type,
|
||||||
|
void * libobs_in,
|
||||||
|
bool ownership,
|
||||||
|
PyObject ** py_out,
|
||||||
|
const char *id,
|
||||||
|
const char *func,
|
||||||
|
int line);
|
||||||
|
|
||||||
|
extern bool py_call(PyObject *call, PyObject **ret, const char *arg_def, ...);
|
||||||
|
extern bool py_import_script(const char *name);
|
||||||
|
|
||||||
|
static inline PyObject *python_none(void)
|
||||||
|
{
|
||||||
|
PyObject *none = Py_None;
|
||||||
|
Py_INCREF(none);
|
||||||
|
return none;
|
||||||
|
}
|
455
deps/obs-scripting/obs-scripting.c
vendored
Normal file
455
deps/obs-scripting/obs-scripting.c
vendored
Normal file
@ -0,0 +1,455 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
Copyright (C) 2017 by Hugh Bailey <jim@obsproject.com>
|
||||||
|
|
||||||
|
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 <http://www.gnu.org/licenses/>.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include <obs.h>
|
||||||
|
#include <util/dstr.h>
|
||||||
|
#include <util/platform.h>
|
||||||
|
#include <util/threading.h>
|
||||||
|
#include <util/circlebuf.h>
|
||||||
|
|
||||||
|
#include "obs-scripting-internal.h"
|
||||||
|
#include "obs-scripting-callback.h"
|
||||||
|
#include "obs-scripting-config.h"
|
||||||
|
|
||||||
|
#if COMPILE_LUA
|
||||||
|
extern obs_script_t *obs_lua_script_create(const char *path,
|
||||||
|
obs_data_t *settings);
|
||||||
|
extern bool obs_lua_script_load(obs_script_t *s);
|
||||||
|
extern void obs_lua_script_unload(obs_script_t *s);
|
||||||
|
extern void obs_lua_script_destroy(obs_script_t *s);
|
||||||
|
extern void obs_lua_load(void);
|
||||||
|
extern void obs_lua_unload(void);
|
||||||
|
|
||||||
|
extern obs_properties_t *obs_lua_script_get_properties(obs_script_t *script);
|
||||||
|
extern void obs_lua_script_update(obs_script_t *script, obs_data_t *settings);
|
||||||
|
extern void obs_lua_script_save(obs_script_t *script);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if COMPILE_PYTHON
|
||||||
|
extern obs_script_t *obs_python_script_create(const char *path,
|
||||||
|
obs_data_t *settings);
|
||||||
|
extern bool obs_python_script_load(obs_script_t *s);
|
||||||
|
extern void obs_python_script_unload(obs_script_t *s);
|
||||||
|
extern void obs_python_script_destroy(obs_script_t *s);
|
||||||
|
extern void obs_python_load(void);
|
||||||
|
extern void obs_python_unload(void);
|
||||||
|
|
||||||
|
extern obs_properties_t *obs_python_script_get_properties(obs_script_t *script);
|
||||||
|
extern void obs_python_script_update(obs_script_t *script, obs_data_t *settings);
|
||||||
|
extern void obs_python_script_save(obs_script_t *script);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
pthread_mutex_t detach_mutex;
|
||||||
|
struct script_callback *detached_callbacks;
|
||||||
|
|
||||||
|
static struct dstr file_filter = {0};
|
||||||
|
static bool scripting_loaded = false;
|
||||||
|
|
||||||
|
static const char *supported_formats[] = {
|
||||||
|
#if COMPILE_LUA
|
||||||
|
"lua",
|
||||||
|
#endif
|
||||||
|
#if COMPILE_PYTHON
|
||||||
|
"py",
|
||||||
|
#endif
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
static pthread_mutex_t defer_call_mutex;
|
||||||
|
static struct circlebuf defer_call_queue;
|
||||||
|
static bool defer_call_exit = false;
|
||||||
|
static os_sem_t *defer_call_semaphore;
|
||||||
|
static pthread_t defer_call_thread;
|
||||||
|
|
||||||
|
struct defer_call {
|
||||||
|
defer_call_cb call;
|
||||||
|
void *cb;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void *defer_thread(void *unused)
|
||||||
|
{
|
||||||
|
UNUSED_PARAMETER(unused);
|
||||||
|
|
||||||
|
while (os_sem_wait(defer_call_semaphore) == 0) {
|
||||||
|
struct defer_call info;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&defer_call_mutex);
|
||||||
|
if (defer_call_exit) {
|
||||||
|
pthread_mutex_unlock(&defer_call_mutex);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
circlebuf_pop_front(&defer_call_queue, &info, sizeof(info));
|
||||||
|
pthread_mutex_unlock(&defer_call_mutex);
|
||||||
|
|
||||||
|
info.call(info.cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void defer_call_post(defer_call_cb call, void *cb)
|
||||||
|
{
|
||||||
|
struct defer_call info;
|
||||||
|
info.call = call;
|
||||||
|
info.cb = cb;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&defer_call_mutex);
|
||||||
|
if (!defer_call_exit)
|
||||||
|
circlebuf_push_back(&defer_call_queue, &info, sizeof(info));
|
||||||
|
pthread_mutex_unlock(&defer_call_mutex);
|
||||||
|
|
||||||
|
os_sem_post(defer_call_semaphore);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
bool obs_scripting_load(void)
|
||||||
|
{
|
||||||
|
circlebuf_init(&defer_call_queue);
|
||||||
|
|
||||||
|
if (pthread_mutex_init(&detach_mutex, NULL) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (pthread_mutex_init(&defer_call_mutex, NULL) != 0) {
|
||||||
|
pthread_mutex_destroy(&detach_mutex);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (os_sem_init(&defer_call_semaphore, 0) != 0) {
|
||||||
|
pthread_mutex_destroy(&defer_call_mutex);
|
||||||
|
pthread_mutex_destroy(&detach_mutex);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pthread_create(&defer_call_thread, NULL, defer_thread, NULL) != 0) {
|
||||||
|
os_sem_destroy(defer_call_semaphore);
|
||||||
|
pthread_mutex_destroy(&defer_call_mutex);
|
||||||
|
pthread_mutex_destroy(&detach_mutex);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if COMPILE_LUA
|
||||||
|
obs_lua_load();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if COMPILE_PYTHON
|
||||||
|
obs_python_load();
|
||||||
|
obs_scripting_load_python(NULL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
scripting_loaded = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void obs_scripting_unload(void)
|
||||||
|
{
|
||||||
|
if (!scripting_loaded)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* ---------------------- */
|
||||||
|
|
||||||
|
#if COMPILE_LUA
|
||||||
|
obs_lua_unload();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if COMPILE_PYTHON
|
||||||
|
obs_python_unload();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
dstr_free(&file_filter);
|
||||||
|
|
||||||
|
/* ---------------------- */
|
||||||
|
|
||||||
|
int total_detached = 0;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&detach_mutex);
|
||||||
|
|
||||||
|
struct script_callback *cur = detached_callbacks;
|
||||||
|
while (cur) {
|
||||||
|
struct script_callback *next = cur->next;
|
||||||
|
just_free_script_callback(cur);
|
||||||
|
cur = next;
|
||||||
|
|
||||||
|
++total_detached;
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&detach_mutex);
|
||||||
|
pthread_mutex_destroy(&detach_mutex);
|
||||||
|
|
||||||
|
blog(LOG_INFO, "[Scripting] Total detached callbacks: %d",
|
||||||
|
total_detached);
|
||||||
|
|
||||||
|
/* ---------------------- */
|
||||||
|
|
||||||
|
pthread_mutex_lock(&defer_call_mutex);
|
||||||
|
|
||||||
|
/* TODO */
|
||||||
|
|
||||||
|
defer_call_exit = true;
|
||||||
|
circlebuf_free(&defer_call_queue);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&defer_call_mutex);
|
||||||
|
|
||||||
|
os_sem_post(defer_call_semaphore);
|
||||||
|
pthread_join(defer_call_thread, NULL);
|
||||||
|
|
||||||
|
pthread_mutex_destroy(&defer_call_mutex);
|
||||||
|
os_sem_destroy(defer_call_semaphore);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char **obs_scripting_supported_formats(void)
|
||||||
|
{
|
||||||
|
return supported_formats;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline bool pointer_valid(const void *x, const char *name,
|
||||||
|
const char *func)
|
||||||
|
{
|
||||||
|
if (!x) {
|
||||||
|
blog(LOG_WARNING, "obs-scripting: [%s] %s is null",
|
||||||
|
func, name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ptr_valid(x) pointer_valid(x, #x, __FUNCTION__)
|
||||||
|
|
||||||
|
obs_script_t *obs_script_create(const char *path, obs_data_t *settings)
|
||||||
|
{
|
||||||
|
obs_script_t *script = NULL;
|
||||||
|
const char *ext;
|
||||||
|
|
||||||
|
if (!scripting_loaded)
|
||||||
|
return NULL;
|
||||||
|
if (!ptr_valid(path))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ext = strrchr(path, '.');
|
||||||
|
if (!ext)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
#if COMPILE_LUA
|
||||||
|
if (strcmp(ext, ".lua") == 0) {
|
||||||
|
script = obs_lua_script_create(path, settings);
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
#if COMPILE_PYTHON
|
||||||
|
if (strcmp(ext, ".py") == 0) {
|
||||||
|
script = obs_python_script_create(path, settings);
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
blog(LOG_WARNING, "Unsupported/unknown script type: %s", path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return script;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *obs_script_get_description(const obs_script_t *script)
|
||||||
|
{
|
||||||
|
return ptr_valid(script) ? script->desc.array : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *obs_script_get_path(const obs_script_t *script)
|
||||||
|
{
|
||||||
|
const char *path = ptr_valid(script) ? script->path.array : "";
|
||||||
|
return path ? path : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *obs_script_get_file(const obs_script_t *script)
|
||||||
|
{
|
||||||
|
const char *file = ptr_valid(script) ? script->file.array : "";
|
||||||
|
return file ? file : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
enum obs_script_lang obs_script_get_lang(const obs_script_t *script)
|
||||||
|
{
|
||||||
|
return ptr_valid(script) ? script->type : OBS_SCRIPT_LANG_UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
obs_data_t *obs_script_get_settings(obs_script_t *script)
|
||||||
|
{
|
||||||
|
obs_data_t *settings;
|
||||||
|
|
||||||
|
if (!ptr_valid(script))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
settings = script->settings;
|
||||||
|
obs_data_addref(settings);
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
obs_properties_t *obs_script_get_properties(obs_script_t *script)
|
||||||
|
{
|
||||||
|
obs_properties_t *props = NULL;
|
||||||
|
|
||||||
|
if (!ptr_valid(script))
|
||||||
|
return NULL;
|
||||||
|
#if COMPILE_LUA
|
||||||
|
if (script->type == OBS_SCRIPT_LANG_LUA) {
|
||||||
|
props = obs_lua_script_get_properties(script);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if COMPILE_PYTHON
|
||||||
|
if (script->type == OBS_SCRIPT_LANG_PYTHON) {
|
||||||
|
props = obs_python_script_get_properties(script);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (!props)
|
||||||
|
props = obs_properties_create();
|
||||||
|
return props;
|
||||||
|
}
|
||||||
|
|
||||||
|
obs_data_t *obs_script_save(obs_script_t *script)
|
||||||
|
{
|
||||||
|
obs_data_t *settings;
|
||||||
|
|
||||||
|
if (!ptr_valid(script))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
#if COMPILE_LUA
|
||||||
|
if (script->type == OBS_SCRIPT_LANG_LUA) {
|
||||||
|
obs_lua_script_save(script);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if COMPILE_PYTHON
|
||||||
|
if (script->type == OBS_SCRIPT_LANG_PYTHON) {
|
||||||
|
obs_python_script_save(script);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
out:
|
||||||
|
settings = script->settings;
|
||||||
|
obs_data_addref(settings);
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clear_queue_signal(void *p_event)
|
||||||
|
{
|
||||||
|
os_event_t *event = p_event;
|
||||||
|
os_event_signal(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clear_call_queue(void)
|
||||||
|
{
|
||||||
|
os_event_t *event;
|
||||||
|
if (os_event_init(&event, OS_EVENT_TYPE_AUTO) != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
defer_call_post(clear_queue_signal, event);
|
||||||
|
|
||||||
|
os_event_wait(event);
|
||||||
|
os_event_destroy(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void obs_script_update(obs_script_t *script, obs_data_t *settings)
|
||||||
|
{
|
||||||
|
if (!ptr_valid(script))
|
||||||
|
return;
|
||||||
|
#if COMPILE_LUA
|
||||||
|
if (script->type == OBS_SCRIPT_LANG_LUA) {
|
||||||
|
obs_lua_script_update(script, settings);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if COMPILE_PYTHON
|
||||||
|
if (script->type == OBS_SCRIPT_LANG_PYTHON) {
|
||||||
|
obs_python_script_update(script, settings);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool obs_script_reload(obs_script_t *script)
|
||||||
|
{
|
||||||
|
if (!scripting_loaded)
|
||||||
|
return false;
|
||||||
|
if (!ptr_valid(script))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#if COMPILE_LUA
|
||||||
|
if (script->type == OBS_SCRIPT_LANG_LUA) {
|
||||||
|
obs_lua_script_unload(script);
|
||||||
|
clear_call_queue();
|
||||||
|
obs_lua_script_load(script);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if COMPILE_PYTHON
|
||||||
|
if (script->type == OBS_SCRIPT_LANG_PYTHON) {
|
||||||
|
obs_python_script_unload(script);
|
||||||
|
clear_call_queue();
|
||||||
|
obs_python_script_load(script);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
out:
|
||||||
|
return script->loaded;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool obs_script_loaded(const obs_script_t *script)
|
||||||
|
{
|
||||||
|
return ptr_valid(script) ? script->loaded : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void obs_script_destroy(obs_script_t *script)
|
||||||
|
{
|
||||||
|
if (!script)
|
||||||
|
return;
|
||||||
|
|
||||||
|
#if COMPILE_LUA
|
||||||
|
if (script->type == OBS_SCRIPT_LANG_LUA) {
|
||||||
|
obs_lua_script_unload(script);
|
||||||
|
obs_lua_script_destroy(script);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#if COMPILE_PYTHON
|
||||||
|
if (script->type == OBS_SCRIPT_LANG_PYTHON) {
|
||||||
|
obs_python_script_unload(script);
|
||||||
|
obs_python_script_destroy(script);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !COMPILE_PYTHON
|
||||||
|
bool obs_scripting_load_python(const char *python_path)
|
||||||
|
{
|
||||||
|
UNUSED_PARAMETER(python_path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool obs_scripting_python_loaded(void)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool obs_scripting_python_runtime_linked(void)
|
||||||
|
{
|
||||||
|
return (bool)true;
|
||||||
|
}
|
||||||
|
#endif
|
73
deps/obs-scripting/obs-scripting.h
vendored
Normal file
73
deps/obs-scripting/obs-scripting.h
vendored
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
Copyright (C) 2017 by Hugh Bailey <jim@obsproject.com>
|
||||||
|
|
||||||
|
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 <http://www.gnu.org/licenses/>.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <util/c99defs.h>
|
||||||
|
#include <obs-data.h>
|
||||||
|
#include <obs-properties.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct obs_script;
|
||||||
|
typedef struct obs_script obs_script_t;
|
||||||
|
|
||||||
|
enum obs_script_lang {
|
||||||
|
OBS_SCRIPT_LANG_UNKNOWN,
|
||||||
|
OBS_SCRIPT_LANG_LUA,
|
||||||
|
OBS_SCRIPT_LANG_PYTHON
|
||||||
|
};
|
||||||
|
|
||||||
|
EXPORT bool obs_scripting_load(void);
|
||||||
|
EXPORT void obs_scripting_unload(void);
|
||||||
|
EXPORT const char **obs_scripting_supported_formats(void);
|
||||||
|
|
||||||
|
typedef void (*scripting_log_handler_t)(
|
||||||
|
void *p,
|
||||||
|
obs_script_t *script,
|
||||||
|
int lvl,
|
||||||
|
const char *msg);
|
||||||
|
|
||||||
|
EXPORT void obs_scripting_set_log_callback(
|
||||||
|
scripting_log_handler_t handler, void *param);
|
||||||
|
|
||||||
|
EXPORT bool obs_scripting_python_runtime_linked(void);
|
||||||
|
EXPORT bool obs_scripting_python_loaded(void);
|
||||||
|
EXPORT bool obs_scripting_load_python(const char *python_path);
|
||||||
|
|
||||||
|
EXPORT obs_script_t *obs_script_create(const char *path, obs_data_t *settings);
|
||||||
|
EXPORT void obs_script_destroy(obs_script_t *script);
|
||||||
|
|
||||||
|
EXPORT const char *obs_script_get_description(const obs_script_t *script);
|
||||||
|
EXPORT const char *obs_script_get_path(const obs_script_t *script);
|
||||||
|
EXPORT const char *obs_script_get_file(const obs_script_t *script);
|
||||||
|
EXPORT enum obs_script_lang obs_script_get_lang(const obs_script_t *script);
|
||||||
|
|
||||||
|
EXPORT obs_properties_t *obs_script_get_properties(obs_script_t *script);
|
||||||
|
EXPORT obs_data_t *obs_script_save(obs_script_t *script);
|
||||||
|
EXPORT obs_data_t *obs_script_get_settings(obs_script_t *script);
|
||||||
|
EXPORT void obs_script_update(obs_script_t *script, obs_data_t *settings);
|
||||||
|
|
||||||
|
EXPORT bool obs_script_loaded(const obs_script_t *script);
|
||||||
|
EXPORT bool obs_script_reload(obs_script_t *script);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
41
deps/obs-scripting/obslua/CMakeLists.txt
vendored
Normal file
41
deps/obs-scripting/obslua/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
cmake_minimum_required(VERSION 2.8)
|
||||||
|
project(obslua)
|
||||||
|
|
||||||
|
find_package(SWIG 2 REQUIRED)
|
||||||
|
include(${SWIG_USE_FILE})
|
||||||
|
|
||||||
|
add_definitions(-DSWIG_TYPE_TABLE=obslua -DSWIG_LUA_INTERPRETER_NO_DEBUG)
|
||||||
|
|
||||||
|
if(MSVC)
|
||||||
|
add_compile_options("/wd4054")
|
||||||
|
add_compile_options("/wd4197")
|
||||||
|
add_compile_options("/wd4244")
|
||||||
|
add_compile_options("/wd4267")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include_directories(SYSTEM "${CMAKE_SOURCE_DIR}/libobs")
|
||||||
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
|
SWIG_ADD_MODULE(obslua lua obslua.i ../cstrcache.cpp ../cstrcache.h)
|
||||||
|
SWIG_LINK_LIBRARIES(obslua obs-scripting libobs ${LUA_LIBRARIES} ${EXTRA_LIBS})
|
||||||
|
|
||||||
|
function(install_plugin_bin_swig target additional_target)
|
||||||
|
if(APPLE)
|
||||||
|
set(_bit_suffix "")
|
||||||
|
elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
|
set(_bit_suffix "64bit/")
|
||||||
|
else()
|
||||||
|
set(_bit_suffix "32bit/")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set_target_properties(${additional_target} PROPERTIES
|
||||||
|
PREFIX "")
|
||||||
|
|
||||||
|
add_custom_command(TARGET ${additional_target} POST_BUILD
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E copy
|
||||||
|
"$<TARGET_FILE:${additional_target}>"
|
||||||
|
"${OBS_OUTPUT_DIR}/$<CONFIGURATION>/bin/${_bit_suffix}$<TARGET_FILE_NAME:${additional_target}>"
|
||||||
|
VERBATIM)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
install_plugin_bin_swig(obs-scripting obslua)
|
99
deps/obs-scripting/obslua/obslua.i
vendored
Normal file
99
deps/obs-scripting/obslua/obslua.i
vendored
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
%module obslua
|
||||||
|
%{
|
||||||
|
#define SWIG_FILE_WITH_INIT
|
||||||
|
#define DEPRECATED_START
|
||||||
|
#define DEPRECATED_END
|
||||||
|
#include <graphics/graphics.h>
|
||||||
|
#include <graphics/vec4.h>
|
||||||
|
#include <graphics/vec3.h>
|
||||||
|
#include <graphics/vec2.h>
|
||||||
|
#include <graphics/quat.h>
|
||||||
|
#include <obs.h>
|
||||||
|
#include <obs-hotkey.h>
|
||||||
|
#include <obs-source.h>
|
||||||
|
#include <obs-data.h>
|
||||||
|
#include <obs-properties.h>
|
||||||
|
#include <obs-interaction.h>
|
||||||
|
#include <callback/calldata.h>
|
||||||
|
#include <callback/proc.h>
|
||||||
|
#include <callback/signal.h>
|
||||||
|
#include <util/bmem.h>
|
||||||
|
#include <util/base.h>
|
||||||
|
#include "cstrcache.h"
|
||||||
|
#include "obs-scripting-config.h"
|
||||||
|
|
||||||
|
#if UI_ENABLED
|
||||||
|
#include "obs-frontend-api.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
%}
|
||||||
|
|
||||||
|
#define DEPRECATED_START
|
||||||
|
#define DEPRECATED_END
|
||||||
|
#define EXPORT
|
||||||
|
|
||||||
|
%rename(blog) wrap_blog;
|
||||||
|
%inline %{
|
||||||
|
static inline void wrap_blog(int log_level, const char *message)
|
||||||
|
{
|
||||||
|
blog(log_level, "%s", message);
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
|
%include "stdint.i"
|
||||||
|
|
||||||
|
/* Used to free when using %newobject functions. E.G.:
|
||||||
|
* %newobject obs_module_get_config_path; */
|
||||||
|
%typemap(newfree) char * "bfree($1);";
|
||||||
|
|
||||||
|
%ignore blog;
|
||||||
|
%ignore blogva;
|
||||||
|
%ignore bcrash;
|
||||||
|
%ignore obs_source_info;
|
||||||
|
%ignore obs_register_source_s(const struct obs_source_info *info, size_t size);
|
||||||
|
%ignore obs_output_set_video(obs_output_t *output, video_t *video);
|
||||||
|
%ignore obs_output_video(const obs_output_t *output);
|
||||||
|
%ignore obs_add_tick_callback;
|
||||||
|
%ignore obs_remove_tick_callback;
|
||||||
|
%ignore obs_add_main_render_callback;
|
||||||
|
%ignore obs_remove_main_render_callback;
|
||||||
|
%ignore obs_enum_sources;
|
||||||
|
%ignore obs_properties_add_button;
|
||||||
|
%ignore obs_property_set_modified_callback;
|
||||||
|
%ignore signal_handler_connect;
|
||||||
|
%ignore signal_handler_disconnect;
|
||||||
|
%ignore signal_handler_connect_global;
|
||||||
|
%ignore signal_handler_disconnect_global;
|
||||||
|
%ignore signal_handler_remove_current;
|
||||||
|
%ignore obs_hotkey_register_frontend;
|
||||||
|
%ignore obs_hotkey_register_encoder;
|
||||||
|
%ignore obs_hotkey_register_output;
|
||||||
|
%ignore obs_hotkey_register_service;
|
||||||
|
%ignore obs_hotkey_register_source;
|
||||||
|
%ignore obs_hotkey_pair_register_frontend;
|
||||||
|
%ignore obs_hotkey_pair_register_encoder;
|
||||||
|
%ignore obs_hotkey_pair_register_output;
|
||||||
|
%ignore obs_hotkey_pair_register_service;
|
||||||
|
%ignore obs_hotkey_pair_register_source;
|
||||||
|
|
||||||
|
%include "graphics/graphics.h"
|
||||||
|
%include "graphics/vec4.h"
|
||||||
|
%include "graphics/vec3.h"
|
||||||
|
%include "graphics/vec2.h"
|
||||||
|
%include "graphics/quat.h"
|
||||||
|
%include "obs-data.h"
|
||||||
|
%include "obs-source.h"
|
||||||
|
%include "obs-properties.h"
|
||||||
|
%include "obs-interaction.h"
|
||||||
|
%include "obs-hotkey.h"
|
||||||
|
%include "obs.h"
|
||||||
|
%include "callback/calldata.h"
|
||||||
|
%include "callback/proc.h"
|
||||||
|
%include "callback/signal.h"
|
||||||
|
%include "util/bmem.h"
|
||||||
|
%include "util/base.h"
|
||||||
|
%include "obs-scripting-config.h"
|
||||||
|
|
||||||
|
#if UI_ENABLED
|
||||||
|
%include "obs-frontend-api.h"
|
||||||
|
#endif
|
60
deps/obs-scripting/obspython/CMakeLists.txt
vendored
Normal file
60
deps/obs-scripting/obspython/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
cmake_minimum_required(VERSION 2.8)
|
||||||
|
project(obspython)
|
||||||
|
|
||||||
|
find_package(SWIG 2 REQUIRED)
|
||||||
|
include(${SWIG_USE_FILE})
|
||||||
|
|
||||||
|
add_definitions(-DSWIG_TYPE_TABLE=obspython -DMS_NO_COREDLL -DPy_ENABLE_SHARED=1 -DSWIG_PYTHON_INTERPRETER_NO_DEBUG)
|
||||||
|
|
||||||
|
if(MSVC)
|
||||||
|
add_compile_options("/wd4054")
|
||||||
|
add_compile_options("/wd4100")
|
||||||
|
add_compile_options("/wd4115")
|
||||||
|
add_compile_options("/wd4197")
|
||||||
|
add_compile_options("/wd4701")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include_directories(${PYTHON_INCLUDE_DIR})
|
||||||
|
include_directories(SYSTEM "${CMAKE_SOURCE_DIR}/libobs")
|
||||||
|
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
|
#add_definitions( -DSWIG_TYPE_TABLE=libobs )
|
||||||
|
SET_SOURCE_FILES_PROPERTIES(obspython.i PROPERTIES SWIG_FLAGS "-modern")
|
||||||
|
SET_SOURCE_FILES_PROPERTIES(obspython.i PROPERTIES SWIG_FLAGS "-builtin")
|
||||||
|
SET_SOURCE_FILES_PROPERTIES(obspython.i PROPERTIES SWIG_FLAGS "-modernargs")
|
||||||
|
SET_SOURCE_FILES_PROPERTIES(obspython.i PROPERTIES SWIG_FLAGS "-includeall")
|
||||||
|
SET_SOURCE_FILES_PROPERTIES(obspython.i PROPERTIES SWIG_FLAGS "-importall")
|
||||||
|
SET_SOURCE_FILES_PROPERTIES(obspython.i PROPERTIES SWIG_FLAGS "-py3")
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
string(REGEX REPLACE "_d" "" PYTHON_LIBRARIES "${PYTHON_LIBRARIES}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
SWIG_ADD_MODULE(obspython python obspython.i ../cstrcache.cpp ../cstrcache.h)
|
||||||
|
SWIG_LINK_LIBRARIES(obspython obs-scripting libobs ${PYTHON_LIBRARIES})
|
||||||
|
|
||||||
|
function(install_plugin_bin_swig target additional_target)
|
||||||
|
if(APPLE)
|
||||||
|
set(_bit_suffix "")
|
||||||
|
elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||||
|
set(_bit_suffix "64bit/")
|
||||||
|
else()
|
||||||
|
set(_bit_suffix "32bit/")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set_target_properties(${additional_target} PROPERTIES
|
||||||
|
PREFIX "")
|
||||||
|
|
||||||
|
add_custom_command(TARGET ${additional_target} POST_BUILD
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E copy
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/obspython.py"
|
||||||
|
"${OBS_OUTPUT_DIR}/$<CONFIGURATION>/bin/${_bit_suffix}/obspython.py"
|
||||||
|
VERBATIM)
|
||||||
|
add_custom_command(TARGET ${additional_target} POST_BUILD
|
||||||
|
COMMAND "${CMAKE_COMMAND}" -E copy
|
||||||
|
"$<TARGET_FILE:${additional_target}>"
|
||||||
|
"${OBS_OUTPUT_DIR}/$<CONFIGURATION>/bin/${_bit_suffix}$<TARGET_FILE_NAME:${additional_target}>"
|
||||||
|
VERBATIM)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
install_plugin_bin_swig(obs-scripting _obspython)
|
106
deps/obs-scripting/obspython/obspython.i
vendored
Normal file
106
deps/obs-scripting/obspython/obspython.i
vendored
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
%module(threads="1") obspython
|
||||||
|
%nothread;
|
||||||
|
%{
|
||||||
|
#define SWIG_FILE_WITH_INIT
|
||||||
|
#define DEPRECATED_START
|
||||||
|
#define DEPRECATED_END
|
||||||
|
#include <graphics/graphics.h>
|
||||||
|
#include <graphics/vec4.h>
|
||||||
|
#include <graphics/vec3.h>
|
||||||
|
#include <graphics/vec2.h>
|
||||||
|
#include <graphics/quat.h>
|
||||||
|
#include <obs.h>
|
||||||
|
#include <obs-hotkey.h>
|
||||||
|
#include <obs-source.h>
|
||||||
|
#include <obs-data.h>
|
||||||
|
#include <obs-properties.h>
|
||||||
|
#include <obs-interaction.h>
|
||||||
|
#include <callback/calldata.h>
|
||||||
|
#include <callback/decl.h>
|
||||||
|
#include <callback/proc.h>
|
||||||
|
#include <callback/signal.h>
|
||||||
|
#include <util/bmem.h>
|
||||||
|
#include <util/base.h>
|
||||||
|
#include "obs-scripting-config.h"
|
||||||
|
|
||||||
|
#if UI_ENABLED
|
||||||
|
#include "obs-frontend-api.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
%}
|
||||||
|
|
||||||
|
#define DEPRECATED_START
|
||||||
|
#define DEPRECATED_END
|
||||||
|
#define EXPORT
|
||||||
|
|
||||||
|
%rename(blog) wrap_blog;
|
||||||
|
%inline %{
|
||||||
|
static inline void wrap_blog(int log_level, const char *message)
|
||||||
|
{
|
||||||
|
blog(log_level, "%s", message);
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
|
%include "stdint.i"
|
||||||
|
|
||||||
|
/* Used to free when using %newobject functions. E.G.:
|
||||||
|
* %newobject obs_module_get_config_path; */
|
||||||
|
%typemap(newfree) char * "bfree($1);";
|
||||||
|
|
||||||
|
%ignore blog;
|
||||||
|
%ignore blogva;
|
||||||
|
%ignore bcrash;
|
||||||
|
%ignore obs_source_info;
|
||||||
|
%ignore obs_register_source_s(const struct obs_source_info *info, size_t size);
|
||||||
|
%ignore obs_output_set_video(obs_output_t *output, video_t *video);
|
||||||
|
%ignore obs_output_video(const obs_output_t *output);
|
||||||
|
%ignore obs_add_tick_callback;
|
||||||
|
%ignore obs_remove_tick_callback;
|
||||||
|
%ignore obs_add_main_render_callback;
|
||||||
|
%ignore obs_remove_main_render_callback;
|
||||||
|
%ignore obs_enum_sources;
|
||||||
|
%ignore obs_properties_add_button;
|
||||||
|
%ignore obs_property_set_modified_callback;
|
||||||
|
%ignore signal_handler_connect;
|
||||||
|
%ignore signal_handler_disconnect;
|
||||||
|
%ignore signal_handler_connect_global;
|
||||||
|
%ignore signal_handler_disconnect_global;
|
||||||
|
%ignore signal_handler_remove_current;
|
||||||
|
%ignore obs_hotkey_register_frontend;
|
||||||
|
%ignore obs_hotkey_register_encoder;
|
||||||
|
%ignore obs_hotkey_register_output;
|
||||||
|
%ignore obs_hotkey_register_service;
|
||||||
|
%ignore obs_hotkey_register_source;
|
||||||
|
%ignore obs_hotkey_pair_register_frontend;
|
||||||
|
%ignore obs_hotkey_pair_register_encoder;
|
||||||
|
%ignore obs_hotkey_pair_register_output;
|
||||||
|
%ignore obs_hotkey_pair_register_service;
|
||||||
|
%ignore obs_hotkey_pair_register_source;
|
||||||
|
|
||||||
|
%include "graphics/graphics.h"
|
||||||
|
%include "graphics/vec4.h"
|
||||||
|
%include "graphics/vec3.h"
|
||||||
|
%include "graphics/vec2.h"
|
||||||
|
%include "graphics/quat.h"
|
||||||
|
%include "obs-data.h"
|
||||||
|
%include "obs-source.h"
|
||||||
|
%include "obs-properties.h"
|
||||||
|
%include "obs-interaction.h"
|
||||||
|
%include "obs-hotkey.h"
|
||||||
|
%include "obs.h"
|
||||||
|
%include "callback/calldata.h"
|
||||||
|
%include "callback/proc.h"
|
||||||
|
%include "callback/signal.h"
|
||||||
|
%include "util/bmem.h"
|
||||||
|
%include "util/base.h"
|
||||||
|
%include "obs-scripting-config.h"
|
||||||
|
|
||||||
|
#if UI_ENABLED
|
||||||
|
%include "obs-frontend-api.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* declare these manually because mutex + GIL = deadlocks */
|
||||||
|
%thread;
|
||||||
|
void obs_enter_graphics(void); //Should only block on entering mutex
|
||||||
|
%nothread;
|
||||||
|
%include "obs.h"
|
Loading…
Reference in New Issue
Block a user