2022-03-22 03:38:35 +05:30
|
|
|
/* WirePlumber
|
|
|
|
|
*
|
|
|
|
|
* Copyright © 2022 Collabora Ltd.
|
|
|
|
|
* @author Ashok Sidipotu <ashok.sidipotu@collabora.com>
|
|
|
|
|
*
|
|
|
|
|
* SPDX-License-Identifier: MIT
|
|
|
|
|
*/
|
|
|
|
|
|
2023-01-10 09:11:15 -05:00
|
|
|
#include "core.h"
|
2022-03-22 03:38:35 +05:30
|
|
|
#include "settings.h"
|
|
|
|
|
#include "metadata.h"
|
|
|
|
|
#include "log.h"
|
2023-01-10 09:11:15 -05:00
|
|
|
#include "object-manager.h"
|
2022-03-22 03:38:35 +05:30
|
|
|
|
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 ("wp-settings")
|
|
|
|
|
|
2022-05-04 14:45:55 +03:00
|
|
|
/*! \defgroup wpsettings WpSettings */
|
2022-03-22 03:38:35 +05:30
|
|
|
/*!
|
|
|
|
|
* \struct WpSettings
|
|
|
|
|
*
|
2022-05-04 14:45:55 +03:00
|
|
|
* WpSettings loads and parses the "sm-settings" (default value) metadata, which
|
2023-09-26 10:00:43 +03:00
|
|
|
* contains wireplumber settings, and provides APIs to its clients (modules, lua
|
|
|
|
|
* scripts etc) to access them.
|
2022-03-22 03:38:35 +05:30
|
|
|
*
|
|
|
|
|
* Being a WpObject subclass, the settings inherits WpObject's activation
|
|
|
|
|
* system.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
struct _WpSettings
|
|
|
|
|
{
|
|
|
|
|
WpObject parent;
|
|
|
|
|
|
|
|
|
|
WpProperties *settings;
|
2022-03-31 12:27:22 +05:30
|
|
|
|
2022-05-26 13:15:22 +05:30
|
|
|
/* element-type: Callback* */
|
|
|
|
|
GPtrArray *callbacks;
|
|
|
|
|
|
2022-04-12 11:20:57 +05:30
|
|
|
gchar *metadata_name;
|
|
|
|
|
WpObjectManager *metadata_om;
|
2022-03-31 12:27:22 +05:30
|
|
|
};
|
|
|
|
|
|
2022-05-26 13:15:22 +05:30
|
|
|
typedef struct
|
|
|
|
|
{
|
|
|
|
|
GClosure *closure;
|
|
|
|
|
gchar *pattern;
|
|
|
|
|
} Callback;
|
|
|
|
|
|
2022-03-31 12:27:22 +05:30
|
|
|
enum {
|
|
|
|
|
PROP_0,
|
|
|
|
|
PROP_METADATA_NAME,
|
|
|
|
|
PROP_PROPERTIES,
|
2022-03-22 03:38:35 +05:30
|
|
|
};
|
|
|
|
|
|
|
|
|
|
G_DEFINE_TYPE (WpSettings, wp_settings, WP_TYPE_OBJECT)
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
wp_settings_init (WpSettings * self)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-10 16:42:01 +02:00
|
|
|
static void
|
|
|
|
|
wp_settings_set_property (GObject * object, guint property_id,
|
|
|
|
|
const GValue * value, GParamSpec * pspec)
|
2022-05-26 13:15:22 +05:30
|
|
|
{
|
2024-02-10 16:42:01 +02:00
|
|
|
WpSettings *self = WP_SETTINGS (object);
|
2022-05-26 13:15:22 +05:30
|
|
|
|
2024-02-10 16:42:01 +02:00
|
|
|
switch (property_id) {
|
|
|
|
|
case PROP_METADATA_NAME:
|
|
|
|
|
self->metadata_name = g_value_dup_string (value);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2022-05-26 13:15:22 +05:30
|
|
|
}
|
2022-03-22 03:38:35 +05:30
|
|
|
|
2024-02-10 16:42:01 +02:00
|
|
|
static void
|
|
|
|
|
wp_settings_get_property (GObject * object, guint property_id,
|
|
|
|
|
GValue * value, GParamSpec * pspec)
|
2022-08-11 11:30:10 -04:00
|
|
|
{
|
2024-02-10 16:42:01 +02:00
|
|
|
WpSettings *self = WP_SETTINGS (object);
|
2022-05-09 12:43:36 +05:30
|
|
|
|
2024-02-10 16:42:01 +02:00
|
|
|
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-05-09 12:43:36 +05:30
|
|
|
}
|
|
|
|
|
|
2022-03-22 03:38:35 +05:30
|
|
|
enum {
|
|
|
|
|
STEP_LOAD = WP_TRANSITION_STEP_CUSTOM_START,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static WpObjectFeatures
|
|
|
|
|
wp_settings_get_supported_features (WpObject * self)
|
|
|
|
|
{
|
|
|
|
|
return WP_SETTINGS_LOADED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static guint
|
|
|
|
|
wp_settings_activate_get_next_step (WpObject * object,
|
|
|
|
|
WpFeatureActivationTransition * transition, guint step,
|
|
|
|
|
WpObjectFeatures missing)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (missing == WP_SETTINGS_LOADED,
|
|
|
|
|
WP_TRANSITION_STEP_ERROR);
|
|
|
|
|
|
|
|
|
|
return STEP_LOAD;
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-26 13:15:22 +05:30
|
|
|
static void
|
|
|
|
|
on_metadata_changed (WpMetadata *m, guint32 subject,
|
|
|
|
|
const gchar *setting, const gchar *type, const gchar *new_value, gpointer d)
|
|
|
|
|
{
|
|
|
|
|
WpSettings *self = WP_SETTINGS(d);
|
2022-09-01 08:22:56 -04:00
|
|
|
const gchar *old_value = NULL;
|
2022-05-26 13:15:22 +05:30
|
|
|
|
2022-09-01 08:22:56 -04:00
|
|
|
/* Only handle JSON metadata values */
|
|
|
|
|
if (!g_str_equal (type, "Spa:String:JSON"))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
old_value = wp_properties_get (self->settings, setting);
|
2022-05-26 13:15:22 +05:30
|
|
|
if (!old_value) {
|
|
|
|
|
wp_info_object (self, "new setting defined \"%s\" = \"%s\"",
|
|
|
|
|
setting, new_value);
|
|
|
|
|
} else {
|
|
|
|
|
wp_info_object (self, "setting \"%s\" new_value changed from \"%s\" ->"
|
|
|
|
|
" \"%s\"", setting, old_value, new_value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wp_properties_set (self->settings, setting, new_value);
|
|
|
|
|
|
|
|
|
|
for (guint i = 0; i < self->callbacks->len; i++) {
|
|
|
|
|
Callback *cb = g_ptr_array_index (self->callbacks, i);
|
|
|
|
|
|
|
|
|
|
if (g_pattern_match_simple (cb->pattern, setting)) {
|
2022-09-01 08:22:56 -04:00
|
|
|
g_autoptr (WpSpaJson) json = NULL;
|
2022-05-26 13:15:22 +05:30
|
|
|
GValue values[3] = { G_VALUE_INIT, G_VALUE_INIT, G_VALUE_INIT };
|
2022-09-01 08:22:56 -04:00
|
|
|
|
2022-05-26 13:15:22 +05:30
|
|
|
g_value_init (&values[0], G_TYPE_OBJECT);
|
|
|
|
|
g_value_init (&values[1], G_TYPE_STRING);
|
2022-09-01 08:22:56 -04:00
|
|
|
g_value_init (&values[2], WP_TYPE_SPA_JSON);
|
2022-05-26 13:15:22 +05:30
|
|
|
|
|
|
|
|
g_value_set_object (&values[0], self);
|
|
|
|
|
g_value_set_string (&values[1], setting);
|
2023-11-14 12:36:10 +02:00
|
|
|
json = new_value ? wp_spa_json_new_wrap_string (new_value) : NULL;
|
2022-09-01 08:22:56 -04:00
|
|
|
g_value_set_boxed (&values[2], json);
|
2022-05-26 13:15:22 +05:30
|
|
|
|
|
|
|
|
g_closure_invoke (cb->closure, NULL, 3, values, NULL);
|
|
|
|
|
|
|
|
|
|
g_value_unset (&values[0]);
|
|
|
|
|
g_value_unset (&values[1]);
|
|
|
|
|
g_value_unset (&values[2]);
|
|
|
|
|
|
|
|
|
|
wp_debug_object (self, "triggered callback(%p)", cb);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-22 03:38:35 +05:30
|
|
|
static void
|
|
|
|
|
on_metadata_added (WpObjectManager *om, WpMetadata *m, gpointer d)
|
|
|
|
|
{
|
|
|
|
|
WpTransition * transition = WP_TRANSITION (d);
|
|
|
|
|
WpSettings * self = wp_transition_get_source_object (transition);
|
|
|
|
|
g_autoptr (WpIterator) it = wp_metadata_new_iterator (WP_METADATA (m), 0);
|
|
|
|
|
g_auto (GValue) val = G_VALUE_INIT;
|
|
|
|
|
|
2022-05-26 13:15:22 +05:30
|
|
|
/* Handle the changed signal */
|
|
|
|
|
g_signal_connect_object (m, "changed", G_CALLBACK (on_metadata_changed),
|
|
|
|
|
self, 0);
|
|
|
|
|
|
2023-01-10 09:11:15 -05:00
|
|
|
/* traverse through all settings */
|
2022-03-22 03:38:35 +05:30
|
|
|
for (; wp_iterator_next (it, &val); g_value_unset (&val)) {
|
2022-08-11 10:08:01 -04:00
|
|
|
const gchar *setting, *value;
|
|
|
|
|
wp_metadata_iterator_item_extract (&val, NULL, &setting, NULL, &value);
|
2023-01-10 09:11:15 -05:00
|
|
|
wp_properties_set (self->settings, setting, value);
|
2022-03-22 03:38:35 +05:30
|
|
|
}
|
|
|
|
|
|
2023-01-10 09:11:15 -05:00
|
|
|
wp_info_object (self, "loaded %d settings and from metadata \"%s\"",
|
2022-04-12 11:20:57 +05:30
|
|
|
wp_properties_get_count (self->settings),
|
|
|
|
|
self->metadata_name);
|
2022-03-22 03:38:35 +05:30
|
|
|
|
|
|
|
|
wp_object_update_features (WP_OBJECT (self), WP_SETTINGS_LOADED, 0);
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-26 13:15:22 +05:30
|
|
|
static void
|
|
|
|
|
callback_unref (Callback * self)
|
|
|
|
|
{
|
|
|
|
|
g_free (self->pattern);
|
|
|
|
|
g_clear_pointer (&self->closure, g_closure_unref);
|
2022-08-15 09:55:46 -04:00
|
|
|
g_slice_free (Callback, self);
|
2022-05-26 13:15:22 +05:30
|
|
|
}
|
|
|
|
|
|
2022-03-22 03:38:35 +05:30
|
|
|
static void
|
|
|
|
|
wp_settings_activate_execute_step (WpObject * object,
|
|
|
|
|
WpFeatureActivationTransition * transition, guint step,
|
|
|
|
|
WpObjectFeatures missing)
|
|
|
|
|
{
|
|
|
|
|
WpSettings * self = WP_SETTINGS (object);
|
|
|
|
|
g_autoptr (WpCore) core = wp_object_get_core (object);
|
|
|
|
|
|
|
|
|
|
switch (step) {
|
|
|
|
|
case STEP_LOAD: {
|
|
|
|
|
self->settings = wp_properties_new_empty ();
|
|
|
|
|
|
2022-05-26 13:15:22 +05:30
|
|
|
self->callbacks = g_ptr_array_new_with_free_func
|
|
|
|
|
((GDestroyNotify) callback_unref);
|
|
|
|
|
|
2022-03-22 03:38:35 +05:30
|
|
|
self->metadata_om = wp_object_manager_new ();
|
|
|
|
|
wp_object_manager_add_interest (self->metadata_om, WP_TYPE_METADATA,
|
|
|
|
|
WP_CONSTRAINT_TYPE_PW_GLOBAL_PROPERTY, "metadata.name", "=s",
|
2022-03-31 12:27:22 +05:30
|
|
|
self->metadata_name, NULL);
|
2022-03-22 03:38:35 +05:30
|
|
|
wp_object_manager_request_object_features (self->metadata_om,
|
|
|
|
|
WP_TYPE_METADATA, WP_OBJECT_FEATURES_ALL);
|
|
|
|
|
g_signal_connect_object (self->metadata_om, "object-added",
|
|
|
|
|
G_CALLBACK (on_metadata_added), transition, 0);
|
|
|
|
|
wp_core_install_object_manager (core, self->metadata_om);
|
|
|
|
|
|
2022-04-25 10:45:34 +05:30
|
|
|
wp_info_object (self, "looking for metadata object named %s",
|
2022-03-31 12:27:22 +05:30
|
|
|
self->metadata_name);
|
2022-03-22 03:38:35 +05:30
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case WP_TRANSITION_STEP_ERROR:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
g_assert_not_reached ();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
wp_settings_deactivate (WpObject * object, WpObjectFeatures features)
|
|
|
|
|
{
|
|
|
|
|
WpSettings *self = WP_SETTINGS (object);
|
|
|
|
|
|
2022-05-26 13:15:22 +05:30
|
|
|
wp_debug_object (self, "%s", self->metadata_name);
|
2022-03-31 12:27:22 +05:30
|
|
|
g_free (self->metadata_name);
|
2022-03-22 03:38:35 +05:30
|
|
|
g_clear_object (&self->metadata_om);
|
2022-05-26 13:15:22 +05:30
|
|
|
g_clear_pointer (&self->callbacks, g_ptr_array_unref);
|
2022-04-12 11:20:57 +05:30
|
|
|
g_clear_pointer (&self->settings, wp_properties_unref);
|
2022-03-22 03:38:35 +05:30
|
|
|
|
|
|
|
|
wp_object_update_features (WP_OBJECT (self), 0, WP_OBJECT_FEATURES_ALL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
wp_settings_class_init (WpSettingsClass * klass)
|
|
|
|
|
{
|
2022-03-31 12:27:22 +05:30
|
|
|
GObjectClass * object_class = (GObjectClass *) klass;
|
2022-03-22 03:38:35 +05:30
|
|
|
WpObjectClass * wpobject_class = (WpObjectClass *) klass;
|
|
|
|
|
|
2022-03-31 12:27:22 +05:30
|
|
|
object_class->set_property = wp_settings_set_property;
|
|
|
|
|
object_class->get_property = wp_settings_get_property;
|
|
|
|
|
|
2024-02-10 16:42:01 +02:00
|
|
|
wpobject_class->get_supported_features = wp_settings_get_supported_features;
|
2022-03-22 03:38:35 +05:30
|
|
|
wpobject_class->activate_get_next_step = wp_settings_activate_get_next_step;
|
|
|
|
|
wpobject_class->activate_execute_step = wp_settings_activate_execute_step;
|
|
|
|
|
wpobject_class->deactivate = wp_settings_deactivate;
|
2022-03-31 12:27:22 +05:30
|
|
|
|
|
|
|
|
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-22 03:38:35 +05:30
|
|
|
}
|
2024-02-10 16:42:01 +02:00
|
|
|
|
2024-02-10 17:48:23 +02:00
|
|
|
/*!
|
|
|
|
|
* \brief Creates a new WpSettings object
|
|
|
|
|
*
|
|
|
|
|
* \ingroup wpsettings
|
|
|
|
|
* \param core the WpCore
|
|
|
|
|
* \param metadata_name (nullable): the name of the metadata object to
|
|
|
|
|
* associate with the settings object; NULL means the default "sm-settings"
|
|
|
|
|
* \returns (transfer full): a new WpSettings object
|
|
|
|
|
*/
|
|
|
|
|
WpSettings *
|
|
|
|
|
wp_settings_new (WpCore * core, const gchar * metadata_name)
|
|
|
|
|
{
|
|
|
|
|
return g_object_new (WP_TYPE_SETTINGS,
|
|
|
|
|
"core", core,
|
|
|
|
|
"metadata-name", metadata_name ? metadata_name : "sm-settings",
|
|
|
|
|
NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-10 16:42:01 +02:00
|
|
|
static gboolean
|
2024-02-10 17:48:23 +02:00
|
|
|
find_settings_func (gpointer g_object, gpointer metadata_name)
|
2024-02-10 16:42:01 +02:00
|
|
|
{
|
2024-02-10 17:48:23 +02:00
|
|
|
if (!WP_IS_SETTINGS (g_object))
|
2024-02-10 16:42:01 +02:00
|
|
|
return FALSE;
|
|
|
|
|
|
2024-02-10 17:48:23 +02:00
|
|
|
return g_str_equal (((WpSettings *) g_object)->metadata_name,
|
|
|
|
|
(gchar *) metadata_name);
|
2024-02-10 16:42:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
2024-02-10 17:48:23 +02:00
|
|
|
* \brief Finds a registered WpSettings object by its metadata name
|
2024-02-10 16:42:01 +02:00
|
|
|
*
|
|
|
|
|
* \ingroup wpsettings
|
2024-02-10 17:48:23 +02:00
|
|
|
* \param core the WpCore
|
|
|
|
|
* \param metadata_name (nullable): the name of the metadata object that the
|
|
|
|
|
* settings object is associated with; NULL means the default "sm-settings"
|
|
|
|
|
* \returns (transfer full) (nullable): the WpSettings object, or NULL if not
|
|
|
|
|
* found
|
2024-02-10 16:42:01 +02:00
|
|
|
*/
|
|
|
|
|
WpSettings *
|
2024-02-10 17:48:23 +02:00
|
|
|
wp_settings_find (WpCore * core, const gchar * metadata_name)
|
2024-02-10 16:42:01 +02:00
|
|
|
{
|
2024-02-10 17:48:23 +02:00
|
|
|
g_return_val_if_fail (WP_IS_CORE (core), NULL);
|
2024-02-10 16:42:01 +02:00
|
|
|
|
2024-02-10 17:48:23 +02:00
|
|
|
GObject *s = wp_core_find_object (core, (GEqualFunc) find_settings_func,
|
|
|
|
|
metadata_name ? metadata_name : "sm-settings");
|
|
|
|
|
return s ? WP_SETTINGS (s) : NULL;
|
2024-02-10 16:42:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* \brief Subscribes callback for a given setting pattern(a glob-style pattern
|
|
|
|
|
* matched using g_pattern_match_simple), this allows clients to look
|
|
|
|
|
* for any changes made in settings through metadata.
|
|
|
|
|
*
|
|
|
|
|
* \ingroup wpsettings
|
|
|
|
|
* \param self the settings object
|
|
|
|
|
* \param pattern name of the pattern to match the settings with
|
|
|
|
|
* \param callback (scope async): the callback triggered when the settings
|
|
|
|
|
* change.
|
|
|
|
|
* \param user_data data to pass to \a callback
|
|
|
|
|
* \returns the subscription ID (always greater than 0 for successful
|
|
|
|
|
* subscriptions)
|
|
|
|
|
*/
|
|
|
|
|
guintptr
|
|
|
|
|
wp_settings_subscribe (WpSettings *self,
|
|
|
|
|
const gchar *pattern, WpSettingsChangedCallback callback,
|
|
|
|
|
gpointer user_data)
|
|
|
|
|
{
|
|
|
|
|
return wp_settings_subscribe_closure (self, pattern,
|
|
|
|
|
g_cclosure_new (G_CALLBACK (callback), user_data, NULL));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* \brief Subscribes callback for a given setting pattern(a glob-style pattern
|
|
|
|
|
* matched using g_pattern_match_simple), this allows clients to look
|
|
|
|
|
* for any changes made in settings through metadata.
|
|
|
|
|
*
|
|
|
|
|
* \ingroup wpsettings
|
|
|
|
|
* \param self the settings object
|
|
|
|
|
* \param pattern name of the pattern to match the settings with
|
|
|
|
|
* \param closure (nullable): a GAsyncReadyCallback wrapped in a GClosure
|
|
|
|
|
* \returns the subscription ID (always greater than 0 for success)
|
|
|
|
|
*/
|
|
|
|
|
guintptr
|
|
|
|
|
wp_settings_subscribe_closure (WpSettings *self, const gchar *pattern,
|
|
|
|
|
GClosure *closure)
|
|
|
|
|
{
|
|
|
|
|
g_return_val_if_fail (WP_IS_SETTINGS (self), 0);
|
|
|
|
|
g_return_val_if_fail (pattern, 0);
|
|
|
|
|
g_return_val_if_fail (closure, 0);
|
|
|
|
|
|
|
|
|
|
Callback *cb = g_slice_new0 (Callback);
|
|
|
|
|
g_return_val_if_fail (cb, 0);
|
|
|
|
|
|
|
|
|
|
cb->closure = g_closure_ref (closure);
|
|
|
|
|
g_closure_sink (closure);
|
|
|
|
|
if (G_CLOSURE_NEEDS_MARSHAL (closure))
|
|
|
|
|
g_closure_set_marshal (closure, g_cclosure_marshal_generic);
|
|
|
|
|
|
|
|
|
|
cb->pattern = g_strdup (pattern);
|
|
|
|
|
|
|
|
|
|
g_ptr_array_add (self->callbacks, cb);
|
|
|
|
|
|
|
|
|
|
wp_debug_object (self, "callback(%p) subscribed for pattern(%s)",
|
|
|
|
|
(void *) cb, pattern);
|
|
|
|
|
|
|
|
|
|
return (guintptr) cb;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* \brief Unsubscribes callback for a given subscription_id.
|
|
|
|
|
*
|
|
|
|
|
* \ingroup wpsettings
|
|
|
|
|
* \param self the settings object
|
|
|
|
|
* \param subscription_id identifies the callback
|
|
|
|
|
* \returns TRUE if success, FALSE otherwise
|
|
|
|
|
*/
|
|
|
|
|
gboolean
|
|
|
|
|
wp_settings_unsubscribe (WpSettings *self, guintptr subscription_id)
|
|
|
|
|
{
|
|
|
|
|
gboolean ret = FALSE;
|
|
|
|
|
g_return_val_if_fail (WP_IS_SETTINGS (self), FALSE);
|
|
|
|
|
g_return_val_if_fail (subscription_id, FALSE);
|
|
|
|
|
|
|
|
|
|
Callback *cb = (Callback *) subscription_id;
|
|
|
|
|
|
|
|
|
|
ret = g_ptr_array_remove (self->callbacks, cb);
|
|
|
|
|
|
|
|
|
|
wp_debug_object (self, "callback(%p) unsubscription %s", (void *) cb,
|
|
|
|
|
(ret)? "succeeded": "failed");
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
|
* \brief Gets the WpSpaJson of a setting
|
|
|
|
|
* \ingroup wpsettings
|
|
|
|
|
* \param self the settings object
|
|
|
|
|
* \param setting name of the setting
|
|
|
|
|
* \returns (transfer full) (nullable): The WpSpaJson of the setting, or NULL
|
|
|
|
|
* if the setting does not exist
|
|
|
|
|
*/
|
|
|
|
|
WpSpaJson *
|
|
|
|
|
wp_settings_get (WpSettings *self, const gchar *setting)
|
|
|
|
|
{
|
|
|
|
|
const gchar *value;
|
|
|
|
|
|
|
|
|
|
g_return_val_if_fail (WP_IS_SETTINGS (self), NULL);
|
|
|
|
|
g_return_val_if_fail (setting, NULL);
|
|
|
|
|
|
|
|
|
|
if (!(wp_object_test_active_features (WP_OBJECT (self), WP_SETTINGS_LOADED)))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
value = wp_properties_get (self->settings, setting);
|
|
|
|
|
return value ? wp_spa_json_new_wrap_string (value) : NULL;
|
|
|
|
|
}
|