mirror of
https://gitlab.freedesktop.org/pipewire/wireplumber.git
synced 2026-05-08 12:48:03 +02:00
scripts: use WpConf API to get configuration values
This patch also moves nested configuration objects that are not considered settings from the wireplumber.settings section to its own configuration section (eg the rules array, the spa plugin properties, etc...). This allows those objects to be merged with other same sections defined in other files.
This commit is contained in:
parent
6c6d5eccf9
commit
360e0b3eaf
27 changed files with 594 additions and 1587 deletions
|
|
@ -8,11 +8,11 @@
|
|||
|
||||
#define G_LOG_DOMAIN "wp-settings"
|
||||
|
||||
#include <wp/wp.h>
|
||||
|
||||
#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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
# }
|
||||
# }
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
# }
|
||||
# }
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
# }
|
||||
# }
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
# }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
# }
|
||||
# }
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
# }
|
||||
# }
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
# }
|
||||
# }
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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"]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 = {}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue