From 43d8753c5ef4cbd4d2f6558182b290d083644521 Mon Sep 17 00:00:00 2001 From: Varnit Singh Date: Wed, 8 Jun 2022 09:25:45 +0000 Subject: [PATCH 2/2] wpctl: allow modifying volume levels using percentage/step amount. --- src/tools/wpctl.c | 63 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 59 insertions(+), 4 deletions(-) diff --git a/src/tools/wpctl.c b/src/tools/wpctl.c index 9f7c6bb..0f5bc8c 100644 --- a/src/tools/wpctl.c +++ b/src/tools/wpctl.c @@ -45,6 +45,7 @@ static struct { guint64 id; gfloat volume; gboolean is_pid; + gchar type; } set_volume; struct { @@ -846,11 +847,38 @@ set_volume_parse_positional (gint argc, gchar ** argv, GError **error) { if (argc < 4) { g_set_error (error, wpctl_error_domain_quark(), 0, - "ID and VOL are required"); + "ID and VOL[%%][-/+] are required"); + return FALSE; + } + + GRegex *regex = g_regex_new ("^(\\d*\\.?\\d*)(%?)([-+]?)$", 0, 0, NULL); + GMatchInfo *info = NULL; + + if (g_regex_match(regex, argv[3], 0, &info)) { + cmdline.set_volume.volume = strtof(g_match_info_fetch(info, 1), NULL); + cmdline.set_volume.type = 'a'; + + if (g_strcmp0(g_match_info_fetch(info, 2), "%") == 0) { + cmdline.set_volume.type = 'p'; + } + + if (g_strcmp0(g_match_info_fetch(info, 3), "-") == 0) { + cmdline.set_volume.volume = -(cmdline.set_volume.volume); + if (cmdline.set_volume.type != 'p') { + cmdline.set_volume.type = 's'; + } + } else if (g_strcmp0(g_match_info_fetch(info, 3), "+") == 0 && cmdline.set_volume.type != 'p') { + cmdline.set_volume.type = 's'; + } + g_match_info_free (info); + g_regex_unref (regex); + } else { + g_regex_unref (regex); + g_set_error (error, wpctl_error_domain_quark(), 0, + "Invalid volume argument. See wpctl set-volume --help"); return FALSE; } - cmdline.set_volume.volume = strtof (argv[3], NULL); return parse_id (!cmdline.set_volume.is_pid, false, argv[2], &cmdline.set_volume.id, error); } @@ -874,6 +902,7 @@ do_set_volume (WpCtl * self, WpPipewireObject *proxy) g_autoptr (GError) error = NULL; GVariant *variant = NULL; gboolean res = FALSE; + gdouble curr_volume = 1.0; guint32 id = wp_proxy_get_bound_id (WP_PROXY (proxy)); if (WP_IS_ENDPOINT (proxy)) { @@ -885,6 +914,27 @@ do_set_volume (WpCtl * self, WpPipewireObject *proxy) id = atoi (str); } + g_signal_emit_by_name (mixer_api, "get-volume", id, &variant); + if (!variant) { + fprintf (stderr, "Node %d does not support volume\n", id); + g_clear_pointer (&variant, g_variant_unref); + return FALSE; + } + g_variant_lookup (variant, "volume", "d", &curr_volume); + g_clear_pointer (&variant, g_variant_unref); + + if (cmdline.set_volume.type == 'a') { + cmdline.set_volume.volume = cmdline.set_volume.volume; + } else if (cmdline.set_volume.type == 's') { + cmdline.set_volume.volume = (cmdline.set_volume.volume + curr_volume); + } else if (cmdline.set_volume.type == 'p') { + gfloat delta = (cmdline.set_volume.volume) * (curr_volume); + cmdline.set_volume.volume = (curr_volume + delta); + } + if (cmdline.set_volume.volume < 0) { + cmdline.set_volume.volume = 0.0; + } + g_variant_builder_add (&b, "{sv}", "volume", g_variant_new_double (cmdline.set_volume.volume)); variant = g_variant_builder_end (&b); @@ -1266,8 +1316,13 @@ static const struct subcommand { }, { .name = "set-volume", - .positional_args = "ID VOL", - .summary = "Sets the volume of ID to VOL (floating point, 1.0 is 100%%)", + .positional_args = "ID VOL[%%][-/+]", + .summary = "Sets the volume of ID from specified argument. " + "(floating point, 1.0 is 100%%)\n VOL%%[-/+] - " + "Step up/down volume by specified percent (Example:" + " 0.5%%+)\n VOL[-/+] - Step up/down volume by" + " specified value (Example: 0.5+)\n VOL - Set " + "volume as the specified value (Example: 0.5)", .description = NULL, .entries = { { "pid", 'p', G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, -- 2.36.1