m-lua-scripting: refactor as a WpComponentLoader
also, add support for loading lua config files, denoted by the "config/lua" component type
This commit is contained in:
@@ -186,8 +186,8 @@ shared_library(
|
|||||||
'wireplumber-module-lua-scripting',
|
'wireplumber-module-lua-scripting',
|
||||||
[
|
[
|
||||||
'module-lua-scripting.c',
|
'module-lua-scripting.c',
|
||||||
'module-lua-scripting/engine.c',
|
|
||||||
'module-lua-scripting/api.c',
|
'module-lua-scripting/api.c',
|
||||||
|
'module-lua-scripting/config.c',
|
||||||
m_lua_scripting_resources,
|
m_lua_scripting_resources,
|
||||||
],
|
],
|
||||||
c_args : [common_c_args, '-DG_LOG_DOMAIN="m-lua-scripting"'],
|
c_args : [common_c_args, '-DG_LOG_DOMAIN="m-lua-scripting"'],
|
||||||
|
@@ -10,107 +10,33 @@
|
|||||||
#include <wplua/wplua.h>
|
#include <wplua/wplua.h>
|
||||||
#include <pipewire/keys.h>
|
#include <pipewire/keys.h>
|
||||||
|
|
||||||
#define WP_TYPE_LUA_SCRIPTING_ENGINE \
|
|
||||||
(wp_lua_scripting_engine_get_type ())
|
|
||||||
GType wp_lua_scripting_engine_get_type ();
|
|
||||||
void wp_lua_scripting_api_init (lua_State *L);
|
void wp_lua_scripting_api_init (lua_State *L);
|
||||||
|
gboolean wp_lua_scripting_load_configuration (const gchar * conf_file,
|
||||||
|
WpCore * core, GError ** error);
|
||||||
|
|
||||||
struct _WpLuaScriptingPlugin
|
struct _WpLuaScriptingPlugin
|
||||||
{
|
{
|
||||||
WpPlugin parent;
|
WpComponentLoader parent;
|
||||||
|
|
||||||
/* properties */
|
|
||||||
gchar *profile;
|
|
||||||
|
|
||||||
/* data */
|
|
||||||
WpCore *export_core;
|
WpCore *export_core;
|
||||||
gchar *config_ext;
|
lua_State *L;
|
||||||
|
|
||||||
WpConfiguration *config;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
|
||||||
PROP_0,
|
|
||||||
PROP_PROFILE,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DECLARE_FINAL_TYPE (WpLuaScriptingPlugin, wp_lua_scripting_plugin,
|
G_DECLARE_FINAL_TYPE (WpLuaScriptingPlugin, wp_lua_scripting_plugin,
|
||||||
WP, LUA_SCRIPTING_PLUGIN, WpPlugin)
|
WP, LUA_SCRIPTING_PLUGIN, WpComponentLoader)
|
||||||
G_DEFINE_TYPE (WpLuaScriptingPlugin, wp_lua_scripting_plugin, WP_TYPE_PLUGIN)
|
G_DEFINE_TYPE (WpLuaScriptingPlugin, wp_lua_scripting_plugin,
|
||||||
|
WP_TYPE_COMPONENT_LOADER)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
wp_lua_scripting_plugin_init (WpLuaScriptingPlugin * self)
|
wp_lua_scripting_plugin_init (WpLuaScriptingPlugin * self)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
wp_lua_scripting_plugin_finalize (GObject * object)
|
|
||||||
{
|
|
||||||
WpLuaScriptingPlugin * self = WP_LUA_SCRIPTING_PLUGIN (object);
|
|
||||||
|
|
||||||
g_clear_pointer (&self->profile, g_free);
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (wp_lua_scripting_plugin_parent_class)->finalize (object);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
wp_lua_scripting_plugin_set_property (GObject * object, guint property_id,
|
|
||||||
const GValue * value, GParamSpec * pspec)
|
|
||||||
{
|
|
||||||
WpLuaScriptingPlugin * self = WP_LUA_SCRIPTING_PLUGIN (object);
|
|
||||||
|
|
||||||
switch (property_id) {
|
|
||||||
case PROP_PROFILE:
|
|
||||||
g_clear_pointer (&self->profile, g_free);
|
|
||||||
self->profile = g_value_dup_string (value);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
wp_lua_scripting_plugin_get_property (GObject * object, guint property_id,
|
|
||||||
GValue * value, GParamSpec * pspec)
|
|
||||||
{
|
|
||||||
WpLuaScriptingPlugin * self = WP_LUA_SCRIPTING_PLUGIN (object);
|
|
||||||
|
|
||||||
switch (property_id) {
|
|
||||||
case PROP_PROFILE:
|
|
||||||
g_value_set_string (value, self->profile);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
wp_lua_scripting_plugin_init_lua_ctx (WpConfigParser * engine, lua_State * L,
|
|
||||||
WpLuaScriptingPlugin * self)
|
|
||||||
{
|
|
||||||
g_autoptr (WpCore) core = wp_object_get_core (WP_OBJECT (self));
|
|
||||||
|
|
||||||
lua_pushliteral (L, "wireplumber_core");
|
|
||||||
lua_pushlightuserdata (L, core);
|
|
||||||
lua_settable (L, LUA_REGISTRYINDEX);
|
|
||||||
|
|
||||||
lua_pushliteral (L, "wireplumber_export_core");
|
|
||||||
lua_pushlightuserdata (L, self->export_core);
|
|
||||||
lua_settable (L, LUA_REGISTRYINDEX);
|
|
||||||
|
|
||||||
wp_lua_scripting_api_init (L);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
wp_lua_scripting_plugin_enable (WpPlugin * plugin, WpTransition * transition)
|
wp_lua_scripting_plugin_enable (WpPlugin * plugin, WpTransition * transition)
|
||||||
{
|
{
|
||||||
WpLuaScriptingPlugin * self = WP_LUA_SCRIPTING_PLUGIN (plugin);
|
WpLuaScriptingPlugin * self = WP_LUA_SCRIPTING_PLUGIN (plugin);
|
||||||
g_autoptr (WpCore) core = wp_object_get_core (WP_OBJECT (plugin));
|
g_autoptr (WpCore) core = wp_object_get_core (WP_OBJECT (plugin));
|
||||||
g_autoptr (WpConfigParser) engine = NULL;
|
|
||||||
|
|
||||||
self->config = wp_configuration_get_instance (core);
|
|
||||||
|
|
||||||
/* initialize secondary connection to pipewire */
|
/* initialize secondary connection to pipewire */
|
||||||
self->export_core = wp_core_clone (core);
|
self->export_core = wp_core_clone (core);
|
||||||
@@ -124,16 +50,20 @@ wp_lua_scripting_plugin_enable (WpPlugin * plugin, WpTransition * transition)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* load the lua scripts & execute them via the engine */
|
/* init lua engine */
|
||||||
self->config_ext = g_strdup_printf ("%s/lua", self->profile);
|
self->L = wplua_new ();
|
||||||
wp_configuration_add_extension (self->config, self->config_ext,
|
|
||||||
WP_TYPE_LUA_SCRIPTING_ENGINE);
|
|
||||||
|
|
||||||
engine = wp_configuration_get_parser (self->config, self->config_ext);
|
lua_pushliteral (self->L, "wireplumber_core");
|
||||||
g_signal_connect_object (engine, "init-lua-context",
|
lua_pushlightuserdata (self->L, core);
|
||||||
G_CALLBACK (wp_lua_scripting_plugin_init_lua_ctx), self, 0);
|
lua_settable (self->L, LUA_REGISTRYINDEX);
|
||||||
|
|
||||||
|
lua_pushliteral (self->L, "wireplumber_export_core");
|
||||||
|
lua_pushlightuserdata (self->L, self->export_core);
|
||||||
|
lua_settable (self->L, LUA_REGISTRYINDEX);
|
||||||
|
|
||||||
|
wp_lua_scripting_api_init (self->L);
|
||||||
|
wplua_enable_sandbox (self->L, WP_LUA_SANDBOX_ISOLATE_ENV);
|
||||||
|
|
||||||
wp_configuration_reload (self->config, self->config_ext);
|
|
||||||
wp_object_update_features (WP_OBJECT (self), WP_PLUGIN_FEATURE_ENABLED, 0);
|
wp_object_update_features (WP_OBJECT (self), WP_PLUGIN_FEATURE_ENABLED, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,47 +72,88 @@ wp_lua_scripting_plugin_disable (WpPlugin * plugin)
|
|||||||
{
|
{
|
||||||
WpLuaScriptingPlugin * self = WP_LUA_SCRIPTING_PLUGIN (plugin);
|
WpLuaScriptingPlugin * self = WP_LUA_SCRIPTING_PLUGIN (plugin);
|
||||||
|
|
||||||
if (self->config && self->config_ext)
|
g_clear_pointer (&self->L, wplua_free);
|
||||||
wp_configuration_remove_extension (self->config, self->config_ext);
|
|
||||||
g_clear_object (&self->config);
|
|
||||||
g_clear_pointer (&self->config_ext, g_free);
|
|
||||||
g_clear_object (&self->export_core);
|
g_clear_object (&self->export_core);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
wp_lua_scripting_plugin_supports_type (WpComponentLoader * cl,
|
||||||
|
const gchar * type)
|
||||||
|
{
|
||||||
|
return (!g_strcmp0 (type, "script/lua") || !g_strcmp0 (type, "config/lua"));
|
||||||
|
}
|
||||||
|
|
||||||
|
static gchar *
|
||||||
|
find_script (const gchar * script)
|
||||||
|
{
|
||||||
|
if (g_path_is_absolute (script) &&
|
||||||
|
g_file_test (script, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
|
||||||
|
return g_strdup (script);
|
||||||
|
|
||||||
|
/* /etc/wireplumber/scripts */
|
||||||
|
{
|
||||||
|
g_autofree gchar * file = g_build_filename (
|
||||||
|
wp_get_config_dir (), "scripts", script, NULL);
|
||||||
|
if (g_file_test (file, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
|
||||||
|
return g_steal_pointer (&file);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* {XDG_DATA_DIRS,/usr/local/share,/usr/share}/wireplumber/scripts */
|
||||||
|
const gchar * const * data_dirs = g_get_system_data_dirs ();
|
||||||
|
while (*data_dirs) {
|
||||||
|
g_autofree gchar * file = g_build_filename (
|
||||||
|
*data_dirs, "wireplumber", "scripts", script, NULL);
|
||||||
|
if (g_file_test (file, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
|
||||||
|
return g_steal_pointer (&file);
|
||||||
|
data_dirs++;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
wp_lua_scripting_plugin_load (WpComponentLoader * cl, const gchar * component,
|
||||||
|
const gchar * type, GVariant * args, GError ** error)
|
||||||
|
{
|
||||||
|
WpLuaScriptingPlugin * self = WP_LUA_SCRIPTING_PLUGIN (cl);
|
||||||
|
|
||||||
|
/* interpret component as a script */
|
||||||
|
if (!g_strcmp0 (type, "script/lua")) {
|
||||||
|
g_autofree gchar * file = find_script (component);
|
||||||
|
if (!file) {
|
||||||
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
|
||||||
|
"Could not locate script '%s'", component);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return wplua_load_path (self->L, file, error);
|
||||||
|
}
|
||||||
|
/* interpret component as a configuration file */
|
||||||
|
else if (!g_strcmp0 (type, "config/lua")) {
|
||||||
|
g_autoptr (WpCore) core = wp_object_get_core (WP_OBJECT (cl));
|
||||||
|
return wp_lua_scripting_load_configuration (component, core, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_return_val_if_reached (FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
wp_lua_scripting_plugin_class_init (WpLuaScriptingPluginClass * klass)
|
wp_lua_scripting_plugin_class_init (WpLuaScriptingPluginClass * klass)
|
||||||
{
|
{
|
||||||
GObjectClass *object_class = (GObjectClass *) klass;
|
|
||||||
WpPluginClass *plugin_class = (WpPluginClass *) klass;
|
WpPluginClass *plugin_class = (WpPluginClass *) klass;
|
||||||
|
WpComponentLoaderClass *cl_class = (WpComponentLoaderClass *) klass;
|
||||||
object_class->finalize = wp_lua_scripting_plugin_finalize;
|
|
||||||
object_class->set_property = wp_lua_scripting_plugin_set_property;
|
|
||||||
object_class->get_property = wp_lua_scripting_plugin_get_property;
|
|
||||||
|
|
||||||
plugin_class->enable = wp_lua_scripting_plugin_enable;
|
plugin_class->enable = wp_lua_scripting_plugin_enable;
|
||||||
plugin_class->disable = wp_lua_scripting_plugin_disable;
|
plugin_class->disable = wp_lua_scripting_plugin_disable;
|
||||||
|
|
||||||
g_object_class_install_property(object_class, PROP_PROFILE,
|
cl_class->supports_type = wp_lua_scripting_plugin_supports_type;
|
||||||
g_param_spec_string ("profile", "profile",
|
cl_class->load = wp_lua_scripting_plugin_load;
|
||||||
"The configuration profile", NULL,
|
|
||||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WP_PLUGIN_EXPORT gboolean
|
WP_PLUGIN_EXPORT gboolean
|
||||||
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
|
wireplumber__module_init (WpCore * core, GVariant * args, GError ** error)
|
||||||
{
|
{
|
||||||
const gchar *profile;
|
|
||||||
|
|
||||||
if (!g_variant_lookup (args, "profile", "&s", &profile)) {
|
|
||||||
g_set_error (error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_INVALID_ARGUMENT,
|
|
||||||
"module-lua-scripting requires a 'profile'");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
wp_plugin_register (g_object_new (wp_lua_scripting_plugin_get_type (),
|
wp_plugin_register (g_object_new (wp_lua_scripting_plugin_get_type (),
|
||||||
"name", "lua-scripting",
|
"name", "lua-scripting",
|
||||||
"core", core,
|
"core", core,
|
||||||
"profile", profile,
|
|
||||||
NULL));
|
NULL));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
226
modules/module-lua-scripting/config.c
Normal file
226
modules/module-lua-scripting/config.c
Normal file
@@ -0,0 +1,226 @@
|
|||||||
|
/* WirePlumber
|
||||||
|
*
|
||||||
|
* Copyright © 2020 Collabora Ltd.
|
||||||
|
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <wp/wp.h>
|
||||||
|
#include <wplua/wplua.h>
|
||||||
|
#include <pipewire/pipewire.h>
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
add_spa_libs (lua_State *L, WpCore * core, GError ** error)
|
||||||
|
{
|
||||||
|
switch (lua_getglobal (L, "spa_libs")) {
|
||||||
|
case LUA_TTABLE:
|
||||||
|
break;
|
||||||
|
case LUA_TNIL:
|
||||||
|
goto done;
|
||||||
|
default:
|
||||||
|
g_set_error (error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_INVALID_ARGUMENT,
|
||||||
|
"Expected 'spa_libs' to be a table");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_pushnil (L);
|
||||||
|
while (lua_next (L, -2)) {
|
||||||
|
if (lua_type (L, -2) != LUA_TSTRING ||
|
||||||
|
lua_type (L, -1) != LUA_TSTRING) {
|
||||||
|
g_set_error (error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_INVALID_ARGUMENT,
|
||||||
|
"'spa_libs' must be a table with string keys and string values");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
const gchar *regex = lua_tostring (L, -2);
|
||||||
|
const gchar *lib = lua_tostring (L, -1);
|
||||||
|
|
||||||
|
int ret = pw_context_add_spa_lib (wp_core_get_pw_context (core), regex,
|
||||||
|
lib);
|
||||||
|
if (ret < 0) {
|
||||||
|
g_set_error (error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_OPERATION_FAILED,
|
||||||
|
"failed to add spa lib ('%s' on '%s'): %s", regex, lib,
|
||||||
|
g_strerror (-ret));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_pop (L, 1); /* pop the value */
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
lua_pop (L, 1); /* pop the spa_libs table */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GVariant *
|
||||||
|
lua_to_gvariant (lua_State *L, int index)
|
||||||
|
{
|
||||||
|
GVariantBuilder b;
|
||||||
|
g_variant_builder_init (&b, G_VARIANT_TYPE_VARDICT);
|
||||||
|
|
||||||
|
int table = lua_absindex (L, index);
|
||||||
|
|
||||||
|
lua_pushnil (L);
|
||||||
|
while (lua_next (L, table)) {
|
||||||
|
/* each argument must have a string as key */
|
||||||
|
if (lua_type (L, -2) != LUA_TSTRING) {
|
||||||
|
wp_warning ("skipping bad component argument key");
|
||||||
|
continue; /* skip, it's probably harmless */
|
||||||
|
}
|
||||||
|
const char *key = lua_tostring (L, -2);
|
||||||
|
|
||||||
|
switch (lua_type (L, -1)) {
|
||||||
|
case LUA_TBOOLEAN:
|
||||||
|
g_variant_builder_add (&b, "{sv}", key,
|
||||||
|
g_variant_new_boolean (lua_toboolean (L, -1)));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LUA_TNUMBER:
|
||||||
|
if (lua_isinteger (L, -1)) {
|
||||||
|
g_variant_builder_add (&b, "{sv}", key,
|
||||||
|
g_variant_new_int64 (lua_tointeger (L, -1)));
|
||||||
|
} else {
|
||||||
|
g_variant_builder_add (&b, "{sv}", key,
|
||||||
|
g_variant_new_double (lua_tonumber (L, -1)));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LUA_TSTRING:
|
||||||
|
g_variant_builder_add (&b, "{sv}", key,
|
||||||
|
g_variant_new_string (lua_tostring (L, -1)));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LUA_TTABLE:
|
||||||
|
g_variant_builder_add (&b, "{sv}", key, lua_to_gvariant (L, -1));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
wp_warning ("skipping bad component argument value");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_pop (L, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_variant_builder_end (&b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
load_components (lua_State *L, WpCore * core, GError ** error)
|
||||||
|
{
|
||||||
|
switch (lua_getglobal (L, "components")) {
|
||||||
|
case LUA_TTABLE:
|
||||||
|
break;
|
||||||
|
case LUA_TNIL:
|
||||||
|
goto done;
|
||||||
|
default:
|
||||||
|
g_set_error (error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_INVALID_ARGUMENT,
|
||||||
|
"Expected 'components' to be a table");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
lua_pushnil (L);
|
||||||
|
while (lua_next (L, -2)) {
|
||||||
|
/* value must be a table */
|
||||||
|
if (lua_type (L, -1) != LUA_TTABLE) {
|
||||||
|
g_set_error (error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_INVALID_ARGUMENT,
|
||||||
|
"'components' must be a table with tables as values");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* record indexes to the current key and value of the components table */
|
||||||
|
int key = lua_absindex (L, -2);
|
||||||
|
int table = lua_absindex (L, -1);
|
||||||
|
|
||||||
|
/* get component */
|
||||||
|
if (lua_geti (L, table, 1) != LUA_TSTRING) {
|
||||||
|
g_set_error (error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_INVALID_ARGUMENT,
|
||||||
|
"components['%s'] has a non-string or unspecified component name",
|
||||||
|
lua_tostring (L, key));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
const char * component = lua_tostring (L, -1);
|
||||||
|
|
||||||
|
/* get component type */
|
||||||
|
if (lua_getfield (L, table, "type") != LUA_TSTRING) {
|
||||||
|
g_set_error (error, WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_INVALID_ARGUMENT,
|
||||||
|
"components['%s'] has a non-string or unspecified component type",
|
||||||
|
lua_tostring (L, key));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
const char * type = lua_tostring (L, -1);
|
||||||
|
|
||||||
|
/* optional component arguments */
|
||||||
|
GVariant *args = NULL;
|
||||||
|
if (lua_getfield (L, table, "args") == LUA_TTABLE) {
|
||||||
|
args = lua_to_gvariant (L, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wp_core_load_component (core, component, type, args, error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* clear the stack up to the key */
|
||||||
|
lua_settop (L, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
lua_pop (L, 1); /* pop the components table */
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
wp_lua_scripting_load_configuration (const gchar * conf_file,
|
||||||
|
WpCore * core, GError ** error)
|
||||||
|
{
|
||||||
|
g_autofree gchar * path = NULL;
|
||||||
|
g_autoptr (lua_State) L = wplua_new ();
|
||||||
|
gboolean found = FALSE;
|
||||||
|
|
||||||
|
wplua_enable_sandbox (L, WP_LUA_SANDBOX_MINIMAL_STD);
|
||||||
|
|
||||||
|
/* load conf_file itself */
|
||||||
|
path = g_build_filename (wp_get_config_dir (), conf_file, NULL);
|
||||||
|
if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
|
||||||
|
wp_info ("loading config file: %s", path);
|
||||||
|
if (!wplua_load_path (L, path, error))
|
||||||
|
return FALSE;
|
||||||
|
found = TRUE;
|
||||||
|
}
|
||||||
|
g_clear_pointer (&path, g_free);
|
||||||
|
|
||||||
|
/* aggregate split files from the ${conf_file}.d subdirectory */
|
||||||
|
path = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "%s.d",
|
||||||
|
wp_get_config_dir (), conf_file);
|
||||||
|
if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
|
||||||
|
g_autoptr (GDir) conf_dir = g_dir_open (path, 0, error);
|
||||||
|
if (!conf_dir)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
const gchar *filename = NULL;
|
||||||
|
while ((filename = g_dir_read_name (conf_dir))) {
|
||||||
|
/* Only parse files that have the proper extension */
|
||||||
|
if (g_str_has_suffix (filename, ".lua")) {
|
||||||
|
g_autofree gchar * file = g_build_filename (path, filename, NULL);
|
||||||
|
wp_info ("loading config file: %s", file);
|
||||||
|
if (!wplua_load_path (L, file, error))
|
||||||
|
return FALSE;
|
||||||
|
found = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found) {
|
||||||
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,
|
||||||
|
"Could not locate configuration file '%s'", conf_file);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!add_spa_libs (L, core, error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!load_components (L, core, error))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
@@ -1,91 +0,0 @@
|
|||||||
/* WirePlumber
|
|
||||||
*
|
|
||||||
* Copyright © 2020 Collabora Ltd.
|
|
||||||
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <wp/wp.h>
|
|
||||||
#include <wplua/wplua.h>
|
|
||||||
|
|
||||||
struct _WpLuaScriptingEngine
|
|
||||||
{
|
|
||||||
GObject parent;
|
|
||||||
lua_State *L;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
|
||||||
SIGNAL_INIT_LUA_CONTEXT,
|
|
||||||
N_SIGNALS,
|
|
||||||
};
|
|
||||||
|
|
||||||
static guint signals[N_SIGNALS] = {0};
|
|
||||||
|
|
||||||
static void wp_lua_scripting_engine_parser_iface_init (WpConfigParserInterface * iface);
|
|
||||||
|
|
||||||
G_DECLARE_FINAL_TYPE (WpLuaScriptingEngine, wp_lua_scripting_engine,
|
|
||||||
WP, LUA_SCRIPTING_ENGINE, GObject)
|
|
||||||
G_DEFINE_TYPE_WITH_CODE (WpLuaScriptingEngine, wp_lua_scripting_engine,
|
|
||||||
G_TYPE_OBJECT,
|
|
||||||
G_IMPLEMENT_INTERFACE (WP_TYPE_CONFIG_PARSER,
|
|
||||||
wp_lua_scripting_engine_parser_iface_init))
|
|
||||||
|
|
||||||
static void
|
|
||||||
wp_lua_scripting_engine_init (WpLuaScriptingEngine * self)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
wp_lua_scripting_engine_finalize (GObject * object)
|
|
||||||
{
|
|
||||||
WpLuaScriptingEngine * self = WP_LUA_SCRIPTING_ENGINE (object);
|
|
||||||
|
|
||||||
g_clear_pointer (&self->L, wplua_free);
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (wp_lua_scripting_engine_parent_class)->finalize (object);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
wp_lua_scripting_engine_class_init (WpLuaScriptingEngineClass * klass)
|
|
||||||
{
|
|
||||||
GObjectClass * object_class = (GObjectClass *) klass;
|
|
||||||
|
|
||||||
object_class->finalize = wp_lua_scripting_engine_finalize;
|
|
||||||
|
|
||||||
signals[SIGNAL_INIT_LUA_CONTEXT] = g_signal_new ("init-lua-context",
|
|
||||||
G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL,
|
|
||||||
G_TYPE_NONE, 1, G_TYPE_POINTER);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
wp_lua_scripting_engine_add_file (WpConfigParser * parser, const gchar * file)
|
|
||||||
{
|
|
||||||
WpLuaScriptingEngine * self = WP_LUA_SCRIPTING_ENGINE (parser);
|
|
||||||
g_autoptr (GError) error = NULL;
|
|
||||||
|
|
||||||
if (!wplua_load_path (self->L, file, &error)) {
|
|
||||||
wp_warning_object (self, "%s", error->message);
|
|
||||||
if (error->domain != WP_DOMAIN_LUA || error->code != WP_LUA_ERROR_RUNTIME)
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
wp_lua_scripting_engine_reset (WpConfigParser * parser)
|
|
||||||
{
|
|
||||||
WpLuaScriptingEngine * self = WP_LUA_SCRIPTING_ENGINE (parser);
|
|
||||||
|
|
||||||
g_clear_pointer (&self->L, wplua_free);
|
|
||||||
self->L = wplua_new ();
|
|
||||||
g_signal_emit (self, signals[SIGNAL_INIT_LUA_CONTEXT], 0, self->L);
|
|
||||||
wplua_enable_sandbox (self->L);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
wp_lua_scripting_engine_parser_iface_init (WpConfigParserInterface * iface)
|
|
||||||
{
|
|
||||||
iface->add_file = wp_lua_scripting_engine_add_file;
|
|
||||||
iface->reset = wp_lua_scripting_engine_reset;
|
|
||||||
}
|
|
@@ -1,22 +0,0 @@
|
|||||||
/* WirePlumber
|
|
||||||
*
|
|
||||||
* Copyright © 2020 Collabora Ltd.
|
|
||||||
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: MIT
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __WIREPLUMBER_LUA_SCRIPTING_ENGINE_H__
|
|
||||||
#define __WIREPLUMBER_LUA_SCRIPTING_ENGINE_H__
|
|
||||||
|
|
||||||
#include <wp/wp.h>
|
|
||||||
#include <wplua/wplua.h>
|
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
|
||||||
|
|
||||||
#define WP_TYPE_LUA_SCRIPTING_ENGINE \
|
|
||||||
(wp_lua_scripting_engine_get_type ())
|
|
||||||
|
|
||||||
G_END_DECLS
|
|
||||||
|
|
||||||
#endif
|
|
Reference in New Issue
Block a user