diff options
author | kotontrion <[email protected]> | 2024-08-20 10:15:16 +0200 |
---|---|---|
committer | kotontrion <[email protected]> | 2024-08-20 10:15:16 +0200 |
commit | 339124618aa57ee7c42cf39e8172ece02e9a54db (patch) | |
tree | c30a97d9eeac82373319c34fa34b978f87292993 /src/endpoint.c | |
parent | c898e652c9a19debc34556d4a3e5f3a1f0da76d7 (diff) |
better handling of multiple channels
Diffstat (limited to 'src/endpoint.c')
-rw-r--r-- | src/endpoint.c | 92 |
1 files changed, 89 insertions, 3 deletions
diff --git a/src/endpoint.c b/src/endpoint.c index 31ac616..5ea1671 100644 --- a/src/endpoint.c +++ b/src/endpoint.c @@ -4,6 +4,7 @@ #include "device.h" #include "endpoint-private.h" +#include "glib.h" #include "wp.h" struct _AstalWpEndpoint { @@ -16,6 +17,7 @@ struct _AstalWpEndpoint { gchar *name; AstalWpMediaClass type; gboolean is_default; + gboolean lock_channels; gchar *icon; }; @@ -55,6 +57,7 @@ typedef enum { ASTAL_WP_ENDPOINT_PROP_DEFAULT, ASTAL_WP_ENDPOINT_PROP_ICON, ASTAL_WP_ENDPOINT_PROP_VOLUME_ICON, + ASTAL_WP_ENDPOINT_PROP_LOCK_CHANNELS, ASTAL_WP_ENDPOINT_N_PROPERTIES, } AstalWpEndpointProperties; @@ -65,9 +68,10 @@ static GParamSpec *astal_wp_endpoint_properties[ASTAL_WP_ENDPOINT_N_PROPERTIES] void astal_wp_endpoint_update_volume(AstalWpEndpoint *self) { AstalWpEndpointPrivate *priv = astal_wp_endpoint_get_instance_private(self); - gdouble volume; + gdouble volume = 0; gboolean mute; GVariant *variant = NULL; + GVariantIter *channels = NULL; g_signal_emit_by_name(priv->mixer, "get-volume", self->id, &variant); @@ -75,6 +79,20 @@ void astal_wp_endpoint_update_volume(AstalWpEndpoint *self) { g_variant_lookup(variant, "volume", "d", &volume); g_variant_lookup(variant, "mute", "b", &mute); + g_variant_lookup(variant, "channelVolumes", "a{sv}", &channels); + + if (channels != NULL) { + const gchar *key; + const gchar *channel_str; + gdouble channel_volume; + GVariant *varvol; + + while (g_variant_iter_loop(channels, "{&sv}", &key, &varvol)) { + g_variant_lookup(varvol, "volume", "d", &channel_volume); + g_variant_lookup(varvol, "channel", "&s", &channel_str); + if (channel_volume > volume) volume = channel_volume; + } + } if (mute != self->mute) { self->mute = mute; @@ -89,15 +107,68 @@ void astal_wp_endpoint_update_volume(AstalWpEndpoint *self) { g_object_notify(G_OBJECT(self), "volume-icon"); } +/** + * astal_wp_endpoint_set_volume: + * @self: the AstalWpEndpoint object + * @volume: The new volume level to set. + * + * Sets the volume level for this endpoint. The volume is clamped to be between + * 0 and 1.5. + */ void astal_wp_endpoint_set_volume(AstalWpEndpoint *self, gdouble volume) { AstalWpEndpointPrivate *priv = astal_wp_endpoint_get_instance_private(self); gboolean ret; if (volume >= 1.5) volume = 1.5; - GVariant *variant = g_variant_new_double(volume); - g_signal_emit_by_name(priv->mixer, "set-volume", self->id, variant, &ret); + if (volume <= 0) volume = 0; + + gboolean mute; + GVariant *variant = NULL; + GVariantIter *channels = NULL; + + g_auto(GVariantBuilder) vol_b = G_VARIANT_BUILDER_INIT(G_VARIANT_TYPE_VARDICT); + g_signal_emit_by_name(priv->mixer, "get-volume", self->id, &variant); + + if (variant == NULL) return; + + g_variant_lookup(variant, "mute", "b", &mute); + g_variant_lookup(variant, "channelVolumes", "a{sv}", &channels); + + if (channels != NULL && !self->lock_channels) { + g_auto(GVariantBuilder) channel_volumes_b = G_VARIANT_BUILDER_INIT(G_VARIANT_TYPE_VARDICT); + + const gchar *key; + const gchar *channel_str; + gdouble channel_volume; + GVariant *varvol; + + while (g_variant_iter_loop(channels, "{&sv}", &key, &varvol)) { + g_auto(GVariantBuilder) channel_b = G_VARIANT_BUILDER_INIT(G_VARIANT_TYPE_VARDICT); + g_variant_lookup(varvol, "volume", "d", &channel_volume); + g_variant_lookup(varvol, "channel", "&s", &channel_str); + gdouble vol = self->volume == 0 ? volume : channel_volume * volume / self->volume; + g_variant_builder_add(&channel_b, "{sv}", "volume", g_variant_new_double(vol)); + g_variant_builder_add(&channel_volumes_b, "{sv}", key, + g_variant_builder_end(&channel_b)); + } + + g_variant_builder_add(&vol_b, "{sv}", "channelVolumes", + g_variant_builder_end(&channel_volumes_b)); + } else { + GVariant *volume_variant = g_variant_new_double(volume); + g_variant_builder_add(&vol_b, "{sv}", "volume", volume_variant); + } + + g_signal_emit_by_name(priv->mixer, "set-volume", self->id, g_variant_builder_end(&vol_b), &ret); } +/** + * astal_wp_endpoint_set_mute: + * @self: the AstalWpEndpoint instance. + * @mute: A boolean indicating whether to mute the endpoint. + * + * Sets the mute status for the endpoint. + */ void astal_wp_endpoint_set_mute(AstalWpEndpoint *self, gboolean mute) { AstalWpEndpointPrivate *priv = astal_wp_endpoint_get_instance_private(self); @@ -139,6 +210,13 @@ void astal_wp_endpoint_set_is_default(AstalWpEndpoint *self, gboolean is_default &ret); } +gboolean astal_wp_endpoint_get_lock_channels(AstalWpEndpoint *self) { return self->lock_channels; } + +void astal_wp_endpoint_set_lock_channels(AstalWpEndpoint *self, gboolean lock_channels) { + self->lock_channels = lock_channels; + astal_wp_endpoint_set_volume(self, self->volume); +} + const gchar *astal_wp_endpoint_get_volume_icon(AstalWpEndpoint *self) { if (self->mute) return "audio-volume-muted-symbolic"; if (self->volume <= 0.33) return "audio-volume-low-symbolic"; @@ -179,6 +257,9 @@ static void astal_wp_endpoint_get_property(GObject *object, guint property_id, G case ASTAL_WP_ENDPOINT_PROP_DEFAULT: g_value_set_boolean(value, self->is_default); break; + case ASTAL_WP_ENDPOINT_PROP_LOCK_CHANNELS: + g_value_set_boolean(value, self->lock_channels); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); break; @@ -203,6 +284,9 @@ static void astal_wp_endpoint_set_property(GObject *object, guint property_id, c g_free(self->icon); self->icon = g_strdup(g_value_get_string(value)); break; + case ASTAL_WP_ENDPOINT_PROP_LOCK_CHANNELS: + astal_wp_endpoint_set_lock_channels(self, g_value_get_boolean(value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec); break; @@ -424,6 +508,8 @@ static void astal_wp_endpoint_class_init(AstalWpEndpointClass *class) { G_PARAM_READABLE); astal_wp_endpoint_properties[ASTAL_WP_ENDPOINT_PROP_DEFAULT] = g_param_spec_boolean("is_default", "is_default", "is_default", FALSE, G_PARAM_READWRITE); + astal_wp_endpoint_properties[ASTAL_WP_ENDPOINT_PROP_LOCK_CHANNELS] = g_param_spec_boolean( + "lock_channels", "lock_channels", "lock channels", FALSE, G_PARAM_READWRITE); g_object_class_install_properties(object_class, ASTAL_WP_ENDPOINT_N_PROPERTIES, astal_wp_endpoint_properties); |