From 638b4e6573f679f617b83ddd369d5caae09c09bd Mon Sep 17 00:00:00 2001 From: Daan Goossens Date: Mon, 2 May 2022 18:11:21 +0200 Subject: [PATCH 1/7] feat: extend bluetooth module --- include/factory.hpp | 6 +- include/modules/bluetooth.hpp | 59 ++++++ man/waybar-bluetooth.5.scd | 99 ++++++++-- meson.build | 14 +- src/factory.cpp | 10 +- src/modules/bluetooth.cpp | 358 ++++++++++++++++++++++++++++++++-- 6 files changed, 497 insertions(+), 49 deletions(-) diff --git a/include/factory.hpp b/include/factory.hpp index b966697..e9d9984 100644 --- a/include/factory.hpp +++ b/include/factory.hpp @@ -56,15 +56,11 @@ #endif #ifdef HAVE_GIO_UNIX #include "modules/inhibitor.hpp" +#include "modules/bluetooth.hpp" #endif #include "bar.hpp" #include "modules/custom.hpp" #include "modules/temperature.hpp" -#if defined(__linux__) -#ifdef WANT_RFKILL -#include "modules/bluetooth.hpp" -#endif -#endif namespace waybar { diff --git a/include/modules/bluetooth.hpp b/include/modules/bluetooth.hpp index 87845c9..0e7bbf3 100644 --- a/include/modules/bluetooth.hpp +++ b/include/modules/bluetooth.hpp @@ -1,18 +1,77 @@ #pragma once #include "ALabel.hpp" +#ifdef WANT_RFKILL #include "util/rfkill.hpp" +#endif +#include +#include +#include +#include namespace waybar::modules { class Bluetooth : public ALabel { + struct AdapterInfo + { + std::string path; + std::string address; + std::string address_type; + // std::string name; // just use alias instead + std::string alias; + bool powered; + bool discoverable; + bool pairable; + bool discovering; + }; + + // NOTE: there are some properties that not all devices provide + struct DeviceInfo + { + std::string path; + std::string paired_adapter; + std::string address; + std::string address_type; + // std::optional name; // just use alias instead + std::string alias; + std::optional icon; + bool paired; + bool trusted; + bool blocked; + bool connected; + bool services_resolved; + // TODO: make experimental in waybar as it is also a experimental feature in bluez + std::optional battery_percentage; + }; + public: Bluetooth(const std::string&, const Json::Value&); ~Bluetooth() = default; auto update() -> void; private: + static auto onInterfaceAddedOrRemoved(GDBusObjectManager*, GDBusObject*, GDBusInterface*, gpointer) -> void; + static auto onInterfaceProxyPropertiesChanged(GDBusObjectManagerClient*, GDBusObjectProxy*, GDBusProxy*, GVariant*, const gchar* const*, gpointer) -> void; + + auto getDeviceBatteryPercentage(GDBusObject*) -> std::optional; + auto getDeviceProperties(GDBusObject*, DeviceInfo&) -> bool; + auto getAdapterProperties(GDBusObject*, AdapterInfo&) -> bool; + + auto findCurAdapter(AdapterInfo&) -> bool; + auto findConnectedDevices(const std::string&, std::vector&) -> void; + + +#ifdef WANT_RFKILL util::Rfkill rfkill_; +#endif + const std::unique_ptr manager_; + + std::string state_; + AdapterInfo cur_adapter_; + std::vector connected_devices_; + DeviceInfo cur_focussed_device_; + + std::vector device_preference_; }; } // namespace waybar::modules diff --git a/man/waybar-bluetooth.5.scd b/man/waybar-bluetooth.5.scd index 1797e80..71faaf8 100644 --- a/man/waybar-bluetooth.5.scd +++ b/man/waybar-bluetooth.5.scd @@ -6,21 +6,44 @@ waybar - bluetooth module # DESCRIPTION -The *bluetooth* module displays information about the status of the device's bluetooth device. +The *bluetooth* module displays information about the bluetooth adapter and its connections. # CONFIGURATION Addressed by *bluetooth* +*adapter-alias*: ++ + typeof: string ++ + Use the adapter with the defined alias (name). Otherwise select a random adapter to display. Recommended to define when there is more than 1 adapter available to the system (use ```bluetoothctl show``` to show all available adapters). + +*format-device-preference*: ++ + typeof: array ++ + A ranking of bluetooth devices, addressed by their alias (name). The order is *first displayed* to *last displayed*. If this config option is not defined or none of the devices in the list are connected, it will fall back to showing the last connected device. A devices alias can be manually changed using the ```bluetoothctl set-alias``` command. + *format*: ++ typeof: string ++ - default: *{icon}* ++ + default: * {status}* ++ The format, how information should be displayed. This format is used when other formats aren't specified. -*format-icons*: ++ - typeof: array/object ++ - Based on the device status, the corresponding icon gets selected. ++ - The order is *low* to *high*. Or by the state if it is an object. +*format-disabled*: ++ + typeof: string ++ + This format is used when the displayed adapter is disabled. + +*format-off*: ++ + typeof: string ++ + This format is used when the displayed adapter is turned off. + +*format-on*: ++ + typeof: string ++ + This format is used when the displayed adapter is turned on with no devices connected. + +*format-connected*: ++ + typeof: string ++ + This format is used when the displayed adapter is connected to at least 1 device. + +*format-connected-battery*: ++ + typeof: string ++ + This format is used when the selected connected device, defined by the config option *format-device-preference*, provides is battery percentage. This needs the experimental features of bluez to be enabled to work. *rotate*: ++ typeof: integer ++ @@ -71,23 +94,65 @@ Addressed by *bluetooth* typeof: string ++ The format, how information should be displayed in the tooltip. This format is used when other formats aren't specified. +*tooltip-format-disabled*: ++ + typeof: string ++ + This format is used when the displayed adapter is disabled. + +*tooltip-format-off*: ++ + typeof: string ++ + This format is used when the displayed adapter is turned off. + +*tooltip-format-on*: ++ + typeof: string ++ + This format is used when the displayed adapter is turned on with no devices connected. + +*tooltip-format-connected*: ++ + typeof: string ++ + This format is used when the displayed adapter is connected to at least 1 device. + +*tooltip-format-connected-battery*: ++ + typeof: string ++ + This format is used when the selected connected device, defined by the config option *format-device-preference*, provides is battery percentage. This needs the experimental features of bluez to be enabled to work. + # FORMAT REPLACEMENTS *{status}*: Status of the bluetooth device. -*{icon}*: Icon, as defined in *format-icons*. +*{num_connections}*: Number of connections the selected adapter has. + +*{adapter_address}*: Address of the selected adapter. + +*{adapter_address_type}*: Address type of the selected adapter. + +*{adapter_alias}*: Alias of the selected adapter. By default equal to the *adapter_name* but can be changed by the user when there are conflicts. + +*{device_address}*: Address of the current selected selected connected device. + +*{device_address_type}*: Address type of the current selected selected connected device. + +*{device_alias}*: Alias of the current selected connected device. By default equal to the *device_name* but can be changed by the user when there are conflicts. + +*{device_battery_percentage}*: Battery percentage of the current selected device if available. Only use in the *format-connected-battery* and *tooltip-format-connected-battery*. # EXAMPLES ``` "bluetooth": { - "format": "{icon}", - "format-alt": "bluetooth: {status}", - "format-icons": { - "enabled": "", - "disabled": "" - }, - "tooltip-format": "{}" + "format": " {status}", + "format-connected": " {device_alias}", + "format-connected-battery": " {device_battery_percentage}%", + "tooltip-format": "{adapter_alias} {adapter_address}" +} +``` + +``` +"bluetooth": { + // "adapter-alias": "adapter1", // specify the adapter alias (name) if there are more than 1 on the system + "format": " {status}", + "format-connected": " {num_connections} connected", + // TODO: make it so that it shows all connected devices in the tooltip + // "tooltip-format-connected": "{device_alias}", + // "tooltip-format-connected-battery": "{device_alias} {device_battery_percentage}%", } ``` @@ -95,3 +160,9 @@ Addressed by *bluetooth* - *#bluetooth* - *#bluetooth.disabled* +- *#bluetooth.off* +- *#bluetooth.on* +- *#bluetooth.connected* +- *#bluetooth.discoverable* +- *#bluetooth.discovering* +- *#bluetooth.pairable* diff --git a/meson.build b/meson.build index 73e74a5..b3a4a4c 100644 --- a/meson.build +++ b/meson.build @@ -253,16 +253,14 @@ endif if (giounix.found() and not get_option('logind').disabled()) add_project_arguments('-DHAVE_GIO_UNIX', language: 'cpp') src_files += 'src/modules/inhibitor.cpp' + src_files += 'src/modules/bluetooth.cpp' endif -if get_option('rfkill').enabled() - if is_linux - add_project_arguments('-DWANT_RFKILL', language: 'cpp') - src_files += files( - 'src/modules/bluetooth.cpp', - 'src/util/rfkill.cpp' - ) - endif +if get_option('rfkill').enabled() and is_linux + add_project_arguments('-DWANT_RFKILL', language: 'cpp') + src_files += files( + 'src/util/rfkill.cpp' + ) endif if tz_dep.found() diff --git a/src/factory.cpp b/src/factory.cpp index 4aaa248..e0d99f1 100644 --- a/src/factory.cpp +++ b/src/factory.cpp @@ -104,17 +104,13 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name) const { if (ref == "inhibitor") { return new waybar::modules::Inhibitor(id, bar_, config_[name]); } -#endif - if (ref == "temperature") { - return new waybar::modules::Temperature(id, config_[name]); - } -#if defined(__linux__) -#ifdef WANT_RFKILL if (ref == "bluetooth") { return new waybar::modules::Bluetooth(id, config_[name]); } #endif -#endif + if (ref == "temperature") { + return new waybar::modules::Temperature(id, config_[name]); + } if (ref.compare(0, 7, "custom/") == 0 && ref.size() > 7) { return new waybar::modules::Custom(ref.substr(7), id, config_[name]); } diff --git a/src/modules/bluetooth.cpp b/src/modules/bluetooth.cpp index 371bc7d..8981083 100644 --- a/src/modules/bluetooth.cpp +++ b/src/modules/bluetooth.cpp @@ -1,30 +1,358 @@ #include "modules/bluetooth.hpp" +#include +#include #include +namespace { + +using GDBusManager = std::unique_ptr; + +auto generateManager() -> GDBusManager { + GError* error = nullptr; + GDBusObjectManager* manager = g_dbus_object_manager_client_new_for_bus_sync( + G_BUS_TYPE_SYSTEM, + GDBusObjectManagerClientFlags::G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START, + "org.bluez", + "/", + NULL, + NULL, + NULL, + NULL, + &error + ); + + if (error) { + spdlog::error("g_dbus_object_manager_client_new_for_bus_sync() failed: {}", error->message); + g_error_free(error); + } + + auto destructor = [](GDBusObjectManager* manager) { + if (manager) { + g_object_unref(manager); + } + }; + + return GDBusManager{manager, destructor}; +} + +auto getBoolProperty(GDBusProxy* proxy, const char* property_name) -> bool { + auto gvar = g_dbus_proxy_get_cached_property(proxy, property_name); + if (gvar) { + bool property_value = g_variant_get_boolean(gvar); + g_variant_unref(gvar); + return property_value; + } + + spdlog::error("getBoolProperty() failed: doesn't have property {}", property_name); + return false; +} + +auto getOptionalStringProperty(GDBusProxy* proxy, const char* property_name) -> std::optional { + auto gvar = g_dbus_proxy_get_cached_property(proxy, property_name); + if (gvar) { + std::string property_value = g_variant_get_string(gvar, NULL); + g_variant_unref(gvar); + return property_value; + } + + return std::nullopt; +} + +auto getStringProperty(GDBusProxy* proxy, const char* property_name) -> std::string { + auto property_value = getOptionalStringProperty(proxy, property_name); + if (!property_value.has_value()) { + spdlog::error("getStringProperty() failed: doesn't have property {}", property_name); + } + return property_value.value_or(""); +} + +auto getUcharProperty(GDBusProxy* proxy, const char* property_name) -> unsigned char { + auto gvar = g_dbus_proxy_get_cached_property(proxy, property_name); + if (gvar) { + unsigned char property_value; + g_variant_get(gvar, "y", &property_value); + g_variant_unref(gvar); + + return property_value; + } + + spdlog::error("getUcharProperty() failed: doesn't have property {}", property_name); + return 0; +} + +} // namespace + waybar::modules::Bluetooth::Bluetooth(const std::string& id, const Json::Value& config) - : ALabel(config, "bluetooth", id, "{icon}", 10), rfkill_{RFKILL_TYPE_BLUETOOTH} { + : ALabel(config, "bluetooth", id, " {status}", 10), +#ifdef WANT_RFKILL + rfkill_{RFKILL_TYPE_BLUETOOTH}, +#endif + manager_(generateManager()) { + + if (config_["format-device-preference"].isArray()) { + std::transform(config_["format-device-preference"].begin(), + config_["format-device-preference"].end(), + std::back_inserter(device_preference_), + [](auto x){ return x.asString(); }); + } + + // NOTE: assumption made that the adapter that is selcected stays unchanged + // for duration of the module + if (!findCurAdapter(cur_adapter_)) { + if (config_["adapter-alias"].isString()) { + spdlog::error("find_cur_adapter() failed: no bluetooth adapter found with alias '{}'", config_["adapter-alias"].asString()); + } else { + spdlog::error("find_cur_adapter() failed: no bluetooth adapter found"); + } + return; + } + findConnectedDevices(cur_adapter_.path, connected_devices_); + + g_signal_connect(manager_.get(), "interface-proxy-properties-changed", G_CALLBACK(onInterfaceProxyPropertiesChanged), this); + g_signal_connect(manager_.get(), "interface-added", G_CALLBACK(onInterfaceAddedOrRemoved), this); + g_signal_connect(manager_.get(), "interface-removed", G_CALLBACK(onInterfaceAddedOrRemoved), this); +#ifdef WANT_RFKILL rfkill_.on_update.connect(sigc::hide(sigc::mem_fun(*this, &Bluetooth::update))); +#endif + + dp.emit(); } auto waybar::modules::Bluetooth::update() -> void { - std::string status = rfkill_.getState() ? "disabled" : "enabled"; - - label_.set_markup( - fmt::format(format_, fmt::arg("status", status), fmt::arg("icon", getIcon(0, status)))); - if (status == "disabled") { - label_.get_style_context()->add_class("disabled"); - } else { - label_.get_style_context()->remove_class("disabled"); + // focussed device is either: + // - the first device in the device_preference_ list that is connected to the + // current adapter (if none fallback to last connected device) + // - it is the last device that connected to the current adapter + if (!connected_devices_.empty()) { + bool preferred_device_connected = false; + if (!device_preference_.empty()) { + for (const std::string& device_alias : device_preference_) { + auto it = std::find_if(connected_devices_.begin(), connected_devices_.end(), [device_alias](auto device){ return device_alias == device.alias; }); + if (it != connected_devices_.end()) { + preferred_device_connected = true; + cur_focussed_device_ = *it; + break; + } + } + } + if (!preferred_device_connected) { + cur_focussed_device_ = connected_devices_.back(); + } } - if (tooltipEnabled()) { - if (config_["tooltip-format"].isString()) { - auto tooltip_format = config_["tooltip-format"].asString(); - auto tooltip_text = fmt::format(tooltip_format, status, fmt::arg("status", status)); - label_.set_tooltip_text(tooltip_text); + std::string state; + std::string tooltip_format; + if (!cur_adapter_.powered) + state = "off"; + else if (!connected_devices_.empty()) + state = "connected"; + else + state = "on"; +#ifdef WANT_RFKILL + if (rfkill_.getState()) + state = "disabled"; +#endif + + if (!alt_) { + if (state == "connected" && cur_focussed_device_.battery_percentage.has_value() && config_["format-connected-battery"].isString()) { + format_ = config_["format-connected-battery"].asString(); + } else if (config_["format-" + state].isString()) { + format_ = config_["format-" + state].asString(); + } else if (config_["format"].isString()) { + format_ = config_["format"].asString(); } else { - label_.set_tooltip_text(status); + format_ = default_format_; + } + } + if (config_["tooltip-format-" + state].isString()) { + tooltip_format = config_["tooltip-format-" + state].asString(); + } else if (config_["tooltip-format"].isString()) { + tooltip_format = config_["tooltip-format"].asString(); + } + + auto update_style_context = [this](const std::string& style_class, bool in_next_state) { + if (in_next_state && !label_.get_style_context()->has_class(style_class)) { + label_.get_style_context()->add_class(style_class); + } else if (!in_next_state && label_.get_style_context()->has_class(style_class)) { + label_.get_style_context()->remove_class(style_class); + } + }; + update_style_context("discoverable", cur_adapter_.discoverable); + update_style_context("discovering", cur_adapter_.discovering); + update_style_context("pairable", cur_adapter_.pairable); + if (!state_.empty()) { + update_style_context(state_, false); + } + update_style_context(state, true); + state_ = state; + + label_.set_markup(fmt::format(format_, + fmt::arg("status", state_), + fmt::arg("num_connections", connected_devices_.size()), + fmt::arg("adapter_address", cur_adapter_.address), + fmt::arg("adapter_address_type", cur_adapter_.address_type), + fmt::arg("adapter_alias", cur_adapter_.alias), + fmt::arg("device_address", cur_focussed_device_.address), + fmt::arg("device_address_type", cur_focussed_device_.address_type), + fmt::arg("device_alias", cur_focussed_device_.alias), + fmt::arg("device_battery_percentage", cur_focussed_device_.battery_percentage.value_or(0)) + )); + + // TODO: make possible to show information about all connected devices in the tooltip + if (tooltipEnabled()) { + label_.set_tooltip_text(fmt::format(tooltip_format, + fmt::arg("status", state_), + fmt::arg("num_connections", connected_devices_.size()), + fmt::arg("adapter_address", cur_adapter_.address), + fmt::arg("adapter_address_type", cur_adapter_.address_type), + fmt::arg("adapter_alias", cur_adapter_.alias), + fmt::arg("device_address", cur_focussed_device_.address), + fmt::arg("device_address_type", cur_focussed_device_.address_type), + fmt::arg("device_alias", cur_focussed_device_.alias), + fmt::arg("device_battery_percentage", cur_focussed_device_.battery_percentage.value_or(0)) + )); + } + + // Call parent update + ALabel::update(); +} + +// NOTE: only for when the org.bluez.Battery1 interface is added/removed after/before a device is connected/disconnected +auto waybar::modules::Bluetooth::onInterfaceAddedOrRemoved(GDBusObjectManager *manager, GDBusObject *object, + GDBusInterface *interface, + gpointer user_data) -> void +{ + std::string interface_name = g_dbus_proxy_get_interface_name(G_DBUS_PROXY(interface)); + std::string object_path = g_dbus_proxy_get_object_path(G_DBUS_PROXY(interface)); + if (interface_name == "org.bluez.Battery1") { + Bluetooth* bt = static_cast(user_data); + auto device = std::find_if(bt->connected_devices_.begin(), bt->connected_devices_.end(), [object_path](auto d){ return d.path == object_path; }); + if (device != bt->connected_devices_.end()) { + device->battery_percentage = bt->getDeviceBatteryPercentage(object); + bt->dp.emit(); } } } + +auto waybar::modules::Bluetooth::onInterfaceProxyPropertiesChanged(GDBusObjectManagerClient *manager, + GDBusObjectProxy *object_proxy, + GDBusProxy *interface_proxy, + GVariant *changed_properties, + const gchar *const *invalidated_properties, + gpointer user_data) -> void +{ + std::string interface_name = g_dbus_proxy_get_interface_name(interface_proxy); + std::string object_path = g_dbus_object_get_object_path(G_DBUS_OBJECT(object_proxy)); + + Bluetooth* bt = static_cast(user_data); + if (interface_name == "org.bluez.Adapter1") { + if (object_path == bt->cur_adapter_.path) { + bt->getAdapterProperties(G_DBUS_OBJECT(object_proxy), bt->cur_adapter_); + bt->dp.emit(); + } + } else if (interface_name == "org.bluez.Device1" || + interface_name == "org.bluez.Battery1") { + DeviceInfo device; + bt->getDeviceProperties(G_DBUS_OBJECT(object_proxy), device); + auto cur_device = std::find_if(bt->connected_devices_.begin(), bt->connected_devices_.end(), [device](auto d){ return d.path == device.path; }); + if (cur_device == bt->connected_devices_.end()) { + if (device.connected) { + bt->connected_devices_.push_back(device); + bt->dp.emit(); + } + } else { + if (!device.connected) { + bt->connected_devices_.erase(cur_device); + } else { + *cur_device = device; + } + bt->dp.emit(); + } + } +} + +auto waybar::modules::Bluetooth::getDeviceBatteryPercentage(GDBusObject* object) -> std::optional { + GDBusProxy* proxy_device_bat = G_DBUS_PROXY(g_dbus_object_get_interface(object, "org.bluez.Battery1")); + if (proxy_device_bat != NULL) { + unsigned char battery_percentage = getUcharProperty(proxy_device_bat, "Percentage"); + g_object_unref(proxy_device_bat); + + return battery_percentage; + } + return std::nullopt; +} + +auto waybar::modules::Bluetooth::getDeviceProperties(GDBusObject* object, DeviceInfo& device_info) -> bool { + GDBusProxy* proxy_device = G_DBUS_PROXY(g_dbus_object_get_interface(object, "org.bluez.Device1")); + + if (proxy_device != NULL) { + device_info.path = g_dbus_object_get_object_path(object); + device_info.paired_adapter = getStringProperty(proxy_device, "Adapter"); + device_info.address = getStringProperty(proxy_device, "Address"); + device_info.address_type = getStringProperty(proxy_device, "AddressType"); + device_info.alias = getStringProperty(proxy_device, "Alias"); + device_info.icon = getOptionalStringProperty(proxy_device, "Icon"); + device_info.paired = getBoolProperty(proxy_device, "Paired"); + device_info.trusted = getBoolProperty(proxy_device, "Trusted"); + device_info.blocked = getBoolProperty(proxy_device, "Blocked"); + device_info.connected = getBoolProperty(proxy_device, "Connected"); + device_info.services_resolved = getBoolProperty(proxy_device, "ServicesResolved"); + + g_object_unref(proxy_device); + + device_info.battery_percentage = getDeviceBatteryPercentage(object); + + return true; + } + return false; +} + +auto waybar::modules::Bluetooth::getAdapterProperties(GDBusObject* object, AdapterInfo& adapter_info) -> bool { + GDBusProxy* proxy_adapter = G_DBUS_PROXY(g_dbus_object_get_interface(object, "org.bluez.Adapter1")); + + if (proxy_adapter != NULL) { + adapter_info.path = g_dbus_object_get_object_path(object); + adapter_info.address = getStringProperty(proxy_adapter, "Address"); + adapter_info.address_type = getStringProperty(proxy_adapter, "AddressType"); + adapter_info.alias = getStringProperty(proxy_adapter, "Alias"); + adapter_info.powered = getBoolProperty(proxy_adapter, "Powered"); + adapter_info.discoverable = getBoolProperty(proxy_adapter, "Discoverable"); + adapter_info.pairable = getBoolProperty(proxy_adapter, "Pairable"); + adapter_info.discovering = getBoolProperty(proxy_adapter, "Discovering"); + + g_object_unref(proxy_adapter); + + return true; + } + return false; +} + +auto waybar::modules::Bluetooth::findCurAdapter(AdapterInfo& adapter_info) -> bool { + bool found_adapter = false; + + GList* objects = g_dbus_object_manager_get_objects(manager_.get()); + for (GList* l = objects; l != NULL; l = l->next) { + GDBusObject* object = G_DBUS_OBJECT(l->data); + if (getAdapterProperties(object, adapter_info) && (!config_["adapter-alias"].isString() || config_["adapter-alias"].asString() == adapter_info.alias)) { + found_adapter = true; + break; + } + } + g_list_free_full(objects, g_object_unref); + + return found_adapter; +} + +auto waybar::modules::Bluetooth::findConnectedDevices(const std::string& cur_adapter_path, std::vector& connected_devices) -> void { + GList* objects = g_dbus_object_manager_get_objects(manager_.get()); + for (GList* l = objects; l != NULL; l = l->next) + { + GDBusObject* object = G_DBUS_OBJECT(l->data); + DeviceInfo device; + if (getDeviceProperties(object, device) && device.connected && device.paired_adapter == cur_adapter_.path) { + connected_devices.push_back(device); + } + } + g_list_free_full(objects, g_object_unref); +} From 794610a1cacae050ac809dcc4338c6bc9913f3fa Mon Sep 17 00:00:00 2001 From: Daan Goossens Date: Wed, 4 May 2022 18:27:29 +0200 Subject: [PATCH 2/7] feat: display all connected devices in tooltip --- include/modules/bluetooth.hpp | 1 + man/waybar-bluetooth.5.scd | 41 ++++++++++++++++++++++++----------- src/modules/bluetooth.cpp | 30 +++++++++++++++++++++++-- 3 files changed, 57 insertions(+), 15 deletions(-) diff --git a/include/modules/bluetooth.hpp b/include/modules/bluetooth.hpp index 0e7bbf3..6be2e78 100644 --- a/include/modules/bluetooth.hpp +++ b/include/modules/bluetooth.hpp @@ -70,6 +70,7 @@ class Bluetooth : public ALabel { AdapterInfo cur_adapter_; std::vector connected_devices_; DeviceInfo cur_focussed_device_; + std::string device_enumerate_; std::vector device_preference_; }; diff --git a/man/waybar-bluetooth.5.scd b/man/waybar-bluetooth.5.scd index 71faaf8..186207d 100644 --- a/man/waybar-bluetooth.5.scd +++ b/man/waybar-bluetooth.5.scd @@ -114,6 +114,15 @@ Addressed by *bluetooth* typeof: string ++ This format is used when the selected connected device, defined by the config option *format-device-preference*, provides is battery percentage. This needs the experimental features of bluez to be enabled to work. +*tooltip-format-enumerate-connected*: ++ + typeof: string ++ + This format is used to define how each connected device should be displayed within the *device_enumerate* format replacement in the tooltip menu. + +*tooltip-format-enumerate-connected-battery*: ++ + typeof: string ++ + This format is used to define how each connected device with a battery should be displayed within the *device_enumerate* format replacement in the tooltip menu. When this config option is not defined, the *tooltip-format-enumerate-connected* format will be used also for the connected devices with a battery. + + # FORMAT REPLACEMENTS *{status}*: Status of the bluetooth device. @@ -134,25 +143,31 @@ Addressed by *bluetooth* *{device_battery_percentage}*: Battery percentage of the current selected device if available. Only use in the *format-connected-battery* and *tooltip-format-connected-battery*. -# EXAMPLES +*{device_enumerate}*: Show a list of all connected devices in the tooltip, each on a seperate line. Only applicable in the *connected* state. Define the format of each device with the *tooltip-format-enumerate-connected* or/and *tooltip-format-enumerate-connected-battery* config options. -``` -"bluetooth": { - "format": " {status}", - "format-connected": " {device_alias}", - "format-connected-battery": " {device_battery_percentage}%", - "tooltip-format": "{adapter_alias} {adapter_address}" -} -``` +# EXAMPLES ``` "bluetooth": { // "adapter-alias": "adapter1", // specify the adapter alias (name) if there are more than 1 on the system "format": " {status}", - "format-connected": " {num_connections} connected", - // TODO: make it so that it shows all connected devices in the tooltip - // "tooltip-format-connected": "{device_alias}", - // "tooltip-format-connected-battery": "{device_alias} {device_battery_percentage}%", + "format-connected": " {num_connections} connected", + "tooltip-format": "{adapter_alias}\t{adapter_address}", + "tooltip-format-connected": "{adapter_alias}\t{adapter_address}\n\n{device_enumerate}", + "tooltip-format-enumerate-connected": "{device_alias}\t{device_address}", + "tooltip-format-enumerate-connected-battery": "{device_alias}\t{device_address}\t{device_battery_percentage}%" +} +``` + +``` +"bluetooth": { + "format": " {status}", + "format-connected": " {device_alias}", + "format-connected-battery": " {device_alias} {device_battery_percentage}%", + // "format-device-preference": [ "alias1", "alias2" ], // preference list deciding which device to show in format-connected format-connected-battery + "tooltip-format": "{adapter_alias}\t{adapter_address}\n\n{num_connections} connected\n\n{device_enumerate}", + "tooltip-format-enumerate-connected": "{device_alias}\t{device_address}", + "tooltip-format-enumerate-connected-battery": "{device_alias}\t{device_address}\t{device_battery_percentage}%" } ``` diff --git a/src/modules/bluetooth.cpp b/src/modules/bluetooth.cpp index 8981083..b0be971 100644 --- a/src/modules/bluetooth.cpp +++ b/src/modules/bluetooth.cpp @@ -1,6 +1,7 @@ #include "modules/bluetooth.hpp" #include +#include #include #include @@ -199,8 +200,32 @@ auto waybar::modules::Bluetooth::update() -> void { fmt::arg("device_battery_percentage", cur_focussed_device_.battery_percentage.value_or(0)) )); - // TODO: make possible to show information about all connected devices in the tooltip if (tooltipEnabled()) { + bool tooltip_enumerate_connections_ = config_["tooltip-format-enumerate-connected"].isString(); + bool tooltip_enumerate_connections_battery_ = config_["tooltip-format-enumerate-connected-battery"].isString(); + if (tooltip_enumerate_connections_ || tooltip_enumerate_connections_battery_) { + std::stringstream ss; + for (DeviceInfo dev : connected_devices_) { + if (tooltip_enumerate_connections_battery_ && dev.battery_percentage.has_value()) { + ss << "\n"; + ss << fmt::format(config_["tooltip-format-enumerate-connected-battery"].asString(), + fmt::arg("device_address", dev.address), + fmt::arg("device_address_type", dev.address_type), + fmt::arg("device_alias", dev.alias), + fmt::arg("device_battery_percentage", dev.battery_percentage.value_or(0))); + } else if (tooltip_enumerate_connections_) { + ss << "\n"; + ss << fmt::format(config_["tooltip-format-enumerate-connected"].asString(), + fmt::arg("device_address", dev.address), + fmt::arg("device_address_type", dev.address_type), + fmt::arg("device_alias", dev.alias)); + } + } + device_enumerate_ = ss.str(); + if (!device_enumerate_.empty()) { + device_enumerate_.erase(0, 1); + } + } label_.set_tooltip_text(fmt::format(tooltip_format, fmt::arg("status", state_), fmt::arg("num_connections", connected_devices_.size()), @@ -210,7 +235,8 @@ auto waybar::modules::Bluetooth::update() -> void { fmt::arg("device_address", cur_focussed_device_.address), fmt::arg("device_address_type", cur_focussed_device_.address_type), fmt::arg("device_alias", cur_focussed_device_.alias), - fmt::arg("device_battery_percentage", cur_focussed_device_.battery_percentage.value_or(0)) + fmt::arg("device_battery_percentage", cur_focussed_device_.battery_percentage.value_or(0)), + fmt::arg("device_enumerate", device_enumerate_) )); } From 13df878bc3588fd312cf95a8a6077ce33c2a4ce0 Mon Sep 17 00:00:00 2001 From: Daan Goossens Date: Thu, 5 May 2022 23:05:30 +0200 Subject: [PATCH 3/7] refactor: logic for enumerating devices in tooltip --- src/modules/bluetooth.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/modules/bluetooth.cpp b/src/modules/bluetooth.cpp index b0be971..e0432e9 100644 --- a/src/modules/bluetooth.cpp +++ b/src/modules/bluetooth.cpp @@ -206,22 +206,18 @@ auto waybar::modules::Bluetooth::update() -> void { if (tooltip_enumerate_connections_ || tooltip_enumerate_connections_battery_) { std::stringstream ss; for (DeviceInfo dev : connected_devices_) { - if (tooltip_enumerate_connections_battery_ && dev.battery_percentage.has_value()) { + if ((tooltip_enumerate_connections_battery_ && dev.battery_percentage.has_value()) || tooltip_enumerate_connections_) { ss << "\n"; - ss << fmt::format(config_["tooltip-format-enumerate-connected-battery"].asString(), + std::string enumerate_format = (tooltip_enumerate_connections_battery_ && dev.battery_percentage.has_value()) ? config_["tooltip-format-enumerate-connected-battery"].asString() : config_["tooltip-format-enumerate-connected"].asString(); + ss << fmt::format(enumerate_format, fmt::arg("device_address", dev.address), fmt::arg("device_address_type", dev.address_type), fmt::arg("device_alias", dev.alias), fmt::arg("device_battery_percentage", dev.battery_percentage.value_or(0))); - } else if (tooltip_enumerate_connections_) { - ss << "\n"; - ss << fmt::format(config_["tooltip-format-enumerate-connected"].asString(), - fmt::arg("device_address", dev.address), - fmt::arg("device_address_type", dev.address_type), - fmt::arg("device_alias", dev.alias)); } } device_enumerate_ = ss.str(); + // don't start the connected devices text with a new line if (!device_enumerate_.empty()) { device_enumerate_.erase(0, 1); } From 954bed3f5e37218e94eeb4ed95840f88bea0cdf2 Mon Sep 17 00:00:00 2001 From: Daan Goossens Date: Fri, 6 May 2022 00:38:04 +0200 Subject: [PATCH 4/7] refactor: adapter renamed to controller Since it is also called controller in bluetoothctl --- include/modules/bluetooth.hpp | 10 ++--- man/waybar-bluetooth.5.scd | 42 +++++++++--------- src/modules/bluetooth.cpp | 80 +++++++++++++++++------------------ 3 files changed, 68 insertions(+), 64 deletions(-) diff --git a/include/modules/bluetooth.hpp b/include/modules/bluetooth.hpp index 6be2e78..56472f2 100644 --- a/include/modules/bluetooth.hpp +++ b/include/modules/bluetooth.hpp @@ -12,7 +12,7 @@ namespace waybar::modules { class Bluetooth : public ALabel { - struct AdapterInfo + struct ControllerInfo { std::string path; std::string address; @@ -29,7 +29,7 @@ class Bluetooth : public ALabel { struct DeviceInfo { std::string path; - std::string paired_adapter; + std::string paired_controller; std::string address; std::string address_type; // std::optional name; // just use alias instead @@ -55,9 +55,9 @@ class Bluetooth : public ALabel { auto getDeviceBatteryPercentage(GDBusObject*) -> std::optional; auto getDeviceProperties(GDBusObject*, DeviceInfo&) -> bool; - auto getAdapterProperties(GDBusObject*, AdapterInfo&) -> bool; + auto getControllerProperties(GDBusObject*, ControllerInfo&) -> bool; - auto findCurAdapter(AdapterInfo&) -> bool; + auto findCurController(ControllerInfo&) -> bool; auto findConnectedDevices(const std::string&, std::vector&) -> void; @@ -67,7 +67,7 @@ class Bluetooth : public ALabel { const std::unique_ptr manager_; std::string state_; - AdapterInfo cur_adapter_; + ControllerInfo cur_controller_; std::vector connected_devices_; DeviceInfo cur_focussed_device_; std::string device_enumerate_; diff --git a/man/waybar-bluetooth.5.scd b/man/waybar-bluetooth.5.scd index 186207d..1567f2c 100644 --- a/man/waybar-bluetooth.5.scd +++ b/man/waybar-bluetooth.5.scd @@ -6,15 +6,18 @@ waybar - bluetooth module # DESCRIPTION -The *bluetooth* module displays information about the bluetooth adapter and its connections. +The *bluetooth* module displays information about the bluetooth controller and its connections. # CONFIGURATION Addressed by *bluetooth* -*adapter-alias*: ++ +*controller*: ++ typeof: string ++ - Use the adapter with the defined alias (name). Otherwise select a random adapter to display. Recommended to define when there is more than 1 adapter available to the system (use ```bluetoothctl show``` to show all available adapters). + Use the controller with the defined alias (name). Otherwise select a + random controller to display. Recommended to define when there is more + than 1 controller available to the system (use ```bluetoothctl show``` + to show all available controller). *format-device-preference*: ++ typeof: array ++ @@ -27,19 +30,19 @@ Addressed by *bluetooth* *format-disabled*: ++ typeof: string ++ - This format is used when the displayed adapter is disabled. + This format is used when the displayed controller is disabled. *format-off*: ++ typeof: string ++ - This format is used when the displayed adapter is turned off. + This format is used when the displayed controller is turned off. *format-on*: ++ typeof: string ++ - This format is used when the displayed adapter is turned on with no devices connected. + This format is used when the displayed controller is turned on with no devices connected. *format-connected*: ++ typeof: string ++ - This format is used when the displayed adapter is connected to at least 1 device. + This format is used when the displayed controller is connected to at least 1 device. *format-connected-battery*: ++ typeof: string ++ @@ -96,19 +99,19 @@ Addressed by *bluetooth* *tooltip-format-disabled*: ++ typeof: string ++ - This format is used when the displayed adapter is disabled. + This format is used when the displayed controller is disabled. *tooltip-format-off*: ++ typeof: string ++ - This format is used when the displayed adapter is turned off. + This format is used when the displayed controller is turned off. *tooltip-format-on*: ++ typeof: string ++ - This format is used when the displayed adapter is turned on with no devices connected. + This format is used when the displayed controller is turned on with no devices connected. *tooltip-format-connected*: ++ typeof: string ++ - This format is used when the displayed adapter is connected to at least 1 device. + This format is used when the displayed controller is connected to at least 1 device. *tooltip-format-connected-battery*: ++ typeof: string ++ @@ -127,13 +130,14 @@ Addressed by *bluetooth* *{status}*: Status of the bluetooth device. -*{num_connections}*: Number of connections the selected adapter has. +*{num_connections}*: Number of connections the selected controller has. -*{adapter_address}*: Address of the selected adapter. +*{controller_address}*: Address of the selected controller. -*{adapter_address_type}*: Address type of the selected adapter. +*{controller_address_type}*: Address type of the selected controller. -*{adapter_alias}*: Alias of the selected adapter. By default equal to the *adapter_name* but can be changed by the user when there are conflicts. +*{controller_alias}*: Alias of the selected controller. By default equal to the +*controller_name* but can be changed by the user when there are conflicts. *{device_address}*: Address of the current selected selected connected device. @@ -149,11 +153,11 @@ Addressed by *bluetooth* ``` "bluetooth": { - // "adapter-alias": "adapter1", // specify the adapter alias (name) if there are more than 1 on the system + // "controller": "controller1", // specify the controller alias (name) if there are more than 1 on the system "format": " {status}", "format-connected": " {num_connections} connected", - "tooltip-format": "{adapter_alias}\t{adapter_address}", - "tooltip-format-connected": "{adapter_alias}\t{adapter_address}\n\n{device_enumerate}", + "tooltip-format": "{controller_alias}\t{controller_address}", + "tooltip-format-connected": "{controller_alias}\t{controller_address}\n\n{device_enumerate}", "tooltip-format-enumerate-connected": "{device_alias}\t{device_address}", "tooltip-format-enumerate-connected-battery": "{device_alias}\t{device_address}\t{device_battery_percentage}%" } @@ -165,7 +169,7 @@ Addressed by *bluetooth* "format-connected": " {device_alias}", "format-connected-battery": " {device_alias} {device_battery_percentage}%", // "format-device-preference": [ "alias1", "alias2" ], // preference list deciding which device to show in format-connected format-connected-battery - "tooltip-format": "{adapter_alias}\t{adapter_address}\n\n{num_connections} connected\n\n{device_enumerate}", + "tooltip-format": "{controller_alias}\t{controller_address}\n\n{num_connections} connected\n\n{device_enumerate}", "tooltip-format-enumerate-connected": "{device_alias}\t{device_address}", "tooltip-format-enumerate-connected-battery": "{device_alias}\t{device_address}\t{device_battery_percentage}%" } diff --git a/src/modules/bluetooth.cpp b/src/modules/bluetooth.cpp index e0432e9..e9b21e9 100644 --- a/src/modules/bluetooth.cpp +++ b/src/modules/bluetooth.cpp @@ -98,17 +98,17 @@ waybar::modules::Bluetooth::Bluetooth(const std::string& id, const Json::Value& [](auto x){ return x.asString(); }); } - // NOTE: assumption made that the adapter that is selcected stays unchanged + // NOTE: assumption made that the controller that is selcected stays unchanged // for duration of the module - if (!findCurAdapter(cur_adapter_)) { - if (config_["adapter-alias"].isString()) { - spdlog::error("find_cur_adapter() failed: no bluetooth adapter found with alias '{}'", config_["adapter-alias"].asString()); + if (!findCurController(cur_controller_)) { + if (config_["controller-alias"].isString()) { + spdlog::error("findCurController() failed: no bluetooth controller found with alias '{}'", config_["controller-alias"].asString()); } else { - spdlog::error("find_cur_adapter() failed: no bluetooth adapter found"); + spdlog::error("findCurController() failed: no bluetooth controller found"); } return; } - findConnectedDevices(cur_adapter_.path, connected_devices_); + findConnectedDevices(cur_controller_.path, connected_devices_); g_signal_connect(manager_.get(), "interface-proxy-properties-changed", G_CALLBACK(onInterfaceProxyPropertiesChanged), this); g_signal_connect(manager_.get(), "interface-added", G_CALLBACK(onInterfaceAddedOrRemoved), this); @@ -123,8 +123,8 @@ waybar::modules::Bluetooth::Bluetooth(const std::string& id, const Json::Value& auto waybar::modules::Bluetooth::update() -> void { // focussed device is either: // - the first device in the device_preference_ list that is connected to the - // current adapter (if none fallback to last connected device) - // - it is the last device that connected to the current adapter + // current controller (if none fallback to last connected device) + // - it is the last device that connected to the current controller if (!connected_devices_.empty()) { bool preferred_device_connected = false; if (!device_preference_.empty()) { @@ -144,7 +144,7 @@ auto waybar::modules::Bluetooth::update() -> void { std::string state; std::string tooltip_format; - if (!cur_adapter_.powered) + if (!cur_controller_.powered) state = "off"; else if (!connected_devices_.empty()) state = "connected"; @@ -179,9 +179,9 @@ auto waybar::modules::Bluetooth::update() -> void { label_.get_style_context()->remove_class(style_class); } }; - update_style_context("discoverable", cur_adapter_.discoverable); - update_style_context("discovering", cur_adapter_.discovering); - update_style_context("pairable", cur_adapter_.pairable); + update_style_context("discoverable", cur_controller_.discoverable); + update_style_context("discovering", cur_controller_.discovering); + update_style_context("pairable", cur_controller_.pairable); if (!state_.empty()) { update_style_context(state_, false); } @@ -191,9 +191,9 @@ auto waybar::modules::Bluetooth::update() -> void { label_.set_markup(fmt::format(format_, fmt::arg("status", state_), fmt::arg("num_connections", connected_devices_.size()), - fmt::arg("adapter_address", cur_adapter_.address), - fmt::arg("adapter_address_type", cur_adapter_.address_type), - fmt::arg("adapter_alias", cur_adapter_.alias), + fmt::arg("controller_address", cur_controller_.address), + fmt::arg("controller_address_type", cur_controller_.address_type), + fmt::arg("controller_alias", cur_controller_.alias), fmt::arg("device_address", cur_focussed_device_.address), fmt::arg("device_address_type", cur_focussed_device_.address_type), fmt::arg("device_alias", cur_focussed_device_.alias), @@ -225,9 +225,9 @@ auto waybar::modules::Bluetooth::update() -> void { label_.set_tooltip_text(fmt::format(tooltip_format, fmt::arg("status", state_), fmt::arg("num_connections", connected_devices_.size()), - fmt::arg("adapter_address", cur_adapter_.address), - fmt::arg("adapter_address_type", cur_adapter_.address_type), - fmt::arg("adapter_alias", cur_adapter_.alias), + fmt::arg("controller_address", cur_controller_.address), + fmt::arg("controller_address_type", cur_controller_.address_type), + fmt::arg("controller_alias", cur_controller_.alias), fmt::arg("device_address", cur_focussed_device_.address), fmt::arg("device_address_type", cur_focussed_device_.address_type), fmt::arg("device_alias", cur_focussed_device_.alias), @@ -269,8 +269,8 @@ auto waybar::modules::Bluetooth::onInterfaceProxyPropertiesChanged(GDBusObjectMa Bluetooth* bt = static_cast(user_data); if (interface_name == "org.bluez.Adapter1") { - if (object_path == bt->cur_adapter_.path) { - bt->getAdapterProperties(G_DBUS_OBJECT(object_proxy), bt->cur_adapter_); + if (object_path == bt->cur_controller_.path) { + bt->getControllerProperties(G_DBUS_OBJECT(object_proxy), bt->cur_controller_); bt->dp.emit(); } } else if (interface_name == "org.bluez.Device1" || @@ -310,7 +310,7 @@ auto waybar::modules::Bluetooth::getDeviceProperties(GDBusObject* object, Device if (proxy_device != NULL) { device_info.path = g_dbus_object_get_object_path(object); - device_info.paired_adapter = getStringProperty(proxy_device, "Adapter"); + device_info.paired_controller = getStringProperty(proxy_device, "Adapter"); device_info.address = getStringProperty(proxy_device, "Address"); device_info.address_type = getStringProperty(proxy_device, "AddressType"); device_info.alias = getStringProperty(proxy_device, "Alias"); @@ -330,49 +330,49 @@ auto waybar::modules::Bluetooth::getDeviceProperties(GDBusObject* object, Device return false; } -auto waybar::modules::Bluetooth::getAdapterProperties(GDBusObject* object, AdapterInfo& adapter_info) -> bool { - GDBusProxy* proxy_adapter = G_DBUS_PROXY(g_dbus_object_get_interface(object, "org.bluez.Adapter1")); +auto waybar::modules::Bluetooth::getControllerProperties(GDBusObject* object, ControllerInfo& controller_info) -> bool { + GDBusProxy* proxy_controller = G_DBUS_PROXY(g_dbus_object_get_interface(object, "org.bluez.Adapter1")); - if (proxy_adapter != NULL) { - adapter_info.path = g_dbus_object_get_object_path(object); - adapter_info.address = getStringProperty(proxy_adapter, "Address"); - adapter_info.address_type = getStringProperty(proxy_adapter, "AddressType"); - adapter_info.alias = getStringProperty(proxy_adapter, "Alias"); - adapter_info.powered = getBoolProperty(proxy_adapter, "Powered"); - adapter_info.discoverable = getBoolProperty(proxy_adapter, "Discoverable"); - adapter_info.pairable = getBoolProperty(proxy_adapter, "Pairable"); - adapter_info.discovering = getBoolProperty(proxy_adapter, "Discovering"); + if (proxy_controller != NULL) { + controller_info.path = g_dbus_object_get_object_path(object); + controller_info.address = getStringProperty(proxy_controller, "Address"); + controller_info.address_type = getStringProperty(proxy_controller, "AddressType"); + controller_info.alias = getStringProperty(proxy_controller, "Alias"); + controller_info.powered = getBoolProperty(proxy_controller, "Powered"); + controller_info.discoverable = getBoolProperty(proxy_controller, "Discoverable"); + controller_info.pairable = getBoolProperty(proxy_controller, "Pairable"); + controller_info.discovering = getBoolProperty(proxy_controller, "Discovering"); - g_object_unref(proxy_adapter); + g_object_unref(proxy_controller); return true; } return false; } -auto waybar::modules::Bluetooth::findCurAdapter(AdapterInfo& adapter_info) -> bool { - bool found_adapter = false; +auto waybar::modules::Bluetooth::findCurController(ControllerInfo& controller_info) -> bool { + bool found_controller = false; GList* objects = g_dbus_object_manager_get_objects(manager_.get()); for (GList* l = objects; l != NULL; l = l->next) { GDBusObject* object = G_DBUS_OBJECT(l->data); - if (getAdapterProperties(object, adapter_info) && (!config_["adapter-alias"].isString() || config_["adapter-alias"].asString() == adapter_info.alias)) { - found_adapter = true; + if (getControllerProperties(object, controller_info) && (!config_["controller-alias"].isString() || config_["controller-alias"].asString() == controller_info.alias)) { + found_controller = true; break; } } g_list_free_full(objects, g_object_unref); - return found_adapter; + return found_controller; } -auto waybar::modules::Bluetooth::findConnectedDevices(const std::string& cur_adapter_path, std::vector& connected_devices) -> void { +auto waybar::modules::Bluetooth::findConnectedDevices(const std::string& cur_controller_path, std::vector& connected_devices) -> void { GList* objects = g_dbus_object_manager_get_objects(manager_.get()); for (GList* l = objects; l != NULL; l = l->next) { GDBusObject* object = G_DBUS_OBJECT(l->data); DeviceInfo device; - if (getDeviceProperties(object, device) && device.connected && device.paired_adapter == cur_adapter_.path) { + if (getDeviceProperties(object, device) && device.connected && device.paired_controller == cur_controller_.path) { connected_devices.push_back(device); } } From 733fb8c62a0ee2efe58f53fa459389a17cb1b61d Mon Sep 17 00:00:00 2001 From: Daan Goossens Date: Fri, 6 May 2022 16:17:11 +0200 Subject: [PATCH 5/7] docs: update + add experimental section --- include/modules/bluetooth.hpp | 2 +- man/waybar-bluetooth.5.scd | 86 +++++++++++++++++++---------------- 2 files changed, 47 insertions(+), 41 deletions(-) diff --git a/include/modules/bluetooth.hpp b/include/modules/bluetooth.hpp index 56472f2..6011dac 100644 --- a/include/modules/bluetooth.hpp +++ b/include/modules/bluetooth.hpp @@ -40,7 +40,7 @@ class Bluetooth : public ALabel { bool blocked; bool connected; bool services_resolved; - // TODO: make experimental in waybar as it is also a experimental feature in bluez + // NOTE: experimental feature in bluez std::optional battery_percentage; }; diff --git a/man/waybar-bluetooth.5.scd b/man/waybar-bluetooth.5.scd index 1567f2c..f69610d 100644 --- a/man/waybar-bluetooth.5.scd +++ b/man/waybar-bluetooth.5.scd @@ -6,7 +6,7 @@ waybar - bluetooth module # DESCRIPTION -The *bluetooth* module displays information about the bluetooth controller and its connections. +The *bluetooth* module displays information about a bluetooth controller and its connections. # CONFIGURATION @@ -14,14 +14,12 @@ Addressed by *bluetooth* *controller*: ++ typeof: string ++ - Use the controller with the defined alias (name). Otherwise select a - random controller to display. Recommended to define when there is more - than 1 controller available to the system (use ```bluetoothctl show``` - to show all available controller). + Use the controller with the defined alias. Otherwise a random controller is used. Recommended to define when there is more than 1 controller available to the system. *format-device-preference*: ++ typeof: array ++ - A ranking of bluetooth devices, addressed by their alias (name). The order is *first displayed* to *last displayed*. If this config option is not defined or none of the devices in the list are connected, it will fall back to showing the last connected device. A devices alias can be manually changed using the ```bluetoothctl set-alias``` command. + A ranking of bluetooth devices, addressed by their alias. The order is from *first displayed* to *last displayed*. ++ + If this config option is not defined or none of the devices in the list are connected, it will fall back to showing the last connected device. *format*: ++ typeof: string ++ @@ -44,10 +42,6 @@ Addressed by *bluetooth* typeof: string ++ This format is used when the displayed controller is connected to at least 1 device. -*format-connected-battery*: ++ - typeof: string ++ - This format is used when the selected connected device, defined by the config option *format-device-preference*, provides is battery percentage. This needs the experimental features of bluez to be enabled to work. - *rotate*: ++ typeof: integer ++ Positive value to rotate the text label. @@ -113,65 +107,77 @@ Addressed by *bluetooth* typeof: string ++ This format is used when the displayed controller is connected to at least 1 device. -*tooltip-format-connected-battery*: ++ - typeof: string ++ - This format is used when the selected connected device, defined by the config option *format-device-preference*, provides is battery percentage. This needs the experimental features of bluez to be enabled to work. - *tooltip-format-enumerate-connected*: ++ typeof: string ++ This format is used to define how each connected device should be displayed within the *device_enumerate* format replacement in the tooltip menu. -*tooltip-format-enumerate-connected-battery*: ++ - typeof: string ++ - This format is used to define how each connected device with a battery should be displayed within the *device_enumerate* format replacement in the tooltip menu. When this config option is not defined, the *tooltip-format-enumerate-connected* format will be used also for the connected devices with a battery. - - # FORMAT REPLACEMENTS *{status}*: Status of the bluetooth device. -*{num_connections}*: Number of connections the selected controller has. +*{num_connections}*: Number of connections the displayed controller has. -*{controller_address}*: Address of the selected controller. +*{controller_address}*: Address of the displayed controller. -*{controller_address_type}*: Address type of the selected controller. +*{controller_address_type}*: Address type of the displayed controller. -*{controller_alias}*: Alias of the selected controller. By default equal to the -*controller_name* but can be changed by the user when there are conflicts. +*{controller_alias}*: Alias of the displayed controller. -*{device_address}*: Address of the current selected selected connected device. +*{device_address}*: Address of the displayed device. -*{device_address_type}*: Address type of the current selected selected connected device. +*{device_address_type}*: Address type of the displayed device. -*{device_alias}*: Alias of the current selected connected device. By default equal to the *device_name* but can be changed by the user when there are conflicts. +*{device_alias}*: Alias of the displayed device. -*{device_battery_percentage}*: Battery percentage of the current selected device if available. Only use in the *format-connected-battery* and *tooltip-format-connected-battery*. +*{device_enumerate}*: Show a list of all connected devices, each on a seperate line. Define the format of each device with the *tooltip-format-enumerate-connected* ++ +and/or *tooltip-format-enumerate-connected-battery* config options. Can only be used in the tooltip related format options. -*{device_enumerate}*: Show a list of all connected devices in the tooltip, each on a seperate line. Only applicable in the *connected* state. Define the format of each device with the *tooltip-format-enumerate-connected* or/and *tooltip-format-enumerate-connected-battery* config options. +# EXPERIMENTAL BATTERY PERCENTAGE FEATURE + +At the time of writing, the experimental features of BlueZ need to be turned on, for the battery percentage options listed below to work. + +## FORMAT REPLACEMENT + +*{device_battery_percentage}*: Battery percentage of the displayed device if available. Use only in the config options defined below. + +## CONFIGURATION + +*format-connected-battery*: ++ + typeof: string ++ + This format is used when the displayed device provides its battery percentage. + +*tooltip-format-connected-battery*: ++ + typeof: string ++ + This format is used when the displayed device provides its battery percentage. + +*tooltip-format-enumerate-connected-battery*: ++ + typeof: string ++ + This format is used to define how each connected device with a battery should be displayed within the *device_enumerate* format replacement option. ++ + When this config option is not defined, it will fall back on the *tooltip-format-enumerate-connected* config option. # EXAMPLES ``` "bluetooth": { - // "controller": "controller1", // specify the controller alias (name) if there are more than 1 on the system + // "controller": "controller1", // specify the alias of the controller if there are more than 1 on the system "format": " {status}", "format-connected": " {num_connections} connected", - "tooltip-format": "{controller_alias}\t{controller_address}", - "tooltip-format-connected": "{controller_alias}\t{controller_address}\n\n{device_enumerate}", - "tooltip-format-enumerate-connected": "{device_alias}\t{device_address}", - "tooltip-format-enumerate-connected-battery": "{device_alias}\t{device_address}\t{device_battery_percentage}%" + "tooltip-format": "{controller_alias}\\t{controller_address}", + "tooltip-format-connected": "{controller_alias}\\t{controller_address}\\n\\n{device_enumerate}", + "tooltip-format-enumerate-connected": "{device_alias}\\t{device_address}" } ``` ``` "bluetooth": { "format": " {status}", - "format-connected": " {device_alias}", - "format-connected-battery": " {device_alias} {device_battery_percentage}%", - // "format-device-preference": [ "alias1", "alias2" ], // preference list deciding which device to show in format-connected format-connected-battery - "tooltip-format": "{controller_alias}\t{controller_address}\n\n{num_connections} connected\n\n{device_enumerate}", - "tooltip-format-enumerate-connected": "{device_alias}\t{device_address}", - "tooltip-format-enumerate-connected-battery": "{device_alias}\t{device_address}\t{device_battery_percentage}%" + "format-connected": " {device_alias}", + "format-connected-battery": " {device_alias} {device_battery_percentage}%", + // "format-device-preference": [ "device1", "device2" ], // preference list deciding the displayed device + "tooltip-format": "{controller_alias}\\t{controller_address}\\n\\n{num_connections} connected", + "tooltip-format-connected": "{controller_alias}\\t{controller_address}\\n\\n{num_connections} connected\\n\\n{device_enumerate}", + "tooltip-format-enumerate-connected": "{device_alias}\\t{device_address}", + "tooltip-format-enumerate-connected-battery": "{device_alias}\\t{device_address}\\t{device_battery_percentage}%" } ``` From 3043d42a89efbd0ac32dcfd9be60371d6c8779c1 Mon Sep 17 00:00:00 2001 From: Daan Goossens Date: Fri, 6 May 2022 17:01:43 +0200 Subject: [PATCH 6/7] style: apply projects clang-format --- include/factory.hpp | 2 +- include/modules/bluetooth.hpp | 19 ++-- src/factory.cpp | 6 +- src/modules/bluetooth.cpp | 167 ++++++++++++++++++---------------- 4 files changed, 102 insertions(+), 92 deletions(-) diff --git a/include/factory.hpp b/include/factory.hpp index e9d9984..2d07b4b 100644 --- a/include/factory.hpp +++ b/include/factory.hpp @@ -55,8 +55,8 @@ #include "modules/sndio.hpp" #endif #ifdef HAVE_GIO_UNIX -#include "modules/inhibitor.hpp" #include "modules/bluetooth.hpp" +#include "modules/inhibitor.hpp" #endif #include "bar.hpp" #include "modules/custom.hpp" diff --git a/include/modules/bluetooth.hpp b/include/modules/bluetooth.hpp index 6011dac..bd9737b 100644 --- a/include/modules/bluetooth.hpp +++ b/include/modules/bluetooth.hpp @@ -5,15 +5,15 @@ #include "util/rfkill.hpp" #endif #include -#include -#include + #include +#include +#include namespace waybar::modules { class Bluetooth : public ALabel { - struct ControllerInfo - { + struct ControllerInfo { std::string path; std::string address; std::string address_type; @@ -26,8 +26,7 @@ class Bluetooth : public ALabel { }; // NOTE: there are some properties that not all devices provide - struct DeviceInfo - { + struct DeviceInfo { std::string path; std::string paired_controller; std::string address; @@ -50,8 +49,11 @@ class Bluetooth : public ALabel { auto update() -> void; private: - static auto onInterfaceAddedOrRemoved(GDBusObjectManager*, GDBusObject*, GDBusInterface*, gpointer) -> void; - static auto onInterfaceProxyPropertiesChanged(GDBusObjectManagerClient*, GDBusObjectProxy*, GDBusProxy*, GVariant*, const gchar* const*, gpointer) -> void; + static auto onInterfaceAddedOrRemoved(GDBusObjectManager*, GDBusObject*, GDBusInterface*, + gpointer) -> void; + static auto onInterfaceProxyPropertiesChanged(GDBusObjectManagerClient*, GDBusObjectProxy*, + GDBusProxy*, GVariant*, const gchar* const*, + gpointer) -> void; auto getDeviceBatteryPercentage(GDBusObject*) -> std::optional; auto getDeviceProperties(GDBusObject*, DeviceInfo&) -> bool; @@ -60,7 +62,6 @@ class Bluetooth : public ALabel { auto findCurController(ControllerInfo&) -> bool; auto findConnectedDevices(const std::string&, std::vector&) -> void; - #ifdef WANT_RFKILL util::Rfkill rfkill_; #endif diff --git a/src/factory.cpp b/src/factory.cpp index e0d99f1..5f2d755 100644 --- a/src/factory.cpp +++ b/src/factory.cpp @@ -101,12 +101,12 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name) const { } #endif #ifdef HAVE_GIO_UNIX - if (ref == "inhibitor") { - return new waybar::modules::Inhibitor(id, bar_, config_[name]); - } if (ref == "bluetooth") { return new waybar::modules::Bluetooth(id, config_[name]); } + if (ref == "inhibitor") { + return new waybar::modules::Inhibitor(id, bar_, config_[name]); + } #endif if (ref == "temperature") { return new waybar::modules::Temperature(id, config_[name]); diff --git a/src/modules/bluetooth.cpp b/src/modules/bluetooth.cpp index e9b21e9..3cc1296 100644 --- a/src/modules/bluetooth.cpp +++ b/src/modules/bluetooth.cpp @@ -1,9 +1,10 @@ #include "modules/bluetooth.hpp" +#include +#include + #include #include -#include -#include namespace { @@ -12,16 +13,9 @@ using GDBusManager = std::unique_ptr GDBusManager { GError* error = nullptr; GDBusObjectManager* manager = g_dbus_object_manager_client_new_for_bus_sync( - G_BUS_TYPE_SYSTEM, - GDBusObjectManagerClientFlags::G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START, - "org.bluez", - "/", - NULL, - NULL, - NULL, - NULL, - &error - ); + G_BUS_TYPE_SYSTEM, + GDBusObjectManagerClientFlags::G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_DO_NOT_AUTO_START, + "org.bluez", "/", NULL, NULL, NULL, NULL, &error); if (error) { spdlog::error("g_dbus_object_manager_client_new_for_bus_sync() failed: {}", error->message); @@ -49,7 +43,8 @@ auto getBoolProperty(GDBusProxy* proxy, const char* property_name) -> bool { return false; } -auto getOptionalStringProperty(GDBusProxy* proxy, const char* property_name) -> std::optional { +auto getOptionalStringProperty(GDBusProxy* proxy, const char* property_name) + -> std::optional { auto gvar = g_dbus_proxy_get_cached_property(proxy, property_name); if (gvar) { std::string property_value = g_variant_get_string(gvar, NULL); @@ -94,15 +89,15 @@ waybar::modules::Bluetooth::Bluetooth(const std::string& id, const Json::Value& if (config_["format-device-preference"].isArray()) { std::transform(config_["format-device-preference"].begin(), config_["format-device-preference"].end(), - std::back_inserter(device_preference_), - [](auto x){ return x.asString(); }); + std::back_inserter(device_preference_), [](auto x) { return x.asString(); }); } // NOTE: assumption made that the controller that is selcected stays unchanged // for duration of the module if (!findCurController(cur_controller_)) { if (config_["controller-alias"].isString()) { - spdlog::error("findCurController() failed: no bluetooth controller found with alias '{}'", config_["controller-alias"].asString()); + spdlog::error("findCurController() failed: no bluetooth controller found with alias '{}'", + config_["controller-alias"].asString()); } else { spdlog::error("findCurController() failed: no bluetooth controller found"); } @@ -110,9 +105,11 @@ waybar::modules::Bluetooth::Bluetooth(const std::string& id, const Json::Value& } findConnectedDevices(cur_controller_.path, connected_devices_); - g_signal_connect(manager_.get(), "interface-proxy-properties-changed", G_CALLBACK(onInterfaceProxyPropertiesChanged), this); + g_signal_connect(manager_.get(), "interface-proxy-properties-changed", + G_CALLBACK(onInterfaceProxyPropertiesChanged), this); g_signal_connect(manager_.get(), "interface-added", G_CALLBACK(onInterfaceAddedOrRemoved), this); - g_signal_connect(manager_.get(), "interface-removed", G_CALLBACK(onInterfaceAddedOrRemoved), this); + g_signal_connect(manager_.get(), "interface-removed", G_CALLBACK(onInterfaceAddedOrRemoved), + this); #ifdef WANT_RFKILL rfkill_.on_update.connect(sigc::hide(sigc::mem_fun(*this, &Bluetooth::update))); #endif @@ -129,7 +126,9 @@ auto waybar::modules::Bluetooth::update() -> void { bool preferred_device_connected = false; if (!device_preference_.empty()) { for (const std::string& device_alias : device_preference_) { - auto it = std::find_if(connected_devices_.begin(), connected_devices_.end(), [device_alias](auto device){ return device_alias == device.alias; }); + auto it = + std::find_if(connected_devices_.begin(), connected_devices_.end(), + [device_alias](auto device) { return device_alias == device.alias; }); if (it != connected_devices_.end()) { preferred_device_connected = true; cur_focussed_device_ = *it; @@ -151,12 +150,12 @@ auto waybar::modules::Bluetooth::update() -> void { else state = "on"; #ifdef WANT_RFKILL - if (rfkill_.getState()) - state = "disabled"; + if (rfkill_.getState()) state = "disabled"; #endif if (!alt_) { - if (state == "connected" && cur_focussed_device_.battery_percentage.has_value() && config_["format-connected-battery"].isString()) { + if (state == "connected" && cur_focussed_device_.battery_percentage.has_value() && + config_["format-connected-battery"].isString()) { format_ = config_["format-connected-battery"].asString(); } else if (config_["format-" + state].isString()) { format_ = config_["format-" + state].asString(); @@ -188,32 +187,35 @@ auto waybar::modules::Bluetooth::update() -> void { update_style_context(state, true); state_ = state; - label_.set_markup(fmt::format(format_, - fmt::arg("status", state_), - fmt::arg("num_connections", connected_devices_.size()), - fmt::arg("controller_address", cur_controller_.address), - fmt::arg("controller_address_type", cur_controller_.address_type), - fmt::arg("controller_alias", cur_controller_.alias), - fmt::arg("device_address", cur_focussed_device_.address), - fmt::arg("device_address_type", cur_focussed_device_.address_type), - fmt::arg("device_alias", cur_focussed_device_.alias), - fmt::arg("device_battery_percentage", cur_focussed_device_.battery_percentage.value_or(0)) - )); + label_.set_markup(fmt::format( + format_, fmt::arg("status", state_), fmt::arg("num_connections", connected_devices_.size()), + fmt::arg("controller_address", cur_controller_.address), + fmt::arg("controller_address_type", cur_controller_.address_type), + fmt::arg("controller_alias", cur_controller_.alias), + fmt::arg("device_address", cur_focussed_device_.address), + fmt::arg("device_address_type", cur_focussed_device_.address_type), + fmt::arg("device_alias", cur_focussed_device_.alias), + fmt::arg("device_battery_percentage", cur_focussed_device_.battery_percentage.value_or(0)))); if (tooltipEnabled()) { bool tooltip_enumerate_connections_ = config_["tooltip-format-enumerate-connected"].isString(); - bool tooltip_enumerate_connections_battery_ = config_["tooltip-format-enumerate-connected-battery"].isString(); + bool tooltip_enumerate_connections_battery_ = + config_["tooltip-format-enumerate-connected-battery"].isString(); if (tooltip_enumerate_connections_ || tooltip_enumerate_connections_battery_) { std::stringstream ss; for (DeviceInfo dev : connected_devices_) { - if ((tooltip_enumerate_connections_battery_ && dev.battery_percentage.has_value()) || tooltip_enumerate_connections_) { + if ((tooltip_enumerate_connections_battery_ && dev.battery_percentage.has_value()) || + tooltip_enumerate_connections_) { ss << "\n"; - std::string enumerate_format = (tooltip_enumerate_connections_battery_ && dev.battery_percentage.has_value()) ? config_["tooltip-format-enumerate-connected-battery"].asString() : config_["tooltip-format-enumerate-connected"].asString(); - ss << fmt::format(enumerate_format, - fmt::arg("device_address", dev.address), - fmt::arg("device_address_type", dev.address_type), - fmt::arg("device_alias", dev.alias), - fmt::arg("device_battery_percentage", dev.battery_percentage.value_or(0))); + std::string enumerate_format = + (tooltip_enumerate_connections_battery_ && dev.battery_percentage.has_value()) + ? config_["tooltip-format-enumerate-connected-battery"].asString() + : config_["tooltip-format-enumerate-connected"].asString(); + ss << fmt::format( + enumerate_format, fmt::arg("device_address", dev.address), + fmt::arg("device_address_type", dev.address_type), + fmt::arg("device_alias", dev.alias), + fmt::arg("device_battery_percentage", dev.battery_percentage.value_or(0))); } } device_enumerate_ = ss.str(); @@ -222,34 +224,35 @@ auto waybar::modules::Bluetooth::update() -> void { device_enumerate_.erase(0, 1); } } - label_.set_tooltip_text(fmt::format(tooltip_format, - fmt::arg("status", state_), - fmt::arg("num_connections", connected_devices_.size()), - fmt::arg("controller_address", cur_controller_.address), - fmt::arg("controller_address_type", cur_controller_.address_type), - fmt::arg("controller_alias", cur_controller_.alias), - fmt::arg("device_address", cur_focussed_device_.address), - fmt::arg("device_address_type", cur_focussed_device_.address_type), - fmt::arg("device_alias", cur_focussed_device_.alias), - fmt::arg("device_battery_percentage", cur_focussed_device_.battery_percentage.value_or(0)), - fmt::arg("device_enumerate", device_enumerate_) - )); + label_.set_tooltip_text(fmt::format( + tooltip_format, fmt::arg("status", state_), + fmt::arg("num_connections", connected_devices_.size()), + fmt::arg("controller_address", cur_controller_.address), + fmt::arg("controller_address_type", cur_controller_.address_type), + fmt::arg("controller_alias", cur_controller_.alias), + fmt::arg("device_address", cur_focussed_device_.address), + fmt::arg("device_address_type", cur_focussed_device_.address_type), + fmt::arg("device_alias", cur_focussed_device_.alias), + fmt::arg("device_battery_percentage", cur_focussed_device_.battery_percentage.value_or(0)), + fmt::arg("device_enumerate", device_enumerate_))); } // Call parent update ALabel::update(); } -// NOTE: only for when the org.bluez.Battery1 interface is added/removed after/before a device is connected/disconnected -auto waybar::modules::Bluetooth::onInterfaceAddedOrRemoved(GDBusObjectManager *manager, GDBusObject *object, - GDBusInterface *interface, - gpointer user_data) -> void -{ +// NOTE: only for when the org.bluez.Battery1 interface is added/removed after/before a device is +// connected/disconnected +auto waybar::modules::Bluetooth::onInterfaceAddedOrRemoved(GDBusObjectManager* manager, + GDBusObject* object, + GDBusInterface* interface, + gpointer user_data) -> void { std::string interface_name = g_dbus_proxy_get_interface_name(G_DBUS_PROXY(interface)); std::string object_path = g_dbus_proxy_get_object_path(G_DBUS_PROXY(interface)); if (interface_name == "org.bluez.Battery1") { Bluetooth* bt = static_cast(user_data); - auto device = std::find_if(bt->connected_devices_.begin(), bt->connected_devices_.end(), [object_path](auto d){ return d.path == object_path; }); + auto device = std::find_if(bt->connected_devices_.begin(), bt->connected_devices_.end(), + [object_path](auto d) { return d.path == object_path; }); if (device != bt->connected_devices_.end()) { device->battery_percentage = bt->getDeviceBatteryPercentage(object); bt->dp.emit(); @@ -257,13 +260,10 @@ auto waybar::modules::Bluetooth::onInterfaceAddedOrRemoved(GDBusObjectManager *m } } -auto waybar::modules::Bluetooth::onInterfaceProxyPropertiesChanged(GDBusObjectManagerClient *manager, - GDBusObjectProxy *object_proxy, - GDBusProxy *interface_proxy, - GVariant *changed_properties, - const gchar *const *invalidated_properties, - gpointer user_data) -> void -{ +auto waybar::modules::Bluetooth::onInterfaceProxyPropertiesChanged( + GDBusObjectManagerClient* manager, GDBusObjectProxy* object_proxy, GDBusProxy* interface_proxy, + GVariant* changed_properties, const gchar* const* invalidated_properties, gpointer user_data) + -> void { std::string interface_name = g_dbus_proxy_get_interface_name(interface_proxy); std::string object_path = g_dbus_object_get_object_path(G_DBUS_OBJECT(object_proxy)); @@ -273,11 +273,11 @@ auto waybar::modules::Bluetooth::onInterfaceProxyPropertiesChanged(GDBusObjectMa bt->getControllerProperties(G_DBUS_OBJECT(object_proxy), bt->cur_controller_); bt->dp.emit(); } - } else if (interface_name == "org.bluez.Device1" || - interface_name == "org.bluez.Battery1") { + } else if (interface_name == "org.bluez.Device1" || interface_name == "org.bluez.Battery1") { DeviceInfo device; bt->getDeviceProperties(G_DBUS_OBJECT(object_proxy), device); - auto cur_device = std::find_if(bt->connected_devices_.begin(), bt->connected_devices_.end(), [device](auto d){ return d.path == device.path; }); + auto cur_device = std::find_if(bt->connected_devices_.begin(), bt->connected_devices_.end(), + [device](auto d) { return d.path == device.path; }); if (cur_device == bt->connected_devices_.end()) { if (device.connected) { bt->connected_devices_.push_back(device); @@ -294,8 +294,10 @@ auto waybar::modules::Bluetooth::onInterfaceProxyPropertiesChanged(GDBusObjectMa } } -auto waybar::modules::Bluetooth::getDeviceBatteryPercentage(GDBusObject* object) -> std::optional { - GDBusProxy* proxy_device_bat = G_DBUS_PROXY(g_dbus_object_get_interface(object, "org.bluez.Battery1")); +auto waybar::modules::Bluetooth::getDeviceBatteryPercentage(GDBusObject* object) + -> std::optional { + GDBusProxy* proxy_device_bat = + G_DBUS_PROXY(g_dbus_object_get_interface(object, "org.bluez.Battery1")); if (proxy_device_bat != NULL) { unsigned char battery_percentage = getUcharProperty(proxy_device_bat, "Percentage"); g_object_unref(proxy_device_bat); @@ -305,7 +307,8 @@ auto waybar::modules::Bluetooth::getDeviceBatteryPercentage(GDBusObject* object) return std::nullopt; } -auto waybar::modules::Bluetooth::getDeviceProperties(GDBusObject* object, DeviceInfo& device_info) -> bool { +auto waybar::modules::Bluetooth::getDeviceProperties(GDBusObject* object, DeviceInfo& device_info) + -> bool { GDBusProxy* proxy_device = G_DBUS_PROXY(g_dbus_object_get_interface(object, "org.bluez.Device1")); if (proxy_device != NULL) { @@ -330,8 +333,10 @@ auto waybar::modules::Bluetooth::getDeviceProperties(GDBusObject* object, Device return false; } -auto waybar::modules::Bluetooth::getControllerProperties(GDBusObject* object, ControllerInfo& controller_info) -> bool { - GDBusProxy* proxy_controller = G_DBUS_PROXY(g_dbus_object_get_interface(object, "org.bluez.Adapter1")); +auto waybar::modules::Bluetooth::getControllerProperties(GDBusObject* object, + ControllerInfo& controller_info) -> bool { + GDBusProxy* proxy_controller = + G_DBUS_PROXY(g_dbus_object_get_interface(object, "org.bluez.Adapter1")); if (proxy_controller != NULL) { controller_info.path = g_dbus_object_get_object_path(object); @@ -356,7 +361,9 @@ auto waybar::modules::Bluetooth::findCurController(ControllerInfo& controller_in GList* objects = g_dbus_object_manager_get_objects(manager_.get()); for (GList* l = objects; l != NULL; l = l->next) { GDBusObject* object = G_DBUS_OBJECT(l->data); - if (getControllerProperties(object, controller_info) && (!config_["controller-alias"].isString() || config_["controller-alias"].asString() == controller_info.alias)) { + if (getControllerProperties(object, controller_info) && + (!config_["controller-alias"].isString() || + config_["controller-alias"].asString() == controller_info.alias)) { found_controller = true; break; } @@ -366,13 +373,15 @@ auto waybar::modules::Bluetooth::findCurController(ControllerInfo& controller_in return found_controller; } -auto waybar::modules::Bluetooth::findConnectedDevices(const std::string& cur_controller_path, std::vector& connected_devices) -> void { +auto waybar::modules::Bluetooth::findConnectedDevices(const std::string& cur_controller_path, + std::vector& connected_devices) + -> void { GList* objects = g_dbus_object_manager_get_objects(manager_.get()); - for (GList* l = objects; l != NULL; l = l->next) - { + for (GList* l = objects; l != NULL; l = l->next) { GDBusObject* object = G_DBUS_OBJECT(l->data); DeviceInfo device; - if (getDeviceProperties(object, device) && device.connected && device.paired_controller == cur_controller_.path) { + if (getDeviceProperties(object, device) && device.connected && + device.paired_controller == cur_controller_.path) { connected_devices.push_back(device); } } From e235f4824571d17fe7ab23a93dec89f9bcdf8553 Mon Sep 17 00:00:00 2001 From: Daan Goossens Date: Sat, 7 May 2022 13:42:27 +0200 Subject: [PATCH 7/7] feat: hide module if empty --- man/waybar-bluetooth.5.scd | 1 + src/modules/bluetooth.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/man/waybar-bluetooth.5.scd b/man/waybar-bluetooth.5.scd index f69610d..cafe23c 100644 --- a/man/waybar-bluetooth.5.scd +++ b/man/waybar-bluetooth.5.scd @@ -161,6 +161,7 @@ At the time of writing, the experimental features of BlueZ need to be turned on, "bluetooth": { // "controller": "controller1", // specify the alias of the controller if there are more than 1 on the system "format": " {status}", + "format-disabled": "", // an empty format will hide the module "format-connected": " {num_connections} connected", "tooltip-format": "{controller_alias}\\t{controller_address}", "tooltip-format-connected": "{controller_alias}\\t{controller_address}\\n\\n{device_enumerate}", diff --git a/src/modules/bluetooth.cpp b/src/modules/bluetooth.cpp index 3cc1296..4c77eb2 100644 --- a/src/modules/bluetooth.cpp +++ b/src/modules/bluetooth.cpp @@ -171,6 +171,8 @@ auto waybar::modules::Bluetooth::update() -> void { tooltip_format = config_["tooltip-format"].asString(); } + format_.empty() ? event_box_.hide() : event_box_.show(); + auto update_style_context = [this](const std::string& style_class, bool in_next_state) { if (in_next_state && !label_.get_style_context()->has_class(style_class)) { label_.get_style_context()->add_class(style_class);