2022-03-08 06:58:00 +05:30
|
|
|
/* WirePlumber
|
|
|
|
|
*
|
|
|
|
|
* Copyright © 2022 Collabora Ltd.
|
|
|
|
|
* @author Ashok Sidipotu <ashok.sidipotu@collabora.com>
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: MIT
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <wp/wp.h>
|
|
|
|
|
#include <pipewire/pipewire.h>
|
|
|
|
|
#include <spa/utils/json.h>
|
|
|
|
|
#include <spa/utils/defs.h>
|
|
|
|
|
|
log: implement a log topics system, like pipewire
The intention is to make checks for enabled log topics faster.
Every topic has its own structure that is statically defined in the file
where the logs are printed from. The structure is initialized transparently
when it is first used and it contains all the log level flags for the levels
that this topic should print messages. It is then checked on the wp_log()
macro before printing the message.
Topics from SPA/PipeWire are also handled natively, so messages are printed
directly without checking if the topic is enabled, since the PipeWire and SPA
macros do the checking themselves.
Messages coming from GLib are checked inside the handler.
An internal WpLogFields object is used to manage the state of each log
message, populating all the fields appropriately from the place they
are coming from (wp_log, spa_log, glib log), formatting the message and
then printing it. For printing to the journald, we still use the glib
message handler, converting all the needed fields to GLogField on demand.
That message handler does not do any checks for the topic or the level, so
we can just call it to send the message.
2023-05-16 11:51:29 +03:00
|
|
|
WP_DEFINE_LOCAL_LOG_TOPIC ("m-settings")
|
|
|
|
|
|
2022-03-08 06:58:00 +05:30
|
|
|
/*
|
|
|
|
|
* This module parses the "wireplumber.settings" section from the .conf file.
|
|
|
|
|
*
|
2022-03-31 12:27:22 +05:30
|
|
|
* Creates "sm-settings"(default) metadata and pushes the settings to it.
|
|
|
|
|
* Looks out for changes done in the metadata via the pw-metadata interface.
|
2022-03-08 06:58:00 +05:30
|
|
|
*
|
|
|
|
|
* If persistent settings is enabled stores the settings in a state file
|
|
|
|
|
* and retains the settings from there on subsequent reboots ignoring the
|
|
|
|
|
* contents of .conf file.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
struct _WpSettingsPlugin
|
|
|
|
|
{
|
|
|
|
|
WpPlugin parent;
|
|
|
|
|
|
2022-09-15 15:55:51 -04:00
|
|
|
/* Props */
|
2022-03-31 12:27:22 +05:30
|
|
|
gchar *metadata_name;
|
2024-02-26 09:58:43 -05:00
|
|
|
gchar *metadata_schema_name;
|
|
|
|
|
gchar *metadata_persistent_name;
|
2022-03-31 12:27:22 +05:30
|
|
|
|
2022-03-08 06:58:00 +05:30
|
|
|
WpImplMetadata *impl_metadata;
|
2024-02-26 09:58:43 -05:00
|
|
|
WpImplMetadata *schema_impl_metadata;
|
2024-02-02 14:02:05 -05:00
|
|
|
WpImplMetadata *persistent_impl_metadata;
|
2022-03-08 06:58:00 +05:30
|
|
|
WpState *state;
|
2024-02-02 14:02:05 -05:00
|
|
|
WpProperties *persistent_settings;
|
2022-03-08 06:58:00 +05:30
|
|
|
};
|
|
|
|
|
|
2022-03-31 12:27:22 +05:30
|
|
|
enum {
|
|
|
|
|
PROP_0,
|
|
|
|
|
PROP_METADATA_NAME,
|
|
|
|
|
PROP_PROPERTIES,
|
|
|
|
|
};
|
|
|
|
|
|
2022-03-08 06:58:00 +05:30
|
|
|
G_DECLARE_FINAL_TYPE (WpSettingsPlugin, wp_settings_plugin,
|
|
|
|
|
WP, SETTINGS_PLUGIN, WpPlugin)
|
|
|
|
|
G_DEFINE_TYPE (WpSettingsPlugin, wp_settings_plugin, WP_TYPE_PLUGIN)
|
|
|
|
|
|
|
|
|
|
#define NAME "sm-settings"
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
wp_settings_plugin_init (WpSettingsPlugin * self)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2024-02-02 14:02:05 -05:00
|
|
|
on_persistent_metadata_changed (WpMetadata *m, guint32 subject,
|
|
|
|
|
const gchar *key, const gchar *type, const gchar *value, gpointer d)
|
2022-03-08 06:58:00 +05:30
|
|
|
{
|
2024-02-02 14:02:05 -05:00
|
|
|
WpSettingsPlugin *self = WP_SETTINGS_PLUGIN (d);
|
2024-01-04 16:38:33 +02:00
|
|
|
g_autoptr (WpCore) core = wp_object_get_core (WP_OBJECT (self));
|
2022-03-08 06:58:00 +05:30
|
|
|
|
2024-02-02 14:02:05 -05:00
|
|
|
/* Update persistent settings with new value and timeout save it */
|
|
|
|
|
wp_properties_set (self->persistent_settings, key, value);
|
2024-02-06 10:55:05 -05:00
|
|
|
if (value)
|
|
|
|
|
wp_info_object (self, "persistent setting updated: %s = %s", key, value);
|
|
|
|
|
else
|
|
|
|
|
wp_info_object (self, "persistent setting removed: %s", key);
|
2024-02-02 14:02:05 -05:00
|
|
|
wp_state_save_after_timeout (self->state, core, self->persistent_settings);
|
2022-03-08 06:58:00 +05:30
|
|
|
|
2024-02-02 14:02:05 -05:00
|
|
|
/* Also update current settings with new value */
|
2024-02-06 10:55:05 -05:00
|
|
|
if (value)
|
|
|
|
|
wp_metadata_set (WP_METADATA (self->impl_metadata), 0, key, type, value);
|
2022-03-08 06:58:00 +05:30
|
|
|
}
|
|
|
|
|
|
2022-12-30 10:02:11 -05:00
|
|
|
WpProperties *
|
|
|
|
|
load_configuration_settings (WpSettingsPlugin *self)
|
2022-03-08 06:58:00 +05:30
|
|
|
{
|
2022-12-30 10:02:11 -05:00
|
|
|
g_autoptr (WpCore) core = wp_object_get_core (WP_OBJECT (self));
|
|
|
|
|
g_autoptr (WpConf) conf = NULL;
|
|
|
|
|
g_autoptr (WpSpaJson) json = NULL;
|
|
|
|
|
g_autoptr (WpProperties) res = wp_properties_new_empty ();
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (core, NULL);
|
conf: refactor configuration loading
Changes:
- Configuration files are no longer located by libpipewire,
which allows us to control the paths that are being looked up.
This is a requirement for installations where pipewire and
wireplumber are built using different prefixes, in which case
the configuration files of wireplumber end up being installed in
a place that libpipewire doesn't look into...
- The location of conf files is now again $prefix/share/wireplumber,
/etc/wireplumber and $XDG_CONFIG_HOME/wireplumber, instead of using
the pipewire directories. Also, since the previous commits, we now
also support $XDG_CONFIG_DIRS/wireplumber (typically /etc/xdg/wireplumber)
and $XDG_DATA_DIRS/wireplumber for system-wide configuration.
- Since libpipewire doesn't expose the parser, we now also do the
parsing of sections ourselves. This has the advantage that we can
optimize it a bit for our use case.
- The WpConf API has changed to not be a singleton and it is a
property of WpCore instead. The configuration is now expected
to be opened before the core is created, which allows the caller
to identify configuration errors in advance. By not being a singleton,
we can also reuse the WpConf API to open other SPA-JSON files.
- WpConf also now has a lazy loading mechanism. The configuration
files are mmap'ed and the various sections are located in advance,
but not parsed until they are actually requested. Also, the sections
are not copied in memory, unlike what happens in libpipewire. They
are only copied when merging is needed.
- WpCore now disables loading of a configuration file in pw_context,
if a WpConf is provided. This is to have complete control here.
The 'context.spa-libs' and 'context.modules' sections are still
loaded, but we load them in WpConf and pass them down to pw_context
for parsing. If a WpConf is not provided, pw_context is left to load
the default configuration file (client.conf normally).
2024-02-28 12:11:38 +02:00
|
|
|
conf = wp_core_get_conf (core);
|
2022-12-30 10:02:11 -05:00
|
|
|
g_return_val_if_fail (conf, NULL);
|
|
|
|
|
|
2024-02-28 18:58:57 +02:00
|
|
|
json = wp_conf_get_section (conf, "wireplumber.settings");
|
2022-12-30 10:02:11 -05:00
|
|
|
if (!json)
|
|
|
|
|
return g_steal_pointer (&res);
|
|
|
|
|
|
|
|
|
|
if (!wp_spa_json_is_object (json)) {
|
|
|
|
|
wp_warning_object (self,
|
|
|
|
|
"ignoring wireplumber.settings from conf as it isn't a JSON object");
|
|
|
|
|
return g_steal_pointer (&res);
|
|
|
|
|
}
|
2022-03-08 06:58:00 +05:30
|
|
|
|
2022-12-30 10:02:11 -05:00
|
|
|
{
|
|
|
|
|
g_autoptr (WpIterator) iter = wp_spa_json_new_iterator (json);
|
|
|
|
|
g_auto (GValue) item = G_VALUE_INIT;
|
|
|
|
|
while (wp_iterator_next (iter, &item)) {
|
|
|
|
|
WpSpaJson *j = g_value_get_boxed (&item);
|
|
|
|
|
g_autofree gchar *name = wp_spa_json_parse_string (j);
|
|
|
|
|
g_autofree gchar *value = NULL;
|
|
|
|
|
|
|
|
|
|
g_value_unset (&item);
|
|
|
|
|
if (!wp_iterator_next (iter, &item)) {
|
|
|
|
|
wp_warning_object (self, "malformed wireplumber.settings from conf");
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
j = g_value_get_boxed (&item);
|
|
|
|
|
|
|
|
|
|
value = wp_spa_json_to_string (j);
|
|
|
|
|
g_value_unset (&item);
|
|
|
|
|
|
|
|
|
|
if (name && value)
|
|
|
|
|
wp_properties_set (res, name, value);
|
2022-05-26 13:15:22 +05:30
|
|
|
}
|
2022-03-08 06:58:00 +05:30
|
|
|
}
|
|
|
|
|
|
2022-12-30 10:02:11 -05:00
|
|
|
return g_steal_pointer (&res);
|
2022-03-08 06:58:00 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2024-02-02 14:02:05 -05:00
|
|
|
on_metadata_activated (WpMetadata * m, GAsyncResult * res,
|
|
|
|
|
gpointer user_data)
|
2022-03-08 06:58:00 +05:30
|
|
|
{
|
|
|
|
|
WpTransition *transition = WP_TRANSITION (user_data);
|
|
|
|
|
WpSettingsPlugin *self = wp_transition_get_source_object (transition);
|
|
|
|
|
g_autoptr (WpCore) core = wp_object_get_core (WP_OBJECT (self));
|
2022-12-30 10:02:11 -05:00
|
|
|
g_autoptr (WpProperties) config_settings = NULL;
|
2022-09-15 15:55:51 -04:00
|
|
|
g_autoptr (GError) error = NULL;
|
2022-03-08 06:58:00 +05:30
|
|
|
g_autoptr (WpIterator) it = NULL;
|
|
|
|
|
g_auto (GValue) item = G_VALUE_INIT;
|
|
|
|
|
|
|
|
|
|
if (!wp_object_activate_finish (WP_OBJECT (m), res, &error)) {
|
2022-03-31 12:27:22 +05:30
|
|
|
g_prefix_error (&error, "Failed to activate \"%s\": "
|
|
|
|
|
"Metadata object ", self->metadata_name);
|
2022-03-08 06:58:00 +05:30
|
|
|
wp_transition_return_error (transition, g_steal_pointer (&error));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-30 10:02:11 -05:00
|
|
|
/* Load settings from configuration */
|
|
|
|
|
config_settings = load_configuration_settings (self);
|
|
|
|
|
if (!config_settings) {
|
2022-03-08 06:58:00 +05:30
|
|
|
wp_transition_return_error (transition, g_error_new (
|
2022-12-30 10:02:11 -05:00
|
|
|
WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_OPERATION_FAILED,
|
2022-09-15 15:55:51 -04:00
|
|
|
"failed to parse settings"));
|
2022-03-08 06:58:00 +05:30
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-02 14:02:05 -05:00
|
|
|
/* Update the configuration properties with persistent settings */
|
|
|
|
|
wp_properties_update (config_settings, self->persistent_settings);
|
2022-03-08 06:58:00 +05:30
|
|
|
|
2024-02-15 14:31:47 -05:00
|
|
|
/* Populate settings metadata from schema using values from configuration if
|
|
|
|
|
* they are present, otherwise use default values */
|
|
|
|
|
it = wp_metadata_new_iterator (WP_METADATA (self->schema_impl_metadata), 0);
|
|
|
|
|
for (; wp_iterator_next (it, &item); g_value_unset (&item)) {
|
|
|
|
|
WpMetadataItem *mi = g_value_get_boxed (&item);
|
|
|
|
|
const gchar *key = wp_metadata_item_get_key (mi);
|
|
|
|
|
const gchar *spec_str = wp_metadata_item_get_value (mi);
|
|
|
|
|
const gchar *value;
|
|
|
|
|
g_autoptr (WpSpaJson) spec_json = NULL;
|
|
|
|
|
g_autoptr (WpSpaJson) def_value = NULL;
|
|
|
|
|
|
|
|
|
|
/* Use configuration value if found, otherwise use default value */
|
|
|
|
|
value = wp_properties_get (config_settings, key);
|
|
|
|
|
if (!value) {
|
|
|
|
|
spec_json = wp_spa_json_new_from_string (spec_str);
|
|
|
|
|
|
|
|
|
|
if (!wp_spa_json_is_object (spec_json)) {
|
|
|
|
|
wp_warning_object (self,
|
|
|
|
|
"settings schema spec for %s is not an object: %s", key, spec_str);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!wp_spa_json_object_get (spec_json, "default", "J", &def_value,
|
|
|
|
|
NULL)) {
|
|
|
|
|
wp_warning_object (self,
|
|
|
|
|
"settings schema spec for %s does not have default value: %s", key,
|
|
|
|
|
spec_str);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
value = wp_spa_json_get_data (def_value);
|
|
|
|
|
}
|
2022-03-08 06:58:00 +05:30
|
|
|
|
2024-02-15 14:31:47 -05:00
|
|
|
/* Add setting in the metadata */
|
2024-02-02 14:02:05 -05:00
|
|
|
wp_debug_object (self, "adding setting to %s metadata: %s = %s",
|
|
|
|
|
self->metadata_name, key, value);
|
|
|
|
|
wp_metadata_set (m, 0, key, "Spa:String:JSON", value);
|
2022-03-08 06:58:00 +05:30
|
|
|
}
|
2022-09-15 15:55:51 -04:00
|
|
|
|
2024-01-26 11:34:08 +02:00
|
|
|
wp_object_update_features (WP_OBJECT (self), WP_PLUGIN_FEATURE_ENABLED, 0);
|
2022-03-08 06:58:00 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2024-02-02 14:02:05 -05:00
|
|
|
on_persistent_metadata_activated (WpMetadata * m, GAsyncResult * res,
|
|
|
|
|
gpointer user_data)
|
2022-03-08 06:58:00 +05:30
|
|
|
{
|
2024-02-02 14:02:05 -05:00
|
|
|
WpTransition *transition = WP_TRANSITION (user_data);
|
|
|
|
|
WpSettingsPlugin *self = wp_transition_get_source_object (transition);
|
|
|
|
|
g_autoptr (WpCore) core = wp_object_get_core (WP_OBJECT (self));
|
|
|
|
|
g_autoptr (GError) error = NULL;
|
|
|
|
|
g_autoptr (WpIterator) it = NULL;
|
|
|
|
|
g_auto (GValue) item = G_VALUE_INIT;
|
|
|
|
|
|
|
|
|
|
if (!wp_object_activate_finish (WP_OBJECT (m), res, &error)) {
|
|
|
|
|
g_prefix_error (&error, "Failed to activate \"%s\": "
|
2024-02-26 09:58:43 -05:00
|
|
|
"Metadata object ", self->metadata_persistent_name);
|
2024-02-02 14:02:05 -05:00
|
|
|
wp_transition_return_error (transition, g_steal_pointer (&error));
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-03-08 06:58:00 +05:30
|
|
|
|
2024-02-02 14:02:05 -05:00
|
|
|
/* Load the persistent settings */
|
2022-09-15 15:55:51 -04:00
|
|
|
self->state = wp_state_new (NAME);
|
2024-02-02 14:02:05 -05:00
|
|
|
self->persistent_settings = wp_state_load (self->state);
|
|
|
|
|
|
|
|
|
|
/* Set persistent settings in persistent metadata */
|
|
|
|
|
for (it = wp_properties_new_iterator (self->persistent_settings);
|
|
|
|
|
wp_iterator_next (it, &item);
|
|
|
|
|
g_value_unset (&item)) {
|
|
|
|
|
WpPropertiesItem *pi = g_value_get_boxed (&item);
|
|
|
|
|
const gchar *key = wp_properties_item_get_key (pi);
|
|
|
|
|
const gchar *value = wp_properties_item_get_value (pi);
|
|
|
|
|
|
|
|
|
|
wp_debug_object (self, "adding persistent setting to %s metadata: %s = %s",
|
2024-02-26 09:58:43 -05:00
|
|
|
self->metadata_persistent_name, key, value);
|
2024-02-02 14:02:05 -05:00
|
|
|
wp_metadata_set (m, 0, key, "Spa:String:JSON", value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* monitor changes in persistent metadata */
|
|
|
|
|
g_signal_connect_object (m, "changed",
|
|
|
|
|
G_CALLBACK (on_persistent_metadata_changed), self, 0);
|
2022-03-08 06:58:00 +05:30
|
|
|
|
|
|
|
|
/* create metadata object */
|
2022-03-31 12:27:22 +05:30
|
|
|
self->impl_metadata = wp_impl_metadata_new_full (core, self->metadata_name,
|
|
|
|
|
NULL);
|
2022-03-08 06:58:00 +05:30
|
|
|
wp_object_activate (WP_OBJECT (self->impl_metadata),
|
|
|
|
|
WP_OBJECT_FEATURES_ALL,
|
|
|
|
|
NULL,
|
|
|
|
|
(GAsyncReadyCallback)on_metadata_activated,
|
|
|
|
|
transition);
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-02 14:02:05 -05:00
|
|
|
static void
|
2024-02-26 09:58:43 -05:00
|
|
|
on_schema_metadata_activated (WpMetadata * m, GAsyncResult * res,
|
|
|
|
|
gpointer user_data)
|
2024-02-02 14:02:05 -05:00
|
|
|
{
|
2024-02-26 09:58:43 -05:00
|
|
|
WpTransition *transition = WP_TRANSITION (user_data);
|
|
|
|
|
WpSettingsPlugin *self = wp_transition_get_source_object (transition);
|
|
|
|
|
g_autoptr (WpCore) core = wp_object_get_core (WP_OBJECT (self));
|
conf: refactor configuration loading
Changes:
- Configuration files are no longer located by libpipewire,
which allows us to control the paths that are being looked up.
This is a requirement for installations where pipewire and
wireplumber are built using different prefixes, in which case
the configuration files of wireplumber end up being installed in
a place that libpipewire doesn't look into...
- The location of conf files is now again $prefix/share/wireplumber,
/etc/wireplumber and $XDG_CONFIG_HOME/wireplumber, instead of using
the pipewire directories. Also, since the previous commits, we now
also support $XDG_CONFIG_DIRS/wireplumber (typically /etc/xdg/wireplumber)
and $XDG_DATA_DIRS/wireplumber for system-wide configuration.
- Since libpipewire doesn't expose the parser, we now also do the
parsing of sections ourselves. This has the advantage that we can
optimize it a bit for our use case.
- The WpConf API has changed to not be a singleton and it is a
property of WpCore instead. The configuration is now expected
to be opened before the core is created, which allows the caller
to identify configuration errors in advance. By not being a singleton,
we can also reuse the WpConf API to open other SPA-JSON files.
- WpConf also now has a lazy loading mechanism. The configuration
files are mmap'ed and the various sections are located in advance,
but not parsed until they are actually requested. Also, the sections
are not copied in memory, unlike what happens in libpipewire. They
are only copied when merging is needed.
- WpCore now disables loading of a configuration file in pw_context,
if a WpConf is provided. This is to have complete control here.
The 'context.spa-libs' and 'context.modules' sections are still
loaded, but we load them in WpConf and pass them down to pw_context
for parsing. If a WpConf is not provided, pw_context is left to load
the default configuration file (client.conf normally).
2024-02-28 12:11:38 +02:00
|
|
|
g_autoptr (WpConf) conf = wp_core_get_conf (core);
|
2024-02-26 09:58:43 -05:00
|
|
|
g_autoptr (GError) error = NULL;
|
|
|
|
|
g_autoptr (WpSpaJson) schema_json = NULL;
|
|
|
|
|
|
|
|
|
|
if (!wp_object_activate_finish (WP_OBJECT (m), res, &error)) {
|
|
|
|
|
wp_transition_return_error (transition, g_error_new (
|
|
|
|
|
WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_OPERATION_FAILED,
|
|
|
|
|
"Failed to activate metadata object %s", self->metadata_schema_name));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Load the schema into metadata if any */
|
2024-02-28 18:58:57 +02:00
|
|
|
schema_json = wp_conf_get_section (conf, "wireplumber.settings.schema");
|
2024-02-26 09:58:43 -05:00
|
|
|
if (schema_json) {
|
|
|
|
|
g_autoptr (WpIterator) it = NULL;
|
|
|
|
|
g_auto (GValue) item = G_VALUE_INIT;
|
|
|
|
|
|
|
|
|
|
if (!wp_spa_json_is_object (schema_json)) {
|
|
|
|
|
wp_transition_return_error (transition, g_error_new (
|
|
|
|
|
WP_DOMAIN_LIBRARY, WP_LIBRARY_ERROR_OPERATION_FAILED,
|
|
|
|
|
"Settings schema is not a JSON object: %s",
|
|
|
|
|
wp_spa_json_get_data (schema_json)));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
it = wp_spa_json_new_iterator (schema_json);
|
|
|
|
|
while (wp_iterator_next (it, &item)) {
|
|
|
|
|
WpSpaJson *j = g_value_get_boxed (&item);
|
|
|
|
|
g_autofree gchar *key = wp_spa_json_parse_string (j);
|
|
|
|
|
g_autofree gchar *value = NULL;
|
|
|
|
|
|
|
|
|
|
g_value_unset (&item);
|
|
|
|
|
if (!wp_iterator_next (it, &item)) {
|
|
|
|
|
wp_transition_return_error (transition, g_error_new (WP_DOMAIN_LIBRARY,
|
|
|
|
|
WP_LIBRARY_ERROR_INVARIANT, "Malformed settings schema"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
j = g_value_get_boxed (&item);
|
|
|
|
|
value = wp_spa_json_to_string (j);
|
|
|
|
|
g_value_unset (&item);
|
|
|
|
|
|
|
|
|
|
wp_debug_object (self, "adding schema setting to %s metadata: %s = %s",
|
|
|
|
|
self->metadata_schema_name, key, value);
|
|
|
|
|
wp_metadata_set (m, 0, key, "Spa:String:JSON", value);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
wp_warning_object (self, "settings schema not found in configuration");
|
|
|
|
|
}
|
2024-02-02 14:02:05 -05:00
|
|
|
|
|
|
|
|
/* create persistent metadata object */
|
|
|
|
|
self->persistent_impl_metadata = wp_impl_metadata_new_full (core,
|
2024-02-26 09:58:43 -05:00
|
|
|
self->metadata_persistent_name, NULL);
|
2024-02-02 14:02:05 -05:00
|
|
|
wp_object_activate (WP_OBJECT (self->persistent_impl_metadata),
|
|
|
|
|
WP_OBJECT_FEATURES_ALL,
|
|
|
|
|
NULL,
|
|
|
|
|
(GAsyncReadyCallback)on_persistent_metadata_activated,
|
|
|
|
|
transition);
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-26 09:58:43 -05:00
|
|
|
static void
|
|
|
|
|
wp_settings_plugin_enable (WpPlugin * plugin, WpTransition * transition)
|
|
|
|
|
{
|
|
|
|
|
WpSettingsPlugin * self = WP_SETTINGS_PLUGIN (plugin);
|
|
|
|
|
g_autoptr (WpCore) core = wp_object_get_core (WP_OBJECT (plugin));
|
|
|
|
|
|
|
|
|
|
/* create schema metadata object */
|
|
|
|
|
self->schema_impl_metadata = wp_impl_metadata_new_full (core,
|
|
|
|
|
self->metadata_schema_name, NULL);
|
|
|
|
|
wp_object_activate (WP_OBJECT (self->schema_impl_metadata),
|
|
|
|
|
WP_OBJECT_FEATURES_ALL,
|
|
|
|
|
NULL,
|
|
|
|
|
(GAsyncReadyCallback)on_schema_metadata_activated,
|
|
|
|
|
transition);
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-08 06:58:00 +05:30
|
|
|
static void
|
|
|
|
|
wp_settings_plugin_disable (WpPlugin * plugin)
|
|
|
|
|
{
|
|
|
|
|
WpSettingsPlugin * self = WP_SETTINGS_PLUGIN (plugin);
|
|
|
|
|
|
|
|
|
|
g_clear_object (&self->impl_metadata);
|
2024-02-02 14:02:05 -05:00
|
|
|
g_clear_object (&self->persistent_impl_metadata);
|
|
|
|
|
g_clear_pointer (&self->persistent_settings, wp_properties_unref);
|
2022-03-08 06:58:00 +05:30
|
|
|
g_clear_object (&self->state);
|
2022-09-15 15:55:51 -04:00
|
|
|
|
|
|
|
|
g_clear_pointer (&self->metadata_name, g_free);
|
2024-02-26 09:58:43 -05:00
|
|
|
g_clear_pointer (&self->metadata_schema_name, g_free);
|
|
|
|
|
g_clear_pointer (&self->metadata_persistent_name, g_free);
|
2022-03-31 12:27:22 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
wp_settings_plugin_set_property (GObject * object, guint property_id,
|
|
|
|
|
const GValue * value, GParamSpec * pspec)
|
|
|
|
|
{
|
|
|
|
|
WpSettingsPlugin *self = WP_SETTINGS_PLUGIN (object);
|
|
|
|
|
|
|
|
|
|
switch (property_id) {
|
|
|
|
|
case PROP_METADATA_NAME:
|
2024-02-02 14:02:05 -05:00
|
|
|
self->metadata_name = g_value_dup_string (value);
|
2024-02-26 09:58:43 -05:00
|
|
|
self->metadata_schema_name = g_strdup_printf (
|
|
|
|
|
WP_SETTINGS_SCHEMA_METADATA_NAME_PREFIX "%s", self->metadata_name);
|
|
|
|
|
self->metadata_persistent_name = g_strdup_printf (
|
|
|
|
|
WP_SETTINGS_PERSISTENT_METADATA_NAME_PREFIX "%s", self->metadata_name);
|
2022-03-31 12:27:22 +05:30
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
wp_settings_plugin_get_property (GObject * object, guint property_id,
|
|
|
|
|
GValue * value, GParamSpec * pspec)
|
|
|
|
|
{
|
|
|
|
|
WpSettingsPlugin *self = WP_SETTINGS_PLUGIN (object);
|
|
|
|
|
|
|
|
|
|
switch (property_id) {
|
|
|
|
|
case PROP_METADATA_NAME:
|
|
|
|
|
g_value_set_string (value, self->metadata_name);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2022-03-08 06:58:00 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
wp_settings_plugin_class_init (WpSettingsPluginClass * klass)
|
|
|
|
|
{
|
|
|
|
|
WpPluginClass *plugin_class = (WpPluginClass *) klass;
|
2022-03-31 12:27:22 +05:30
|
|
|
GObjectClass *object_class = (GObjectClass *) klass;
|
2022-03-08 06:58:00 +05:30
|
|
|
|
|
|
|
|
plugin_class->enable = wp_settings_plugin_enable;
|
|
|
|
|
plugin_class->disable = wp_settings_plugin_disable;
|
2022-03-31 12:27:22 +05:30
|
|
|
|
|
|
|
|
object_class->set_property = wp_settings_plugin_set_property;
|
|
|
|
|
object_class->get_property = wp_settings_plugin_get_property;
|
|
|
|
|
|
|
|
|
|
g_object_class_install_property (object_class, PROP_METADATA_NAME,
|
|
|
|
|
g_param_spec_string ("metadata-name", "metadata-name",
|
|
|
|
|
"The metadata object to look after", NULL,
|
|
|
|
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
|
2022-03-08 06:58:00 +05:30
|
|
|
}
|
|
|
|
|
|
2023-02-09 13:11:14 -05:00
|
|
|
WP_PLUGIN_EXPORT GObject *
|
2023-05-25 18:29:58 +03:00
|
|
|
wireplumber__module_init (WpCore * core, WpSpaJson * args, GError ** error)
|
2022-03-08 06:58:00 +05:30
|
|
|
{
|
2023-05-25 18:29:58 +03:00
|
|
|
g_autofree gchar *metadata_name = NULL;
|
2022-09-15 15:55:51 -04:00
|
|
|
if (args)
|
2024-01-26 11:34:08 +02:00
|
|
|
wp_spa_json_object_get (args, "metadata.name", "s", &metadata_name, NULL);
|
2022-03-31 12:27:22 +05:30
|
|
|
|
2023-02-09 13:11:14 -05:00
|
|
|
return G_OBJECT (g_object_new (wp_settings_plugin_get_type (),
|
2022-03-08 06:58:00 +05:30
|
|
|
"name", "settings",
|
|
|
|
|
"core", core,
|
2023-05-25 18:29:58 +03:00
|
|
|
"metadata-name", metadata_name ? metadata_name : "sm-settings",
|
2022-03-08 06:58:00 +05:30
|
|
|
NULL));
|
|
|
|
|
}
|