Merge pull request #2212 from evyatark2/wpscroll

wireplumber: Support for scrolling
This commit is contained in:
Alexis Rouillard 2023-07-02 11:46:56 +02:00 committed by GitHub
commit 91588fb8bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 112 additions and 41 deletions

View File

@ -27,6 +27,8 @@ class Wireplumber : public ALabel {
static void onMixerChanged(waybar::modules::Wireplumber* self, uint32_t id); static void onMixerChanged(waybar::modules::Wireplumber* self, uint32_t id);
static void onDefaultNodesApiChanged(waybar::modules::Wireplumber* self); static void onDefaultNodesApiChanged(waybar::modules::Wireplumber* self);
bool handleScroll(GdkEventScroll* e) override;
WpCore* wp_core_; WpCore* wp_core_;
GPtrArray* apis_; GPtrArray* apis_;
WpObjectManager* om_; WpObjectManager* om_;
@ -36,6 +38,7 @@ class Wireplumber : public ALabel {
uint32_t pending_plugins_; uint32_t pending_plugins_;
bool muted_; bool muted_;
double volume_; double volume_;
double min_step_;
uint32_t node_id_{0}; uint32_t node_id_{0};
std::string node_name_; std::string node_name_;
}; };

View File

@ -51,12 +51,12 @@ Additionally you can control the volume by scrolling *up* or *down* while the cu
The maximum length in character the module should display. The maximum length in character the module should display.
*min-length*: ++ *min-length*: ++
typeof: integer ++ typeof: integer ++
The minimum length in characters the module should take up. The minimum length in characters the module should take up.
*align*: ++ *align*: ++
typeof: float ++ typeof: float ++
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text. The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
*scroll-step*: ++ *scroll-step*: ++
typeof: float ++ typeof: float ++

View File

@ -11,59 +11,77 @@ The *wireplumber* module displays the current volume reported by WirePlumber.
# CONFIGURATION # CONFIGURATION
*format*: ++ *format*: ++
typeof: string ++ typeof: string ++
default: *{volume}%* ++ default: *{volume}%* ++
The format, how information should be displayed. This format is used when other formats aren't specified. The format, how information should be displayed. This format is used when other formats aren't specified.
*format-muted*: ++ *format-muted*: ++
typeof: string ++ typeof: string ++
This format is used when the sound is muted. This format is used when the sound is muted.
*tooltip*: ++ *tooltip*: ++
typeof: bool ++ typeof: bool ++
default: *true* ++ default: *true* ++
Option to disable tooltip on hover. Option to disable tooltip on hover.
*tooltip-format*: ++ *tooltip-format*: ++
typeof: string ++ typeof: string ++
default: *{node_name}* ++ default: *{node_name}* ++
The format of information displayed in the tooltip. The format of information displayed in the tooltip.
*rotate*: ++ *rotate*: ++
typeof: integer ++ typeof: integer ++
Positive value to rotate the text label. Positive value to rotate the text label.
*states*: ++ *states*: ++
typeof: object ++ typeof: object ++
A number of volume states which get activated on certain volume levels. See *waybar-states(5)*. A number of volume states which get activated on certain volume levels. See *waybar-states(5)*.
*max-length*: ++ *max-length*: ++
typeof: integer ++ typeof: integer ++
The maximum length in character the module should display. The maximum length in character the module should display.
*min-length*: ++ *min-length*: ++
typeof: integer ++ typeof: integer ++
The minimum length in characters the module should take up. The minimum length in characters the module should take up.
*align*: ++ *align*: ++
typeof: float ++ typeof: float ++
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text. The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
*scroll-step*: ++
typeof: float ++
default: 1.0 ++
The speed in which to change the volume when scrolling.
*on-click*: ++ *on-click*: ++
typeof: string ++ typeof: string ++
Command to execute when clicked on the module. Command to execute when clicked on the module.
*on-click-middle*: ++ *on-click-middle*: ++
typeof: string ++ typeof: string ++
Command to execute when middle-clicked on the module using mousewheel. Command to execute when middle-clicked on the module using mousewheel.
*on-click-right*: ++ *on-click-right*: ++
typeof: string ++ typeof: string ++
Command to execute when you right clicked on the module. Command to execute when you right clicked on the module.
*on-update*: ++ *on-update*: ++
typeof: string ++ typeof: string ++
Command to execute when the module is updated. Command to execute when the module is updated.
*on-scroll-up*: ++
typeof: string ++
Command to execute when scrolling up on the module. This replaces the default behaviour of volume control.
*on-scroll-down*: ++
typeof: string ++
Command to execute when scrolling down on the module. This replaces the default behaviour of volume control.
*max-volume*: ++
typeof: float ++
default: 100 ++
The maximum volume that can be set, in percentage.
# FORMAT REPLACEMENTS # FORMAT REPLACEMENTS

View File

