main: Add support for deps flag in loading modules
- support loading modules dependent on wireplumber settings in JSON config. - load the settings module before parsing wireplumber.components, so that dependencies can be fetched during parsing. - access lua scripts are switched to JSON based config and lua configs are removed.
This commit is contained in:

committed by
Julian Bouzas

parent
a5d62b7bbd
commit
a4f16a98f0
@@ -114,8 +114,7 @@ gboolean wp_settings_apply_rule (WpSettings *self, const gchar *rule,
|
|||||||
g_return_val_if_fail (rule, false);
|
g_return_val_if_fail (rule, false);
|
||||||
g_return_val_if_fail (client_props, false);
|
g_return_val_if_fail (client_props, false);
|
||||||
|
|
||||||
wp_debug_object (self, "applying rule(%s) for client props(%d)",
|
wp_debug_object (self, "applying rule(%s) for client props", rule);
|
||||||
rule, wp_properties_get_count (client_props));
|
|
||||||
|
|
||||||
for (guint i = 0; i < self->rules->len; i++) {
|
for (guint i = 0; i < self->rules->len; i++) {
|
||||||
Rule *r = g_ptr_array_index (self->rules, i);
|
Rule *r = g_ptr_array_index (self->rules, i);
|
||||||
@@ -135,8 +134,8 @@ gboolean wp_settings_apply_rule (WpSettings *self, const gchar *rule,
|
|||||||
else
|
else
|
||||||
wp_properties_add (client_props, m->actions);
|
wp_properties_add (client_props, m->actions);
|
||||||
|
|
||||||
wp_debug_object (self, ". match found with actions(%d)",
|
wp_debug_object (self, ". match found for rule(%s) with actions"
|
||||||
wp_properties_get_count(m->actions));
|
"(%d)", rule, wp_properties_get_count(m->actions));
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@@ -1476,12 +1476,12 @@ static gboolean
|
|||||||
get_boolean (lua_State *L)
|
get_boolean (lua_State *L)
|
||||||
{
|
{
|
||||||
const char *setting = luaL_checkstring (L, 1);
|
const char *setting = luaL_checkstring (L, 1);
|
||||||
const char *metadata_name = NULL;
|
const char *m = NULL;
|
||||||
|
|
||||||
if (lua_type (L, 2) == LUA_TSTRING)
|
if (lua_type (L, 2) == LUA_TSTRING)
|
||||||
metadata_name = luaL_checkstring (L, 2);
|
m = luaL_checkstring (L, 2);
|
||||||
|
|
||||||
g_autoptr (WpSettings) s = wp_settings_get_instance (get_wp_core (L), metadata_name);
|
g_autoptr (WpSettings) s = wp_settings_get_instance (get_wp_core (L), m);
|
||||||
|
|
||||||
if (s)
|
if (s)
|
||||||
{
|
{
|
||||||
@@ -1497,14 +1497,14 @@ static gboolean
|
|||||||
apply_rule (lua_State *L)
|
apply_rule (lua_State *L)
|
||||||
{
|
{
|
||||||
const char *r = luaL_checkstring (L, 1);
|
const char *r = luaL_checkstring (L, 1);
|
||||||
const char *metadata_name = NULL;
|
const char *m = NULL;
|
||||||
g_autoptr (WpProperties) cp = wplua_table_to_properties (L, 2);
|
g_autoptr (WpProperties) cp = wplua_table_to_properties (L, 2);
|
||||||
g_autoptr (WpProperties) ap = wp_properties_new_empty ();
|
g_autoptr (WpProperties) ap = wp_properties_new_empty ();
|
||||||
|
|
||||||
if (lua_type (L, -1) == LUA_TSTRING)
|
if (lua_type (L, -1) == LUA_TSTRING)
|
||||||
metadata_name = luaL_checkstring (L, -1);
|
m = luaL_checkstring (L, -1);
|
||||||
|
|
||||||
g_autoptr (WpSettings) s = wp_settings_get_instance (get_wp_core (L), metadata_name);
|
g_autoptr (WpSettings) s = wp_settings_get_instance (get_wp_core (L), m);
|
||||||
|
|
||||||
if (s)
|
if (s)
|
||||||
{
|
{
|
||||||
|
@@ -56,6 +56,7 @@ wp_lua_scripting_package_searcher (lua_State *L)
|
|||||||
lua_pushcfunction (L, wp_lua_scripting_package_loader);
|
lua_pushcfunction (L, wp_lua_scripting_package_loader);
|
||||||
|
|
||||||
/* 2. loader data (param to 1) */
|
/* 2. loader data (param to 1) */
|
||||||
|
wp_debug ("Executing script %s", script);
|
||||||
if (!wplua_load_path (L, script, &error)) {
|
if (!wplua_load_path (L, script, &error)) {
|
||||||
lua_pop (L, 1);
|
lua_pop (L, 1);
|
||||||
lua_pushstring (L, error->message);
|
lua_pushstring (L, error->message);
|
||||||
@@ -206,6 +207,7 @@ wp_lua_scripting_plugin_load (WpComponentLoader * cl, const gchar * component,
|
|||||||
wp_plugin_register (g_steal_pointer (&script));
|
wp_plugin_register (g_steal_pointer (&script));
|
||||||
} else {
|
} else {
|
||||||
/* keep in a list and delay registering until the plugin is enabled */
|
/* keep in a list and delay registering until the plugin is enabled */
|
||||||
|
wp_debug ("queing script %s", filename);
|
||||||
g_ptr_array_add (self->scripts, g_steal_pointer (&script));
|
g_ptr_array_add (self->scripts, g_steal_pointer (&script));
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
@@ -145,7 +145,6 @@ do_parse_settings (void *data, const char *location,
|
|||||||
g_autoptr (WpIterator) iter = wp_spa_json_new_iterator (json);
|
g_autoptr (WpIterator) iter = wp_spa_json_new_iterator (json);
|
||||||
g_auto (GValue) item = G_VALUE_INIT;
|
g_auto (GValue) item = G_VALUE_INIT;
|
||||||
|
|
||||||
|
|
||||||
if (!wp_spa_json_is_object (json)) {
|
if (!wp_spa_json_is_object (json)) {
|
||||||
/* "wireplumber.settings" section has to be a JSON object element. */
|
/* "wireplumber.settings" section has to be a JSON object element. */
|
||||||
wp_transition_return_error (transition, g_error_new (
|
wp_transition_return_error (transition, g_error_new (
|
||||||
|
@@ -1,19 +0,0 @@
|
|||||||
default_access = {}
|
|
||||||
default_access.properties = {}
|
|
||||||
default_access.rules = {}
|
|
||||||
|
|
||||||
function default_access.enable()
|
|
||||||
if default_access.enabled == false then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
load_access("default", {
|
|
||||||
rules = default_access.rules
|
|
||||||
})
|
|
||||||
|
|
||||||
if default_access.properties["enable-flatpak-portal"] then
|
|
||||||
-- Enables portal permissions via org.freedesktop.impl.portal.PermissionStore
|
|
||||||
load_module("portal-permissionstore")
|
|
||||||
load_access("portal")
|
|
||||||
end
|
|
||||||
end
|
|
@@ -2,9 +2,6 @@
|
|||||||
-- dynamic properties of pipewire objects in RAM
|
-- dynamic properties of pipewire objects in RAM
|
||||||
load_module("metadata")
|
load_module("metadata")
|
||||||
|
|
||||||
-- Default client access policy
|
|
||||||
default_access.enable()
|
|
||||||
|
|
||||||
-- Load devices
|
-- Load devices
|
||||||
alsa_monitor.enable()
|
alsa_monitor.enable()
|
||||||
v4l2_monitor.enable()
|
v4l2_monitor.enable()
|
||||||
|
@@ -85,11 +85,9 @@ wireplumber.components = [
|
|||||||
# The lua scripting engine
|
# The lua scripting engine
|
||||||
{ name = libwireplumber-module-lua-scripting, type = module }
|
{ name = libwireplumber-module-lua-scripting, type = module }
|
||||||
|
|
||||||
# Parses all the wireplumber settings in the .conf file, loads them into a
|
{ name = access/access-default.lua, type = script/lua }
|
||||||
# "sm-settings" pipewire metadata and updates the settings to a state file,
|
{ name = libwireplumber-module-portal-permissionstore , type = module, deps = access.enable-flatpak-portal }
|
||||||
# when persitent behavior is enabled.
|
{ name = access/access-portal.lua, type = script/lua, deps = access.enable-flatpak-portal }
|
||||||
|
|
||||||
{ name = libwireplumber-module-settings, type = module }
|
|
||||||
|
|
||||||
# The lua configuration file(s)
|
# The lua configuration file(s)
|
||||||
# Other components are loaded from there
|
# Other components are loaded from there
|
||||||
@@ -137,6 +135,7 @@ wireplumber.settings = {
|
|||||||
# till the time the setting is set to false.
|
# till the time the setting is set to false.
|
||||||
#
|
#
|
||||||
persistent.settings = false
|
persistent.settings = false
|
||||||
|
|
||||||
access.enable-flatpak-portal = true
|
access.enable-flatpak-portal = true
|
||||||
access = [
|
access = [
|
||||||
{
|
{
|
||||||
|
106
src/main.c
106
src/main.c
@@ -46,10 +46,10 @@ struct _WpInitTransition
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
STEP_LOAD_COMPONENTS = WP_TRANSITION_STEP_CUSTOM_START,
|
STEP_CONNECT = WP_TRANSITION_STEP_CUSTOM_START,
|
||||||
STEP_CONNECT,
|
|
||||||
STEP_CHECK_MEDIA_SESSION,
|
|
||||||
STEP_ACTIVATE_SETTINGS,
|
STEP_ACTIVATE_SETTINGS,
|
||||||
|
STEP_LOAD_COMPONENTS,
|
||||||
|
STEP_CHECK_MEDIA_SESSION,
|
||||||
STEP_ACTIVATE_PLUGINS,
|
STEP_ACTIVATE_PLUGINS,
|
||||||
STEP_ACTIVATE_SCRIPTS,
|
STEP_ACTIVATE_SCRIPTS,
|
||||||
STEP_CLEANUP,
|
STEP_CLEANUP,
|
||||||
@@ -68,11 +68,11 @@ static guint
|
|||||||
wp_init_transition_get_next_step (WpTransition * transition, guint step)
|
wp_init_transition_get_next_step (WpTransition * transition, guint step)
|
||||||
{
|
{
|
||||||
switch (step) {
|
switch (step) {
|
||||||
case WP_TRANSITION_STEP_NONE: return STEP_LOAD_COMPONENTS;
|
case WP_TRANSITION_STEP_NONE: return STEP_CONNECT;
|
||||||
case STEP_LOAD_COMPONENTS: return STEP_CONNECT;
|
case STEP_CONNECT: return STEP_ACTIVATE_SETTINGS;
|
||||||
case STEP_CONNECT: return STEP_CHECK_MEDIA_SESSION;
|
case STEP_ACTIVATE_SETTINGS: return STEP_LOAD_COMPONENTS;
|
||||||
case STEP_CHECK_MEDIA_SESSION:return STEP_ACTIVATE_SETTINGS;
|
case STEP_LOAD_COMPONENTS: return STEP_CHECK_MEDIA_SESSION;
|
||||||
case STEP_ACTIVATE_SETTINGS: return STEP_ACTIVATE_PLUGINS;
|
case STEP_CHECK_MEDIA_SESSION:return STEP_ACTIVATE_PLUGINS;
|
||||||
case STEP_CLEANUP: return WP_TRANSITION_STEP_NONE;
|
case STEP_CLEANUP: return WP_TRANSITION_STEP_NONE;
|
||||||
|
|
||||||
case STEP_ACTIVATE_PLUGINS: {
|
case STEP_ACTIVATE_PLUGINS: {
|
||||||
@@ -147,6 +147,7 @@ do_load_components(void *data, const char *location, const char *section,
|
|||||||
g_autoptr (WpSpaJson) json = NULL;
|
g_autoptr (WpSpaJson) json = NULL;
|
||||||
g_autoptr (WpIterator) it = NULL;
|
g_autoptr (WpIterator) it = NULL;
|
||||||
g_auto (GValue) item = G_VALUE_INIT;
|
g_auto (GValue) item = G_VALUE_INIT;
|
||||||
|
g_autoptr (WpSettings) settings = wp_settings_get_instance (core, NULL);
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
|
|
||||||
json = wp_spa_json_new_from_stringn (str, len);
|
json = wp_spa_json_new_from_stringn (str, len);
|
||||||
@@ -163,6 +164,7 @@ do_load_components(void *data, const char *location, const char *section,
|
|||||||
WpSpaJson *o = g_value_get_boxed (&item);
|
WpSpaJson *o = g_value_get_boxed (&item);
|
||||||
g_autofree gchar *name = NULL;
|
g_autofree gchar *name = NULL;
|
||||||
g_autofree gchar *type = NULL;
|
g_autofree gchar *type = NULL;
|
||||||
|
g_autofree gchar *deps = NULL;
|
||||||
|
|
||||||
if (!wp_spa_json_is_object (o) ||
|
if (!wp_spa_json_is_object (o) ||
|
||||||
!wp_spa_json_object_get (o,
|
!wp_spa_json_object_get (o,
|
||||||
@@ -174,6 +176,15 @@ do_load_components(void *data, const char *location, const char *section,
|
|||||||
"component must have both a 'name' and a 'type'"));
|
"component must have both a 'name' and a 'type'"));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wp_spa_json_object_get (o, "deps", "s", &deps, NULL) && deps) {
|
||||||
|
if (!wp_settings_get_boolean (settings, deps)) {;
|
||||||
|
wp_info ("deps(%s) not met for component(%s), skip loading it",
|
||||||
|
deps, name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!wp_core_load_component (core, name, type, NULL, &error)) {
|
if (!wp_core_load_component (core, name, type, NULL, &error)) {
|
||||||
wp_transition_return_error (transition, error);
|
wp_transition_return_error (transition, error);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -228,25 +239,13 @@ wp_init_transition_execute_step (WpTransition * transition, guint step)
|
|||||||
WpCore *core = wp_transition_get_source_object (transition);
|
WpCore *core = wp_transition_get_source_object (transition);
|
||||||
struct pw_context *pw_ctx = wp_core_get_pw_context (core);
|
struct pw_context *pw_ctx = wp_core_get_pw_context (core);
|
||||||
const struct pw_properties *props = pw_context_get_properties (pw_ctx);
|
const struct pw_properties *props = pw_context_get_properties (pw_ctx);
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
switch (step) {
|
switch (step) {
|
||||||
case STEP_LOAD_COMPONENTS: {
|
|
||||||
struct data data = { .transition = transition };
|
|
||||||
|
|
||||||
if (pw_context_conf_section_for_each(pw_ctx, "wireplumber.components",
|
|
||||||
do_load_components, &data) < 0)
|
|
||||||
return;
|
|
||||||
if (data.count == 0) {
|
|
||||||
wp_transition_return_error (transition, g_error_new (
|
|
||||||
WP_DOMAIN_DAEMON, WP_EXIT_CONFIG,
|
|
||||||
"No components configured in the context conf file; nothing to do"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
wp_transition_advance (transition);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case STEP_CONNECT: {
|
case STEP_CONNECT: {
|
||||||
|
wp_info_object (self, "Core 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);
|
||||||
|
|
||||||
@@ -283,6 +282,50 @@ wp_init_transition_execute_step (WpTransition * transition, guint step)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case STEP_ACTIVATE_SETTINGS: {
|
||||||
|
|
||||||
|
wp_info_object (self, "Activating settings...");
|
||||||
|
|
||||||
|
/* load settings module */
|
||||||
|
if (!wp_core_load_component (core, "libwireplumber-module-settings",
|
||||||
|
"module", NULL, &error)) {
|
||||||
|
wp_transition_return_error (transition, error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get handle to module to settings module/plugin & activate it */
|
||||||
|
WpPlugin *p = wp_plugin_find (core, "settings");
|
||||||
|
if (!p) {
|
||||||
|
wp_transition_return_error (transition, g_error_new (
|
||||||
|
WP_DOMAIN_DAEMON, WP_EXIT_CONFIG,
|
||||||
|
"unable to find settings plugin"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wp_object_activate (WP_OBJECT (p), WP_OBJECT_FEATURES_ALL, NULL,
|
||||||
|
(GAsyncReadyCallback) on_settings_plugin_ready, self);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case STEP_LOAD_COMPONENTS: {
|
||||||
|
struct data data = { .transition = transition };
|
||||||
|
|
||||||
|
wp_info_object (self, "Load Wireplumber Components...");
|
||||||
|
|
||||||
|
if (pw_context_conf_section_for_each(pw_ctx, "wireplumber.components",
|
||||||
|
do_load_components, &data) < 0)
|
||||||
|
return;
|
||||||
|
if (data.count == 0) {
|
||||||
|
wp_transition_return_error (transition, g_error_new (
|
||||||
|
WP_DOMAIN_DAEMON, WP_EXIT_CONFIG,
|
||||||
|
"No components configured in the context conf file; nothing to do"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
wp_transition_advance (transition);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case STEP_CHECK_MEDIA_SESSION: {
|
case STEP_CHECK_MEDIA_SESSION: {
|
||||||
wp_info_object (self, "Checking for session manager conflicts...");
|
wp_info_object (self, "Checking for session manager conflicts...");
|
||||||
|
|
||||||
@@ -296,23 +339,6 @@ wp_init_transition_execute_step (WpTransition * transition, guint step)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case STEP_ACTIVATE_SETTINGS: {
|
|
||||||
/* find and activate settings plugin */
|
|
||||||
WpPlugin *p = wp_plugin_find (core, "settings");
|
|
||||||
if (!p) {
|
|
||||||
wp_transition_return_error (transition, g_error_new (
|
|
||||||
WP_DOMAIN_DAEMON, WP_EXIT_CONFIG,
|
|
||||||
"unable to find settings plugin"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
wp_info_object (self, "Activating wpsettings plugin");
|
|
||||||
|
|
||||||
wp_object_activate (WP_OBJECT (p), WP_OBJECT_FEATURES_ALL, NULL,
|
|
||||||
(GAsyncReadyCallback) on_settings_plugin_ready, self);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case STEP_ACTIVATE_PLUGINS: {
|
case STEP_ACTIVATE_PLUGINS: {
|
||||||
const char *engine = pw_properties_get (props, "wireplumber.script-engine");
|
const char *engine = pw_properties_get (props, "wireplumber.script-engine");
|
||||||
|
|
||||||
|
@@ -5,32 +5,11 @@
|
|||||||
--
|
--
|
||||||
-- SPDX-License-Identifier: MIT
|
-- SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
local config = ... or {}
|
|
||||||
|
|
||||||
-- preprocess rules and create Interest objects
|
|
||||||
for _, r in ipairs(config.rules or {}) do
|
|
||||||
r.interests = {}
|
|
||||||
for _, i in ipairs(r.matches) do
|
|
||||||
local interest_desc = { type = "properties" }
|
|
||||||
for _, c in ipairs(i) do
|
|
||||||
c.type = "pw"
|
|
||||||
table.insert(interest_desc, Constraint(c))
|
|
||||||
end
|
|
||||||
local interest = Interest(interest_desc)
|
|
||||||
table.insert(r.interests, interest)
|
|
||||||
end
|
|
||||||
r.matches = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
function rulesGetDefaultPermissions(properties)
|
function rulesGetDefaultPermissions(properties)
|
||||||
for _, r in ipairs(config.rules or {}) do
|
local matched, mprops = Settings.apply_rule ("access", properties)
|
||||||
if r.default_permissions then
|
|
||||||
for _, interest in ipairs(r.interests) do
|
if (matched and mprops["default_permissions"]) then
|
||||||
if interest:matches(properties) then
|
return mprops["default_permissions"]
|
||||||
return r.default_permissions
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user