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:
Ashok Sidipotu
2022-04-27 18:18:03 +05:30
committed by Julian Bouzas
parent a5d62b7bbd
commit a4f16a98f0
9 changed files with 86 additions and 104 deletions

View File

@@ -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 (client_props, false);
wp_debug_object (self, "applying rule(%s) for client props(%d)",
rule, wp_properties_get_count (client_props));
wp_debug_object (self, "applying rule(%s) for client props", rule);
for (guint i = 0; i < self->rules->len; 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
wp_properties_add (client_props, m->actions);
wp_debug_object (self, ". match found with actions(%d)",
wp_properties_get_count(m->actions));
wp_debug_object (self, ". match found for rule(%s) with actions"
"(%d)", rule, wp_properties_get_count(m->actions));
return TRUE;
}

View File

@@ -1476,12 +1476,12 @@ static gboolean
get_boolean (lua_State *L)
{
const char *setting = luaL_checkstring (L, 1);
const char *metadata_name = NULL;
const char *m = NULL;
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)
{
@@ -1497,14 +1497,14 @@ static gboolean
apply_rule (lua_State *L)
{
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) ap = wp_properties_new_empty ();
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)
{

View File

@@ -56,6 +56,7 @@ wp_lua_scripting_package_searcher (lua_State *L)
lua_pushcfunction (L, wp_lua_scripting_package_loader);
/* 2. loader data (param to 1) */
wp_debug ("Executing script %s", script);
if (!wplua_load_path (L, script, &error)) {
lua_pop (L, 1);
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));
} else {
/* 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));
}
return TRUE;

View File

@@ -145,7 +145,6 @@ do_parse_settings (void *data, const char *location,
g_autoptr (WpIterator) iter = wp_spa_json_new_iterator (json);
g_auto (GValue) item = G_VALUE_INIT;
if (!wp_spa_json_is_object (json)) {
/* "wireplumber.settings" section has to be a JSON object element. */
wp_transition_return_error (transition, g_error_new (

View File

@@ -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

View File

@@ -2,9 +2,6 @@
-- dynamic properties of pipewire objects in RAM
load_module("metadata")
-- Default client access policy
default_access.enable()
-- Load devices
alsa_monitor.enable()
v4l2_monitor.enable()

View File

@@ -85,11 +85,9 @@ wireplumber.components = [
# The lua scripting engine
{ name = libwireplumber-module-lua-scripting, type = module }
# Parses all the wireplumber settings in the .conf file, loads them into a
# "sm-settings" pipewire metadata and updates the settings to a state file,
# when persitent behavior is enabled.
{ name = libwireplumber-module-settings, type = module }
{ name = access/access-default.lua, type = script/lua }
{ name = libwireplumber-module-portal-permissionstore , type = module, deps = access.enable-flatpak-portal }
{ name = access/access-portal.lua, type = script/lua, deps = access.enable-flatpak-portal }
# The lua configuration file(s)
# Other components are loaded from there
@@ -137,6 +135,7 @@ wireplumber.settings = {
# till the time the setting is set to false.
#
persistent.settings = false
access.enable-flatpak-portal = true
access = [
{

View File

@@ -46,10 +46,10 @@ struct _WpInitTransition
};
enum {
STEP_LOAD_COMPONENTS = WP_TRANSITION_STEP_CUSTOM_START,
STEP_CONNECT,
STEP_CHECK_MEDIA_SESSION,
STEP_CONNECT = WP_TRANSITION_STEP_CUSTOM_START,
STEP_ACTIVATE_SETTINGS,
STEP_LOAD_COMPONENTS,
STEP_CHECK_MEDIA_SESSION,
STEP_ACTIVATE_PLUGINS,
STEP_ACTIVATE_SCRIPTS,
STEP_CLEANUP,
@@ -68,11 +68,11 @@ static guint
wp_init_transition_get_next_step (WpTransition * transition, guint step)
{
switch (step) {
case WP_TRANSITION_STEP_NONE: return STEP_LOAD_COMPONENTS;
case STEP_LOAD_COMPONENTS: return STEP_CONNECT;
case STEP_CONNECT: return STEP_CHECK_MEDIA_SESSION;
case STEP_CHECK_MEDIA_SESSION:return STEP_ACTIVATE_SETTINGS;
case STEP_ACTIVATE_SETTINGS: return STEP_ACTIVATE_PLUGINS;
case WP_TRANSITION_STEP_NONE: return STEP_CONNECT;
case STEP_CONNECT: return STEP_ACTIVATE_SETTINGS;
case STEP_ACTIVATE_SETTINGS: return STEP_LOAD_COMPONENTS;
case STEP_LOAD_COMPONENTS: return STEP_CHECK_MEDIA_SESSION;
case STEP_CHECK_MEDIA_SESSION:return STEP_ACTIVATE_PLUGINS;
case STEP_CLEANUP: return WP_TRANSITION_STEP_NONE;
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 (WpIterator) it = NULL;
g_auto (GValue) item = G_VALUE_INIT;
g_autoptr (WpSettings) settings = wp_settings_get_instance (core, NULL);
GError *error = NULL;
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);
g_autofree gchar *name = NULL;
g_autofree gchar *type = NULL;
g_autofree gchar *deps = NULL;
if (!wp_spa_json_is_object (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'"));
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)) {
wp_transition_return_error (transition, error);
return -EINVAL;
@@ -228,25 +239,13 @@ wp_init_transition_execute_step (WpTransition * transition, guint step)
WpCore *core = wp_transition_get_source_object (transition);
struct pw_context *pw_ctx = wp_core_get_pw_context (core);
const struct pw_properties *props = pw_context_get_properties (pw_ctx);
GError *error = NULL;
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: {
wp_info_object (self, "Core connect...");
g_signal_connect_object (core, "connected",
G_CALLBACK (wp_transition_advance), transition, G_CONNECT_SWAPPED);
@@ -283,6 +282,50 @@ wp_init_transition_execute_step (WpTransition * transition, guint step)
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: {
wp_info_object (self, "Checking for session manager conflicts...");
@@ -296,23 +339,6 @@ wp_init_transition_execute_step (WpTransition * transition, guint step)
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: {
const char *engine = pw_properties_get (props, "wireplumber.script-engine");

View File

@@ -5,32 +5,11 @@
--
-- 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)
for _, r in ipairs(config.rules or {}) do
if r.default_permissions then
for _, interest in ipairs(r.interests) do
if interest:matches(properties) then
return r.default_permissions
end
end
end
local matched, mprops = Settings.apply_rule ("access", properties)
if (matched and mprops["default_permissions"]) then
return mprops["default_permissions"]
end
end