wireplumber: add more volume formats

- Add the possibility to show the volume in linear, cubic, db, and
  cubic percent (default for backward compatibility).
- Add the ability to change the scale for the scrolling action.
- Make the minimal step flexible to fit any scale.
This commit is contained in:
Marc Bornand
2025-08-21 13:48:00 +02:00
parent 41de8964f1
commit aaffebed4c
2 changed files with 88 additions and 18 deletions
+22 -1
View File
@@ -63,6 +63,11 @@ The *wireplumber* module displays the current volume reported by WirePlumber.
default: 1.0 ++ default: 1.0 ++
The speed at which to change the volume when scrolling. The speed at which to change the volume when scrolling.
*scroll-scale*: ++
typeof: string ++
default: cubic_percent
The scale to use for the scrolling volume change. Options are 'linear', 'db', 'cubic', and 'cubic_percent'.
*on-click*: ++ *on-click*: ++
typeof: string ++ typeof: string ++
Command to execute when clicked on the module. Command to execute when clicked on the module.
@@ -107,7 +112,13 @@ The *wireplumber* module displays the current volume reported by WirePlumber.
# FORMAT REPLACEMENTS # FORMAT REPLACEMENTS
*{volume}*: Volume in percentage. *{volume}*: Volume in percentage, cubic scale as integer.
*{volume_linear}*: Volume in linear scale as float.
*{volume_cubic}*: Volume in cubic scale as float.
*{volume_db}*: Volume in decibel scale as float.
*{node_name}*: The node's nickname as reported by WirePlumber (*node.nick* property) *{node_name}*: The node's nickname as reported by WirePlumber (*node.nick* property)
@@ -143,6 +154,16 @@ The *wireplumber* module displays the current volume reported by WirePlumber.
} }
``` ```
## Use a Different Scale
```
"wireplumber": {
"format": "{volume_db:.2f}dB",
"scroll-scale": "db",
"scroll-step": 2.5
}
```
# STYLE # STYLE
- *#wireplumber* - *#wireplumber*
+66 -17
View File
@@ -1,6 +1,8 @@
#include "modules/wireplumber.hpp" #include "modules/wireplumber.hpp"
#include <spdlog/spdlog.h> #include <spdlog/spdlog.h>
#include <cmath>
#include <string>
bool isValidNodeId(uint32_t id) { return id > 0 && id < G_MAXUINT32; } bool isValidNodeId(uint32_t id) { return id > 0 && id < G_MAXUINT32; }
@@ -396,7 +398,7 @@ void waybar::modules::Wireplumber::onMixerApiLoaded(WpObject* p, GAsyncResult* r
spdlog::debug("[{}]: loaded mixer API", self->name_); spdlog::debug("[{}]: loaded mixer API", self->name_);
g_ptr_array_add(self->apis_, ({ g_ptr_array_add(self->apis_, ({
WpPlugin* p = wp_plugin_find(self->wp_core_, "mixer-api"); WpPlugin* p = wp_plugin_find(self->wp_core_, "mixer-api");
g_object_set(G_OBJECT(p), "scale", 1 /* cubic */, nullptr); g_object_set(G_OBJECT(p), "scale", 0 /* linear */, nullptr);
p; p;
})); }));
@@ -436,8 +438,16 @@ auto waybar::modules::Wireplumber::update() -> void {
label_.get_style_context()->remove_class("source-muted"); label_.get_style_context()->remove_class("source-muted");
} }
int vol = round(volume_ * 100.0);
int source_vol = round(source_volume_ * 100.0); double vol_cube = pow(volume_, 3);
double source_vol_cube = pow(source_volume_, 3);
int vol = round(vol_cube * 100.0);
int source_vol = round(source_vol_cube * 100.0);
double vol_db = 20.0 * log10(volume_);
double source_vol_db = 20.0 * log10(source_volume_);
// Get the state and apply state-specific format if available // Get the state and apply state-specific format if available
auto state = getState(vol); auto state = getState(vol);
@@ -468,7 +478,10 @@ auto waybar::modules::Wireplumber::update() -> void {
std::string markup = std::string markup =
fmt::format(fmt::runtime(format), fmt::arg("node_name", node_name_), fmt::arg("volume", vol), fmt::format(fmt::runtime(format), fmt::arg("node_name", node_name_), fmt::arg("volume", vol),
fmt::arg("icon", getIcon(vol)), fmt::arg("format_source", formatted_source), fmt::arg("icon", getIcon(vol)), fmt::arg("format_source", formatted_source),
fmt::arg("source_volume", source_vol), fmt::arg("source_desc", source_name_)); fmt::arg("source_volume", source_vol), fmt::arg("source_desc", source_name_),
fmt::arg("volume_linear", volume_), fmt::arg("volume_cubic", vol_cube),
fmt::arg("volume_db", vol_db),fmt::arg("source_volume_linear", source_volume_),
fmt::arg("source_volume_cubic", source_vol_cube), fmt::arg("source_volume_db", source_vol_db));
label_.set_markup(markup); label_.set_markup(markup);
if (tooltipEnabled()) { if (tooltipEnabled()) {
@@ -480,7 +493,10 @@ auto waybar::modules::Wireplumber::update() -> void {
label_.set_tooltip_text(fmt::format( label_.set_tooltip_text(fmt::format(
fmt::runtime(tooltipFormat), fmt::arg("node_name", node_name_), fmt::arg("volume", vol), fmt::runtime(tooltipFormat), fmt::arg("node_name", node_name_), fmt::arg("volume", vol),
fmt::arg("icon", getIcon(vol)), fmt::arg("format_source", formatted_source), fmt::arg("icon", getIcon(vol)), fmt::arg("format_source", formatted_source),
fmt::arg("source_volume", source_vol), fmt::arg("source_desc", source_name_))); fmt::arg("source_volume", source_vol), fmt::arg("source_desc", source_name_),
fmt::arg("volume_linear", volume_), fmt::arg("volume_cubic", vol_cube),
fmt::arg("volume_db", vol_db), fmt::arg("source_volume_linear", source_volume_),
fmt::arg("source_volume_cubic", source_vol_cube), fmt::arg("source_volume_db", source_vol_db)));
} else { } else {
label_.set_tooltip_text(node_name_); label_.set_tooltip_text(node_name_);
} }
@@ -499,28 +515,61 @@ bool waybar::modules::Wireplumber::handleScroll(GdkEventScroll* e) {
return true; return true;
} }
double maxVolume = 1; double maxVolume = 1;
double step = 1.0 / 100.0; double step = 1.0;
if (config_["scroll-step"].isDouble()) { if (config_["scroll-step"].isDouble()) {
step = config_["scroll-step"].asDouble() / 100.0; step = config_["scroll-step"].asDouble();
} }
if (config_["max-volume"].isDouble()) { if (config_["max-volume"].isDouble()) {
maxVolume = config_["max-volume"].asDouble() / 100.0; maxVolume = config_["max-volume"].asDouble();
} }
if (step < min_step_) step = min_step_; double vol = volume_;
std::string scale = "cubic_percent";
if (config_["scroll-scale"].isString()) {
scale = config_["scroll-scale"].asString();
}
double newVol = volume_; if (scale == "cubic") {
vol = pow(vol, 3);
}
else if (scale == "db") {
vol = log10(vol) * 20.0;
}
else if (scale == "cubic_percent") {
vol = pow(vol, 3) * 100.0;
}
double newVol = vol;
if (dir == SCROLL_DIR::UP) { if (dir == SCROLL_DIR::UP) {
if (volume_ < maxVolume) { newVol = vol + step;
newVol = volume_ + step; } else if (dir == SCROLL_DIR::DOWN) {
if (newVol > maxVolume) newVol = maxVolume; newVol = vol - step;
}
if (scale == "cubic") {
newVol = cbrt(newVol);
}
else if (scale == "db") {
newVol = exp10(newVol / 20.0);
}
else if (scale == "cubic_percent") {
newVol = cbrt(newVol / 100.0);
}
if (dir == SCROLL_DIR::UP) {
if (volume_ + min_step_ > newVol) {
newVol = volume_ + min_step_;
} }
} else if (dir == SCROLL_DIR::DOWN) { } else if (dir == SCROLL_DIR::DOWN) {
if (volume_ > 0) { if (volume_ - min_step_ < newVol) {
newVol = volume_ - step; newVol = volume_ - min_step_;
}
}
if (newVol < 0) newVol = 0; if (newVol < 0) newVol = 0;
} else if (newVol > maxVolume) newVol = maxVolume;
}
if (newVol != volume_) { if (newVol != volume_) {
GVariant* variant = g_variant_new_double(newVol); GVariant* variant = g_variant_new_double(newVol);
gboolean ret; gboolean ret;