@ -15,6 +15,7 @@ waybar::modules::Wireplumber::Wireplumber(const std::string& id, const Json::Val
pending_plugins_(0), pending_plugins_(0),
muted_(false), muted_(false),
volume_(0.0), volume_(0.0),
min_step_(0.0),
node_id_(0) { node_id_(0) {
wp_init(WP_INIT_PIPEWIRE); wp_init(WP_INIT_PIPEWIRE);
wp_core_ = wp_core_new(NULL, NULL); wp_core_ = wp_core_new(NULL, NULL);
@ -39,6 +40,9 @@ waybar::modules::Wireplumber::Wireplumber(const std::string& id, const Json::Val
activatePlugins(); activatePlugins();
dp.emit(); dp.emit();
event_box_.add_events(Gdk::SCROLL_MASK | Gdk::SMOOTH_SCROLL_MASK);
event_box_.signal_scroll_event().connect(sigc::mem_fun(*this, &Wireplumber::handleScroll));
} }
waybar::modules::Wireplumber::~Wireplumber() { waybar::modules::Wireplumber::~Wireplumber() {
@ -83,7 +87,6 @@ void waybar::modules::Wireplumber::updateNodeName(waybar::modules::Wireplumber*
void waybar::modules::Wireplumber::updateVolume(waybar::modules::Wireplumber* self, uint32_t id) { void waybar::modules::Wireplumber::updateVolume(waybar::modules::Wireplumber* self, uint32_t id) {
spdlog::debug("[{}]: updating volume", self->name_); spdlog::debug("[{}]: updating volume", self->name_);
double vol;
GVariant* variant = NULL; GVariant* variant = NULL;
if (!isValidNodeId(id)) { if (!isValidNodeId(id)) {
@ -99,11 +102,11 @@ void waybar::modules::Wireplumber::updateVolume(waybar::modules::Wireplumber* se
throw std::runtime_error(err); throw std::runtime_error(err);
} }
g_variant_lookup(variant, "volume", "d", &vol); g_variant_lookup(variant, "volume", "d", &self->volume_);
g_variant_lookup(variant, "step", "d", &self->min_step_);
g_variant_lookup(variant, "mute", "b", &self->muted_); g_variant_lookup(variant, "mute", "b", &self->muted_);
g_clear_pointer(&variant, g_variant_unref); g_clear_pointer(&variant, g_variant_unref);
self->volume_ = std::round(vol * 100.0F);
self->dp.emit(); self->dp.emit();
} }
@ -280,11 +283,12 @@ auto waybar::modules::Wireplumber::update() -> void {
label_.get_style_context()->remove_class("muted"); label_.get_style_context()->remove_class("muted");
} }
int vol = round(volume_ * 100.0);
std::string markup = fmt::format(fmt::runtime(format), fmt::arg("node_name", node_name_), std::string markup = fmt::format(fmt::runtime(format), fmt::arg("node_name", node_name_),
fmt::arg("volume", volume_), fmt::arg("icon", getIcon(volume_))); fmt::arg("volume", vol), fmt::arg("icon", getIcon(vol)));
label_.set_markup(markup); label_.set_markup(markup);
getState(volume_); getState(vol);
if (tooltipEnabled()) { if (tooltipEnabled()) {
if (tooltip_format.empty() && config_["tooltip-format"].isString()) { if (tooltip_format.empty() && config_["tooltip-format"].isString()) {
@ -292,9 +296,9 @@ auto waybar::modules::Wireplumber::update() -> void {
} }
if (!tooltip_format.empty()) { if (!tooltip_format.empty()) {
label_.set_tooltip_text( label_.set_tooltip_text(fmt::format(fmt::runtime(tooltip_format),
fmt::format(fmt::runtime(tooltip_format), fmt::arg("node_name", node_name_), fmt::arg("node_name", node_name_),
fmt::arg("volume", volume_), fmt::arg("icon", getIcon(volume_)))); fmt::arg("volume", vol), fmt::arg("icon", getIcon(vol))));
} else { } else {
label_.set_tooltip_text(node_name_); label_.set_tooltip_text(node_name_);
} }
@ -303,3 +307,49 @@ auto waybar::modules::Wireplumber::update() -> void {
// Call parent update // Call parent update
ALabel::update(); ALabel::update();
} }
bool waybar::modules::Wireplumber::handleScroll(GdkEventScroll* e) {
if (config_["on-scroll-up"].isString() || config_["on-scroll-down"].isString()) {
return AModule::handleScroll(e);
}
auto dir = AModule::getScrollDir(e);
if (dir == SCROLL_DIR::NONE) {
return true;
}
if (config_["reverse-scrolling"].asInt() == 1) {
if (dir == SCROLL_DIR::UP) {
dir = SCROLL_DIR::DOWN;
} else if (dir == SCROLL_DIR::DOWN) {
dir = SCROLL_DIR::UP;
}
}
double max_volume = 1;
double step = 1.0 / 100.0;
if (config_["scroll-step"].isDouble()) {
step = config_["scroll-step"].asDouble() / 100.0;
}
if (config_["max-volume"].isDouble()) {
max_volume = config_["max-volume"].asDouble() / 100.0;
}
if (step < min_step_) step = min_step_;
double new_vol = volume_;
if (dir == SCROLL_DIR::UP) {
if (volume_ < max_volume) {
new_vol = volume_ + step;
if (new_vol > max_volume) new_vol = max_volume;
}
} else if (dir == SCROLL_DIR::DOWN) {
if (volume_ > 0) {
new_vol = volume_ - step;
if (new_vol < 0) new_vol = 0;
}
}
if (new_vol != volume_) {
GVariant* variant = g_variant_new_double(new_vol);
gboolean ret;
g_signal_emit_by_name(mixer_api_, "set-volume", node_id_, variant, &ret);
}
return true;
}