mirror of
https://gitlab.freedesktop.org/pipewire/wireplumber.git
synced 2026-05-05 17:08:01 +02:00
modules: replace session-settings with default-metadata
This commit is contained in:
parent
453f9a34d2
commit
9cb79dc3d6
4 changed files with 340 additions and 277 deletions
|
|
@ -89,16 +89,16 @@ shared_library(
|
|||
dependencies : [wp_dep, pipewire_dep],
|
||||
)
|
||||
|
||||
# shared_library(
|
||||
# 'wireplumber-module-session-settings',
|
||||
# [
|
||||
# 'module-session-settings.c',
|
||||
# ],
|
||||
# c_args : [common_c_args, '-DG_LOG_DOMAIN="m-session-settings"'],
|
||||
# install : true,
|
||||
# install_dir : wireplumber_module_dir,
|
||||
# dependencies : [wp_dep],
|
||||
# )
|
||||
shared_library(
|
||||
'wireplumber-module-default-metadata',
|
||||
[
|
||||
'module-default-metadata.c',
|
||||
],
|
||||
c_args : [common_c_args, '-DG_LOG_DOMAIN="m-default-metadata"'],
|
||||
install : true,
|
||||
install_dir : wireplumber_module_dir,
|
||||
dependencies : [wp_dep],
|
||||
)
|
||||
|
||||
shared_library(
|
||||
'wireplumber-module-config-static-objects',
|
||||
|
|
|
|||
328
modules/module-default-metadata.c
Normal file
328
modules/module-default-metadata.c
Normal file
|
|
@ -0,0 +1,328 @@
|
|||
/* WirePlumber
|
||||
*
|
||||
* Copyright © 2020 Collabora Ltd.
|
||||
* @author Julian Bouzas <julian.bouzas@collabora.com>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <wp/wp.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define STATE_NAME "default-metadata"
|
||||
#define SAVE_INTERVAL_MS 1000
|
||||
|
||||
#define direction_to_dbg_string(dir) \
|
||||
((dir == WP_DIRECTION_INPUT) ? "sink" : "source")
|
||||
|
||||
#define default_endpoint_key(dir) ((dir == WP_DIRECTION_INPUT) ? \
|
||||
"default.session.endpoint.sink" : "default.session.endpoint.source")
|
||||
|
||||
G_DECLARE_FINAL_TYPE (WpDefaultMetadata, wp_default_metadata, WP,
|
||||
DEFAULT_METADATA, WpPlugin)
|
||||
|
||||
struct _WpDefaultEndpoints
|
||||
{
|
||||
WpDefaultMetadata *self;
|
||||
gchar *group;
|
||||
WpProperties *props;
|
||||
};
|
||||
typedef struct _WpDefaultEndpoints WpDefaultEndpoints;
|
||||
|
||||
struct _WpDefaultMetadata
|
||||
{
|
||||
WpPlugin parent;
|
||||
WpState *state;
|
||||
WpDefaultEndpoints default_endpoints[2];
|
||||
WpObjectManager *metadatas_om;
|
||||
WpObjectManager *sessions_om;
|
||||
guint metadata_id;
|
||||
GSource *timeout_source;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (WpDefaultMetadata, wp_default_metadata, WP_TYPE_PLUGIN)
|
||||
|
||||
static gboolean
|
||||
timeout_save_callback (gpointer p)
|
||||
{
|
||||
WpDefaultEndpoints *d = p;
|
||||
WpDefaultMetadata *self = d->self;
|
||||
|
||||
if (!wp_state_save (self->state, d->group, d->props))
|
||||
wp_warning_object (self, "could not save default endpoints in %s",
|
||||
STATE_NAME);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
timeout_save_default_endpoints (WpDefaultMetadata *self, guint dir, guint ms)
|
||||
{
|
||||
g_autoptr (WpCore) core = wp_plugin_get_core (WP_PLUGIN (self));
|
||||
g_return_if_fail (core);
|
||||
|
||||
/* Clear the current timeout callback */
|
||||
if (self->timeout_source)
|
||||
g_source_destroy (self->timeout_source);
|
||||
g_clear_pointer (&self->timeout_source, g_source_unref);
|
||||
|
||||
/* Add the timeout callback */
|
||||
wp_core_timeout_add (core, &self->timeout_source, ms, timeout_save_callback,
|
||||
self->default_endpoints + dir, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
on_default_metadata_changed (WpMetadata *m, guint32 subject,
|
||||
const gchar *key, const gchar *type, const gchar *value, gpointer *d)
|
||||
{
|
||||
WpDefaultMetadata * self = WP_DEFAULT_METADATA (d);
|
||||
g_autoptr (WpSession) session = NULL;
|
||||
g_autoptr (WpEndpoint) ep = NULL;
|
||||
const gchar *session_name = NULL, *ep_name = NULL;
|
||||
guint dir = WP_DIRECTION_INPUT;
|
||||
|
||||
/* Get the direction */
|
||||
if (!g_strcmp0 (key, default_endpoint_key (WP_DIRECTION_INPUT)))
|
||||
dir = WP_DIRECTION_INPUT;
|
||||
else if (!g_strcmp0 (key, default_endpoint_key (WP_DIRECTION_OUTPUT)))
|
||||
dir = WP_DIRECTION_OUTPUT;
|
||||
else
|
||||
return;
|
||||
|
||||
/* Find the session */
|
||||
session = wp_object_manager_lookup (self->sessions_om, WP_TYPE_SESSION,
|
||||
WP_CONSTRAINT_TYPE_G_PROPERTY, "bound-id", "=u", subject, NULL);
|
||||
if (!session)
|
||||
return;
|
||||
|
||||
/* Find the endpoint */
|
||||
ep = wp_session_lookup_endpoint (session, WP_CONSTRAINT_TYPE_G_PROPERTY,
|
||||
"bound-id", "=u", atoi (value), NULL);
|
||||
if (!ep)
|
||||
return;
|
||||
|
||||
/* Get the session name and endpoint name */
|
||||
session_name = wp_session_get_name (session);
|
||||
g_return_if_fail (session_name);
|
||||
ep_name = wp_endpoint_get_name (ep);
|
||||
g_return_if_fail (ep_name);
|
||||
|
||||
/* Set the property and save state */
|
||||
wp_properties_set (self->default_endpoints[dir].props, session_name, ep_name);
|
||||
timeout_save_default_endpoints (self, dir, SAVE_INTERVAL_MS);
|
||||
}
|
||||
|
||||
static guint32
|
||||
find_highest_prio (WpSession * session, WpDirection dir)
|
||||
{
|
||||
g_autoptr (WpIterator) it = NULL;
|
||||
g_auto (GValue) val = G_VALUE_INIT;
|
||||
gint highest_prio = 0;
|
||||
guint32 id = 0;
|
||||
|
||||
it = wp_session_iterate_endpoints_filtered (session,
|
||||
WP_CONSTRAINT_TYPE_PW_PROPERTY, "media.class", "#s",
|
||||
(dir == WP_DIRECTION_INPUT) ? "*/Sink" : "*/Source",
|
||||
NULL);
|
||||
|
||||
for (; wp_iterator_next (it, &val); g_value_unset (&val)) {
|
||||
WpProxy *ep = g_value_get_object (&val);
|
||||
const gchar *prio_str = wp_pipewire_object_get_property (
|
||||
WP_PIPEWIRE_OBJECT (ep), "endpoint.priority");
|
||||
gint prio = atoi (prio_str);
|
||||
|
||||
if (prio > highest_prio || id == 0) {
|
||||
highest_prio = prio;
|
||||
id = wp_proxy_get_bound_id (ep);
|
||||
}
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
static void
|
||||
reevaluate_default_endpoints (WpDefaultMetadata * self, WpMetadata *m,
|
||||
WpSession *session, guint dir)
|
||||
{
|
||||
guint32 ep_id = 0;
|
||||
const gchar *session_name = NULL, *ep_name = NULL;
|
||||
|
||||
g_return_if_fail (m);
|
||||
g_return_if_fail (self->default_endpoints[dir].props);
|
||||
|
||||
/* Find the default endpoint */
|
||||
session_name = wp_session_get_name (session);
|
||||
ep_name = wp_properties_get (self->default_endpoints[dir].props, session_name);
|
||||
if (ep_name) {
|
||||
g_autoptr (WpEndpoint) ep = wp_session_lookup_endpoint (session,
|
||||
WP_CONSTRAINT_TYPE_PW_PROPERTY, "endpoint.name", "=s", ep_name,
|
||||
WP_CONSTRAINT_TYPE_PW_PROPERTY, "media.class", "#s",
|
||||
(dir == WP_DIRECTION_INPUT) ? "*/Sink" : "*/Source", NULL);
|
||||
if (ep)
|
||||
ep_id = wp_proxy_get_bound_id (WP_PROXY (ep));
|
||||
}
|
||||
|
||||
/* If not found, use the highest priority one */
|
||||
if (ep_id == 0)
|
||||
ep_id = find_highest_prio (session, dir);
|
||||
|
||||
if (ep_id != 0) {
|
||||
/* block the signal to avoid storing this; only selections done by the user
|
||||
* should be stored */
|
||||
g_autofree gchar *value = g_strdup_printf ("%d", ep_id);
|
||||
g_signal_handlers_block_by_func (m, on_default_metadata_changed, self);
|
||||
wp_metadata_set (m, wp_proxy_get_bound_id (WP_PROXY (session)),
|
||||
default_endpoint_key (dir), "Spa:Int", value);
|
||||
g_signal_handlers_unblock_by_func (m, on_default_metadata_changed, self);
|
||||
|
||||
wp_info_object (self, "set default %s endpoint with id %d on session '%s'",
|
||||
direction_to_dbg_string (dir), ep_id, session_name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
on_endpoints_changed (WpSession * session, WpDefaultMetadata * self)
|
||||
{
|
||||
g_autoptr (WpMetadata) metadata = NULL;
|
||||
|
||||
/* Get the metadata */
|
||||
metadata = wp_object_manager_lookup (self->metadatas_om, WP_TYPE_METADATA,
|
||||
WP_CONSTRAINT_TYPE_G_PROPERTY, "bound-id", "=u", self->metadata_id, NULL);
|
||||
if (!metadata)
|
||||
return;
|
||||
|
||||
wp_trace_object (session, "endpoints changed, re-evaluating defaults");
|
||||
reevaluate_default_endpoints (self, metadata, session, WP_DIRECTION_INPUT);
|
||||
reevaluate_default_endpoints (self, metadata, session, WP_DIRECTION_OUTPUT);
|
||||
}
|
||||
|
||||
static void
|
||||
on_session_added (WpObjectManager * om, WpSession * session,
|
||||
WpDefaultMetadata * self)
|
||||
{
|
||||
g_signal_connect_object (session, "endpoints-changed",
|
||||
G_CALLBACK (on_endpoints_changed), self, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
on_metadata_added (WpObjectManager *om, WpMetadata *metadata, gpointer d)
|
||||
{
|
||||
WpDefaultMetadata * self = WP_DEFAULT_METADATA (d);
|
||||
g_autoptr (WpCore) core = wp_plugin_get_core (WP_PLUGIN (self));
|
||||
|
||||
g_return_if_fail (core);
|
||||
|
||||
/* Only handle the first available metadata and skip the rest */
|
||||
if (self->metadata_id > 0)
|
||||
return;
|
||||
self->metadata_id = wp_proxy_get_bound_id (WP_PROXY (metadata));
|
||||
|
||||
/* Handle the changed signal */
|
||||
g_signal_connect_object (metadata, "changed",
|
||||
G_CALLBACK (on_default_metadata_changed), self, 0);
|
||||
|
||||
/* Create the sessions object manager */
|
||||
self->sessions_om = wp_object_manager_new ();
|
||||
wp_object_manager_add_interest (self->sessions_om, WP_TYPE_SESSION, NULL);
|
||||
wp_object_manager_request_object_features (self->sessions_om, WP_TYPE_SESSION,
|
||||
WP_OBJECT_FEATURES_ALL);
|
||||
g_signal_connect_object (self->sessions_om, "object-added",
|
||||
G_CALLBACK (on_session_added), self, 0);
|
||||
wp_core_install_object_manager (core, self->sessions_om);
|
||||
}
|
||||
|
||||
static void
|
||||
wp_default_metadata_activate (WpPlugin * plugin)
|
||||
{
|
||||
WpDefaultMetadata * self = WP_DEFAULT_METADATA (plugin);
|
||||
g_autoptr (WpCore) core = wp_plugin_get_core (plugin);
|
||||
|
||||
g_return_if_fail (core);
|
||||
|
||||
/* Create the metadatas object manager */
|
||||
self->metadata_id = 0;
|
||||
self->metadatas_om = wp_object_manager_new ();
|
||||
wp_object_manager_add_interest (self->metadatas_om, WP_TYPE_METADATA, NULL);
|
||||
wp_object_manager_request_object_features (self->metadatas_om,
|
||||
WP_TYPE_METADATA, WP_OBJECT_FEATURES_ALL);
|
||||
g_signal_connect_object (self->metadatas_om, "object-added",
|
||||
G_CALLBACK (on_metadata_added), self, 0);
|
||||
wp_core_install_object_manager (core, self->metadatas_om);
|
||||
}
|
||||
|
||||
static void
|
||||
wp_default_metadata_deactivate (WpPlugin * plugin)
|
||||
{
|
||||
WpDefaultMetadata * self = WP_DEFAULT_METADATA (plugin);
|
||||
|
||||
g_clear_object (&self->metadatas_om);
|
||||
g_clear_object (&self->sessions_om);
|
||||
}
|
||||
|
||||
static void
|
||||
unload_default_endpoints (WpDefaultMetadata * self, WpDefaultEndpoints * d)
|
||||
{
|
||||
g_clear_pointer (&d->props, wp_properties_unref);
|
||||
g_clear_pointer (&d->group, g_free);
|
||||
d->self = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
load_default_endpoints (WpDefaultMetadata * self, WpDefaultEndpoints * d,
|
||||
const gchar *group)
|
||||
{
|
||||
d->self = self;
|
||||
d->group = g_strdup (group);
|
||||
d->props = wp_state_load (self->state, d->group);
|
||||
if (!d->props)
|
||||
wp_warning_object ("could not load default endpoints from %s",
|
||||
STATE_NAME);
|
||||
}
|
||||
|
||||
static void
|
||||
wp_default_metadata_finalize (GObject * object)
|
||||
{
|
||||
WpDefaultMetadata * self = WP_DEFAULT_METADATA (object);
|
||||
|
||||
/* Clear the current timeout callback */
|
||||
if (self->timeout_source)
|
||||
g_source_destroy (self->timeout_source);
|
||||
g_clear_pointer (&self->timeout_source, g_source_unref);
|
||||
|
||||
unload_default_endpoints (self, self->default_endpoints + WP_DIRECTION_INPUT);
|
||||
unload_default_endpoints (self, self->default_endpoints + WP_DIRECTION_OUTPUT);
|
||||
g_clear_object (&self->state);
|
||||
|
||||
G_OBJECT_CLASS (wp_default_metadata_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
wp_default_metadata_init (WpDefaultMetadata * self)
|
||||
{
|
||||
self->state = wp_state_new (STATE_NAME);
|
||||
load_default_endpoints (self, self->default_endpoints + WP_DIRECTION_INPUT,
|
||||
default_endpoint_key (WP_DIRECTION_INPUT));
|
||||
load_default_endpoints (self, self->default_endpoints + WP_DIRECTION_OUTPUT,
|
||||
default_endpoint_key (WP_DIRECTION_OUTPUT));
|
||||
}
|
||||
|
||||
static void
|
||||
wp_default_metadata_class_init (WpDefaultMetadataClass * klass)
|
||||
{
|
||||
GObjectClass *object_class = (GObjectClass *) klass;
|
||||
WpPluginClass *plugin_class = (WpPluginClass *) klass;
|
||||
|
||||
object_class->finalize = wp_default_metadata_finalize;
|
||||
|
||||
plugin_class->activate = wp_default_metadata_activate;
|
||||
plugin_class->deactivate = wp_default_metadata_deactivate;
|
||||
}
|
||||
|
||||
WP_PLUGIN_EXPORT void
|
||||
wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
|
||||
{
|
||||
wp_plugin_register (g_object_new (wp_default_metadata_get_type (),
|
||||
"name", "default-metadata",
|
||||
"module", module,
|
||||
NULL));
|
||||
}
|
||||
|
|
@ -1,264 +0,0 @@
|
|||
/* WirePlumber
|
||||
*
|
||||
* Copyright © 2020 Collabora Ltd.
|
||||
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
/*
|
||||
* This module selects "default" source & sink endpoints for each session
|
||||
* and when the user modifies them, it stores the user preference in text
|
||||
* files in $XDG_CONFIG_DIR, similarly to pulseaudio
|
||||
*/
|
||||
|
||||
#include <wp/wp.h>
|
||||
#include <errno.h>
|
||||
|
||||
G_DEFINE_QUARK (wp-session-settings-sink-file, session_settings_sink_file)
|
||||
G_DEFINE_QUARK (wp-session-settings-source-file, session_settings_source_file)
|
||||
|
||||
#define direction_to_dbg_string(dir) \
|
||||
((dir == WP_DIRECTION_INPUT) ? "sink" : "source")
|
||||
|
||||
struct _WpSessionSettings
|
||||
{
|
||||
WpPlugin parent;
|
||||
WpObjectManager *sessions_om;
|
||||
gchar *config_dir;
|
||||
};
|
||||
|
||||
G_DECLARE_FINAL_TYPE (WpSessionSettings, wp_session_settings,
|
||||
WP, SESSION_SETTINGS, WpPlugin)
|
||||
G_DEFINE_TYPE (WpSessionSettings, wp_session_settings, WP_TYPE_PLUGIN)
|
||||
|
||||
static void
|
||||
wp_session_settings_init (WpSessionSettings * self)
|
||||
{
|
||||
self->config_dir = g_build_filename (g_get_user_config_dir (),
|
||||
"wireplumber", NULL);
|
||||
if (g_mkdir_with_parents (self->config_dir, 0755) < 0) {
|
||||
wp_warning_object (self, "failed to create '%s': %s", self->config_dir,
|
||||
strerror (errno));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
wp_session_settings_finalize (GObject * object)
|
||||
{
|
||||
WpSessionSettings * self = WP_SESSION_SETTINGS (object);
|
||||
|
||||
g_free (self->config_dir);
|
||||
|
||||
G_OBJECT_CLASS (wp_session_settings_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
on_default_endpoint_changed (WpSession * session, WpDirection dir,
|
||||
guint32 id, WpSessionSettings * self)
|
||||
{
|
||||
GFile *file = NULL;
|
||||
g_autoptr (GFileOutputStream) out_stream = NULL;
|
||||
g_autoptr (GError) error = NULL;
|
||||
g_autoptr (WpEndpoint) ep = NULL;
|
||||
|
||||
wp_debug_object (self, "default %s on " WP_OBJECT_FORMAT " changed (%u), "
|
||||
"storing", direction_to_dbg_string (dir), WP_OBJECT_ARGS (session), id);
|
||||
|
||||
file = g_object_get_qdata (G_OBJECT (session),
|
||||
(dir == WP_DIRECTION_INPUT) ?
|
||||
session_settings_sink_file_quark () :
|
||||
session_settings_source_file_quark ());
|
||||
g_return_if_fail (file);
|
||||
|
||||
ep = wp_session_lookup_endpoint (session,
|
||||
WP_CONSTRAINT_TYPE_G_PROPERTY, "bound-id", "=u", id, NULL);
|
||||
if (!ep) {
|
||||
wp_warning_object (self, "default %s (%u) on " WP_OBJECT_FORMAT " not found",
|
||||
direction_to_dbg_string (dir), id, WP_OBJECT_ARGS (session));
|
||||
return;
|
||||
}
|
||||
|
||||
out_stream = g_file_replace (file, NULL, FALSE, G_FILE_CREATE_NONE, NULL,
|
||||
&error);
|
||||
if (out_stream) {
|
||||
/* write the name plus its terminating null byte */
|
||||
const gchar *name = wp_endpoint_get_name (ep);
|
||||
if (!g_output_stream_write_all (G_OUTPUT_STREAM (out_stream),
|
||||
name, strlen (name) + 1, NULL, NULL, &error)) {
|
||||
wp_warning_object (self, "error writing %s: %s", g_file_peek_path (file),
|
||||
error->message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static guint32
|
||||
find_highest_prio (WpSession * session, WpDirection dir)
|
||||
{
|
||||
g_autoptr (WpIterator) it = NULL;
|
||||
g_auto (GValue) val = G_VALUE_INIT;
|
||||
gint highest_prio = 0;
|
||||
guint32 id = 0;
|
||||
|
||||
it = wp_session_iterate_endpoints_filtered (session,
|
||||
WP_CONSTRAINT_TYPE_PW_PROPERTY, "media.class", "#s",
|
||||
(dir == WP_DIRECTION_INPUT) ? "*/Sink" : "*/Source",
|
||||
NULL);
|
||||
|
||||
for (; wp_iterator_next (it, &val); g_value_unset (&val)) {
|
||||
WpProxy *ep = g_value_get_object (&val);
|
||||
const gchar *prio_str = wp_proxy_get_property (ep, "endpoint.priority");
|
||||
gint prio = atoi (prio_str);
|
||||
|
||||
if (prio > highest_prio || id == 0) {
|
||||
highest_prio = prio;
|
||||
id = wp_proxy_get_bound_id (ep);
|
||||
}
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
static void
|
||||
reevaluate_defaults (WpSessionSettings * self,
|
||||
WpSession * session, WpDirection dir)
|
||||
{
|
||||
guint32 id = 0;
|
||||
GFile *file;
|
||||
g_autoptr (GFileInputStream) in_stream = NULL;
|
||||
g_autoptr (GError) error = NULL;
|
||||
gchar buffer[128];
|
||||
|
||||
/* try to read the default endpoint's name from the settings file */
|
||||
|
||||
file = g_object_get_qdata (G_OBJECT (session),
|
||||
(dir == WP_DIRECTION_INPUT) ?
|
||||
session_settings_sink_file_quark () :
|
||||
session_settings_source_file_quark ());
|
||||
|
||||
in_stream = g_file_read (file, NULL, &error);
|
||||
if (in_stream) {
|
||||
gsize bytes_read = 0;
|
||||
g_autoptr (WpEndpoint) ep = NULL;
|
||||
|
||||
if (!g_input_stream_read_all (G_INPUT_STREAM (in_stream), buffer,
|
||||
sizeof (buffer), &bytes_read, NULL, &error)) {
|
||||
wp_warning_object (self, "error reading %s: %s", g_file_peek_path (file),
|
||||
error->message);
|
||||
} else {
|
||||
/* the file should have a null byte, but let's not trust it */
|
||||
buffer[MIN (bytes_read, sizeof (buffer) - 1)] = '\0';
|
||||
ep = wp_session_lookup_endpoint (session,
|
||||
WP_CONSTRAINT_TYPE_PW_PROPERTY, "endpoint.name", "=s", buffer,
|
||||
WP_CONSTRAINT_TYPE_PW_PROPERTY, "media.class", "#s",
|
||||
(dir == WP_DIRECTION_INPUT) ? "*/Sink" : "*/Source",
|
||||
NULL);
|
||||
if (ep)
|
||||
id = wp_proxy_get_bound_id (WP_PROXY (ep));
|
||||
}
|
||||
}
|
||||
else if (error) {
|
||||
/* this is an expected condition if no settings are stored; just debug */
|
||||
wp_debug_object (self, "file read error (%s): %s", g_file_peek_path (file),
|
||||
error->message);
|
||||
}
|
||||
|
||||
/* if not found by settings, find the highest priority one */
|
||||
if (id == 0)
|
||||
id = find_highest_prio (session, dir);
|
||||
|
||||
wp_debug_object (self, "selecting default %s for " WP_OBJECT_FORMAT ": %u",
|
||||
direction_to_dbg_string (dir), WP_OBJECT_ARGS (session), id);
|
||||
|
||||
/* block the signal to avoid storing this on the file;
|
||||
only selections done by the user should be stored */
|
||||
g_signal_handlers_block_by_func (session, on_default_endpoint_changed, self);
|
||||
wp_session_set_default_endpoint (session, dir, id);
|
||||
g_signal_handlers_unblock_by_func (session, on_default_endpoint_changed, self);
|
||||
}
|
||||
|
||||
static void
|
||||
on_endpoints_changed (WpSession * session, WpSessionSettings * self)
|
||||
{
|
||||
wp_trace_object (session, "endpoints changed, re-evaluating defaults");
|
||||
reevaluate_defaults (self, session, WP_DIRECTION_INPUT);
|
||||
reevaluate_defaults (self, session, WP_DIRECTION_OUTPUT);
|
||||
}
|
||||
|
||||
static void
|
||||
on_session_added (WpObjectManager * om, WpSession * session,
|
||||
WpSessionSettings * self)
|
||||
{
|
||||
GFile *sink_file;
|
||||
GFile *source_file;
|
||||
gchar *filename;
|
||||
|
||||
filename = g_strdup_printf ("%s%c%s-default-sink", self->config_dir,
|
||||
G_DIR_SEPARATOR, wp_session_get_name (session));
|
||||
sink_file = g_file_new_for_path (filename);
|
||||
g_free (filename);
|
||||
|
||||
filename = g_strdup_printf ("%s%c%s-default-source", self->config_dir,
|
||||
G_DIR_SEPARATOR, wp_session_get_name (session));
|
||||
source_file = g_file_new_for_path (filename);
|
||||
g_free (filename);
|
||||
|
||||
g_object_set_qdata_full (G_OBJECT (session),
|
||||
session_settings_sink_file_quark (), sink_file, g_object_unref);
|
||||
g_object_set_qdata_full (G_OBJECT (session),
|
||||
session_settings_source_file_quark (), source_file, g_object_unref);
|
||||
|
||||
g_signal_connect_object (session, "default-endpoint-changed",
|
||||
G_CALLBACK (on_default_endpoint_changed), self, 0);
|
||||
g_signal_connect_object (session, "endpoints-changed",
|
||||
G_CALLBACK (on_endpoints_changed), self, 0);
|
||||
|
||||
on_endpoints_changed (session, self);
|
||||
}
|
||||
|
||||
static void
|
||||
wp_session_settings_activate (WpPlugin * plugin)
|
||||
{
|
||||
WpSessionSettings * self = WP_SESSION_SETTINGS (plugin);
|
||||
g_autoptr (WpCore) core = wp_plugin_get_core (plugin);
|
||||
|
||||
g_return_if_fail (core);
|
||||
|
||||
self->sessions_om = wp_object_manager_new ();
|
||||
wp_object_manager_add_interest (self->sessions_om, WP_TYPE_SESSION, NULL);
|
||||
wp_object_manager_request_proxy_features (self->sessions_om, WP_TYPE_SESSION,
|
||||
WP_PROXY_FEATURES_STANDARD |
|
||||
WP_PROXY_FEATURE_PROPS |
|
||||
WP_SESSION_FEATURE_ENDPOINTS);
|
||||
g_signal_connect_object (self->sessions_om, "object-added",
|
||||
G_CALLBACK (on_session_added), self, 0);
|
||||
wp_core_install_object_manager (core, self->sessions_om);
|
||||
}
|
||||
|
||||
static void
|
||||
wp_session_settings_deactivate (WpPlugin * plugin)
|
||||
{
|
||||
WpSessionSettings * self = WP_SESSION_SETTINGS (plugin);
|
||||
|
||||
g_clear_object (&self->sessions_om);
|
||||
}
|
||||
|
||||
static void
|
||||
wp_session_settings_class_init (WpSessionSettingsClass * klass)
|
||||
{
|
||||
GObjectClass *object_class = (GObjectClass *) klass;
|
||||
WpPluginClass *plugin_class = (WpPluginClass *) klass;
|
||||
|
||||
object_class->finalize = wp_session_settings_finalize;
|
||||
|
||||
plugin_class->activate = wp_session_settings_activate;
|
||||
plugin_class->deactivate = wp_session_settings_deactivate;
|
||||
}
|
||||
|
||||
WP_PLUGIN_EXPORT void
|
||||
wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args)
|
||||
{
|
||||
wp_plugin_register (g_object_new (wp_session_settings_get_type (),
|
||||
"name", "session-settings",
|
||||
"module", module,
|
||||
NULL));
|
||||
}
|
||||
|
|
@ -64,9 +64,8 @@ load-module C libwireplumber-module-device-activation
|
|||
# Automatically suspends idle nodes after 3 seconds
|
||||
load-module C libwireplumber-module-node-suspension
|
||||
|
||||
# Sets endpoint defaults on each session and stores default endpoint
|
||||
# user settings in XDG_CONFIG_DIR
|
||||
#load-module C libwireplumber-module-session-settings
|
||||
# Grants functionality to store and restore default metadata such as default endpoints
|
||||
load-module C libwireplumber-module-default-metadata
|
||||
|
||||
# Implements static objects creation based on TOML configuration files
|
||||
load-module C libwireplumber-module-config-static-objects
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue