daemon: add a mode to execute lua scripts from the command line
This can be useful for quick testing of scripts, or to build small utilities that do something in pipewire utilizing our lua API
This commit is contained in:
@@ -37,7 +37,7 @@ if SANDBOX_CONFIG["minimal_std"] then
|
|||||||
else
|
else
|
||||||
-- full list, used for scripts
|
-- full list, used for scripts
|
||||||
([[
|
([[
|
||||||
_VERSION assert error ipairs next pairs
|
_VERSION assert error ipairs next pairs print
|
||||||
pcall select tonumber tostring type xpcall
|
pcall select tonumber tostring type xpcall
|
||||||
|
|
||||||
table utf8
|
table utf8
|
||||||
|
@@ -101,11 +101,37 @@ core_sync (lua_State *L)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
core_disconnect (WpCore * core)
|
||||||
|
{
|
||||||
|
wp_core_disconnect (core);
|
||||||
|
return G_SOURCE_REMOVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
core_quit (lua_State *L)
|
||||||
|
{
|
||||||
|
WpCore * core = get_wp_core (L);
|
||||||
|
g_autoptr (WpProperties) p = wp_core_get_properties (core);
|
||||||
|
const gchar *interactive = wp_properties_get (p, "wireplumber.interactive");
|
||||||
|
if (!interactive || g_strcmp0 (interactive, "true") != 0) {
|
||||||
|
wp_warning ("script attempted to quit, but wireplumber "
|
||||||
|
"is not running in script interactive mode; ignoring");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* wp_core_disconnect() will immediately destroy the lua plugin
|
||||||
|
and the lua engine, so we cannot call it directly */
|
||||||
|
wp_core_idle_add (core, NULL, G_SOURCE_FUNC (core_disconnect), core, NULL);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const luaL_Reg core_funcs[] = {
|
static const luaL_Reg core_funcs[] = {
|
||||||
{ "get_info", core_get_info },
|
{ "get_info", core_get_info },
|
||||||
{ "idle_add", core_idle_add },
|
{ "idle_add", core_idle_add },
|
||||||
{ "timeout_add", core_timeout_add },
|
{ "timeout_add", core_timeout_add },
|
||||||
{ "sync", core_sync },
|
{ "sync", core_sync },
|
||||||
|
{ "quit", core_quit },
|
||||||
{ NULL, NULL }
|
{ NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
68
src/main.c
68
src/main.c
@@ -10,15 +10,6 @@
|
|||||||
#include <glib-unix.h>
|
#include <glib-unix.h>
|
||||||
#include <pipewire/keys.h>
|
#include <pipewire/keys.h>
|
||||||
|
|
||||||
static gchar * config_file = NULL;
|
|
||||||
|
|
||||||
static GOptionEntry entries[] =
|
|
||||||
{
|
|
||||||
{ "config-file", 'c', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &config_file,
|
|
||||||
"The configuration file to load components from", NULL },
|
|
||||||
{ NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
#define WP_DOMAIN_DAEMON (wp_domain_daemon_quark ())
|
#define WP_DOMAIN_DAEMON (wp_domain_daemon_quark ())
|
||||||
static G_DEFINE_QUARK (wireplumber-daemon, wp_domain_daemon);
|
static G_DEFINE_QUARK (wireplumber-daemon, wp_domain_daemon);
|
||||||
|
|
||||||
@@ -30,6 +21,40 @@ enum WpExitCode
|
|||||||
WP_CODE_INVALID_ARGUMENT,
|
WP_CODE_INVALID_ARGUMENT,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static gchar * config_file = NULL;
|
||||||
|
static gchar * exec_script = NULL;
|
||||||
|
static GVariantBuilder exec_args_b =
|
||||||
|
G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE_VARDICT);
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
parse_exec_script_arg (const gchar *option_name, const gchar *value,
|
||||||
|
gpointer data, GError **error)
|
||||||
|
{
|
||||||
|
g_auto(GStrv) tokens = g_strsplit (value, "=", 2);
|
||||||
|
if (!tokens[0] || *g_strstrip (tokens[0]) == '\0') {
|
||||||
|
g_set_error (error, WP_DOMAIN_DAEMON, WP_CODE_INVALID_ARGUMENT,
|
||||||
|
"invalid script argument '%s'; must be in key=value format", value);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_variant_builder_add (&exec_args_b, "{sv}", tokens[0], tokens[1] ?
|
||||||
|
g_variant_new_string (g_strstrip (tokens[1])) :
|
||||||
|
g_variant_new_boolean (TRUE));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GOptionEntry entries[] =
|
||||||
|
{
|
||||||
|
{ "config-file", 'c', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &config_file,
|
||||||
|
"The configuration file to load components from", NULL },
|
||||||
|
{ "execute", 'e', G_OPTION_FLAG_NONE, G_OPTION_ARG_STRING, &exec_script,
|
||||||
|
"Runs WirePlumber in interactive script execution mode, "
|
||||||
|
"executing the given script", NULL },
|
||||||
|
{ G_OPTION_REMAINING, 0, G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK,
|
||||||
|
parse_exec_script_arg, NULL, NULL },
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
/*** WpInitTransition ***/
|
/*** WpInitTransition ***/
|
||||||
|
|
||||||
struct _WpInitTransition
|
struct _WpInitTransition
|
||||||
@@ -42,6 +67,7 @@ struct _WpInitTransition
|
|||||||
enum {
|
enum {
|
||||||
STEP_LOAD_MODULE = WP_TRANSITION_STEP_CUSTOM_START,
|
STEP_LOAD_MODULE = WP_TRANSITION_STEP_CUSTOM_START,
|
||||||
STEP_LOAD_CONFIG,
|
STEP_LOAD_CONFIG,
|
||||||
|
STEP_LOAD_SCRIPT,
|
||||||
STEP_CONNECT,
|
STEP_CONNECT,
|
||||||
STEP_ACTIVATE_PLUGINS,
|
STEP_ACTIVATE_PLUGINS,
|
||||||
STEP_ACTIVATE_SCRIPTS,
|
STEP_ACTIVATE_SCRIPTS,
|
||||||
@@ -61,9 +87,16 @@ wp_init_transition_get_next_step (WpTransition * transition, guint step)
|
|||||||
{
|
{
|
||||||
switch (step) {
|
switch (step) {
|
||||||
case WP_TRANSITION_STEP_NONE: return STEP_LOAD_MODULE;
|
case WP_TRANSITION_STEP_NONE: return STEP_LOAD_MODULE;
|
||||||
case STEP_LOAD_MODULE: return STEP_LOAD_CONFIG;
|
|
||||||
case STEP_LOAD_CONFIG: return STEP_CONNECT;
|
|
||||||
case STEP_CONNECT: return STEP_ACTIVATE_PLUGINS;
|
case STEP_CONNECT: return STEP_ACTIVATE_PLUGINS;
|
||||||
|
case STEP_ACTIVATE_SCRIPTS: return WP_TRANSITION_STEP_NONE;
|
||||||
|
|
||||||
|
case STEP_LOAD_MODULE:
|
||||||
|
return exec_script ? STEP_LOAD_SCRIPT : STEP_LOAD_CONFIG;
|
||||||
|
|
||||||
|
case STEP_LOAD_CONFIG:
|
||||||
|
case STEP_LOAD_SCRIPT:
|
||||||
|
return STEP_CONNECT;
|
||||||
|
|
||||||
case STEP_ACTIVATE_PLUGINS: {
|
case STEP_ACTIVATE_PLUGINS: {
|
||||||
WpInitTransition *self = WP_INIT_TRANSITION (transition);
|
WpInitTransition *self = WP_INIT_TRANSITION (transition);
|
||||||
if (self->pending_plugins == 0)
|
if (self->pending_plugins == 0)
|
||||||
@@ -71,7 +104,7 @@ wp_init_transition_get_next_step (WpTransition * transition, guint step)
|
|||||||
else
|
else
|
||||||
return STEP_ACTIVATE_PLUGINS;
|
return STEP_ACTIVATE_PLUGINS;
|
||||||
}
|
}
|
||||||
case STEP_ACTIVATE_SCRIPTS: return WP_TRANSITION_STEP_NONE;
|
|
||||||
default:
|
default:
|
||||||
g_return_val_if_reached (WP_TRANSITION_STEP_ERROR);
|
g_return_val_if_reached (WP_TRANSITION_STEP_ERROR);
|
||||||
}
|
}
|
||||||
@@ -127,6 +160,16 @@ wp_init_transition_execute_step (WpTransition * transition, guint step)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case STEP_LOAD_SCRIPT: {
|
||||||
|
GVariant *args = g_variant_builder_end (&exec_args_b);
|
||||||
|
if (!wp_core_load_component (core, exec_script, "script/lua", args, &error)) {
|
||||||
|
wp_transition_return_error (transition, error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wp_transition_advance (transition);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case STEP_CONNECT:
|
case STEP_CONNECT:
|
||||||
g_signal_connect_object (core, "connected",
|
g_signal_connect_object (core, "connected",
|
||||||
G_CALLBACK (wp_transition_advance), transition, G_CONNECT_SWAPPED);
|
G_CALLBACK (wp_transition_advance), transition, G_CONNECT_SWAPPED);
|
||||||
@@ -281,6 +324,7 @@ main (gint argc, gchar **argv)
|
|||||||
d.loop = g_main_loop_new (NULL, FALSE);
|
d.loop = g_main_loop_new (NULL, FALSE);
|
||||||
d.core = wp_core_new (NULL, wp_properties_new (
|
d.core = wp_core_new (NULL, wp_properties_new (
|
||||||
PW_KEY_APP_NAME, "WirePlumber",
|
PW_KEY_APP_NAME, "WirePlumber",
|
||||||
|
"wireplumber.interactive", exec_script ? "true" : "false",
|
||||||
NULL));
|
NULL));
|
||||||
g_signal_connect (d.core, "disconnected", G_CALLBACK (on_disconnected), &d);
|
g_signal_connect (d.core, "disconnected", G_CALLBACK (on_disconnected), &d);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user