diff --git a/lib/wp/settings.c b/lib/wp/settings.c index 9a195134..7d121d45 100644 --- a/lib/wp/settings.c +++ b/lib/wp/settings.c @@ -8,11 +8,11 @@ #define G_LOG_DOMAIN "wp-settings" -#include - +#include "core.h" #include "settings.h" #include "metadata.h" #include "log.h" +#include "object-manager.h" #include "private/registry.h" /*! \defgroup wpsettings WpSettings */ @@ -20,8 +20,8 @@ * \struct WpSettings * * WpSettings loads and parses the "sm-settings" (default value) metadata, which - * contains wireplumber settings and rules. It provides APIs to its clients - * (modules, lua scripts etc) to access and change them. + * contains wireplumber settings. It provides APIs to its clients (modules, lua + * scripts etc) to access and change them. * * Being a WpObject subclass, the settings inherits WpObject's activation * system. @@ -33,9 +33,6 @@ struct _WpSettings WpProperties *settings; - /* element-type: Rule* */ - GPtrArray *rules; - /* element-type: Callback* */ GPtrArray *callbacks; @@ -43,20 +40,6 @@ struct _WpSettings WpObjectManager *metadata_om; }; -typedef struct -{ - gchar *rule; - /* element-type: Match* */ - GPtrArray *matches; -} Rule; - -typedef struct -{ - /* element-type: WpObjectInterest* */ - GPtrArray *interests; - WpProperties *actions; -} Match; - typedef struct { GClosure *closure; @@ -185,159 +168,6 @@ wp_settings_get (WpSettings *self, const gchar *setting) return value ? wp_spa_json_new_from_string (value) : NULL; } -/*! - * \brief Safely parses a boolean setting, using the fallback value if the - * setting does not exist, or the setting cannot be parsed. A warning is also - * logged when the setting cannot be parsed. - * - * \ingroup wpsettings - * \param self the settings object - * \param setting name of the setting - * \param value fallback value to use in case of error - * \returns The value of the setting, or the fallback value in case of error - */ -gboolean -wp_settings_parse_boolean_safe (WpSettings *self, const gchar *setting, - gboolean value) -{ - g_autoptr (WpSpaJson) json = wp_settings_get(self, setting); - gboolean res = value; - if (json && !wp_spa_json_parse_boolean (json, &res)) - wp_warning_object (self, "Could not parse setting '%s' as boolean", - setting); - return res; -} - -/*! - * \brief Safely parses an integer setting, using the fallback value if the - * setting does not exist, or the setting cannot be parsed. A warning is also - * logged when the setting cannot be parsed. - * - * \ingroup wpsettings - * \param self the settings object - * \param setting name of the setting - * \param value fallback value to use in case of error - * \returns The value of the setting, or the fallback value in case of error - */ -gint -wp_settings_parse_int_safe (WpSettings *self, const gchar *setting, gint value) -{ - g_autoptr (WpSpaJson) json = wp_settings_get(self, setting); - gint res = value; - if (json && !wp_spa_json_parse_int (json, &res)) - wp_warning_object (self, "Could not parse setting '%s' as int", setting); - return res; -} - -/*! - * \brief Safely parses a float setting, using the fallback value if the - * setting does not exist, or the setting cannot be parsed. A warning is also - * logged when the setting cannot be parsed. - * - * \ingroup wpsettings - * \param self the settings object - * \param setting name of the setting - * \param value fallback value to use in case of error - * \returns The value of the setting, or the fallback value in case of error - */ -float -wp_settings_parse_float_safe (WpSettings *self, const gchar *setting, - float value) -{ - g_autoptr (WpSpaJson) json = wp_settings_get(self, setting); - float res = value; - if (json && !wp_spa_json_parse_float (json, &res)) - wp_warning_object (self, "Could not parse setting '%s' as float", setting); - return res; -} - -/*! - * \brief Safely parses a string setting, using the fallback value if the - * setting does not exist, or the setting cannot be parsed. A warning is also - * logged when the setting cannot be parsed. - * - * \ingroup wpsettings - * \param self the settings object - * \param setting name of the setting - * \param value fallback value to use in case of error - * \returns (transfer full): The value of the setting, or the fallback value in - * case of error - */ -gchar * -wp_settings_parse_string_safe (WpSettings *self, const gchar *setting, - const gchar *value) -{ - g_autoptr (WpSpaJson) json = wp_settings_get(self, setting); - if (json) { - gchar *res = wp_spa_json_parse_string (json); - if (res) - return res; - else - wp_warning_object (self, "Could not parse setting '%s' as string", - setting); - } - return g_strdup (value); -} - -/*! - * \brief Applies the rules and returns the applied properties. - * - * This function applies the rules on the client properties and if - * there is a match, it returns TRUE and also copies the applied properties. - * - * \ingroup wpsettings - * \param self the settings object - * \param rule name of the rule; this will match with the section mentioned - * in the conf file. - * \param client_props (transfer none)(inout): client properties array; these - * properties are inputs on which the rules are applied. - * \param applied_props (transfer none)(nullable)(out): the resultant - * actions/properties as a result of the application of rules are copied; - * if this is NULL, properties will be appended to \a client_props instead - * \returns TRUE if there is a match for the client_props and the - * applied properties are returned, FALSE otherwise - */ -gboolean -wp_settings_apply_rule (WpSettings *self, const gchar *rule, - WpProperties *client_props, WpProperties *applied_props) -{ - g_return_val_if_fail (WP_IS_SETTINGS (self), FALSE); - 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", rule); - - for (guint i = 0; i < self->rules->len; i++) { - Rule *r = g_ptr_array_index (self->rules, i); - - if (g_str_equal (rule, r->rule)) { - for (guint j = 0; j < r->matches->len; j++) { - Match *m = g_ptr_array_index (r->matches, j); - - for (guint k = 0; k < m->interests->len; k++) { - WpObjectInterest *interest = g_ptr_array_index (m->interests, k); - - wp_debug_object (self, ". working on interest obj(%p)", interest); - - if (wp_object_interest_matches (interest, client_props)) { - if (applied_props) - wp_properties_add (applied_props, m->actions); - else - wp_properties_add (client_props, m->actions); - - wp_debug_object (self, "match found for rule(%s) with actions" - "(%d)", rule, wp_properties_get_count(m->actions)); - - return TRUE; - } - } - } - } - } - - return FALSE; -} - enum { STEP_LOAD = WP_TRANSITION_STEP_CUSTOM_START, }; @@ -409,240 +239,6 @@ wp_settings_get_instance (WpCore *core, const gchar *metadata_name) return settings; } -static void -match_unref (Match * self) -{ - g_clear_pointer (&self->actions, wp_properties_unref); - g_clear_pointer (&self->interests, g_ptr_array_unref); - g_slice_free (Match, self); -} - -static WpProperties * -parse_actions (const gchar *actions) -{ - g_autoptr (WpSpaJson) o = wp_spa_json_new_from_string (actions); - g_autofree gchar *update_props = NULL; - g_autoptr (WpProperties) a_props = wp_properties_new_empty (); - - wp_debug(".. parsing actions"); - - if (!o || !wp_spa_json_is_object (o)) { - wp_warning ("malformated JSON: actions has to be an object JSON element" - ", skip processing this one"); - return NULL; - } - - if (wp_spa_json_object_get (o, - "update-props", "s", &update_props, - NULL)) { - g_autoptr (WpSpaJson) json = wp_spa_json_new_from_string (update_props); - g_autoptr (WpIterator) iter = wp_spa_json_new_iterator (json); - g_auto (GValue) item = G_VALUE_INIT; - - wp_debug (".. update-props=%s", update_props); - - while (wp_iterator_next (iter, &item)) { - WpSpaJson *p = g_value_get_boxed (&item); - g_autofree gchar *prop = wp_spa_json_parse_string (p); - g_autofree gchar *value = NULL; - - g_value_unset (&item); - if (!wp_iterator_next (iter, &item)) - break; - p = g_value_get_boxed (&item); - - value = wp_spa_json_parse_string (p); - g_value_unset (&item); - - if (prop && value) { - wp_debug (".. prop=%s value=%s", prop, value); - wp_properties_set (a_props, prop, value); - } - } - } else { - return NULL; - } - - return g_steal_pointer (&a_props); -} - -static Match * -parse_matches (const gchar *match) -{ - g_autoptr (WpSpaJson) a = wp_spa_json_new_from_string (match); - g_autoptr (WpIterator) a_iter = wp_spa_json_new_iterator (a); - g_auto (GValue) a_item = G_VALUE_INIT; - Match *m = g_slice_new0 (Match); - - g_return_val_if_fail (m, NULL); - - wp_debug(".. parsing match"); - m->interests = g_ptr_array_new_with_free_func - ((GDestroyNotify) wp_object_interest_unref); - - if (!wp_spa_json_is_array (a)) { - wp_warning ("malformated JSON: matches has to be an array JSON element" - ", skip processing this one"); - return NULL; - } - - for (; wp_iterator_next (a_iter, &a_item); g_value_unset (&a_item)) { - g_autoptr (WpObjectInterest) i = wp_object_interest_new_type - (WP_TYPE_PROPERTIES); - WpSpaJson *o = g_value_get_boxed (&a_item); - g_autoptr (WpIterator) o_iter = wp_spa_json_new_iterator (o); - g_auto (GValue) o_item = G_VALUE_INIT; - int count = 0; - - while (wp_iterator_next (o_iter, &o_item)) { - WpSpaJson *p = g_value_get_boxed (&o_item); - if (wp_spa_json_is_container (p)) { - wp_warning ("malformated JSON: misplaced container object, pls check" - " JSON formatting of .conf file, skipping this container"); - continue; - } - g_autofree gchar *isubject = wp_spa_json_parse_string (p); - g_autofree gchar *value = NULL; - gchar *ivalue = NULL; - WpConstraintVerb iverb = WP_CONSTRAINT_VERB_EQUALS; - - g_value_unset (&o_item); - if (!wp_iterator_next (o_iter, &o_item)) - break; - p = g_value_get_boxed (&o_item); - - ivalue = value = wp_spa_json_parse_string (p); - g_value_unset (&o_item); - - if (value[0] == '~') { - iverb = WP_CONSTRAINT_VERB_MATCHES; - ivalue = value+1; - } - if (isubject && ivalue) { - wp_object_interest_add_constraint (i, WP_CONSTRAINT_TYPE_PW_PROPERTY, - isubject, iverb, g_variant_new_string(ivalue)); - count++; - wp_debug (".. subject=%s verb=%d value=%s of interest obj=%p", - isubject, iverb, ivalue, i); - } - } - wp_debug (".. loaded interest obj(%p) with (%d) constraints", i, count); - g_ptr_array_add (m->interests, g_steal_pointer(&i)); - } - return m; -} - -static Rule * -parse_rule (const gchar *rule, const gchar *value) -{ - g_autoptr (WpSpaJson) json = wp_spa_json_new_from_string (value); - g_autoptr (WpIterator) iter = wp_spa_json_new_iterator (json); - g_auto (GValue) item = G_VALUE_INIT; - Rule *r = g_slice_new0 (Rule); - - g_return_val_if_fail (r, NULL); - - r->rule = g_strdup (rule); - - wp_debug (". parsing rule(%s)", r->rule); - r->matches = g_ptr_array_new_with_free_func - ((GDestroyNotify) match_unref); - - for (; wp_iterator_next (iter, &item); g_value_unset (&item)) { - WpSpaJson *o = g_value_get_boxed (&item); - g_autofree gchar *match = NULL; - g_autofree gchar *actions = NULL; - Match *m = NULL; - - if (!o || !wp_spa_json_is_object (o)) { - wp_warning ("malformated JSON: rule has to be an object JSON element" - ", skip processing this one"); - continue; - } - - if (!wp_spa_json_object_get (o, - "matches", "s", &match, - "actions", "s", &actions, - NULL)) - continue; - - m = parse_matches (match); - g_ptr_array_add (r->matches, m); - wp_debug (". loaded (%d) interest objects for this match for rule(%s)", - m->interests->len, r->rule); - - m->actions = parse_actions (actions); - wp_debug (". loaded (%d) actions for this match for rule(%s)", - wp_properties_get_count (m->actions), r->rule); - } - - return r; -} - -static gboolean -is_rule (WpSpaJson *json) -{ - /* rule is an array and starts with an object */ - if (wp_spa_json_is_array (json)) { - g_autoptr (WpIterator) iter = wp_spa_json_new_iterator (json); - g_auto (GValue) item = G_VALUE_INIT; - - if (wp_iterator_next (iter, &item)) { - WpSpaJson *o = g_value_get_boxed (&item); - if (o && wp_spa_json_is_object (o)) - return TRUE; - } - } - return FALSE; -} - -static Rule * -find_rule (WpSettings *self, const gchar *name) -{ - for (guint i = 0; i < self->rules->len; i++) { - Rule *r = g_ptr_array_index (self->rules, i); - if (g_str_equal (r->rule, name)) - return r; - } - return NULL; -} - -static void -rule_unref (Rule * self) -{ - g_clear_pointer (&self->rule, g_free); - g_clear_pointer (&self->matches, g_ptr_array_unref); - g_slice_free (Rule, self); -} - -static void -parse_setting (const gchar *setting, const gchar *value, WpSettings *self) -{ - g_autoptr (WpSpaJson) json = wp_spa_json_new_from_string (value); - - if (is_rule (json)) { - Rule *r = find_rule (self, setting); - if (r) { - /* append new matches to existing rule */ - Rule *new_r = parse_rule (setting, value); - if (new_r) { - for (guint i = 0; i < new_r->matches->len; i++) { - Match *m = g_ptr_array_index (new_r->matches, i); - g_ptr_array_add (r->matches, m); - } - rule_unref (new_r); - } - } else { - r = parse_rule (setting, value); - g_ptr_array_add (self->rules, r); - } - wp_debug_object (self, "added (%d) matches for rule (%s)", r->matches->len, - r->rule); - } else { - wp_properties_set (self->settings, setting, value); - } -} - static void on_metadata_changed (WpMetadata *m, guint32 subject, const gchar *setting, const gchar *type, const gchar *new_value, gpointer d) @@ -704,16 +300,15 @@ on_metadata_added (WpObjectManager *om, WpMetadata *m, gpointer d) g_signal_connect_object (m, "changed", G_CALLBACK (on_metadata_changed), self, 0); - /* traverse through all settings and rules */ + /* traverse through all settings */ for (; wp_iterator_next (it, &val); g_value_unset (&val)) { const gchar *setting, *value; wp_metadata_iterator_item_extract (&val, NULL, &setting, NULL, &value); - parse_setting (setting, value, self); + wp_properties_set (self->settings, setting, value); } - wp_info_object (self, "loaded %d settings and %d rules from metadata \"%s\"", + wp_info_object (self, "loaded %d settings and from metadata \"%s\"", wp_properties_get_count (self->settings), - self->rules->len, self->metadata_name); wp_object_update_features (WP_OBJECT (self), WP_SETTINGS_LOADED, 0); @@ -739,8 +334,6 @@ wp_settings_activate_execute_step (WpObject * object, case STEP_LOAD: { self->settings = wp_properties_new_empty (); - self->rules = g_ptr_array_new_with_free_func ((GDestroyNotify) rule_unref); - self->callbacks = g_ptr_array_new_with_free_func ((GDestroyNotify) callback_unref); @@ -773,7 +366,6 @@ wp_settings_deactivate (WpObject * object, WpObjectFeatures features) wp_debug_object (self, "%s", self->metadata_name); g_free (self->metadata_name); g_clear_object (&self->metadata_om); - g_clear_pointer (&self->rules, g_ptr_array_unref); g_clear_pointer (&self->callbacks, g_ptr_array_unref); g_clear_pointer (&self->settings, wp_properties_unref); diff --git a/lib/wp/settings.h b/lib/wp/settings.h index b76f908f..9ce3af5e 100644 --- a/lib/wp/settings.h +++ b/lib/wp/settings.h @@ -64,26 +64,6 @@ gboolean wp_settings_unsubscribe (WpSettings *self, WP_API WpSpaJson * wp_settings_get (WpSettings *self, const gchar *setting); -WP_API -gboolean wp_settings_parse_boolean_safe (WpSettings *self, const gchar *setting, - gboolean value); - -WP_API -gint wp_settings_parse_int_safe (WpSettings *self, const gchar *setting, - gint value); - -WP_API -float wp_settings_parse_float_safe (WpSettings *self, const gchar *setting, - float value); - -WP_API -gchar * wp_settings_parse_string_safe (WpSettings *self, const gchar *setting, - const gchar *value); - -WP_API -gboolean wp_settings_apply_rule (WpSettings *self, const gchar *rule, - WpProperties *client_props, WpProperties *applied_props); - G_END_DECLS #endif diff --git a/modules/module-lua-scripting/api/api.c b/modules/module-lua-scripting/api/api.c index f7774eab..f78ef7c1 100644 --- a/modules/module-lua-scripting/api/api.c +++ b/modules/module-lua-scripting/api/api.c @@ -1659,157 +1659,6 @@ settings_get (lua_State *L) return 1; } -static int -settings_parse_boolean_safe (lua_State *L) -{ - const char *setting = luaL_checkstring (L, 1); - const gboolean v = lua_toboolean (L, 2) ? TRUE : FALSE; - g_autoptr (WpSettings) s = wp_settings_get_instance (get_wp_core (L), - "sm-settings"); - - if (s) - lua_pushboolean (L, wp_settings_parse_boolean_safe (s, setting, v)); - else - lua_pushboolean (L, v); - return 1; -} - -static int -settings_parse_int_safe (lua_State *L) -{ - const char *setting = luaL_checkstring (L, 1); - const gint v = luaL_checkinteger (L, 2); - g_autoptr (WpSettings) s = wp_settings_get_instance (get_wp_core (L), - "sm-settings"); - - if (s) - lua_pushinteger (L, wp_settings_parse_int_safe (s, setting, v)); - else - lua_pushinteger (L, v); - return 1; -} - -static int -settings_parse_float_safe (lua_State *L) -{ - const char *setting = luaL_checkstring (L, 1); - const float v = lua_tonumber (L, 2); - g_autoptr (WpSettings) s = wp_settings_get_instance (get_wp_core (L), - "sm-settings"); - - if (s) - lua_pushnumber (L, wp_settings_parse_float_safe (s, setting, v)); - else - lua_pushnumber (L, v); - return 1; -} - -static int -settings_parse_string_safe (lua_State *L) -{ - const char *setting = luaL_checkstring (L, 1); - const char *v = luaL_checkstring (L, 2); - g_autofree gchar *res = NULL; - g_autoptr (WpSettings) s = wp_settings_get_instance (get_wp_core (L), - "sm-settings"); - - res = s ? wp_settings_parse_string_safe (s, setting, v) : g_strdup (v); - lua_pushstring (L, res); - return 1; -} - -static int -settings_parse_array_safe (lua_State *L) -{ - const char *setting = luaL_checkstring (L, 1); - g_autoptr (WpSpaJson) json_default = NULL; - g_autoptr (WpSettings) s = wp_settings_get_instance (get_wp_core (L), - "sm-settings"); - - if (lua_isuserdata (L, 2)) { - WpSpaJson *v = wplua_checkboxed (L, 2, WP_TYPE_SPA_JSON); - if (v && wp_spa_json_is_array (v)) - json_default = wp_spa_json_ref (v); - } - if (!json_default) { - wp_warning ("Using empty array for setting '%s' as fallback value isn't " - "a JSON array", setting); - json_default = wp_spa_json_new_array (NULL, NULL); - } - - if (s) { - g_autoptr (WpSpaJson) j = wp_settings_get (s, setting); - if (j) { - if (wp_spa_json_is_array (j)) { - push_luajson (L, j); - return 1; - } else { - wp_warning ("Ignoring setting '%s' as it isn't a JSON array", setting); - } - } - } - - push_luajson (L, json_default); - return 1; -} - -static int -settings_parse_object_safe (lua_State *L) -{ - const char *setting = luaL_checkstring (L, 1); - g_autoptr (WpSpaJson) json_default = NULL; - g_autoptr (WpSettings) s = wp_settings_get_instance (get_wp_core (L), - "sm-settings"); - - if (lua_isuserdata (L, 2)) { - WpSpaJson *v = wplua_checkboxed (L, 2, WP_TYPE_SPA_JSON); - if (v && wp_spa_json_is_object (v)) - json_default = wp_spa_json_ref (v); - } - if (!json_default) { - wp_warning ("Using empty object for setting '%s' as fallback value isn't " - "a JSON object", setting); - json_default = wp_spa_json_new_array (NULL, NULL); - } - - if (s) { - g_autoptr (WpSpaJson) j = wp_settings_get (s, setting); - if (j) { - if (wp_spa_json_is_object (j)) { - push_luajson (L, j); - return 1; - } else { - wp_warning ("Ignoring setting '%s' as it isn't a JSON object", setting); - } - } - } - - push_luajson (L, json_default); - return 1; -} - -static int -settings_apply_rule (lua_State *L) -{ - const char *r = luaL_checkstring (L, 1); - g_autoptr (WpSettings) s = wp_settings_get_instance (get_wp_core (L), - "sm-settings"); - - g_autoptr (WpProperties) cp = wplua_table_to_properties (L, 2); - g_autoptr (WpProperties) ap = wp_properties_new_empty (); - - - if (s) { - gboolean value = wp_settings_apply_rule (s, r, cp, ap); - lua_pushboolean (L, value); - wplua_properties_to_table (L, ap); - return 2; - } - - lua_pushnil (L); - return 1; -} - static int settings_subscribe (lua_State *L) { @@ -1828,7 +1677,6 @@ settings_subscribe (lua_State *L) return 1; } - static int settings_unsubscribe (lua_State *L) { @@ -1846,13 +1694,6 @@ settings_unsubscribe (lua_State *L) static const luaL_Reg settings_methods[] = { { "get", settings_get }, - { "parse_boolean_safe", settings_parse_boolean_safe }, - { "parse_int_safe", settings_parse_int_safe }, - { "parse_float_safe", settings_parse_float_safe }, - { "parse_string_safe", settings_parse_string_safe }, - { "parse_array_safe", settings_parse_array_safe }, - { "parse_object_safe", settings_parse_object_safe }, - { "apply_rule", settings_apply_rule }, { "subscribe", settings_subscribe }, { "unsubscribe", settings_unsubscribe }, { NULL, NULL } diff --git a/src/config/wireplumber.conf.d/access.conf b/src/config/wireplumber.conf.d/access.conf index d1424f2b..719f32bf 100644 --- a/src/config/wireplumber.conf.d/access.conf +++ b/src/config/wireplumber.conf.d/access.conf @@ -3,46 +3,41 @@ wireplumber.settings = { ## Enables flatpak portal # access-enable-flatpak-portal = true - - ## The list of access rules - access.rules = [ - ## The following are the default rules applied if none overrides them. - # { - # matches = [ - # { - # pipewire.access = "flatpak" - # media.category = "Manager" - # } - # ] - # actions = { - # update-props = { - # default_permissions = "all", - # } - # } - # } - # { - # matches = [ - # { - # pipewire.access = "flatpak" - # } - # ] - # actions = { - # update-props = { - # default_permissions = "rx" - # } - # } - # } - # { - # matches = [ - # { - # pipewire.access = "restricted" - # } - # ] - # actions = { - # update-props = { - # default_permissions = "rx" - # } - # } - # } - ] } + +access.rules = [ + ## The list of access rules + + ## The following are the default rules applied if none overrides them. + # { + # matches = [ + # { + # pipewire.access = "flatpak" + # media.category = "Manager" + # } + # ] + # update-props = { + # default_permissions = "all", + # } + # } + # { + # matches = [ + # { + # pipewire.access = "flatpak" + # } + # ] + # update-props = { + # default_permissions = "rx" + # } + # } + # { + # matches = [ + # { + # pipewire.access = "restricted" + # } + # ] + # update-props = { + # default_permissions = "rx" + # } + # } +] diff --git a/src/config/wireplumber.conf.d/alsa.conf b/src/config/wireplumber.conf.d/alsa.conf index ff9c087d..2728b417 100644 --- a/src/config/wireplumber.conf.d/alsa.conf +++ b/src/config/wireplumber.conf.d/alsa.conf @@ -21,153 +21,152 @@ wireplumber.settings = { ## not used by the session manager, in order to be able to ## connect to the real JACK server. # monitor.alsa.jack-device = false +} +monitor.alsa.properties = { ## The properties used when constructing the 'api.alsa.enum.udev' plugin - # monitor.alsa.properties = {} +} +monitor.alsa.midi.node-properties = { + ## MIDI bridge node properties + + ## Name set for the node with ALSA MIDI ports + node.name = "Midi-Bridge" + + ## Removes longname/number from MIDI port names + api.alsa.disable-longname = true +} + +monitor.alsa.vm.node.defaults = { ## These properties override node defaults when running in a virtual machine. ## The rules below still override those. - # monitor.alsa.vm.node.defaults = { - # api.alsa.period-size = 256 - # api.alsa.headroom = 8192 - # } - ## MIDI bridge node properties - # monitor.alsa.midi.node-properties = { - # ## Name set for the node with ALSA MIDI ports - # node.name = "Midi-Bridge" - # ## Removes longname/number from MIDI port names - # api.alsa.disable-longname = true - # } - - ## The list of monitor rules - monitor.alsa.rules = [ - ## The following are the default rules applied if none overrides them. - # { - # matches = [ - # { - # device.name = "~alsa_card.*" - # } - # ] - # actions = { - # update-props = { - # api.alsa.use-acp = true - # api.acp.auto-port = false - # } - # } - # } - - ## This rule example allows changing properties on all ALSA devices. - # { - # matches = [ - # { - # ## This matches all cards. - # device.name = "~alsa_card.*" - # } - # ] - # actions = { - # update-props = { - # ## Use ALSA-Card-Profile devices. They use UCM or the profile - # ## configuration to configure the device and mixer settings. - # api.alsa.use-acp = false - # - # ## Use UCM instead of profile when available. Can be - # ## disabled to skip trying to use the UCM profile. - # api.alsa.use-ucm = false - # - # ## Don't use the hardware mixer for volume control. It - # ## will only use software volume. The mixer is still used - # ## to mute unused paths based on the selected port. - # api.alsa.soft-mixer = false - # - # ## Ignore decibel settings of the driver. Can be used to - # ## work around buggy drivers that report wrong values. - # api.alsa.ignore-dB = false - # - # ## The profile set to use for the device. Usually this is - # ## "default.conf" but can be changed with a udev rule or here. - # device.profile-set = "profileset-name" - # - # ## The default active profile. Is by default set to "Off". - # device.profile = "default profile name" - # - # ## Automatically select the best profile. This is the - # ## highest priority available profile. This is disabled - # ## here and instead implemented in the session manager - # ## where it can save and load previous preferences. - # api.acp.auto-profile = false - # - # ## Automatically switch to the highest priority available port. - # ## This is disabled here and implemented in the session manager instead. - # api.acp.auto-port = true - # - # ## Other properties can be set here. - # device.nick = "My Device" - # - # ## Whether to disable the device or not - # device.disabled = false - # } - # } - # } - - ## This rule example allows changing properties on all ALSA nodes. - # { - # matches = [ - # { - # ## Matches all sources. - # node.name = "~alsa_input.*" - # } - # { - # ## Matches all sinks. - # node.name = "~alsa_output.*" - # } - # ] - # actions = { - # update-props = { - # node.nick = "My Node" - # node.description = "My Node Description" - # priority.driver = 100 - # priority.session = 100 - # node.pause-on-idle = false - # monitor.channel-volumes = false - # resample.quality = 4 - # resample.disable = false - # channelmix.normalize = false - # channelmix.mix-lfe = false - # channelmix.upmix = true - # - # ## only "psd", "none" or "simple" values are accepted - # channelmix.upmix-method = "psd" - # - # channelmix.lfe-cutoff = 150 - # channelmix.fc-cutoff = 12000 - # channelmix.rear-delay = 12.0 - # channelmix.stereo-widen = 0.0 - # channelmix.hilbert-taps = 0 - # channelmix.disable = false - # dither.noise = 0 - # dither.method = "none" - # audio.channels = 2 - # audio.format = "S16LE" - # audio.rate = 44100 - # audio.allowed-rates = "32000,96000" - # audio.position = "FLFR" - # api.alsa.period-size = 1024 - # api.alsa.period-num = 2 - # api.alsa.headroom = 0 - # api.alsa.start-delay = 0 - # api.alsa.disable-mmap = false - # api.alsa.disable-batch = false - # api.alsa.use-chmap = false - # api.alsa.multirate = true - # latency.internal.rate = 0 - # latency.internal.ns = 0 - # clock.name = "api.alsa.0" - # - # ## 0 disables suspend - # session.suspend-timeout-seconds = 5 - # } - # } - # } - ] + api.alsa.period-size = 256 + api.alsa.headroom = 8192 } + +monitor.alsa.rules = [ + ## The list of monitor rules + + ## The following are the default rules applied if none overrides them. + # { + # matches = [ + # { + # device.name = "~alsa_card.*" + # } + # ] + # update-props = { + # api.alsa.use-acp = true + # api.acp.auto-port = false + # } + # } + + ## This rule example allows changing properties on all ALSA devices. + # { + # matches = [ + # { + # ## This matches all cards. + # device.name = "~alsa_card.*" + # } + # ] + # update-props = { + # ## Use ALSA-Card-Profile devices. They use UCM or the profile + # ## configuration to configure the device and mixer settings. + # api.alsa.use-acp = false + # + # ## Use UCM instead of profile when available. Can be + # ## disabled to skip trying to use the UCM profile. + # api.alsa.use-ucm = false + # + # ## Don't use the hardware mixer for volume control. It + # ## will only use software volume. The mixer is still used + # ## to mute unused paths based on the selected port. + # api.alsa.soft-mixer = false + # + # ## Ignore decibel settings of the driver. Can be used to + # ## work around buggy drivers that report wrong values. + # api.alsa.ignore-dB = false + # + # ## The profile set to use for the device. Usually this is + # ## "default.conf" but can be changed with a udev rule or here. + # device.profile-set = "profileset-name" + # + # ## The default active profile. Is by default set to "Off". + # device.profile = "default profile name" + # + # ## Automatically select the best profile. This is the + # ## highest priority available profile. This is disabled + # ## here and instead implemented in the session manager + # ## where it can save and load previous preferences. + # api.acp.auto-profile = false + # + # ## Automatically switch to the highest priority available port. + # ## This is disabled here and implemented in the session manager instead. + # api.acp.auto-port = true + # + # ## Other properties can be set here. + # device.nick = "My Device" + # + # ## Whether to disable the device or not + # device.disabled = false + # } + # } + + ## This rule example allows changing properties on all ALSA nodes. + # { + # matches = [ + # { + # ## Matches all sources. + # node.name = "~alsa_input.*" + # } + # { + # ## Matches all sinks. + # node.name = "~alsa_output.*" + # } + # ] + # update-props = { + # node.nick = "My Node" + # node.description = "My Node Description" + # priority.driver = 100 + # priority.session = 100 + # node.pause-on-idle = false + # monitor.channel-volumes = false + # resample.quality = 4 + # resample.disable = false + # channelmix.normalize = false + # channelmix.mix-lfe = false + # channelmix.upmix = true + # + # ## only "psd", "none" or "simple" values are accepted + # channelmix.upmix-method = "psd" + # + # channelmix.lfe-cutoff = 150 + # channelmix.fc-cutoff = 12000 + # channelmix.rear-delay = 12.0 + # channelmix.stereo-widen = 0.0 + # channelmix.hilbert-taps = 0 + # channelmix.disable = false + # dither.noise = 0 + # dither.method = "none" + # audio.channels = 2 + # audio.format = "S16LE" + # audio.rate = 44100 + # audio.allowed-rates = "32000,96000" + # audio.position = "FLFR" + # api.alsa.period-size = 1024 + # api.alsa.period-num = 2 + # api.alsa.headroom = 0 + # api.alsa.start-delay = 0 + # api.alsa.disable-mmap = false + # api.alsa.disable-batch = false + # api.alsa.use-chmap = false + # api.alsa.multirate = true + # latency.internal.rate = 0 + # latency.internal.ns = 0 + # clock.name = "api.alsa.0" + # + # ## 0 disables suspend + # session.suspend-timeout-seconds = 5 + # } + # } +] diff --git a/src/config/wireplumber.conf.d/bluetooth.conf b/src/config/wireplumber.conf.d/bluetooth.conf index 9fc5c73d..55ab5f3a 100644 --- a/src/config/wireplumber.conf.d/bluetooth.conf +++ b/src/config/wireplumber.conf.d/bluetooth.conf @@ -8,186 +8,187 @@ wireplumber.settings = { ## This requires access to the D-Bus user session; disable if you are running ## a system-wide instance of wireplumber. # monitor.bluetooth.enable-logind = true +} +monitor.bluetooth.properties = { ## The properties used when constructing the 'api.bluez5.enum.dbus' plugin - # monitor.bluetooth.properties = { - # ## Whether to support connection info or not - # api.bluez5.connection-info = true - # ## These features do not work on all headsets, so they are enabled - # ## by default based on the hardware database. They can also be - # ## forced on/off for all devices by the following options: - # bluez5.enable-sbc-xq = true - # bluez5.enable-msbc = true - # bluez5.enable-hw-volume = true + ## Whether to support connection info or not + api.bluez5.connection-info = true - # ## Enabled roles (default: [ a2dp_sink a2dp_source bap_sink bap_source hfp_hf hfp_ag ]) - # ## - # ## Currently some headsets (Sony WH-1000XM3) are not working with - # ## both hsp_ag and hfp_ag enabled, so by default we enable only HFP. - # ## - # ## Supported roles: hsp_hs (HSP Headset), - # ## hsp_ag (HSP Audio Gateway), - # ## hfp_hf (HFP Hands-Free), - # ## hfp_ag (HFP Audio Gateway) - # ## a2dp_sink (A2DP Audio Sink) - # ## a2dp_source (A2DP Audio Source) - # ## bap_sink (LE Audio Basic Audio Profile Sink) - # ## bap_source (LE Audio Basic Audio Profile Source) - # # bluez5.roles = "[ a2dp_sink a2dp_source bap_sink bap_source hsp_hs hsp_ag hfp_hf hfp_ag ]" + ## Enabled roles (default: [ a2dp_sink a2dp_source bap_sink bap_source hfp_hf hfp_ag ]) + ## + ## Currently some headsets (Sony WH-1000XM3) are not working with + ## both hsp_ag and hfp_ag enabled, so by default we enable only HFP. + ## + ## Supported roles: hsp_hs (HSP Headset), + ## hsp_ag (HSP Audio Gateway), + ## hfp_hf (HFP Hands-Free), + ## hfp_ag (HFP Audio Gateway) + ## a2dp_sink (A2DP Audio Sink) + ## a2dp_source (A2DP Audio Source) + ## bap_sink (LE Audio Basic Audio Profile Sink) + ## bap_source (LE Audio Basic Audio Profile Source) + # bluez5.roles = "[ a2dp_sink a2dp_source bap_sink bap_source hsp_hs hsp_ag hfp_hf hfp_ag ]" - # ## Enabled A2DP codecs (default: all). - # bluez5.codecs = "[ sbc sbc_xq aac ldac aptx aptx_hd aptx_ll aptx_ll_duplex faststream faststream_duplex ]" + ## Enabled A2DP codecs (default: all). + # bluez5.codecs = "[ sbc sbc_xq aac ldac aptx aptx_hd aptx_ll aptx_ll_duplex faststream faststream_duplex ]" - # ## HFP/HSP backend (default: native). - # ## Available values: any, none, hsphfpd, ofono, native - # bluez5.hfphsp-backend = "native" + ## These features do not work on all headsets, so they are enabled + ## by default based on the hardware database. They can also be + ## forced on/off for all devices by the following options: + # bluez5.enable-sbc-xq = true + # bluez5.enable-msbc = true + # bluez5.enable-hw-volume = true - # ## HFP/HSP native backend modem (default: none). - # ## Available values: none, any or the modem device string as found in - # ## 'Device' property of org.freedesktop.ModemManager1.Modem interface - # bluez5.hfphsp-backend-native-modem = "none" + ## HFP/HSP backend (default: native). + ## Available values: any, none, hsphfpd, ofono, native + # bluez5.hfphsp-backend = "native" - # ## HFP/HSP hardware offload SCO support (default: false). - # bluez5.hw-offload-sco = false + ## HFP/HSP native backend modem (default: none). + ## Available values: none, any or the modem device string as found in + ## 'Device' property of org.freedesktop.ModemManager1.Modem interface + # bluez5.hfphsp-backend-native-modem = "none" - # ## Properties for the A2DP codec configuration - # bluez5.default.rate = 48000 - # bluez5.default.channels = 2 + ## HFP/HSP hardware offload SCO support (default: false). + # bluez5.hw-offload-sco = false - # ## Register dummy AVRCP player, required for AVRCP volume function. - # ## Disable if you are running mpris-proxy or equivalent. - # bluez5.dummy-avrcp-player = true + ## Properties for the A2DP codec configuration + # bluez5.default.rate = 48000 + # bluez5.default.channels = 2 - # ## Opus Pro Audio mode settings - # bluez5.a2dp.opus.pro.channels = 3 - # bluez5.a2dp.opus.pro.coupled-streams = 1 - # bluez5.a2dp.opus.pro.locations = "FL,FR,LFE" - # bluez5.a2dp.opus.pro.max-bitrate = 600000 - # bluez5.a2dp.opus.pro.frame-dms = 50 - # bluez5.a2dp.opus.pro.bidi.channels = 1 - # bluez5.a2dp.opus.pro.bidi.coupled-streams = 0 - # bluez5.a2dp.opus.pro.bidi.locations = "FC" - # bluez5.a2dp.opus.pro.bidi.max-bitrate = 160000 - # bluez5.a2dp.opus.pro.bidi.frame-dms = 400 - # } + ## Register dummy AVRCP player, required for AVRCP volume function. + ## Disable if you are running mpris-proxy or equivalent. + # bluez5.dummy-avrcp-player = true + ## Opus Pro Audio mode settings + # bluez5.a2dp.opus.pro.channels = 3 + # bluez5.a2dp.opus.pro.coupled-streams = 1 + # bluez5.a2dp.opus.pro.locations = "FL,FR,LFE" + # bluez5.a2dp.opus.pro.max-bitrate = 600000 + # bluez5.a2dp.opus.pro.frame-dms = 50 + # bluez5.a2dp.opus.pro.bidi.channels = 1 + # bluez5.a2dp.opus.pro.bidi.coupled-streams = 0 + # bluez5.a2dp.opus.pro.bidi.locations = "FC" + # bluez5.a2dp.opus.pro.bidi.max-bitrate = 160000 + # bluez5.a2dp.opus.pro.bidi.frame-dms = 400 +} + +monitor.bluetooth-midi.properties = { ## The properties used when constructing the 'api.bluez5.midi.enum' plugin - monitor.bluetooth-midi.properties = {} +} +monitor.bluetooth-midi.servers = [ ## List of MIDI server node names. Each node name given will create a new instance ## of a BLE MIDI service. Typical BLE MIDI instruments have on service instance, ## so adding more than one here may confuse some clients. The node property matching ## rules below apply also to these servers. - monitor.bluetooth-midi.servers = [ "bluez_midi.server" ] + "bluez_midi.server" +] + +monitor.bluetooth.rules = [ ## The list of monitor rules - monitor.bluetooth = [ - ## The following are the default rules applied if none overrides them. - # { - # matches = [ - # { - # device.name = "~bluez_card.*" - # } - # ] - # actions = { - # update-props = { - # bluez5.auto-connect = "[ hfp_hf hsp_hs a2dp_sink ]" - # } - # } - # } - ## This rule example allows changing properties on all Bluetooth devices. - # { - # matches = [ - # { - # ## This matches all cards. - # device.name = "~bluez_card.*" - # } - # ] - # actions = { - # update-props = { - # ## Auto-connect device profiles on start up or when only partial - # ## profiles have connected. Disabled by default if the property - # ## is not specified. - # bluez5.auto-connect = "[ hfp_hf hsp_hs a2dp_sink hfp_ag hsp_ag a2dp_source ]" - # - # ## Hardware volume control (default: [ hfp_ag hsp_ag a2dp_source ]) - # bluez5.hw-volume = "[ hfp_hf hsp_hs a2dp_sink hfp_ag hsp_ag a2dp_source ]" - # - # ## LDAC encoding quality - # ## Available values: auto (Adaptive Bitrate, default) - # ## hq (High Quality, 990/909kbps) - # ## sq (Standard Quality, 660/606kbps) - # ## mq (Mobile use Quality, 330/303kbps) - # bluez5.a2dp.ldac.quality = "auto" - # - # ## AAC variable bitrate mode - # ## Available values: 0 (cbr, default), 1-5 (quality level) - # bluez5.a2dp.aac.bitratemode = 0 - # - # ## Profile connected first - # ## Available values: a2dp-sink (default), headset-head-unit - # device.profile = "a2dp-sink" - # - # ## Opus Pro Audio encoding mode: audio, voip, lowdelay - # bluez5.a2dp.opus.pro.application = "audio" - # bluez5.a2dp.opus.pro.bidi.application = "audio" - # } - # } - # } + ## The following are the default rules applied if none overrides them. + # { + # matches = [ + # { + # device.name = "~bluez_card.*" + # } + # ] + # update-props = { + # bluez5.auto-connect = "[ hfp_hf hsp_hs a2dp_sink ]" + # } + # } - ## This rule example allows changing properties on all Bluetooth nodes. - # { - # matches = [ - # { - # ## Matches all sources. - # node.name = "~bluez_input.*" - # } - # { - # ## Matches all sinks. - # node.name = "~bluez_output.*" - # } - # ] - # actions = { - # update-props = { - # node.nick = "My Node" - # priority.driver = 100 - # priority.session = 100 - # node.pause-on-idle = false - # resample.quality = 4 - # channelmix.normalize = false - # channelmix.mix-lfe = false - # session.suspend-timeout-seconds = 5 - # monitor.channel-volumes = false - # - # ## Media source role, "input" or "playback" - # ## Defaults to "playback", playing stream to speakers - # ## Set to "input" to use as an input for apps - # bluez5.media-source-role = "input" - # } - # } - # } - ] + ## This rule example allows changing properties on all Bluetooth devices. + # { + # matches = [ + # { + # ## This matches all cards. + # device.name = "~bluez_card.*" + # } + # ] + # update-props = { + # ## Auto-connect device profiles on start up or when only partial + # ## profiles have connected. Disabled by default if the property + # ## is not specified. + # bluez5.auto-connect = "[ hfp_hf hsp_hs a2dp_sink hfp_ag hsp_ag a2dp_source ]" + # + # ## Hardware volume control (default: [ hfp_ag hsp_ag a2dp_source ]) + # bluez5.hw-volume = "[ hfp_hf hsp_hs a2dp_sink hfp_ag hsp_ag a2dp_source ]" + # + # ## LDAC encoding quality + # ## Available values: auto (Adaptive Bitrate, default) + # ## hq (High Quality, 990/909kbps) + # ## sq (Standard Quality, 660/606kbps) + # ## mq (Mobile use Quality, 330/303kbps) + # bluez5.a2dp.ldac.quality = "auto" + # + # ## AAC variable bitrate mode + # ## Available values: 0 (cbr, default), 1-5 (quality level) + # bluez5.a2dp.aac.bitratemode = 0 + # + # ## Profile connected first + # ## Available values: a2dp-sink (default), headset-head-unit + # device.profile = "a2dp-sink" + # + # ## Opus Pro Audio encoding mode: audio, voip, lowdelay + # bluez5.a2dp.opus.pro.application = "audio" + # bluez5.a2dp.opus.pro.bidi.application = "audio" + # } + # } + ## This rule example allows changing properties on all Bluetooth nodes. + # { + # matches = [ + # { + # ## Matches all sources. + # node.name = "~bluez_input.*" + # } + # { + # ## Matches all sinks. + # node.name = "~bluez_output.*" + # } + # ] + # update-props = { + # node.nick = "My Node" + # priority.driver = 100 + # priority.session = 100 + # node.pause-on-idle = false + # resample.quality = 4 + # channelmix.normalize = false + # channelmix.mix-lfe = false + # session.suspend-timeout-seconds = 5 + # monitor.channel-volumes = false + # + # ## Media source role, "input" or "playback" + # ## Defaults to "playback", playing stream to speakers + # ## Set to "input" to use as an input for apps + # bluez5.media-source-role = "input" + # } + # } +] + +monitor.bluetooth-midi.rules = [ ## The list of monitor MIDI rules - monitor.bluetooth-midi = [ - ## This rule example allows changing properties on all Bluetooth MIDI nodes. - # { - # matches = { - # { - # ## Matches all nodes. - # { "node.name", "matches", "bluez_midi.*" }, - # }, - # }, - # update-props = { - # node.nick = "My Node" - # priority.driver = 100 - # priority.session = 100 - # node.pause-on-idle = false - # session.suspend-timeout-seconds = 5 - # monitor.channel-volumes = false - # } - # } - ] -} + + ## This rule example allows changing properties on all Bluetooth MIDI nodes. + # { + # matches = { + # { + # ## Matches all nodes. + # { "node.name", "matches", "bluez_midi.*" }, + # }, + # }, + # update-props = { + # node.nick = "My Node" + # priority.driver = 100 + # priority.session = 100 + # node.pause-on-idle = false + # session.suspend-timeout-seconds = 5 + # monitor.channel-volumes = false + # } + # } +] diff --git a/src/config/wireplumber.conf.d/device.conf b/src/config/wireplumber.conf.d/device.conf index 9f8aebba..c50b0afe 100644 --- a/src/config/wireplumber.conf.d/device.conf +++ b/src/config/wireplumber.conf.d/device.conf @@ -23,24 +23,4 @@ wireplumber.settings = { ## Sets the default echo-cancel-source node name to automatically switch to # device.echo-cancel-source-name = "echo-cancel-source" - - ## Sets persistent device profiles that should never be changed, when - ## wireplumber is running, even if a new profile with higher priority becomes - ## available - device.rules = [ - ## The following are the default rules applied if none overrides them. - # { - # matches = [ - # { - # ## Matches all devices - # device.name = "~*" - # } - # ] - # actions = { - # update-props = { - # persistent_profile_names = "off pro-audio" - # } - # } - # } - ] } diff --git a/src/config/wireplumber.conf.d/endpoint.conf b/src/config/wireplumber.conf.d/endpoint.conf index bf8251c9..3d4824b9 100644 --- a/src/config/wireplumber.conf.d/endpoint.conf +++ b/src/config/wireplumber.conf.d/endpoint.conf @@ -1,95 +1,95 @@ ## The WirePlumber endpoint configuration -wireplumber.settings = { +endpoints = { ## The list of endpoints to create - endpoints = { - # endpoint.capture = { - # media.class = "Audio/Source" - # role = "Capture" - # } - # endpoint.multimedia = { - # media.class = "Audio/Sink" - # role = "Multimedia" - # } - # endpoint.speech_low = { - # media.class = "Audio/Sink" - # role = "Speech-Low" - # } - # endpoint.custom_low = { - # media.class = "Audio/Sink" - # role = "Custom-Low" - # } - # endpoint.navigation = { - # media.class = "Audio/Sink" - # role = "Navigation" - # } - # endpoint.speech_high = { - # media.class = "Audio/Sink" - # role = "Speech-High" - # } - # endpoint.custom_high = { - # media.class = "Audio/Sink" - # role = "Custom-High" - # } - # endpoint.communication = { - # media.class = "Audio/Sink" - # role = "Communication" - # } - # endpoint.emergency = { - # media.class = "Audio/Sink" - # role = "Emergency" - # } - } - ## The list of endpoint roles to use - endpoints-roles = { - # Capture = { - # alias = [ "Multimedia", "Music", "Voice", "Capture" ] - # priority = 25 - # action.default = "cork" - # action.capture = "mix" - # media.class = "Audio/Source" - # } - # Multimedia = { - # alias = [ "Movie" "Music" "Game" ] - # priority = 25 - # action.default = "cork" - # } - # Speech-Low = { - # priority = 30 - # action.default = "cork" - # action.Speech-Low = "mix" - # } - # Custom-Low = { - # priority = 35 - # action.default = "cork" - # action.Custom-Low = "mix" - # } - # Navigation = { - # priority = 50 - # action.default = "duck" - # action.Navigation = "mix" - # } - # Speech-High = { - # priority = 60 - # action.default = "cork" - # action.Speech-High = "mix" - # } - # Custom-High = { - # priority = 65 - # action.default = "cork" - # action.Custom-High = "mix" - # } - # Communication = { - # priority = 75 - # action.default = "cork" - # action.Communication = "mix" - # } - # Emergency = { - # alias = [ "Alert" ] - # priority = 99 - # action.default = "cork" - # action.Emergency = "mix" - # } - } + # endpoint.capture = { + # media.class = "Audio/Source" + # role = "Capture" + # } + # endpoint.multimedia = { + # media.class = "Audio/Sink" + # role = "Multimedia" + # } + # endpoint.speech_low = { + # media.class = "Audio/Sink" + # role = "Speech-Low" + # } + # endpoint.custom_low = { + # media.class = "Audio/Sink" + # role = "Custom-Low" + # } + # endpoint.navigation = { + # media.class = "Audio/Sink" + # role = "Navigation" + # } + # endpoint.speech_high = { + # media.class = "Audio/Sink" + # role = "Speech-High" + # } + # endpoint.custom_high = { + # media.class = "Audio/Sink" + # role = "Custom-High" + # } + # endpoint.communication = { + # media.class = "Audio/Sink" + # role = "Communication" + # } + # endpoint.emergency = { + # media.class = "Audio/Sink" + # role = "Emergency" + # } +} + +endpoint-roles = { + ## The list of endpoint roles to use + + # Capture = { + # alias = [ "Multimedia", "Music", "Voice", "Capture" ] + # priority = 25 + # action.default = "cork" + # action.capture = "mix" + # media.class = "Audio/Source" + # } + # Multimedia = { + # alias = [ "Movie" "Music" "Game" ] + # priority = 25 + # action.default = "cork" + # } + # Speech-Low = { + # priority = 30 + # action.default = "cork" + # action.Speech-Low = "mix" + # } + # Custom-Low = { + # priority = 35 + # action.default = "cork" + # action.Custom-Low = "mix" + # } + # Navigation = { + # priority = 50 + # action.default = "duck" + # action.Navigation = "mix" + # } + # Speech-High = { + # priority = 60 + # action.default = "cork" + # action.Speech-High = "mix" + # } + # Custom-High = { + # priority = 65 + # action.default = "cork" + # action.Custom-High = "mix" + # } + # Communication = { + # priority = 75 + # action.default = "cork" + # action.Communication = "mix" + # } + # Emergency = { + # alias = [ "Alert" ] + # priority = 99 + # action.default = "cork" + # action.Emergency = "mix" + # } } diff --git a/src/config/wireplumber.conf.d/libcamera.conf b/src/config/wireplumber.conf.d/libcamera.conf index 6cd93d85..a9ddf679 100644 --- a/src/config/wireplumber.conf.d/libcamera.conf +++ b/src/config/wireplumber.conf.d/libcamera.conf @@ -3,47 +3,45 @@ wireplumber.settings = { ## Enables libcamera monitor # monitor.libcamera.enable = true - - ## The properties used when constructing the 'api.libcamera.enum.manager' plugin - # monitor.libcamera.properties = {} - - ## The list of monitor rules - monitor.libcamera.rules = [ - ## This rule example allows changing properties on all libcamera devices. - # { - # matches = [ - # { - # ## This matches all cards. - # device.name = "~libcamera_device.*" - # } - # ] - # actions = { - # update-props = { - # device.nick = "My Device" - # } - # } - # } - - ## This rule example allows changing properties on all libcamera nodes. - # { - # matches = [ - # { - # ## Matches all sources. - # node.name = "~libcamera_input.*" - # } - # { - # ## Matches all sinks. - # node.name = "~libcamera_output.*" - # } - # ] - # actions = { - # update-props = { - # node.nick = "My Node" - # priority.driver = 100 - # priority.session = 100 - # node.pause-on-idle = false - # } - # } - # } - ] } + +monitor.libcamera.properties = { + ## The properties used when constructing the 'api.libcamera.enum.manager' plugin +} + +monitor.libcamera.rules = [ + ## The list of monitor rules + + ## This rule example allows changing properties on all libcamera devices. + # { + # matches = [ + # { + # ## This matches all cards. + # device.name = "~libcamera_device.*" + # } + # ] + # update-props = { + # device.nick = "My Device" + # } + # } + + ## This rule example allows changing properties on all libcamera nodes. + # { + # matches = [ + # { + # ## Matches all sources. + # node.name = "~libcamera_input.*" + # } + # { + # ## Matches all sinks. + # node.name = "~libcamera_output.*" + # } + # ] + # update-props = { + # node.nick = "My Node" + # priority.driver = 100 + # priority.session = 100 + # node.pause-on-idle = false + # } + # } +] diff --git a/src/config/wireplumber.conf.d/policy.conf b/src/config/wireplumber.conf.d/policy.conf index db486133..18d73123 100644 --- a/src/config/wireplumber.conf.d/policy.conf +++ b/src/config/wireplumber.conf.d/policy.conf @@ -30,10 +30,10 @@ wireplumber.settings = { ## Application names correspond to application.name in stream properties. ## Applications which do not set media.role but which should be considered ## for role based profile switching can be specified here. - # policy.bluetooth.media-role.applications = [ - # "Firefox", "Chromium input", "Google Chrome input", "Brave input", - # "Microsoft Edge input", "Vivaldi input", "ZOOM VoiceEngine", - # "Telegram Desktop", "telegram-desktop", "linphone", "Mumble", - # "WEBRTC VoiceEngine", "Skype" - # ] + policy.bluetooth.media-role.applications = [ + "Firefox", "Chromium input", "Google Chrome input", "Brave input", + "Microsoft Edge input", "Vivaldi input", "ZOOM VoiceEngine", + "Telegram Desktop", "telegram-desktop", "linphone", "Mumble", + "WEBRTC VoiceEngine", "Skype" + ] } diff --git a/src/config/wireplumber.conf.d/stream.conf b/src/config/wireplumber.conf.d/stream.conf index 60910e79..1f7473a4 100644 --- a/src/config/wireplumber.conf.d/stream.conf +++ b/src/config/wireplumber.conf.d/stream.conf @@ -10,22 +10,21 @@ wireplumber.settings = { ## The default channel volume for new streams whose props were never saved ## previously. This is only used if "restore-props" is set to true. # stream.default-channel-volume = 1.0 - - ## The list of stream rules - stream.rules = [ - ## This rule example allows setting properties on the "pw-play" stream. - # { - # matches = [ - # ## Matches all devices - # { application.name = "pw-play" } - # ] - # actions = { - # update-props = { - # state.restore-props = false - # state.restore-target = false - # state.default-channel-volume = 1.0 - # } - # } - # } - ] } + +stream.rules = [ + ## The list of stream rules + + ## This rule example allows setting properties on the "pw-play" stream. + # { + # matches = [ + # ## Matches all devices + # { application.name = "pw-play" } + # ] + # update-props = { + # state.restore-props = false + # state.restore-target = false + # state.default-channel-volume = 1.0 + # } + # } +] diff --git a/src/config/wireplumber.conf.d/v4l2.conf b/src/config/wireplumber.conf.d/v4l2.conf index 38fedd7c..6f4420d0 100644 --- a/src/config/wireplumber.conf.d/v4l2.conf +++ b/src/config/wireplumber.conf.d/v4l2.conf @@ -1,46 +1,42 @@ ## The WirePlumber V4L2 configuration -wireplumber.settings = { +monitor.v4l2.properties = { ## The properties used when constructing the 'api.v4l2.enum.udev' plugin - # monitor.v4l2.properties = {} - - ## The list of monitor rules - monitor.v4l2.rules = [ - ## This rule example allows changing properties on all V4L2 devices. - # { - # matches = [ - # { - # ## This matches all cards. - # device.name = "~v4l2_device.*" - # } - # ] - # actions = { - # update-props = { - # device.nick = "My Device" - # } - # } - # } - - ## This rule example allows changing properties on all V4L2 nodes. - # { - # matches = [ - # { - # ## Matches all sources. - # node.name = "~v4l2_input.*" - # } - # { - # ## Matches all sinks. - # node.name = "~v4l2_output.*" - # } - # ] - # actions = { - # update-props = { - # node.nick = "My Node" - # priority.driver = 100 - # priority.session = 100 - # node.pause-on-idle = false - # } - # } - # } - ] } + +monitor.v4l2.rules = [ + ## The list of monitor rules. + + ## This rule example allows changing properties on all V4L2 devices. + # { + # matches = [ + # { + # ## This matches all cards. + # device.name = "~v4l2_device.*" + # } + # ] + # update-props = { + # device.nick = "My Device" + # } + # } + + ## This rule example allows changing properties on all V4L2 nodes. + # { + # matches = [ + # { + # ## Matches all sources. + # node.name = "~v4l2_input.*" + # } + # { + # ## Matches all sinks. + # node.name = "~v4l2_output.*" + # } + # ] + # update-props = { + # node.nick = "My Node" + # priority.driver = 100 + # priority.session = 100 + # node.pause-on-idle = false + # } + # } +] diff --git a/src/scripts/client/access-default.lua b/src/scripts/client/access-default.lua index 898d44e5..f52b8468 100644 --- a/src/scripts/client/access-default.lua +++ b/src/scripts/client/access-default.lua @@ -19,7 +19,8 @@ function getDefaultPermissions (properties) end function getPermissions (properties) - local matched, mprops = Settings.apply_rule ("access.rules", properties) + local matched, mprops = Conf.apply_rules ("access.rules", + properties) if (matched and mprops["default_permissions"]) then return mprops["default_permissions"] diff --git a/src/scripts/lib/common-utils.lua b/src/scripts/lib/common-utils.lua index ce3b8e4e..541eb168 100644 --- a/src/scripts/lib/common-utils.lua +++ b/src/scripts/lib/common-utils.lua @@ -51,7 +51,7 @@ cutils.default_metadata_om = ObjectManager { } function cutils.evaluateRulesApplyProperties (properties, name) - local matched, mprops = Settings.apply_rule (name, properties) + local matched, mprops = Conf.apply_rules (name, properties) if (matched and mprops) then for k, v in pairs (mprops) do diff --git a/src/scripts/monitors/alsa-midi.lua b/src/scripts/monitors/alsa-midi.lua index fa8fe463..8e06aec8 100644 --- a/src/scripts/monitors/alsa-midi.lua +++ b/src/scripts/monitors/alsa-midi.lua @@ -6,14 +6,11 @@ -- SPDX-License-Identifier: MIT local defaults = {} -defaults.node_properties = Json.Object { - ["node.name"] = "Midi-Bridge", - ["api.alsa.disable-longname"] = true -} +defaults.node_properties = Json.Object {} local config = {} -config.node_properties = Settings.parse_object_safe ( - "monitor.alsa.midi.node-properties", defaults.node_properties) +config.node_properties = Conf.get_section ( + "monitor.alsa.midi.node-properties", defaults.node_properties):parse () SND_PATH = "/dev/snd" SEQ_NAME = "seq" diff --git a/src/scripts/monitors/alsa.lua b/src/scripts/monitors/alsa.lua index f105129a..3ddf6d91 100644 --- a/src/scripts/monitors/alsa.lua +++ b/src/scripts/monitors/alsa.lua @@ -12,22 +12,19 @@ defaults.reserve_priority = -20 defaults.reserve_application_name = "WirePlumber" defaults.jack_device = false defaults.properties = Json.Object {} -defaults.vm_node_defaults = Json.Object { - ["api.alsa.period-size"] = 256, - ["api.alsa.headroom"] = 8192 -} +defaults.vm_node_defaults = Json.Object {} local config = {} -config.reserve_priority = Settings.parse_int_safe ( +config.reserve_priority = Conf.get_value_int ("wireplumber.settings", "monitor.alsa.reserve-priority", defaults.reserve_priority) -config.reserve_application_name = Settings.parse_string_safe ( +config.reserve_application_name = Conf.get_value_string ("wireplumber.settings", "monitor.alsa.reserve-application-name", defaults.reserve_application_name) -config.jack_device = Settings.parse_boolean_safe ( +config.jack_device = Conf.get_value_boolean ("wireplumber.settings", "monitor.alsa.jack-device", defaults.jack_device) -config.properties = Settings.parse_object_safe ( - "monitor.alsa.properties", defaults.properties) -config.vm_node_defaults = Settings.parse_object_safe ( - "monitor.alsa.vm.node.defaults", defaults.vm_node_defaults) +config.properties = Conf.get_section ( + "monitor.alsa.properties", defaults.properties):parse () +config.vm_node_defaults = Conf.get_section ( + "monitor.alsa.vm.node.defaults", defaults.vm_node_defaults):parse () -- unique device/node name tables device_names_table = nil @@ -270,7 +267,8 @@ function prepareDevice(parent, id, obj_type, factory, properties) end -- apply properties from rules defined in JSON .conf file - local applied = cutils.evaluateRulesApplyProperties (properties, "monitor.alsa.rules") + local applied = cutils.evaluateRulesApplyProperties (properties, + "monitor.alsa.rules") if not applied then applyDefaultDeviceProperties (properties) end diff --git a/src/scripts/monitors/bluez-midi.lua b/src/scripts/monitors/bluez-midi.lua index 5ca2888c..46858975 100644 --- a/src/scripts/monitors/bluez-midi.lua +++ b/src/scripts/monitors/bluez-midi.lua @@ -12,10 +12,10 @@ defaults.properties = Json.Object {} defaults.servers = Json.Array { "bluez_midi.server" } local config = {} -config.properties = Settings.parse_object_safe ( - "monitor.bluetooth-midi.properties", defaults.properties) -config.servers = Settings.parse_array_safe ( - "monitor.bluetooth-midi.servers", defaults.servers) +config.properties = Conf.get_section ( + "monitor.bluetooth-midi.properties", defaults.properties): parse () +config.servers = Conf.get_section ( + "monitor.bluetooth-midi.servers", defaults.servers): parse () -- unique device/node name tables node_names_table = nil @@ -60,7 +60,7 @@ function createNode(parent, id, type, factory, properties) properties["api.glib.mainloop"] = "true" -- apply properties from bluetooth.conf - cutils.evaluateRulesApplyProperties (properties, "monitor.bluetooth-midi") + cutils.evaluateRulesApplyProperties (properties, "monitor.bluetooth-midi.rules") local latency_offset = properties["node.latency-offset-msec"] properties["node.latency-offset-msec"] = nil @@ -116,7 +116,7 @@ function createServers() ["factory.name"] = "api.bluez5.midi.node", ["api.glib.mainloop"] = "true", } - cutils.evaluateRulesApplyProperties (node_props, "monitor.bluetooth-midi") + cutils.evaluateRulesApplyProperties (node_props, "monitor.bluetooth-midi.rules") local latency_offset = node_props["node.latency-offset-msec"] node_props["node.latency-offset-msec"] = nil diff --git a/src/scripts/monitors/bluez.lua b/src/scripts/monitors/bluez.lua index bee38bc2..66c5c40a 100644 --- a/src/scripts/monitors/bluez.lua +++ b/src/scripts/monitors/bluez.lua @@ -10,13 +10,11 @@ local COMBINE_OFFSET = 64 local cutils = require ("common-utils") local defaults = {} -defaults.properties = Json.Object { - ["api.bluez5.connection-info"] = true -} +defaults.properties = Json.Object {} local config = {} -config.properties = Settings.parse_object_safe ( - "monitor.bluetooth.properties", defaults.properties) +config.properties = Conf.get_section ( + "monitor.bluetooth.properties", defaults.properties): parse () devices_om = ObjectManager { Interest { @@ -282,7 +280,7 @@ function createNode(parent, id, type, factory, properties) end -- apply properties from bluetooth.conf - cutils.evaluateRulesApplyProperties (properties, "monitor.bluetooth") + cutils.evaluateRulesApplyProperties (properties, "monitor.bluetooth.rules") -- create the node; bluez requires "local" nodes, i.e. ones that run in -- the same process as the spa device, for several reasons @@ -344,7 +342,8 @@ function createDevice(parent, id, type, factory, properties) properties["api.bluez5.id"] = id -- apply properties from bluetooth.conf - local applied = cutils.evaluateRulesApplyProperties (properties, "monitor.bluetooth") + local applied = cutils.evaluateRulesApplyProperties (properties, + "monitor.bluetooth.rules") if not applied then applyDefaultDeviceProperties (properties) end diff --git a/src/scripts/monitors/libcamera.lua b/src/scripts/monitors/libcamera.lua index b03b7841..bcc885fe 100644 --- a/src/scripts/monitors/libcamera.lua +++ b/src/scripts/monitors/libcamera.lua @@ -11,8 +11,8 @@ local defaults = {} defaults.properties = Json.Object {} local config = {} -config.properties = Settings.parse_object_safe ( - "monitor.libcamera.properties", defaults.properties) +config.properties = Conf.get_section ( + "monitor.libcamera.properties", defaults.properties): parse () function findDuplicate(parent, id, property, value) for i = 0, id - 1, 1 do diff --git a/src/scripts/monitors/v4l2.lua b/src/scripts/monitors/v4l2.lua index 78c2766e..a416b980 100644 --- a/src/scripts/monitors/v4l2.lua +++ b/src/scripts/monitors/v4l2.lua @@ -11,8 +11,8 @@ local defaults = {} defaults.properties = Json.Object {} local config = {} -config.properties = Settings.parse_object_safe ( - "monitor.v4l2.properties", defaults.properties) +config.properties = Conf.get_section ( + "monitor.v4l2.properties", defaults.properties): parse () function findDuplicate(parent, id, property, value) for i = 0, id - 1, 1 do diff --git a/src/scripts/policy-bluetooth.lua b/src/scripts/policy-bluetooth.lua index 2d12ca24..05727749 100644 --- a/src/scripts/policy-bluetooth.lua +++ b/src/scripts/policy-bluetooth.lua @@ -31,20 +31,15 @@ local cutils = require ("common-utils") local defaults = {} defaults.use_persistent_storage = true defaults.use_headset_profile = true -defaults.app_settings = Json.Array { - "Firefox", "Chromium input", "Google Chrome input", "Brave input", - "Microsoft Edge input", "Vivaldi input", "ZOOM VoiceEngine", - "Telegram Desktop", "telegram-desktop", "linphone", "Mumble", - "WEBRTC VoiceEngine", "Skype" -} +defaults.app_settings = Json.Array {} local config = {} -config.use_persistent_storage = Settings.parse_boolean_safe ( +config.use_persistent_storage = Conf.get_value_boolean ("wireplumber.settings", "policy.bluetooth.use-persistent-storage", defaults.use_persistent_storage) -config.use_headset_profile = Settings.parse_boolean_safe ( +config.use_headset_profile = Conf.get_value_boolean ("wireplumber.settings", "policy.bluetooth.media-role.use-headset-profile", defaults.use_headset_profile) -config.apps_setting = Settings.parse_array_safe ( - "policy.bluetooth.media-role.applications", defaults.app_settings) +config.apps_setting = Conf.get_value ("wireplumber.settings", + "policy.bluetooth.media-role.applications", defaults.app_settings): parse () state = nil headset_profiles = nil @@ -60,17 +55,17 @@ function handlePersistantSetting (enable) end end -local function settingsChangedCallback (_, setting, _) - if setting == "policy.bluetooth.use-persistent-storage" then - config.use_persistent_storage = Settings.parse_boolean_safe - ("policy.bluetooth.use-persistent-storage", config.use_persistent_storage) +local function settingsChangedCallback (_, setting, json) + if setting == "policy.bluetooth.use-persistent-storage" and + json:is_boolean () then + config.use_persistent_storage = json:parse () handlePersistantSetting (config.use_persistent_storage) - elseif setting == "policy.bluetooth.media-role.use-headset-profile" then - config.use_headset_profile = Settings.parse_boolean_safe - ("policy.bluetooth.media-role.use-headset-profile", config.use_headset_profile) - elseif setting == "policy.bluetooth.media-role.applications" then - local new_apps_setting = Settings.parse_array_safe - ("policy.bluetooth.media-role.applications", Json.Array {}) + elseif setting == "policy.bluetooth.media-role.use-headset-profile" and + json:is_boolean () then + config.use_headset_profile = json:parse () + elseif setting == "policy.bluetooth.media-role.applications" + and json:is_array () then + local new_apps_setting = json:parse () if #new_apps_setting > 0 then config.apps_setting = new_apps_setting loadAppNames (config.apps_setting) diff --git a/src/scripts/policy-endpoint-client-links.lua b/src/scripts/policy-endpoint-client-links.lua index 50363a7c..2fc78c44 100644 --- a/src/scripts/policy-endpoint-client-links.lua +++ b/src/scripts/policy-endpoint-client-links.lua @@ -10,10 +10,10 @@ defaults.duck_level = 0.3 defaults.roles = Json.Object {} local config = {} -config.duck_level = Settings.parse_float_safe ( +config.duck_level = Conf.get_value_float ("wireplumber.settings", "policy.default.duck-level", defaults.duck_level) -config.roles = Settings.parse_object_safe ( - "endpoints-roles", defaults.roles) +config.roles = Conf.get_section ( + "endpoint-roles", defaults.roles):parse () function findRole(role) if role and not config.roles[role] then diff --git a/src/scripts/policy-endpoint-client.lua b/src/scripts/policy-endpoint-client.lua index cb7af7c1..9184b17b 100644 --- a/src/scripts/policy-endpoint-client.lua +++ b/src/scripts/policy-endpoint-client.lua @@ -11,8 +11,8 @@ local defaults = {} defaults.roles = Json.Object {} local config = {} -config.roles = Settings.parse_object_safe ( - "endpoints-roles", defaults.roles) +config.roles = Conf.get_section ( + "endpoint-roles", defaults.roles):parse () local self = {} self.scanning = false diff --git a/src/scripts/policy-endpoint-device.lua b/src/scripts/policy-endpoint-device.lua index 2dbd06e8..8d71810b 100644 --- a/src/scripts/policy-endpoint-device.lua +++ b/src/scripts/policy-endpoint-device.lua @@ -9,7 +9,7 @@ local defaults = {} defaults.follow = true local config = {} -config.follow = Settings.parse_boolean_safe ( +config.follow = Conf.get_value_boolean ("wireplumber.settings", "policy.default.follow", defaults.follow) local self = {} diff --git a/src/scripts/static-endpoints.lua b/src/scripts/static-endpoints.lua index 608d42c8..e5541eee 100644 --- a/src/scripts/static-endpoints.lua +++ b/src/scripts/static-endpoints.lua @@ -11,8 +11,8 @@ local defaults = {} defaults.endpoints = Json.Object {} local config = {} -config.endpoints = Settings.parse_object_safe ( - "endpoints", defaults.endpoints) +config.endpoints = Conf.get_section ( + "endpoints", defaults.endpoints):parse () function createEndpoint (factory_name, properties) -- create endpoint diff --git a/tests/wp/settings.c b/tests/wp/settings.c index 42a1cc35..f64fc3fa 100644 --- a/tests/wp/settings.c +++ b/tests/wp/settings.c @@ -268,12 +268,6 @@ test_wpsettings (TestSettingsFixture *self, gconstpointer data) g_assert_nonnull (j2); g_assert_true (wp_spa_json_parse_boolean (j2, &value)); g_assert_true (value); - - value = wp_settings_parse_boolean_safe (s, "test-setting2", FALSE); - g_assert_true (value); - - value = wp_settings_parse_boolean_safe (s, "test-setting-undefined", TRUE); - g_assert_true (value); } { @@ -284,12 +278,6 @@ test_wpsettings (TestSettingsFixture *self, gconstpointer data) g_assert_nonnull (j); g_assert_true (wp_spa_json_parse_int (j, &value)); g_assert_cmpint (value, ==, -20); - - value = wp_settings_parse_int_safe (s, "test-setting3-int", 3); - g_assert_cmpint (value, ==, -20); - - value = wp_settings_parse_int_safe (s, "test-setting-undefined", 3); - g_assert_cmpint (value, ==, 3); } { @@ -303,20 +291,6 @@ test_wpsettings (TestSettingsFixture *self, gconstpointer data) g_assert_cmpstr (value, ==, "blahblah"); } - { - g_autofree gchar *value = NULL; - value = wp_settings_parse_string_safe (s, "test-setting4-string", - "fallback-string"); - g_assert_cmpstr (value, ==, "blahblah"); - } - - { - g_autofree gchar *value = NULL; - value = wp_settings_parse_string_safe (s, "test-setting-undefined", - "fallback-string"); - g_assert_cmpstr (value, ==, "fallback-string"); - } - { g_autofree gchar *value = NULL; g_autoptr (WpSpaJson) j = NULL; @@ -340,12 +314,6 @@ test_wpsettings (TestSettingsFixture *self, gconstpointer data) g_assert_nonnull (j2); g_assert_true (wp_spa_json_parse_float (j2, &value)); g_assert_cmpfloat_with_epsilon (value, 0.4, 0.001); - - value = wp_settings_parse_float_safe (s, "test-setting-float1", 4.14); - g_assert_cmpfloat_with_epsilon (value, 3.14, 0.001); - - value = wp_settings_parse_float_safe (s, "test-setting-undefined", 4.14); - g_assert_cmpfloat_with_epsilon (value, 4.14, 0.001); } /* test the wp_settings_get_instance () API */ @@ -447,170 +415,6 @@ test_wpsettings (TestSettingsFixture *self, gconstpointer data) } } -static void -test_rules (TestSettingsFixture *self, gconstpointer data) -{ - WpSettings *s = self->s; - - { - g_autoptr (WpProperties) props = wp_properties_new ( - "test-string2", "juggler", - NULL); - - g_assert_true (wp_settings_apply_rule (s, "rule_one", props, NULL)); - } - - { - g_autoptr (WpProperties) props = wp_properties_new ( - "test-string2", "jugglr", - NULL); - - g_assert_false (wp_settings_apply_rule (s, "rule_one", props, NULL)); - } - - { - g_autoptr (WpProperties) props = wp_properties_new ( - "test-string1", "copper", - "test-int1", "100", - NULL); - - g_assert_true (wp_settings_apply_rule (s, "rule_one", props, NULL)); - } - - { - g_autoptr (WpProperties) props = wp_properties_new ( - "test-string1", "copper", - NULL); - - g_assert_false (wp_settings_apply_rule (s, "rule_one", props, NULL)); - } - - { - g_autoptr (WpProperties) props = wp_properties_new ( - "test-string2", "juggler", - NULL); - gint before = wp_properties_get_count (props), after = 0; - guint prop_int1 = 0; - g_assert_true (wp_settings_apply_rule (s, "rule_one", props, NULL)); - after = wp_properties_get_count (props); - - g_assert_cmpint (after-before, ==, 2); - g_assert_cmpstr (wp_properties_get(props, "prop-string1"), ==, "metal"); - g_assert_cmpstr (wp_properties_get(props, "prop-string2"), ==, NULL); - g_assert_cmpstr (wp_properties_get(props, "prop-int1"), ==, "123"); - spa_atou32 (wp_properties_get(props, "prop-int1"), &prop_int1, 0); - g_assert_cmpint (prop_int1, ==, 123); - } - - { - g_autoptr (WpProperties) props = wp_properties_new ( - "test-string4", "ferrous", - "test-int2", "100", - "test-string5", "blend", - NULL); - gint before = wp_properties_get_count (props), after = 0; - guint prop_int2 = 0; - g_assert_true (wp_settings_apply_rule (s, "rule_one", props, NULL)); - after = wp_properties_get_count (props); - - g_assert_cmpint (after-before, ==, 3); - g_assert_cmpstr (wp_properties_get(props, "prop-string1"), ==, NULL); - g_assert_cmpstr (wp_properties_get(props, "prop-string2"), ==, "standard"); - g_assert_cmpstr (wp_properties_get(props, "prop-int2"), ==, "26"); - spa_atou32 (wp_properties_get(props, "prop-int2"), &prop_int2, 0); - g_assert_cmpint (prop_int2, ==, 26); - g_assert_true (spa_atob(wp_properties_get(props, "prop-bool1"))); - } - - { - g_autoptr (WpProperties) props = wp_properties_new ( - "test-string6", "ethylene", - "test-int2", "625", - "test-string5", "blend", - NULL); - g_autoptr (WpProperties) applied_props = wp_properties_new_empty (); - guint prop_int2 = 0; - g_assert_false (wp_settings_apply_rule (s, "rule_one", props, NULL)); - g_assert_true (wp_settings_apply_rule (s, "rule_two", props, - applied_props)); - - g_assert_cmpint (wp_properties_get_count (applied_props), ==, 2); - g_assert_cmpstr (wp_properties_get(applied_props, "prop-string1"), - ==, NULL); - g_assert_cmpstr (wp_properties_get(applied_props, "prop-string2"), - ==, "spray"); - g_assert_cmpstr (wp_properties_get(applied_props, "prop-int2"), ==, "111"); - spa_atou32 (wp_properties_get(applied_props, "prop-int2"), &prop_int2, 0); - g_assert_cmpint (prop_int2, ==, 111); - g_assert_false (spa_atob(wp_properties_get(applied_props, "prop-bool1"))); - } - - /* test the regular experession syntax */ - { - g_autoptr (WpProperties) props = wp_properties_new ( - "test.string6", "metal.iron", - "test.table.entry", "true", - NULL); - g_autoptr (WpProperties) applied_props = wp_properties_new_empty (); - g_assert_false (wp_settings_apply_rule (s, "rule_one", props, NULL)); - g_assert_false (wp_settings_apply_rule (s, "rule_two", props, - applied_props)); - g_assert_true (wp_settings_apply_rule (s, "rule_three", props, - applied_props)); - - g_assert_cmpint (wp_properties_get_count (applied_props), ==, 3); - g_assert_cmpstr (wp_properties_get(applied_props, "prop.string1"), - ==, NULL); - g_assert_cmpstr (wp_properties_get(applied_props, "prop.state"), - ==, "solid"); - g_assert_cmpstr (wp_properties_get(applied_props, "prop.example"), - ==, "ferrous"); - g_assert_true (spa_atob(wp_properties_get(applied_props, - "prop.electrical.conductivity"))); - } - - { - g_autoptr (WpProperties) props = wp_properties_new ( - "test.string6", "metal.iron", - "test.table.entry", "false", - NULL); - g_assert_false (wp_settings_apply_rule (s, "rule_three", props, - NULL)); - } - - { - g_autoptr (WpProperties) props = wp_properties_new ( - "test.string6", "metl.iron", - "test.table.entry", "true", - NULL); - g_assert_false (wp_settings_apply_rule (s, "rule_three", props, - NULL)); - } - - { - g_autoptr (WpProperties) props = wp_properties_new ( - "test.string6", "gas.neon", - "test.table.entry", "maybe", - NULL); - g_autoptr (WpProperties) applied_props = wp_properties_new_empty (); - g_assert_false (wp_settings_apply_rule (s, "rule_one", props, NULL)); - g_assert_false (wp_settings_apply_rule (s, "rule_two", props, - applied_props)); - g_assert_true (wp_settings_apply_rule (s, "rule_three", props, - applied_props)); - - g_assert_cmpint (wp_properties_get_count (applied_props), ==, 3); - g_assert_cmpstr (wp_properties_get(applied_props, "prop.string1"), - ==, NULL); - g_assert_cmpstr (wp_properties_get(applied_props, "prop.state"), - ==, "gas"); - g_assert_cmpstr (wp_properties_get(applied_props, "prop.example"), - ==, "neon"); - g_assert_false (spa_atob(wp_properties_get(applied_props, - "prop.electrical.conductivity"))); - } -} - void wp_settings_changed_callback (WpSettings *obj, const gchar *setting, WpSpaJson *json, gpointer user_data) { @@ -640,7 +444,6 @@ void wp_settings_changed_callback (WpSettings *obj, const gchar *setting, } } - static void test_callbacks (TestSettingsFixture *self, gconstpointer data) { @@ -722,8 +525,6 @@ main (gint argc, gchar *argv[]) test_metadata_setup, test_metadata, test_metadata_teardown); g_test_add ("/wp/settings/wpsettings-creation-get", TestSettingsFixture, NULL, test_wpsettings_setup, test_wpsettings, test_wpsettings_teardown); - g_test_add ("/wp/settings/wpsettings-creation-rules", TestSettingsFixture, NULL, - test_wpsettings_setup, test_rules, test_wpsettings_teardown); g_test_add ("/wp/settings/wpsettings-callbacks", TestSettingsFixture, NULL, test_wpsettings_setup, test_callbacks, test_wpsettings_teardown); diff --git a/tests/wplua/scripts/settings.lua b/tests/wplua/scripts/settings.lua index 85c49438..80250b46 100644 --- a/tests/wplua/scripts/settings.lua +++ b/tests/wplua/scripts/settings.lua @@ -17,24 +17,12 @@ value = Settings.get ("test-setting2"):parse() assert ("boolean" == type (value)) assert (value == true) -value = Settings.parse_boolean_safe ("test-setting2", false) -assert (value == true) - -value = Settings.parse_boolean_safe ("test-setting-undefined", true) -assert (value == true) - -- test settings _get_int () value = Settings.get ("test-setting3-int"):parse() assert ("number" == type (value)) assert (value == -20) -value = Settings.parse_int_safe ("test-setting3-int", 10) -assert (value == -20) - -value = Settings.parse_int_safe ("test-setting-undefined", 10) -assert (value == 10) - -- test settings _get_string () value = Settings.get ("test-setting4-string"):parse() @@ -45,12 +33,6 @@ value = Settings.get ("test-setting5-string-with-quotes"):parse() assert ("string" == type (value)) assert (value == "a string with \"quotes\"") -value = Settings.parse_string_safe ("test-setting4-string", "fallback-string") -assert (value == "blahblah") - -value = Settings.parse_string_safe ("test-setting-undefined", "fallback-string") -assert (value == "fallback-string") - -- test settings _get_float () value = Settings.get ("test-setting-float1"):parse() @@ -60,34 +42,13 @@ assert ((value - 3.14) < 0.00001) value = Settings.get ("test-setting-float2"):parse() assert ((value - 0.4) < 0.00001) -value = Settings.parse_float_safe ("test-setting-float1", 4.14) -assert ((value - 3.14) < 0.00001) - -value = Settings.parse_float_safe ("test-setting-undefined", 4.14) -assert ((value - 4.14) < 0.00001) - -- test settings _get () value = Settings.get ("test-setting-json") assert (value ~= nil) assert (value:is_array()) assert (value:get_data() == "[1, 2, 3]") -value = Settings.parse_array_safe ("test-setting-json", Json.Array {}) -assert (value ~= nil) -assert (value[1] == 1) -assert (value[2] == 2) -assert (value[3] == 3) - -value = Settings.parse_array_safe ("test-setting-undefined", nil) -assert (value ~= nil) -assert (#value == 0) - -value = Settings.parse_array_safe ("test-setting-undefined", Json.Array { 1, 2 }) -assert (value ~= nil) -assert (value[1] == 1) -assert (value[2] == 2) - -value = Settings.get ("test-setting-json2") +value = Settings.get ("test-setting-json2", "test-settings") assert (value ~= nil) assert (value:is_array()) assert (value:get_data() == @@ -111,132 +72,6 @@ assert (val.key1 == "value") assert (val.key2 == 2) assert (val.key3 == true) -value = Settings.parse_object_safe ("test-setting-json3", Json.Object {}) -assert (value ~= nil) -assert (value.key1 == "value") -assert (value.key2 == 2) -assert (value.key3 == true) - -value = Settings.parse_object_safe ("test-setting-undefined", nil) -assert (value ~= nil) -assert (#value == 0) - -value = Settings.parse_object_safe ("test-setting-undefined", Json.Object { key1 = "value", key2 = 2}) -assert (value ~= nil) -assert (value.key1 == "value") -assert (value.key2 == 2) - --- test rules --- test #1 -local cp = { - ["test-string2"]="juggler" -} -local ap = {} - -local applied, ap = Settings.apply_rule( "rule_one", cp) - -assert (applied == true) -assert (ap["prop-string1"] == "metal") -assert (ap["prop-int1"] == "123") -assert (ap["blah blah"] == nil) - --- test #2 -local cp = { - ["test-string2"]="jugler" -} -local ap = {} - -local applied, ap = Settings.apply_rule ("rule_one", cp) - -assert (applied == false) - --- test #3 -local cp = { - ["test-string4"] = "ferrous", - ["test-int2"] = "100", - ["test-string5"] = "blend" -} - -local applied, ap = Settings.apply_rule ("rule_one", cp) - -assert (applied == true) -assert (ap["prop-string1"] == nil) -assert (ap["prop-string2"] == "standard") -assert (ap["prop-int2"] == "26") -assert (ap["prop-bool1"] == "true") - --- test #4 -local cp = { - ["test-string6"] = "alum", -} - -local applied, ap = Settings.apply_rule ("rule_one", cp) - -assert (applied == false) - --- test #5 -local cp = { - ["test-string6"] = "alum", - ["test-int3"] = "24", -} - -local applied, ap = Settings.apply_rule ("rule_one", cp) - -assert (applied == true) -assert (ap["prop-string1"] == nil) -assert (ap["prop-string2"] == "standard") -assert (ap["prop-int2"] == "26") -assert (ap["prop-bool1"] == "true") - --- test #6 --- test regular expression syntax -local cp = { - ["test.string6"] = "metal.ferrous", - ["test.table.entry"] = "yes", -} - -local applied, ap = Settings.apply_rule ("rule_three", cp) - -assert (applied == false) - --- test #7 -local cp = { - ["test.string6"] = "metal.ferrous", - ["test.table.entry"] = "true", -} - -local applied, ap = Settings.apply_rule ("rule_three", cp) - -assert (applied == true) -assert (ap["prop.electrical.conductivity"] == "true") -assert (ap["prop.state"] == "solid") -assert (ap["prop.example"] == "ferrous") - --- test #8 -local cp = { - ["test.string6"] = "gas.xenon", - ["test.table.entry"] = "maybe", -} - -local applied, ap = Settings.apply_rule ("rule_three", cp) - -assert (applied == true) -assert (ap["prop.electrical.conductivity"] == "false") -assert (ap["prop.state"] == "gas") -assert (ap["prop.example"] == "neon") - --- test #9 -local cp = { - ["test-string6-wildcard"] = "wild_cat", -} - -local applied, ap = Settings.apply_rule ("rule_three", cp) - -assert (applied == true) -assert (ap["prop.electrical.conductivity"] == "true") -assert (ap["prop.state"] == "solid") -assert (ap["prop.example"] == "ferrous") - -- test callbacks metadata_om = ObjectManager {