#include "widgets/volumeWidget.hpp" #include #include #include #include #include "helpers/command.hpp" #include "giomm/applicationcommandline.h" VolumeWidget::VolumeWidget() : Gtk::Box(Gtk::Orientation::HORIZONTAL) { set_valign(Gtk::Align::CENTER); set_halign(Gtk::Align::CENTER); label.set_halign(Gtk::Align::CENTER); label.set_valign(Gtk::Align::CENTER); label.set_text("Vol"); append(label); click = Gtk::GestureClick::create(); click->set_button(GDK_BUTTON_PRIMARY); click->signal_released().connect([this](int, double, double) { try { (void)CommandHelper::exec( "wpctl set-mute @DEFAULT_SINK@ toggle"); } catch (const std::exception &ex) { std::cerr << "[VolumeWidget] failed to toggle mute: " << ex.what() << std::endl; } this->update(); }); add_controller(click); update(); this->timeoutConn = Glib::signal_timeout().connect( sigc::mem_fun(*this, &VolumeWidget::on_timeout), 100); } VolumeWidget::~VolumeWidget() { if (this->timeoutConn.connected()) this->timeoutConn.disconnect(); } void VolumeWidget::update() { try { const std::string out = CommandHelper::exec("wpctl get-volume @DEFAULT_SINK@"); std::smatch m; std::regex r_percent(R"((\d+(?:\.\d+)?)%)"); std::regex r_number(R"((\d+(?:\.\d+)?))"); std::string text = out; int percent = -1; if (std::regex_search(text, m, r_percent)) { percent = static_cast(std::round(std::stod(m[1].str()))); } else if (std::regex_search(text, m, r_number)) { const double v = std::stod(m[1].str()); if (v <= 1.0) percent = static_cast(std::round(v * 100.0)); else percent = static_cast(std::round(v)); } if (percent >= 0) { label.set_text(std::to_string(percent) + "%"); } else { auto pos = text.find_first_not_of(" \t\n\r"); if (pos != std::string::npos) { auto end = text.find_last_not_of(" \t\n\r"); label.set_text(text.substr(pos, end - pos + 1)); } else { label.set_text("?"); } } } catch (const std::exception &ex) { std::cerr << "[VolumeWidget] failed to read volume: " << ex.what() << std::endl; label.set_text("N/A"); } } bool VolumeWidget::on_timeout() { update(); return true; // keep timeout active }