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 (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;
|
||||
}
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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;
|
||||
|
@@ -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 (
|
||||
|
@@ -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
|
||||
load_module("metadata")
|
||||
|
||||
-- Default client access policy
|
||||
default_access.enable()
|
||||
|
||||
-- Load devices
|
||||
alsa_monitor.enable()
|
||||
v4l2_monitor.enable()
|
||||
|
@@ -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 = [
|
||||
{
|
||||
|
106
src/main.c
106
src/main.c
@@ -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");
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
Reference in New Issue
Block a user