Skip to content
Snippets Groups Projects
Commit 653fea82 authored by George Kiagiadakis's avatar George Kiagiadakis
Browse files

m-session-settings: implement storing and loading default endpoint user settings

parent 49c6d00e
No related branches found
No related tags found
No related merge requests found
......@@ -6,12 +6,23 @@
* 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)
struct _WpSessionSettings
{
WpPlugin parent;
WpObjectManager *sessions_om;
gchar *config_dir;
};
G_DECLARE_FINAL_TYPE (WpSessionSettings, wp_session_settings,
......@@ -21,6 +32,63 @@ 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, const gchar * type,
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, "%s on " WP_OBJECT_FORMAT " changed (%u), storing",
type, WP_OBJECT_ARGS (session), id);
if (g_strcmp0 (type, "Wp:defaultSink") == 0)
file = g_object_get_qdata (G_OBJECT (session),
session_settings_sink_file_quark ());
else if (g_strcmp0 (type, "Wp:defaultSource") == 0)
file = g_object_get_qdata (G_OBJECT (session),
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, "%s (%u) on " WP_OBJECT_FORMAT " not found",
type, 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
......@@ -54,36 +122,102 @@ find_highest_prio (WpSession * session, WpDirection dir)
}
static void
reevaluate_defaults (WpSession * session, WpDirection dir)
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 ());
/* TODO
if (settings exist)
id = lookup endpoint in settings
*/
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",
(dir == WP_DIRECTION_INPUT) ? "sink" : "source",
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 == WP_DIRECTION_INPUT) ? "Wp:defaultSink" : "Wp:defaultSource", id);
g_signal_handlers_unblock_by_func (session, on_default_endpoint_changed, self);
}
static void
on_endpoints_changed (WpSession * session, WpSessionSettings * self)
{
reevaluate_defaults (session, WP_DIRECTION_INPUT);
reevaluate_defaults (session, WP_DIRECTION_OUTPUT);
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)
{
on_endpoints_changed (session, 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
......@@ -116,8 +250,11 @@ wp_session_settings_deactivate (WpPlugin * plugin)
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;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment