From 949da4e8292601d027d73fc2988efd84c1741daa Mon Sep 17 00:00:00 2001 From: Lena Date: Fri, 10 Oct 2025 20:19:27 +0200 Subject: [PATCH 01/12] create partial wwan module --- include/modules/wwan.hpp | 51 +++++ man/waybar-wwan.5.scd | 119 +++++++++++ man/waybar-wwan.scd | 111 +++++++++++ meson.build | 10 +- meson_options.txt | 1 + src/factory.cpp | 8 + src/modules/wwan.cpp | 414 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 713 insertions(+), 1 deletion(-) create mode 100644 include/modules/wwan.hpp create mode 100644 man/waybar-wwan.5.scd create mode 100644 man/waybar-wwan.scd create mode 100644 src/modules/wwan.cpp diff --git a/include/modules/wwan.hpp b/include/modules/wwan.hpp new file mode 100644 index 00000000..d1635654 --- /dev/null +++ b/include/modules/wwan.hpp @@ -0,0 +1,51 @@ +#pragma once + +#include +#include + +#include + +#include + +#include "ALabel.hpp" +#include "util/format.hpp" +#include "util/sleeper_thread.hpp" + +namespace waybar::modules { + + class Wwan : public ALabel { + public: + Wwan(const std::string&, const Json::Value&); + virtual ~Wwan(); + auto update() -> void override; + + private: + + const void updateCurrentModem(); + const MMModemState getModemState() const; + const std::string getModemStateString() const; + const std::string getModemStateFormatString() const; + const std::string getAccessTechnologiesString() const; + const int getSignalQuality() const; + const std::string getPowerStateString() const; + const std::string getImeiString() const; + + const MMModemModeCombination getCurrentModes() const; + const std::string getPreferredModeString() const; + const std::string getCurrentModesString() const; + const std::string getOperatorNameString() const; + + util::SleeperThread thread_; + std::string state_; + GDBusConnection* connection; + MMManager* manager; + MMModem* current_modem; + + bool hideDisconnected = true; + + const std::string dbus_name = "org.freedesktop.ModemManager1"; + const std::string dbus_obj_path = "/org/freedesktop/ModemManager1/"; + const std::string dbus_modems_path = "/org/freedesktop/ModemManager1/Modems/"; + }; + +} // namespace waybar::modules diff --git a/man/waybar-wwan.5.scd b/man/waybar-wwan.5.scd new file mode 100644 index 00000000..3f6e4870 --- /dev/null +++ b/man/waybar-wwan.5.scd @@ -0,0 +1,119 @@ +waybar-wwan(5) "waybar-wwan" "User Manual" + +# NAME + +waybar - wwan module + +# DESCRIPTION + +*wwan* module for ModemManager. + + +# FILES + +$XDG_CONFIG_HOME/waybar/config ++ + Per user configuration file + +# ADDITIONAL FILES + +libmm-glib lives in: + +. /usr/lib/libmm-glib.so or /usr/lib64/libmm-glib.so +. /usr/lib/pkgconfig/libgps.pc or /usr/lib64/pkgconfig/libgps.pc +. /usr/include/libmm-glib + +# CONFIGURATION + +*format*: ++ + typeof: string ++ + default: {glyph} ++ + The text format. + +*tooltip*: ++ + typeof: bool ++ + default: true ++ + Option to disable tooltip on hover. + +*tooltip-format*: ++ + typeof: string ++ + default: Games running: {glyph} ++ + The text format of the tooltip. + +*interval*: ++ + typeof: integer ++ + default: 5 ++ + The interval in which the WWAN information gets polled (e.g. carrier name). + +*hide-failed*: ++ + typeof: bool ++ + default: true ++ + Defines if the module should be hidden if the modem cannot start. + +*hide-disabled*: ++ + typeof: bool ++ + default: false ++ + Defines if the module should be hidden if the modem is disabled. + +*hide-not-registered*: ++ + typeof: bool ++ + default: false ++ + Defines if the module should be hidden if the modem isn't registered with any carrier network. + + +# FORMAT REPLACEMENTS + +*{mode}*: Fix mode + +*{status}*: Technology used for GPS fix. Not all GPS receivers report this. + +*{latitude}*: Latitude, decimal degrees. Can be NaN. + +*{latitude_error}*: Latitude uncertainty, meters. Can be NaN. + +*{longitude}*: Longitude, decimal degrees. Can be NaN. + +*{longitude_error}*: Longitude uncertainty, meters. Can be NaN. + +*{altitude_hae}*: Altitude, height above ellipsoid, meters. Can be NaN. + +*{altitude_msl}*: Longitude, MSL, meters. Can be NaN. + +*{altitude_error}*: Altitude uncertainty, meters. Can be NaN. + +*{speed}*: Speed over ground, meters/sec. Can be NaN. + +*{speed_error}*: Speed uncertainty, meters/sec. Can be NaN. + +*{climb}*: Vertical speed, meters/sec. Can be NaN. + +*{climb_error}*: Vertical speed uncertainty, meters/sec. Can be NaN. + +*{satellites_visible}*: Number of satellites visible from the GPS receiver. + +*{satellites_used}*: Number of satellites used for the GPS fix. + +# EXAMPLES + +``` +"wwan": { + "format": "{state}", + "format-disabled": "", // an empty format will hide the module + "format-locked": "SIM Locked", + "format-connected": "{operator_name} {preferred_mode}" + "tooltip-format": "{mode}", + "tooltip-format-locked": "{satellites_visible} satellites visible", + "tooltip-format-registered": "{satellites_used}/{satellites_visible} satellites used", + "tooltip-format-connected": "", + "hide-disconnected": false +} +``` +# STYLE + +- *#wwan* +- *#wwan.failed* Applied when the modem cannot start. +- *#wwan.locked* Applied when the SIM on the modem is locked. +- *#wwan.disabled* Applied when the modem is disabled. +- *#wwan.enabled* Applied when the modem is enabled, but isn't registered to any carrier network. +- *#wwan.searching* Applied when the modem is looking for a carrier network to register to. +- *#wwan.registered* Applied when the modem is registered to a network, but no data connection is active. +- *#wwan.connected* Applied when the modem is registered to a network, and there is an active data connection. diff --git a/man/waybar-wwan.scd b/man/waybar-wwan.scd new file mode 100644 index 00000000..e7473601 --- /dev/null +++ b/man/waybar-wwan.scd @@ -0,0 +1,111 @@ +waybar-gps(5) "waybar-gps" "User Manual" + +# NAME + +waybar - gps module + +# DESCRIPTION + +*gps* module for gpsd. + + +# FILES + +$XDG_CONFIG_HOME/waybar/config ++ + Per user configuration file + +# ADDITIONAL FILES + +libgps lives in: + +. /usr/lib/libgps.so or /usr/lib64/libgps.so +. /usr/lib/pkgconfig/libgps.pc or /usr/lib64/pkgconfig/libgps.pc +. /usr/include/gps + +# CONFIGURATION + +*format*: ++ + typeof: string ++ + default: {glyph} ++ + The text format. + +*tooltip*: ++ + typeof: bool ++ + default: true ++ + Option to disable tooltip on hover. + +*tooltip-format*: ++ + typeof: string ++ + default: Games running: {glyph} ++ + The text format of the tooltip. + +*interval*: ++ + typeof: integer ++ + default: 5 ++ + The interval in which the GPS information gets polled (e.g. current speed). + Significant updates (e.g. the current fix mode) are updated immediately. + +*hide-disconnected*: ++ + typeof: bool ++ + default: true ++ + Defines if the module should be hidden if there is no GPS receiver. + +*hide-no-fix*: ++ + typeof: bool ++ + default: false ++ + Defines if the module should be hidden if there is no GPS fix. + +# FORMAT REPLACEMENTS + +*{mode}*: Fix mode + +*{status}*: Technology used for GPS fix. Not all GPS receivers report this. + +*{latitude}*: Latitude, decimal degrees. Can be NaN. + +*{latitude_error}*: Latitude uncertainty, meters. Can be NaN. + +*{longitude}*: Longitude, decimal degrees. Can be NaN. + +*{longitude_error}*: Longitude uncertainty, meters. Can be NaN. + +*{altitude_hae}*: Altitude, height above ellipsoid, meters. Can be NaN. + +*{altitude_msl}*: Longitude, MSL, meters. Can be NaN. + +*{altitude_error}*: Altitude uncertainty, meters. Can be NaN. + +*{speed}*: Speed over ground, meters/sec. Can be NaN. + +*{speed_error}*: Speed uncertainty, meters/sec. Can be NaN. + +*{climb}*: Vertical speed, meters/sec. Can be NaN. + +*{climb_error}*: Vertical speed uncertainty, meters/sec. Can be NaN. + +*{satellites_visible}*: Number of satellites visible from the GPS receiver. + +*{satellites_used}*: Number of satellites used for the GPS fix. + +# EXAMPLES + +``` +"gps": { + "format": "{mode}", + "format-disabled": "", // an empty format will hide the module + "format-no-fix": "No fix", + "format-fix-3d": "{status}", + "tooltip-format": "{mode}", + "tooltip-format-no-fix": "{satellites_visible} satellites visible", + "tooltip-format-fix-2d": "{satellites_used}/{satellites_visible} satellites used", + "tooltip-format-fix-3d": "Altitude: {altitude_hae}m", + "hide-disconnected": false +} +``` +# STYLE + +- *#gps* +- *#gps.disabled* Applied when GPS is disabled. +- *#gps.fix-none* Applied when GPS is present, but there is no fix. +- *#gps.fix-2d* Applied when there is a 2D fix. +- *#gps.fix-3d* Applied when there is a 3D fix. diff --git a/meson.build b/meson.build index 5563d610..737a4199 100644 --- a/meson.build +++ b/meson.build @@ -94,6 +94,7 @@ xkbregistry = dependency('xkbregistry') libjack = dependency('jack', required: get_option('jack')) libwireplumber = dependency('wireplumber-0.5', required: get_option('wireplumber')) libgps = dependency('libgps', required: get_option('gps')) +libmm_glib = dependency('libmm-glib', required: get_option('wwan')) libsndio = compiler.find_library('sndio', required: get_option('sndio')) if libsndio.found() @@ -557,6 +558,12 @@ if libgps.found() man_files += files('man/waybar-gps.5.scd') endif +if libmm_glib.found() + add_project_arguments('-DHAVE_LIBMM_GLIB', language: 'cpp') + src_files += files('src/modules/wwan.cpp') + #man_files += files('man/waybar-wwan.5.scd') +endif + subdir('protocol') app_resources = [] @@ -598,7 +605,8 @@ executable( xkbregistry, cava, eproxy, - libgps + libgps, + libmm_glib ], include_directories: inc_dirs, install: true, diff --git a/meson_options.txt b/meson_options.txt index 278fdd02..139ed6cb 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -23,3 +23,4 @@ option('niri', type: 'boolean', description: 'Enable support for niri') option('mango', type: 'boolean', description: 'Enable support for mango') option('login-proxy', type: 'boolean', description: 'Enable interfacing with dbus login interface') option('gps', type: 'feature', value: 'auto', description: 'Enable support for gps') +option('wwan', type: 'feature', value: 'auto', description: 'Enable support for WWAN') diff --git a/src/factory.cpp b/src/factory.cpp index 6969da6b..096729ac 100644 --- a/src/factory.cpp +++ b/src/factory.cpp @@ -123,6 +123,9 @@ #include "modules/gps.hpp" #endif #include "modules/cava/cava_frontend.hpp" +#ifdef HAVE_LIBMM_GLIB +#include "modules/wwan.hpp" +#endif #include "modules/cffi.hpp" #include "modules/custom.hpp" #include "modules/custom_graph.hpp" @@ -380,6 +383,11 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name, if (ref == "gps") { return new waybar::modules::Gps(id, config_[name]); } +#endif +#ifdef HAVE_LIBMM_GLIB + if (ref == "wwan") { + return new waybar::modules::Wwan(id, config_[name]); + } #endif if (ref == "temperature") { return new waybar::modules::Temperature(id, config_[name]); diff --git a/src/modules/wwan.cpp b/src/modules/wwan.cpp new file mode 100644 index 00000000..f829df17 --- /dev/null +++ b/src/modules/wwan.cpp @@ -0,0 +1,414 @@ +#include "modules/wwan.hpp" +#include + +#include +#include +#include "ModemManager.h" +#include "libmm-glib.h" + +// In the 80000 version of fmt library authors decided to optimize imports +// and moved declarations required for fmt::dynamic_format_arg_store in new +// header fmt/args.h +#if (FMT_VERSION >= 80000) +#include +#else +#include +#endif + +namespace { + using namespace waybar::util; + constexpr const char *DEFAULT_FORMAT = "{state}"; +} // namespace + + +waybar::modules::Wwan::Wwan(const std::string& id, const Json::Value& config) +: ALabel(config, "wwan", id, "{}", 5) { + thread_ = [this] { + dp.emit(); + thread_.sleep_for(interval_); + }; + + GError* error = nullptr; + connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &error); + if (error) { + g_error_free(error); + return; + } + + + manager = mm_manager_new_sync( + connection, + G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, + nullptr, // cancellable + &error + ); + + if (error) { + spdlog::error("Failed to create ModemManager proxy: " + std::string(error->message)); + g_error_free(error); + g_object_unref(connection); + return; + } + + updateCurrentModem(); + + + if (config_["hide-disconnected"].isBool()) { + hideDisconnected = config_["hide-disconnected"].asBool(); + } + +} + +const void waybar::modules::Wwan::updateCurrentModem(){ + // get 1st modem (or modem with the specified hardware path) + + GList* modems = g_dbus_object_manager_get_objects(G_DBUS_OBJECT_MANAGER(manager)); + if (!modems) { + spdlog::warn("No modems found"); + g_object_unref(manager); + g_object_unref(connection); + return; + } + + for (GList* m = modems; m; m = g_list_next(m)) { + MMObject* modem_obj = MM_OBJECT(m->data); + + MMModem* modem = mm_object_get_modem(modem_obj); + + if (config_["path"].isString()) { + std::string path = config_["path"].asString(); + std::string other = mm_modem_dup_path(modem); + + if(path != other) { + g_object_unref(modem); + continue; + } + } + + if (config_["imei"].isString()) { + std::string imei = config_["imei"].asString(); + std::string other = mm_modem_dup_equipment_identifier(modem); + + if(imei != other) { + g_object_unref(modem); + continue; + } + } + + current_modem = modem; + g_list_free_full(modems, g_object_unref); + return; +} +// no modems found +g_list_free_full(modems, g_object_unref); +} + +const MMModemState waybar::modules::Wwan::getModemState() const { + if(current_modem == nullptr) { + return MMModemState::MM_MODEM_STATE_UNKNOWN; + } + return mm_modem_get_state(current_modem); +} + +const std::string waybar::modules::Wwan::getModemStateString() const { + switch (getModemState()) { + case MMModemState::MM_MODEM_STATE_FAILED: + return "Failed"; + case MMModemState::MM_MODEM_STATE_INITIALIZING: + return "Initializing"; + case MMModemState::MM_MODEM_STATE_LOCKED: + return "Locked"; + case MMModemState::MM_MODEM_STATE_DISABLED: + return "Disabled"; + case MMModemState::MM_MODEM_STATE_DISABLING: + return "Disabling"; + case MMModemState::MM_MODEM_STATE_ENABLED: + return "Enabled"; + case MMModemState::MM_MODEM_STATE_ENABLING: + return "Enabling"; + case MMModemState::MM_MODEM_STATE_SEARCHING: + return "Searching"; + case MMModemState::MM_MODEM_STATE_REGISTERED: + return "Registered"; + case MMModemState::MM_MODEM_STATE_DISCONNECTING: + return "Disconnecting"; + case MMModemState::MM_MODEM_STATE_CONNECTING: + return "Connecting"; + case MMModemState::MM_MODEM_STATE_CONNECTED: + return "Connected"; + default: + return "Unknown"; + } +} + +const std::string waybar::modules::Wwan::getModemStateFormatString() const { + switch (getModemState()) { + case MMModemState::MM_MODEM_STATE_FAILED: + return "failed"; + case MMModemState::MM_MODEM_STATE_LOCKED: + return "locked"; + case MMModemState::MM_MODEM_STATE_DISABLED: + return "disabled"; + case MMModemState::MM_MODEM_STATE_ENABLED: + return "enabled"; + case MMModemState::MM_MODEM_STATE_SEARCHING: + return "searching"; + case MMModemState::MM_MODEM_STATE_REGISTERED: + return "registered"; + case MMModemState::MM_MODEM_STATE_CONNECTED: + return "connected"; + default: + return ""; + } +} + +const int waybar::modules::Wwan::getSignalQuality() const { + if(current_modem == nullptr) { + return MMModemState::MM_MODEM_STATE_UNKNOWN; + } + + gboolean recent; + + return mm_modem_get_signal_quality(current_modem, &recent); +} + +const std::string stringifyAccessTechnologies(MMModemAccessTechnology technologies) { + std::string buffer; + + if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_POTS) + buffer += "POTS, "; + if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_GSM) + buffer += "GSM, "; + if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_GSM_COMPACT) + buffer += "GSM Compact, "; + if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_GPRS) + buffer += "GPRS, "; + if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_EDGE) + buffer += "EDGE, "; + if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_UMTS) + buffer += "UMTS, "; + if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_HSDPA) + buffer += "HSDPA, "; + if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_HSUPA) + buffer += "HSUPA, "; + if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_HSPA) + buffer += "HSPA, "; + if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_HSPA_PLUS) + buffer += "HSPA+, "; + if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_1XRTT) + buffer += "1xRTT, "; + if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_EVDO0) + buffer += "EVDO0, "; + if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_EVDOA) + buffer += "EVDOA, "; + if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_EVDOB) + buffer += "EVDOB, "; + if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_LTE) + buffer += "LTE, "; + if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_5GNR) + buffer += "5GNR, "; + if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_LTE_CAT_M) + buffer += "LTE CAT-M, "; + if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_LTE_NB_IOT) + buffer += "LTE NB-IoT, "; + + if (buffer.length() > 2) { + buffer.erase(buffer.length()-2); + } + return buffer; + +} + +const std::string stringifyModemMode(MMModemMode mmode){ + + switch (mmode) { + case MM_MODEM_MODE_CS: + return "CS"; + case MM_MODEM_MODE_2G: + return "2G"; + case MM_MODEM_MODE_3G: + return "3G"; + case MM_MODEM_MODE_4G: + return "4G"; + case MM_MODEM_MODE_5G: + return "5G"; + default: + return "No Service"; + } +} + +const std::string waybar::modules::Wwan::getAccessTechnologiesString() const { + + if(current_modem == nullptr) { + return ""; + } + + MMModemAccessTechnology technologies = mm_modem_get_access_technologies(current_modem); + + return stringifyAccessTechnologies(technologies); +} + +const MMModemModeCombination waybar::modules::Wwan::getCurrentModes() const { + + MMModemModeCombination combination; + + mm_modem_get_current_modes(current_modem, &combination.allowed, &combination.preferred); + + return combination; +} + +const std::string waybar::modules::Wwan::getPreferredModeString() const { + + if(current_modem == nullptr) { + return ""; + } + + MMModemModeCombination combination = getCurrentModes(); + + return stringifyModemMode(combination.preferred); +} + + +const std::string waybar::modules::Wwan::getCurrentModesString() const { + + if(current_modem == nullptr) { + return ""; + } + + MMModemModeCombination combination = getCurrentModes(); + + // TODO: fix + return stringifyModemMode(combination.allowed); +} + +const std::string waybar::modules::Wwan::getPowerStateString() const { + + if(current_modem == nullptr) { + return ""; + } + + MMModemPowerState state = mm_modem_get_power_state(current_modem); + + switch (state) { + case MM_MODEM_POWER_STATE_ON: + return "On"; + case MM_MODEM_POWER_STATE_OFF: + return "Off"; + case MM_MODEM_POWER_STATE_LOW: + return "Low"; + default: + return "Unknown"; + } +} + +const std::string waybar::modules::Wwan::getImeiString() const { + + if(current_modem == nullptr) { + return ""; + } + + return mm_modem_dup_equipment_identifier(current_modem); +} + +const std::string waybar::modules::Wwan::getOperatorNameString() const { + + if(current_modem == nullptr) { + return ""; + } + + MMSim* sim = mm_modem_get_sim_sync(current_modem, nullptr, nullptr); + + if (sim == nullptr) { + return "No SIM"; + } + + std::string name = mm_sim_dup_operator_name(sim); + g_object_unref(sim); + return name; +} + +auto waybar::modules::Wwan::update() -> void { + + if (current_modem == nullptr) { + event_box_.set_visible(false); + updateCurrentModem(); + return; + } + + if (hideDisconnected) { + event_box_.set_visible(false); + + return; + } + + // Show the module + if (!event_box_.get_visible()) event_box_.set_visible(true); + + std::string tooltip_format; + + if (!alt_) { + std::string state = getModemStateFormatString(); + if (!state_.empty() && label_.get_style_context()->has_class(state_)) { + label_.get_style_context()->remove_class(state_); + } + if (config_["format-" + state].isString()) { + default_format_ = config_["format-" + state].asString(); + } else if (config_["format"].isString()) { + default_format_ = config_["format"].asString(); + } else { + default_format_ = DEFAULT_FORMAT; + } + if (config_["tooltip-format-" + state].isString()) { + tooltip_format = config_["tooltip-format-" + state].asString(); + } + if (!label_.get_style_context()->has_class(state)) { + label_.get_style_context()->add_class(state); + } + format_ = default_format_; + state_ = state; + } + + + auto format = format_; + + fmt::dynamic_format_arg_store store; + store.push_back(fmt::arg("state", getModemStateString())); + + store.push_back(fmt::arg("access_technologies", getAccessTechnologiesString())); + + store.push_back(fmt::arg("current_modes", getCurrentModesString())); + store.push_back(fmt::arg("preferred_mode", getPreferredModeString())); + //store.push_back(fmt::arg("supported_modes", getSupportedModesString())); + + //store.push_back(fmt::arg("current_bands", getCurrentBandsString())); + //store.push_back(fmt::arg("supported_bands", getSupportedBandsString())); + + store.push_back(fmt::arg("signal_quality", getSignalQuality())); + store.push_back(fmt::arg("power_state", getPowerStateString())); + store.push_back(fmt::arg("imei", getImeiString())); + + store.push_back(fmt::arg("operator_name", getOperatorNameString())); + //store.push_back(fmt::arg("registration_state", getRegistrationStateString())); + + auto text = fmt::vformat(format, store); + + if (tooltipEnabled()) { + if (tooltip_format.empty() && config_["tooltip-format"].isString()) { + tooltip_format = config_["tooltip-format"].asString(); + } + if (!tooltip_format.empty()) { + auto tooltip_text = fmt::vformat(tooltip_format, store); + if (label_.get_tooltip_text() != tooltip_text) { + label_.set_tooltip_markup(tooltip_text); + } + } else if (label_.get_tooltip_text() != text) { + label_.set_tooltip_markup(text); + } + } + label_.set_markup(text); + // Call parent update + ALabel::update(); +} + +waybar::modules::Wwan::~Wwan() { +} From 90a0f46e37f7a659f02775c8db1b4f7e820a998d Mon Sep 17 00:00:00 2001 From: Lena Date: Sat, 11 Oct 2025 15:27:56 +0200 Subject: [PATCH 02/12] almost done --- include/modules/wwan.hpp | 12 ---- man/waybar-wwan.5.scd | 34 +++++---- man/waybar-wwan.scd | 111 ----------------------------- src/modules/wwan.cpp | 148 +++++++++++++-------------------------- 4 files changed, 69 insertions(+), 236 deletions(-) delete mode 100644 man/waybar-wwan.scd diff --git a/include/modules/wwan.hpp b/include/modules/wwan.hpp index d1635654..0cbb5d8d 100644 --- a/include/modules/wwan.hpp +++ b/include/modules/wwan.hpp @@ -22,18 +22,6 @@ namespace waybar::modules { private: const void updateCurrentModem(); - const MMModemState getModemState() const; - const std::string getModemStateString() const; - const std::string getModemStateFormatString() const; - const std::string getAccessTechnologiesString() const; - const int getSignalQuality() const; - const std::string getPowerStateString() const; - const std::string getImeiString() const; - - const MMModemModeCombination getCurrentModes() const; - const std::string getPreferredModeString() const; - const std::string getCurrentModesString() const; - const std::string getOperatorNameString() const; util::SleeperThread thread_; std::string state_; diff --git a/man/waybar-wwan.5.scd b/man/waybar-wwan.5.scd index 3f6e4870..74eda493 100644 --- a/man/waybar-wwan.5.scd +++ b/man/waybar-wwan.5.scd @@ -19,7 +19,7 @@ $XDG_CONFIG_HOME/waybar/config ++ libmm-glib lives in: . /usr/lib/libmm-glib.so or /usr/lib64/libmm-glib.so -. /usr/lib/pkgconfig/libgps.pc or /usr/lib64/pkgconfig/libgps.pc +. /usr/lib/pkgconfig/libmm-glib.pc or /usr/lib64/pkgconfig/libmm-glib.pc . /usr/include/libmm-glib # CONFIGURATION @@ -35,7 +35,7 @@ libmm-glib lives in: Option to disable tooltip on hover. *tooltip-format*: ++ - typeof: string ++ + typeof: strirng ++ default: Games running: {glyph} ++ The text format of the tooltip. @@ -44,6 +44,16 @@ libmm-glib lives in: default: 5 ++ The interval in which the WWAN information gets polled (e.g. carrier name). +*imei*: ++ + typeof: string ++ + default: {glyph} ++ + Select only the modem with the corresponding imei. + +*path*: ++ + typeof: string ++ + default: {glyph} ++ + Select only the modem with the corresponding hardware path. + *hide-failed*: ++ typeof: bool ++ default: true ++ @@ -62,25 +72,23 @@ libmm-glib lives in: # FORMAT REPLACEMENTS -*{mode}*: Fix mode +*{state}*: Modem state. -*{status}*: Technology used for GPS fix. Not all GPS receivers report this. +*{access_technologies}*: List of all the supported access technologies. -*{latitude}*: Latitude, decimal degrees. Can be NaN. +*{current_modes}*: List of all the currently active connection modes. -*{latitude_error}*: Latitude uncertainty, meters. Can be NaN. +*{preferred_mode}*: The preferred connection mode in use. -*{longitude}*: Longitude, decimal degrees. Can be NaN. +*{supported_modes}*: List of all the supported connection modes. -*{longitude_error}*: Longitude uncertainty, meters. Can be NaN. +*{current_bands}*: List of all the currently active frequency bands. -*{altitude_hae}*: Altitude, height above ellipsoid, meters. Can be NaN. +*{supported_bands}*: List of all the supported frequency bands. -*{altitude_msl}*: Longitude, MSL, meters. Can be NaN. +*{signal_quality}*: Signal quality (0-100). -*{altitude_error}*: Altitude uncertainty, meters. Can be NaN. - -*{speed}*: Speed over ground, meters/sec. Can be NaN. +*{operator_name}*: Name of the network operator. *{speed_error}*: Speed uncertainty, meters/sec. Can be NaN. diff --git a/man/waybar-wwan.scd b/man/waybar-wwan.scd deleted file mode 100644 index e7473601..00000000 --- a/man/waybar-wwan.scd +++ /dev/null @@ -1,111 +0,0 @@ -waybar-gps(5) "waybar-gps" "User Manual" - -# NAME - -waybar - gps module - -# DESCRIPTION - -*gps* module for gpsd. - - -# FILES - -$XDG_CONFIG_HOME/waybar/config ++ - Per user configuration file - -# ADDITIONAL FILES - -libgps lives in: - -. /usr/lib/libgps.so or /usr/lib64/libgps.so -. /usr/lib/pkgconfig/libgps.pc or /usr/lib64/pkgconfig/libgps.pc -. /usr/include/gps - -# CONFIGURATION - -*format*: ++ - typeof: string ++ - default: {glyph} ++ - The text format. - -*tooltip*: ++ - typeof: bool ++ - default: true ++ - Option to disable tooltip on hover. - -*tooltip-format*: ++ - typeof: string ++ - default: Games running: {glyph} ++ - The text format of the tooltip. - -*interval*: ++ - typeof: integer ++ - default: 5 ++ - The interval in which the GPS information gets polled (e.g. current speed). - Significant updates (e.g. the current fix mode) are updated immediately. - -*hide-disconnected*: ++ - typeof: bool ++ - default: true ++ - Defines if the module should be hidden if there is no GPS receiver. - -*hide-no-fix*: ++ - typeof: bool ++ - default: false ++ - Defines if the module should be hidden if there is no GPS fix. - -# FORMAT REPLACEMENTS - -*{mode}*: Fix mode - -*{status}*: Technology used for GPS fix. Not all GPS receivers report this. - -*{latitude}*: Latitude, decimal degrees. Can be NaN. - -*{latitude_error}*: Latitude uncertainty, meters. Can be NaN. - -*{longitude}*: Longitude, decimal degrees. Can be NaN. - -*{longitude_error}*: Longitude uncertainty, meters. Can be NaN. - -*{altitude_hae}*: Altitude, height above ellipsoid, meters. Can be NaN. - -*{altitude_msl}*: Longitude, MSL, meters. Can be NaN. - -*{altitude_error}*: Altitude uncertainty, meters. Can be NaN. - -*{speed}*: Speed over ground, meters/sec. Can be NaN. - -*{speed_error}*: Speed uncertainty, meters/sec. Can be NaN. - -*{climb}*: Vertical speed, meters/sec. Can be NaN. - -*{climb_error}*: Vertical speed uncertainty, meters/sec. Can be NaN. - -*{satellites_visible}*: Number of satellites visible from the GPS receiver. - -*{satellites_used}*: Number of satellites used for the GPS fix. - -# EXAMPLES - -``` -"gps": { - "format": "{mode}", - "format-disabled": "", // an empty format will hide the module - "format-no-fix": "No fix", - "format-fix-3d": "{status}", - "tooltip-format": "{mode}", - "tooltip-format-no-fix": "{satellites_visible} satellites visible", - "tooltip-format-fix-2d": "{satellites_used}/{satellites_visible} satellites used", - "tooltip-format-fix-3d": "Altitude: {altitude_hae}m", - "hide-disconnected": false -} -``` -# STYLE - -- *#gps* -- *#gps.disabled* Applied when GPS is disabled. -- *#gps.fix-none* Applied when GPS is present, but there is no fix. -- *#gps.fix-2d* Applied when there is a 2D fix. -- *#gps.fix-3d* Applied when there is a 3D fix. diff --git a/src/modules/wwan.cpp b/src/modules/wwan.cpp index f829df17..522b2e9c 100644 --- a/src/modules/wwan.cpp +++ b/src/modules/wwan.cpp @@ -52,7 +52,6 @@ waybar::modules::Wwan::Wwan(const std::string& id, const Json::Value& config) updateCurrentModem(); - if (config_["hide-disconnected"].isBool()) { hideDisconnected = config_["hide-disconnected"].asBool(); } @@ -64,9 +63,6 @@ const void waybar::modules::Wwan::updateCurrentModem(){ GList* modems = g_dbus_object_manager_get_objects(G_DBUS_OBJECT_MANAGER(manager)); if (!modems) { - spdlog::warn("No modems found"); - g_object_unref(manager); - g_object_unref(connection); return; } @@ -77,10 +73,11 @@ const void waybar::modules::Wwan::updateCurrentModem(){ if (config_["path"].isString()) { std::string path = config_["path"].asString(); - std::string other = mm_modem_dup_path(modem); + std::string other = mm_modem_dup_physdev(modem); if(path != other) { g_object_unref(modem); + modem = nullptr; continue; } } @@ -91,6 +88,7 @@ const void waybar::modules::Wwan::updateCurrentModem(){ if(imei != other) { g_object_unref(modem); + modem = nullptr; continue; } } @@ -98,51 +96,45 @@ const void waybar::modules::Wwan::updateCurrentModem(){ current_modem = modem; g_list_free_full(modems, g_object_unref); return; -} -// no modems found -g_list_free_full(modems, g_object_unref); -} - -const MMModemState waybar::modules::Wwan::getModemState() const { - if(current_modem == nullptr) { - return MMModemState::MM_MODEM_STATE_UNKNOWN; } - return mm_modem_get_state(current_modem); + // no modems found + current_modem = nullptr; + g_list_free_full(modems, g_object_unref); } -const std::string waybar::modules::Wwan::getModemStateString() const { - switch (getModemState()) { +const std::string getModemStateString(MMModem* modem) { + switch (mm_modem_get_state(modem)) { case MMModemState::MM_MODEM_STATE_FAILED: - return "Failed"; + return "Failed"; case MMModemState::MM_MODEM_STATE_INITIALIZING: - return "Initializing"; + return "Initializing"; case MMModemState::MM_MODEM_STATE_LOCKED: - return "Locked"; + return "Locked"; case MMModemState::MM_MODEM_STATE_DISABLED: - return "Disabled"; + return "Disabled"; case MMModemState::MM_MODEM_STATE_DISABLING: - return "Disabling"; + return "Disabling"; case MMModemState::MM_MODEM_STATE_ENABLED: - return "Enabled"; + return "Enabled"; case MMModemState::MM_MODEM_STATE_ENABLING: - return "Enabling"; + return "Enabling"; case MMModemState::MM_MODEM_STATE_SEARCHING: - return "Searching"; + return "Searching"; case MMModemState::MM_MODEM_STATE_REGISTERED: - return "Registered"; + return "Registered"; case MMModemState::MM_MODEM_STATE_DISCONNECTING: - return "Disconnecting"; + return "Disconnecting"; case MMModemState::MM_MODEM_STATE_CONNECTING: - return "Connecting"; + return "Connecting"; case MMModemState::MM_MODEM_STATE_CONNECTED: - return "Connected"; + return "Connected"; default: - return "Unknown"; + return "Unknown"; } } -const std::string waybar::modules::Wwan::getModemStateFormatString() const { - switch (getModemState()) { +const std::string getModemStateFormatString(MMModem* modem) { + switch (mm_modem_get_state(modem)) { case MMModemState::MM_MODEM_STATE_FAILED: return "failed"; case MMModemState::MM_MODEM_STATE_LOCKED: @@ -162,17 +154,9 @@ const std::string waybar::modules::Wwan::getModemStateFormatString() const { } } -const int waybar::modules::Wwan::getSignalQuality() const { - if(current_modem == nullptr) { - return MMModemState::MM_MODEM_STATE_UNKNOWN; - } +const std::string getAccessTechnologiesString(MMModem* modem) { + MMModemAccessTechnology technologies = mm_modem_get_access_technologies(modem); - gboolean recent; - - return mm_modem_get_signal_quality(current_modem, &recent); -} - -const std::string stringifyAccessTechnologies(MMModemAccessTechnology technologies) { std::string buffer; if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_POTS) @@ -219,7 +203,7 @@ const std::string stringifyAccessTechnologies(MMModemAccessTechnology technologi } -const std::string stringifyModemMode(MMModemMode mmode){ +const std::string stringifyModemMode(MMModemMode mmode) { switch (mmode) { case MM_MODEM_MODE_CS: @@ -237,57 +221,33 @@ const std::string stringifyModemMode(MMModemMode mmode){ } } -const std::string waybar::modules::Wwan::getAccessTechnologiesString() const { - - if(current_modem == nullptr) { - return ""; - } - - MMModemAccessTechnology technologies = mm_modem_get_access_technologies(current_modem); - - return stringifyAccessTechnologies(technologies); -} - -const MMModemModeCombination waybar::modules::Wwan::getCurrentModes() const { +const MMModemModeCombination getCurrentModes(MMModem* modem) { MMModemModeCombination combination; - mm_modem_get_current_modes(current_modem, &combination.allowed, &combination.preferred); + mm_modem_get_current_modes(modem, &combination.allowed, &combination.preferred); return combination; } -const std::string waybar::modules::Wwan::getPreferredModeString() const { +const std::string getPreferredModeString(MMModem* modem) { - if(current_modem == nullptr) { - return ""; - } - - MMModemModeCombination combination = getCurrentModes(); + MMModemModeCombination combination = getCurrentModes(modem); return stringifyModemMode(combination.preferred); } -const std::string waybar::modules::Wwan::getCurrentModesString() const { +const std::string getCurrentModesString(MMModem* modem) { - if(current_modem == nullptr) { - return ""; - } - - MMModemModeCombination combination = getCurrentModes(); + MMModemModeCombination combination = getCurrentModes(modem); // TODO: fix return stringifyModemMode(combination.allowed); } -const std::string waybar::modules::Wwan::getPowerStateString() const { - - if(current_modem == nullptr) { - return ""; - } - - MMModemPowerState state = mm_modem_get_power_state(current_modem); +const std::string getPowerStateString(MMModem* modem) { + MMModemPowerState state = mm_modem_get_power_state(modem); switch (state) { case MM_MODEM_POWER_STATE_ON: @@ -301,22 +261,9 @@ const std::string waybar::modules::Wwan::getPowerStateString() const { } } -const std::string waybar::modules::Wwan::getImeiString() const { +const std::string getOperatorNameString(MMModem* modem) { - if(current_modem == nullptr) { - return ""; - } - - return mm_modem_dup_equipment_identifier(current_modem); -} - -const std::string waybar::modules::Wwan::getOperatorNameString() const { - - if(current_modem == nullptr) { - return ""; - } - - MMSim* sim = mm_modem_get_sim_sync(current_modem, nullptr, nullptr); + MMSim* sim = mm_modem_get_sim_sync(modem, nullptr, nullptr); if (sim == nullptr) { return "No SIM"; @@ -328,7 +275,6 @@ const std::string waybar::modules::Wwan::getOperatorNameString() const { } auto waybar::modules::Wwan::update() -> void { - if (current_modem == nullptr) { event_box_.set_visible(false); updateCurrentModem(); @@ -347,7 +293,7 @@ auto waybar::modules::Wwan::update() -> void { std::string tooltip_format; if (!alt_) { - std::string state = getModemStateFormatString(); + std::string state = getModemStateFormatString(current_modem); if (!state_.empty() && label_.get_style_context()->has_class(state_)) { label_.get_style_context()->remove_class(state_); } @@ -372,23 +318,22 @@ auto waybar::modules::Wwan::update() -> void { auto format = format_; fmt::dynamic_format_arg_store store; - store.push_back(fmt::arg("state", getModemStateString())); + store.push_back(fmt::arg("state", getModemStateString(current_modem))); - store.push_back(fmt::arg("access_technologies", getAccessTechnologiesString())); + store.push_back(fmt::arg("access_technologies", getAccessTechnologiesString(current_modem))); - store.push_back(fmt::arg("current_modes", getCurrentModesString())); - store.push_back(fmt::arg("preferred_mode", getPreferredModeString())); + store.push_back(fmt::arg("current_modes", getCurrentModesString(current_modem))); + store.push_back(fmt::arg("preferred_mode", getPreferredModeString(current_modem))); //store.push_back(fmt::arg("supported_modes", getSupportedModesString())); //store.push_back(fmt::arg("current_bands", getCurrentBandsString())); //store.push_back(fmt::arg("supported_bands", getSupportedBandsString())); - store.push_back(fmt::arg("signal_quality", getSignalQuality())); - store.push_back(fmt::arg("power_state", getPowerStateString())); - store.push_back(fmt::arg("imei", getImeiString())); + store.push_back(fmt::arg("signal_quality", mm_modem_get_signal_quality(current_modem, nullptr))); + store.push_back(fmt::arg("power_state", getPowerStateString(current_modem))); + store.push_back(fmt::arg("imei", mm_modem_dup_equipment_identifier(current_modem))); - store.push_back(fmt::arg("operator_name", getOperatorNameString())); - //store.push_back(fmt::arg("registration_state", getRegistrationStateString())); + store.push_back(fmt::arg("operator_name", getOperatorNameString(current_modem))); auto text = fmt::vformat(format, store); @@ -411,4 +356,7 @@ auto waybar::modules::Wwan::update() -> void { } waybar::modules::Wwan::~Wwan() { + g_object_unref(current_modem); + g_object_unref(manager); + g_object_unref(connection); } From fa5abc37f6c4ac5a1a5ef1c465cb12c7796446ad Mon Sep 17 00:00:00 2001 From: Lena Date: Sat, 11 Oct 2025 15:51:12 +0200 Subject: [PATCH 03/12] remove useless junk --- man/waybar-wwan.5.scd | 18 ------- src/modules/wwan.cpp | 108 +++++++++++------------------------------- 2 files changed, 28 insertions(+), 98 deletions(-) diff --git a/man/waybar-wwan.5.scd b/man/waybar-wwan.5.scd index 74eda493..4363911b 100644 --- a/man/waybar-wwan.5.scd +++ b/man/waybar-wwan.5.scd @@ -74,32 +74,14 @@ libmm-glib lives in: *{state}*: Modem state. -*{access_technologies}*: List of all the supported access technologies. - *{current_modes}*: List of all the currently active connection modes. *{preferred_mode}*: The preferred connection mode in use. -*{supported_modes}*: List of all the supported connection modes. - -*{current_bands}*: List of all the currently active frequency bands. - -*{supported_bands}*: List of all the supported frequency bands. - *{signal_quality}*: Signal quality (0-100). *{operator_name}*: Name of the network operator. -*{speed_error}*: Speed uncertainty, meters/sec. Can be NaN. - -*{climb}*: Vertical speed, meters/sec. Can be NaN. - -*{climb_error}*: Vertical speed uncertainty, meters/sec. Can be NaN. - -*{satellites_visible}*: Number of satellites visible from the GPS receiver. - -*{satellites_used}*: Number of satellites used for the GPS fix. - # EXAMPLES ``` diff --git a/src/modules/wwan.cpp b/src/modules/wwan.cpp index 522b2e9c..93fca11a 100644 --- a/src/modules/wwan.cpp +++ b/src/modules/wwan.cpp @@ -154,96 +154,50 @@ const std::string getModemStateFormatString(MMModem* modem) { } } -const std::string getAccessTechnologiesString(MMModem* modem) { - MMModemAccessTechnology technologies = mm_modem_get_access_technologies(modem); +const std::string getPreferredModeString(MMModem* modem) { - std::string buffer; + MMModemModeCombination combination; + mm_modem_get_current_modes(modem, &combination.allowed, &combination.preferred); - if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_POTS) - buffer += "POTS, "; - if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_GSM) - buffer += "GSM, "; - if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_GSM_COMPACT) - buffer += "GSM Compact, "; - if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_GPRS) - buffer += "GPRS, "; - if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_EDGE) - buffer += "EDGE, "; - if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_UMTS) - buffer += "UMTS, "; - if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_HSDPA) - buffer += "HSDPA, "; - if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_HSUPA) - buffer += "HSUPA, "; - if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_HSPA) - buffer += "HSPA, "; - if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_HSPA_PLUS) - buffer += "HSPA+, "; - if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_1XRTT) - buffer += "1xRTT, "; - if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_EVDO0) - buffer += "EVDO0, "; - if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_EVDOA) - buffer += "EVDOA, "; - if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_EVDOB) - buffer += "EVDOB, "; - if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_LTE) - buffer += "LTE, "; - if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_5GNR) - buffer += "5GNR, "; - if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_LTE_CAT_M) - buffer += "LTE CAT-M, "; - if(technologies & MMModemAccessTechnology::MM_MODEM_ACCESS_TECHNOLOGY_LTE_NB_IOT) - buffer += "LTE NB-IoT, "; - - if (buffer.length() > 2) { - buffer.erase(buffer.length()-2); - } - return buffer; - -} - -const std::string stringifyModemMode(MMModemMode mmode) { - - switch (mmode) { - case MM_MODEM_MODE_CS: + switch (combination.preferred) { + case MMModemMode::MM_MODEM_MODE_CS: return "CS"; - case MM_MODEM_MODE_2G: + case MMModemMode::MM_MODEM_MODE_2G: return "2G"; - case MM_MODEM_MODE_3G: + case MMModemMode::MM_MODEM_MODE_3G: return "3G"; - case MM_MODEM_MODE_4G: + case MMModemMode::MM_MODEM_MODE_4G: return "4G"; - case MM_MODEM_MODE_5G: + case MMModemMode::MM_MODEM_MODE_5G: return "5G"; default: return "No Service"; } } -const MMModemModeCombination getCurrentModes(MMModem* modem) { - - MMModemModeCombination combination; - - mm_modem_get_current_modes(modem, &combination.allowed, &combination.preferred); - - return combination; -} - -const std::string getPreferredModeString(MMModem* modem) { - - MMModemModeCombination combination = getCurrentModes(modem); - - return stringifyModemMode(combination.preferred); -} - const std::string getCurrentModesString(MMModem* modem) { - MMModemModeCombination combination = getCurrentModes(modem); + MMModemModeCombination combination; + mm_modem_get_current_modes(modem, &combination.allowed, &combination.preferred); - // TODO: fix - return stringifyModemMode(combination.allowed); + std::string buffer; + + if(combination.allowed & MMModemMode::MM_MODEM_MODE_CS) + buffer += "CS | "; + if(combination.allowed & MMModemMode::MM_MODEM_MODE_2G) + buffer += "2G | "; + if(combination.allowed & MMModemMode::MM_MODEM_MODE_3G) + buffer += "3G | "; + if(combination.allowed & MMModemMode::MM_MODEM_MODE_4G) + buffer += "4G | "; + if(combination.allowed & MMModemMode::MM_MODEM_MODE_5G) + buffer += "5G | "; + + if (buffer.length() > 2) { + buffer.erase(buffer.length()-2); + } + return buffer; } const std::string getPowerStateString(MMModem* modem) { @@ -320,14 +274,8 @@ auto waybar::modules::Wwan::update() -> void { fmt::dynamic_format_arg_store store; store.push_back(fmt::arg("state", getModemStateString(current_modem))); - store.push_back(fmt::arg("access_technologies", getAccessTechnologiesString(current_modem))); - store.push_back(fmt::arg("current_modes", getCurrentModesString(current_modem))); store.push_back(fmt::arg("preferred_mode", getPreferredModeString(current_modem))); - //store.push_back(fmt::arg("supported_modes", getSupportedModesString())); - - //store.push_back(fmt::arg("current_bands", getCurrentBandsString())); - //store.push_back(fmt::arg("supported_bands", getSupportedBandsString())); store.push_back(fmt::arg("signal_quality", mm_modem_get_signal_quality(current_modem, nullptr))); store.push_back(fmt::arg("power_state", getPowerStateString(current_modem))); From 7e65b091f25c54619e9900eae25450bdea333e47 Mon Sep 17 00:00:00 2001 From: Lena Date: Sat, 11 Oct 2025 15:57:45 +0200 Subject: [PATCH 04/12] cleanup --- src/modules/wwan.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/modules/wwan.cpp b/src/modules/wwan.cpp index 93fca11a..7cb8ba8b 100644 --- a/src/modules/wwan.cpp +++ b/src/modules/wwan.cpp @@ -58,7 +58,7 @@ waybar::modules::Wwan::Wwan(const std::string& id, const Json::Value& config) } -const void waybar::modules::Wwan::updateCurrentModem(){ +void waybar::modules::Wwan::updateCurrentModem(){ // get 1st modem (or modem with the specified hardware path) GList* modems = g_dbus_object_manager_get_objects(G_DBUS_OBJECT_MANAGER(manager)); @@ -102,7 +102,7 @@ const void waybar::modules::Wwan::updateCurrentModem(){ g_list_free_full(modems, g_object_unref); } -const std::string getModemStateString(MMModem* modem) { +std::string getModemStateString(MMModem* modem) { switch (mm_modem_get_state(modem)) { case MMModemState::MM_MODEM_STATE_FAILED: return "Failed"; @@ -133,7 +133,7 @@ const std::string getModemStateString(MMModem* modem) { } } -const std::string getModemStateFormatString(MMModem* modem) { +std::string getModemStateFormatString(MMModem* modem) { switch (mm_modem_get_state(modem)) { case MMModemState::MM_MODEM_STATE_FAILED: return "failed"; @@ -154,7 +154,7 @@ const std::string getModemStateFormatString(MMModem* modem) { } } -const std::string getPreferredModeString(MMModem* modem) { +std::string getPreferredModeString(MMModem* modem) { MMModemModeCombination combination; mm_modem_get_current_modes(modem, &combination.allowed, &combination.preferred); @@ -176,7 +176,7 @@ const std::string getPreferredModeString(MMModem* modem) { } -const std::string getCurrentModesString(MMModem* modem) { +std::string getCurrentModesString(MMModem* modem) { MMModemModeCombination combination; mm_modem_get_current_modes(modem, &combination.allowed, &combination.preferred); @@ -200,7 +200,7 @@ const std::string getCurrentModesString(MMModem* modem) { return buffer; } -const std::string getPowerStateString(MMModem* modem) { +std::string getPowerStateString(MMModem* modem) { MMModemPowerState state = mm_modem_get_power_state(modem); switch (state) { @@ -215,7 +215,7 @@ const std::string getPowerStateString(MMModem* modem) { } } -const std::string getOperatorNameString(MMModem* modem) { +std::string getOperatorNameString(MMModem* modem) { MMSim* sim = mm_modem_get_sim_sync(modem, nullptr, nullptr); From d7274a041f331efd32247c54dddbcb20f367e6df Mon Sep 17 00:00:00 2001 From: Lena Date: Sat, 11 Oct 2025 16:14:44 +0200 Subject: [PATCH 05/12] improve manpage --- man/waybar-wwan.5.scd | 77 +++++++++++++++++++++++++++++++++++++------ src/modules/wwan.cpp | 5 ++- 2 files changed, 71 insertions(+), 11 deletions(-) diff --git a/man/waybar-wwan.5.scd b/man/waybar-wwan.5.scd index 4363911b..6f5168cd 100644 --- a/man/waybar-wwan.5.scd +++ b/man/waybar-wwan.5.scd @@ -25,9 +25,42 @@ libmm-glib lives in: # CONFIGURATION *format*: ++ + typeof: string ++ + default: *{state}* ++ + The format, how information should be displayed. This format is used when other formats aren't specified. + +*format-failed*: ++ typeof: string ++ - default: {glyph} ++ - The text format. + This format is used when the modem cannot start. + +*format-locked*: ++ + typeof: string ++ + This format is used when the SIM on the modem is locked. + +*format-disabled*: ++ + typeof: string ++ + This format is used when the modem is disabled. + +*format-enabled*: ++ + typeof: string ++ + This format is used when the modem is enabled, but isn't registered to any carrier network. + +*format-searching*: ++ + typeof: string ++ + This format is used when the modem is looking for a carrier network to register to. + +*format-registered*: ++ + typeof: string ++ + This format is used when the modem is registered to a network, but no data connection is active. + +*format-connected*: ++ + typeof: string ++ + This format is used when the modem is registered to a network, and there is an active data connection. + +*format-icons*: ++ + typeof: array/object ++ + Based on the current signal strength, the corresponding icon gets selected. ++ + The order is *low* to *high*. Or by the state if it is an object. *tooltip*: ++ typeof: bool ++ @@ -36,8 +69,36 @@ libmm-glib lives in: *tooltip-format*: ++ typeof: strirng ++ - default: Games running: {glyph} ++ - The text format of the tooltip. + default: {state} ++ + The format, how information should be displayed in the tooltip. This format is used when other formats aren't specified. + +*tooltip-format-failed*: ++ + typeof: string ++ + This format is used when the modem cannot start. + +*tooltip-format-locked*: ++ + typeof: string ++ + This format is used when the SIM on the modem is locked. + +*tooltip-format-disabled*: ++ + typeof: string ++ + This format is used when the modem is disabled. + +*tooltip-format-enabled*: ++ + typeof: string ++ + This format is used when the modem is enabled, but isn't registered to any carrier network. + +*tooltip-format-searching*: ++ + typeof: string ++ + This format is used when the modem is looking for a carrier network to register to. + +*tooltip-format-registered*: ++ + typeof: string ++ + This format is used when the modem is registered to a network, but no data connection is active. + +*tooltip-format-connected*: ++ + typeof: string ++ + This format is used when the modem is registered to a network, and there is an active data connection. *interval*: ++ typeof: integer ++ @@ -46,12 +107,10 @@ libmm-glib lives in: *imei*: ++ typeof: string ++ - default: {glyph} ++ Select only the modem with the corresponding imei. *path*: ++ typeof: string ++ - default: {glyph} ++ Select only the modem with the corresponding hardware path. *hide-failed*: ++ @@ -89,11 +148,9 @@ libmm-glib lives in: "format": "{state}", "format-disabled": "", // an empty format will hide the module "format-locked": "SIM Locked", - "format-connected": "{operator_name} {preferred_mode}" + "format-connected": "{operator_name} {preferred_mode} | {signal_quality}%" "tooltip-format": "{mode}", - "tooltip-format-locked": "{satellites_visible} satellites visible", - "tooltip-format-registered": "{satellites_used}/{satellites_visible} satellites used", - "tooltip-format-connected": "", + "tooltip-format-connected": "{current_modes}", "hide-disconnected": false } ``` diff --git a/src/modules/wwan.cpp b/src/modules/wwan.cpp index 7cb8ba8b..5a328a73 100644 --- a/src/modules/wwan.cpp +++ b/src/modules/wwan.cpp @@ -277,7 +277,10 @@ auto waybar::modules::Wwan::update() -> void { store.push_back(fmt::arg("current_modes", getCurrentModesString(current_modem))); store.push_back(fmt::arg("preferred_mode", getPreferredModeString(current_modem))); - store.push_back(fmt::arg("signal_quality", mm_modem_get_signal_quality(current_modem, nullptr))); + int percentage = mm_modem_get_signal_quality(current_modem, nullptr); + store.push_back(fmt::arg("signal_quality", percentage)); + store.push_back(fmt::arg("icon", getIcon(percentage))); + store.push_back(fmt::arg("power_state", getPowerStateString(current_modem))); store.push_back(fmt::arg("imei", mm_modem_dup_equipment_identifier(current_modem))); From cd73e6cdfb05d9252179da9d2987a3bf4e11adf6 Mon Sep 17 00:00:00 2001 From: Lena Date: Tue, 14 Oct 2025 13:32:58 +0200 Subject: [PATCH 06/12] clang complained --- include/modules/wwan.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/modules/wwan.hpp b/include/modules/wwan.hpp index 0cbb5d8d..8b18e999 100644 --- a/include/modules/wwan.hpp +++ b/include/modules/wwan.hpp @@ -21,7 +21,7 @@ namespace waybar::modules { private: - const void updateCurrentModem(); + void updateCurrentModem(); util::SleeperThread thread_; std::string state_; From 11fdbe8ae3b0de90119ff53a7681562c36c34f83 Mon Sep 17 00:00:00 2001 From: Lena Date: Tue, 14 Oct 2025 13:42:48 +0200 Subject: [PATCH 07/12] clang-format --- include/modules/wwan.hpp | 38 +++++++++++++++---------------- src/modules/wwan.cpp | 48 ++++++++++++++-------------------------- 2 files changed, 35 insertions(+), 51 deletions(-) diff --git a/include/modules/wwan.hpp b/include/modules/wwan.hpp index 8b18e999..4ef851af 100644 --- a/include/modules/wwan.hpp +++ b/include/modules/wwan.hpp @@ -1,39 +1,37 @@ #pragma once #include +#include #include #include -#include - #include "ALabel.hpp" #include "util/format.hpp" #include "util/sleeper_thread.hpp" namespace waybar::modules { - class Wwan : public ALabel { - public: - Wwan(const std::string&, const Json::Value&); - virtual ~Wwan(); - auto update() -> void override; +class Wwan : public ALabel { + public: + Wwan(const std::string&, const Json::Value&); + virtual ~Wwan(); + auto update() -> void override; - private: + private: + void updateCurrentModem(); - void updateCurrentModem(); + util::SleeperThread thread_; + std::string state_; + GDBusConnection* connection; + MMManager* manager; + MMModem* current_modem; - util::SleeperThread thread_; - std::string state_; - GDBusConnection* connection; - MMManager* manager; - MMModem* current_modem; + bool hideDisconnected = true; - bool hideDisconnected = true; - - const std::string dbus_name = "org.freedesktop.ModemManager1"; - const std::string dbus_obj_path = "/org/freedesktop/ModemManager1/"; - const std::string dbus_modems_path = "/org/freedesktop/ModemManager1/Modems/"; - }; + const std::string dbus_name = "org.freedesktop.ModemManager1"; + const std::string dbus_obj_path = "/org/freedesktop/ModemManager1/"; + const std::string dbus_modems_path = "/org/freedesktop/ModemManager1/Modems/"; +}; } // namespace waybar::modules diff --git a/src/modules/wwan.cpp b/src/modules/wwan.cpp index 5a328a73..8cd3aefe 100644 --- a/src/modules/wwan.cpp +++ b/src/modules/wwan.cpp @@ -1,8 +1,10 @@ #include "modules/wwan.hpp" + #include #include #include + #include "ModemManager.h" #include "libmm-glib.h" @@ -16,13 +18,12 @@ #endif namespace { - using namespace waybar::util; - constexpr const char *DEFAULT_FORMAT = "{state}"; +using namespace waybar::util; +constexpr const char* DEFAULT_FORMAT = "{state}"; } // namespace - waybar::modules::Wwan::Wwan(const std::string& id, const Json::Value& config) -: ALabel(config, "wwan", id, "{}", 5) { + : ALabel(config, "wwan", id, "{}", 5) { thread_ = [this] { dp.emit(); thread_.sleep_for(interval_); @@ -35,13 +36,9 @@ waybar::modules::Wwan::Wwan(const std::string& id, const Json::Value& config) return; } - - manager = mm_manager_new_sync( - connection, - G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, - nullptr, // cancellable - &error - ); + manager = mm_manager_new_sync(connection, G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, + nullptr, // cancellable + &error); if (error) { spdlog::error("Failed to create ModemManager proxy: " + std::string(error->message)); @@ -55,10 +52,9 @@ waybar::modules::Wwan::Wwan(const std::string& id, const Json::Value& config) if (config_["hide-disconnected"].isBool()) { hideDisconnected = config_["hide-disconnected"].asBool(); } - } -void waybar::modules::Wwan::updateCurrentModem(){ +void waybar::modules::Wwan::updateCurrentModem() { // get 1st modem (or modem with the specified hardware path) GList* modems = g_dbus_object_manager_get_objects(G_DBUS_OBJECT_MANAGER(manager)); @@ -75,7 +71,7 @@ void waybar::modules::Wwan::updateCurrentModem(){ std::string path = config_["path"].asString(); std::string other = mm_modem_dup_physdev(modem); - if(path != other) { + if (path != other) { g_object_unref(modem); modem = nullptr; continue; @@ -86,7 +82,7 @@ void waybar::modules::Wwan::updateCurrentModem(){ std::string imei = config_["imei"].asString(); std::string other = mm_modem_dup_equipment_identifier(modem); - if(imei != other) { + if (imei != other) { g_object_unref(modem); modem = nullptr; continue; @@ -155,7 +151,6 @@ std::string getModemStateFormatString(MMModem* modem) { } std::string getPreferredModeString(MMModem* modem) { - MMModemModeCombination combination; mm_modem_get_current_modes(modem, &combination.allowed, &combination.preferred); @@ -175,27 +170,20 @@ std::string getPreferredModeString(MMModem* modem) { } } - std::string getCurrentModesString(MMModem* modem) { - MMModemModeCombination combination; mm_modem_get_current_modes(modem, &combination.allowed, &combination.preferred); std::string buffer; - if(combination.allowed & MMModemMode::MM_MODEM_MODE_CS) - buffer += "CS | "; - if(combination.allowed & MMModemMode::MM_MODEM_MODE_2G) - buffer += "2G | "; - if(combination.allowed & MMModemMode::MM_MODEM_MODE_3G) - buffer += "3G | "; - if(combination.allowed & MMModemMode::MM_MODEM_MODE_4G) - buffer += "4G | "; - if(combination.allowed & MMModemMode::MM_MODEM_MODE_5G) - buffer += "5G | "; + if (combination.allowed & MMModemMode::MM_MODEM_MODE_CS) buffer += "CS | "; + if (combination.allowed & MMModemMode::MM_MODEM_MODE_2G) buffer += "2G | "; + if (combination.allowed & MMModemMode::MM_MODEM_MODE_3G) buffer += "3G | "; + if (combination.allowed & MMModemMode::MM_MODEM_MODE_4G) buffer += "4G | "; + if (combination.allowed & MMModemMode::MM_MODEM_MODE_5G) buffer += "5G | "; if (buffer.length() > 2) { - buffer.erase(buffer.length()-2); + buffer.erase(buffer.length() - 2); } return buffer; } @@ -216,7 +204,6 @@ std::string getPowerStateString(MMModem* modem) { } std::string getOperatorNameString(MMModem* modem) { - MMSim* sim = mm_modem_get_sim_sync(modem, nullptr, nullptr); if (sim == nullptr) { @@ -268,7 +255,6 @@ auto waybar::modules::Wwan::update() -> void { state_ = state; } - auto format = format_; fmt::dynamic_format_arg_store store; From 2aa74a523ce69992e63d6197211c1e94cbaebad6 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 3 Jul 2026 22:12:39 +0200 Subject: [PATCH 08/12] wwan: fix hide-disconnected default, plug dup() leaks, meson/man cleanup - update(): only hide the module when hide-disconnected is set AND the modem is not in the CONNECTED state, instead of hiding it unconditionally (the module was invisible by default). - free the gchar* returned by mm_modem_dup_physdev/ mm_modem_dup_equipment_identifier/mm_sim_dup_operator_name. - meson.build: drop duplicate libgps dependency, install the wwan man page. - man: document hide-disconnected (replacing the unimplemented hide-failed/hide-disabled/hide-not-registered options). - remove stray empty subprojects/.wraplock. --- man/waybar-wwan.5.scd | 14 ++------------ meson.build | 2 +- src/modules/wwan.cpp | 19 ++++++++++++++----- subprojects/.wraplock | 0 4 files changed, 17 insertions(+), 18 deletions(-) delete mode 100644 subprojects/.wraplock diff --git a/man/waybar-wwan.5.scd b/man/waybar-wwan.5.scd index 6f5168cd..0169de07 100644 --- a/man/waybar-wwan.5.scd +++ b/man/waybar-wwan.5.scd @@ -113,20 +113,10 @@ libmm-glib lives in: typeof: string ++ Select only the modem with the corresponding hardware path. -*hide-failed*: ++ +*hide-disconnected*: ++ typeof: bool ++ default: true ++ - Defines if the module should be hidden if the modem cannot start. - -*hide-disabled*: ++ - typeof: bool ++ - default: false ++ - Defines if the module should be hidden if the modem is disabled. - -*hide-not-registered*: ++ - typeof: bool ++ - default: false ++ - Defines if the module should be hidden if the modem isn't registered with any carrier network. + Defines if the module should be hidden while the modem does not have an active data connection. # FORMAT REPLACEMENTS diff --git a/meson.build b/meson.build index 737a4199..f1b9cb75 100644 --- a/meson.build +++ b/meson.build @@ -561,7 +561,7 @@ endif if libmm_glib.found() add_project_arguments('-DHAVE_LIBMM_GLIB', language: 'cpp') src_files += files('src/modules/wwan.cpp') - #man_files += files('man/waybar-wwan.5.scd') + man_files += files('man/waybar-wwan.5.scd') endif subdir('protocol') diff --git a/src/modules/wwan.cpp b/src/modules/wwan.cpp index 8cd3aefe..86e68624 100644 --- a/src/modules/wwan.cpp +++ b/src/modules/wwan.cpp @@ -69,7 +69,9 @@ void waybar::modules::Wwan::updateCurrentModem() { if (config_["path"].isString()) { std::string path = config_["path"].asString(); - std::string other = mm_modem_dup_physdev(modem); + gchar* physdev = mm_modem_dup_physdev(modem); + std::string other = physdev ? physdev : ""; + g_free(physdev); if (path != other) { g_object_unref(modem); @@ -80,7 +82,9 @@ void waybar::modules::Wwan::updateCurrentModem() { if (config_["imei"].isString()) { std::string imei = config_["imei"].asString(); - std::string other = mm_modem_dup_equipment_identifier(modem); + gchar* equipment_id = mm_modem_dup_equipment_identifier(modem); + std::string other = equipment_id ? equipment_id : ""; + g_free(equipment_id); if (imei != other) { g_object_unref(modem); @@ -210,7 +214,9 @@ std::string getOperatorNameString(MMModem* modem) { return "No SIM"; } - std::string name = mm_sim_dup_operator_name(sim); + gchar* operator_name = mm_sim_dup_operator_name(sim); + std::string name = operator_name ? operator_name : ""; + g_free(operator_name); g_object_unref(sim); return name; } @@ -222,7 +228,7 @@ auto waybar::modules::Wwan::update() -> void { return; } - if (hideDisconnected) { + if (hideDisconnected && mm_modem_get_state(current_modem) != MM_MODEM_STATE_CONNECTED) { event_box_.set_visible(false); return; @@ -268,7 +274,10 @@ auto waybar::modules::Wwan::update() -> void { store.push_back(fmt::arg("icon", getIcon(percentage))); store.push_back(fmt::arg("power_state", getPowerStateString(current_modem))); - store.push_back(fmt::arg("imei", mm_modem_dup_equipment_identifier(current_modem))); + gchar* imei_raw = mm_modem_dup_equipment_identifier(current_modem); + std::string imei = imei_raw ? imei_raw : ""; + g_free(imei_raw); + store.push_back(fmt::arg("imei", imei)); store.push_back(fmt::arg("operator_name", getOperatorNameString(current_modem))); diff --git a/subprojects/.wraplock b/subprojects/.wraplock deleted file mode 100644 index e69de29b..00000000 From 41d86d92a884184ca051a7b33cad65cdde87c59f Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 3 Jul 2026 22:17:26 +0200 Subject: [PATCH 09/12] fix(wwan): null-initialize pointer members to avoid UB in destructor --- include/modules/wwan.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/modules/wwan.hpp b/include/modules/wwan.hpp index 4ef851af..0aa7112c 100644 --- a/include/modules/wwan.hpp +++ b/include/modules/wwan.hpp @@ -23,9 +23,9 @@ class Wwan : public ALabel { util::SleeperThread thread_; std::string state_; - GDBusConnection* connection; - MMManager* manager; - MMModem* current_modem; + GDBusConnection* connection = nullptr; + MMManager* manager = nullptr; + MMModem* current_modem = nullptr; bool hideDisconnected = true; From 247e18fb0b7aab4a083c06ee34d831d4a3693fe7 Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 3 Jul 2026 23:51:14 +0200 Subject: [PATCH 10/12] Fix clang-format --- src/factory.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/factory.cpp b/src/factory.cpp index 096729ac..c0d018b7 100644 --- a/src/factory.cpp +++ b/src/factory.cpp @@ -385,9 +385,9 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name, } #endif #ifdef HAVE_LIBMM_GLIB - if (ref == "wwan") { - return new waybar::modules::Wwan(id, config_[name]); - } + if (ref == "wwan") { + return new waybar::modules::Wwan(id, config_[name]); + } #endif if (ref == "temperature") { return new waybar::modules::Temperature(id, config_[name]); From 8fa58b1000240b6bf9ff601d74f1ed8d8ebc6bde Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 4 Jul 2026 00:34:42 +0200 Subject: [PATCH 11/12] nix: add libmm-glib for the wwan module --- nix/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/nix/default.nix b/nix/default.nix index 1850a414..8102363a 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -36,6 +36,7 @@ waybar.overrideAttrs (oldAttrs: { ++ [ pkgs.wireplumber pkgs.gpsd + pkgs.modemmanager ]; postUnpack = '' From 5ecda401667e946540140b40f1cc809c2b1b1e57 Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 4 Jul 2026 01:37:11 +0200 Subject: [PATCH 12/12] meson: fix libmm-glib dependency to use correct pkg-config name 'mm-glib' The ModemManager libmm-glib library installs its pkg-config file as mm-glib.pc (not libmm-glib.pc), so dependency('libmm-glib') never resolved and the nix-flake-check build failed with the wwan module enabled. --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index f1b9cb75..7bbad3fe 100644 --- a/meson.build +++ b/meson.build @@ -94,7 +94,7 @@ xkbregistry = dependency('xkbregistry') libjack = dependency('jack', required: get_option('jack')) libwireplumber = dependency('wireplumber-0.5', required: get_option('wireplumber')) libgps = dependency('libgps', required: get_option('gps')) -libmm_glib = dependency('libmm-glib', required: get_option('wwan')) +libmm_glib = dependency('mm-glib', required: get_option('wwan')) libsndio = compiler.find_library('sndio', required: get_option('sndio')) if libsndio.found()