Add hotplug detection of bluetooth controllers

This commit is contained in:
Lukas Fink 2024-06-14 02:24:24 +02:00
parent 79a6229522
commit ab91d0bac3
2 changed files with 64 additions and 18 deletions

View File

@ -49,6 +49,9 @@ class Bluetooth : public ALabel {
auto update() -> void override; auto update() -> void override;
private: private:
static auto onObjectAdded(GDBusObjectManager*, GDBusObject*, gpointer) -> void;
static auto onObjectRemoved(GDBusObjectManager*, GDBusObject*, gpointer) -> void;
static auto onInterfaceAddedOrRemoved(GDBusObjectManager*, GDBusObject*, GDBusInterface*, static auto onInterfaceAddedOrRemoved(GDBusObjectManager*, GDBusObject*, GDBusInterface*,
gpointer) -> void; gpointer) -> void;
static auto onInterfaceProxyPropertiesChanged(GDBusObjectManagerClient*, GDBusObjectProxy*, static auto onInterfaceProxyPropertiesChanged(GDBusObjectManagerClient*, GDBusObjectProxy*,

View File

@ -98,19 +98,21 @@ waybar::modules::Bluetooth::Bluetooth(const std::string& id, const Json::Value&
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 selected stays unchanged
// for duration of the module
if (cur_controller_ = findCurController(); !cur_controller_) { if (cur_controller_ = findCurController(); !cur_controller_) {
if (config_["controller-alias"].isString()) { if (config_["controller-alias"].isString()) {
spdlog::error("findCurController() failed: no bluetooth controller found with alias '{}'", spdlog::warn("no bluetooth controller found with alias '{}'",
config_["controller-alias"].asString()); config_["controller-alias"].asString());
} else { } else {
spdlog::error("findCurController() failed: no bluetooth controller found"); spdlog::warn("no bluetooth controller found");
} }
update(); update();
} else { } else {
// These calls only make sense if a controller could be found // This call only make sense if a controller could be found
findConnectedDevices(cur_controller_->path, connected_devices_); findConnectedDevices(cur_controller_->path, connected_devices_);
}
g_signal_connect(manager_.get(), "object-added", G_CALLBACK(onObjectAdded), this);
g_signal_connect(manager_.get(), "object-removed", G_CALLBACK(onObjectRemoved), this);
g_signal_connect(manager_.get(), "interface-proxy-properties-changed", g_signal_connect(manager_.get(), "interface-proxy-properties-changed",
G_CALLBACK(onInterfaceProxyPropertiesChanged), this); G_CALLBACK(onInterfaceProxyPropertiesChanged), this);
g_signal_connect(manager_.get(), "interface-added", G_CALLBACK(onInterfaceAddedOrRemoved), g_signal_connect(manager_.get(), "interface-added", G_CALLBACK(onInterfaceAddedOrRemoved),
@ -121,7 +123,6 @@ waybar::modules::Bluetooth::Bluetooth(const std::string& id, const Json::Value&
#ifdef WANT_RFKILL #ifdef WANT_RFKILL
rfkill_.on_update.connect(sigc::hide(sigc::mem_fun(*this, &Bluetooth::update))); rfkill_.on_update.connect(sigc::hide(sigc::mem_fun(*this, &Bluetooth::update)));
#endif #endif
}
dp.emit(); dp.emit();
} }
@ -282,6 +283,41 @@ auto waybar::modules::Bluetooth::update() -> void {
ALabel::update(); ALabel::update();
} }
auto waybar::modules::Bluetooth::onObjectAdded(GDBusObjectManager* manager,
GDBusObject* object,
gpointer user_data) -> void {
ControllerInfo info;
Bluetooth* bt = static_cast<Bluetooth*>(user_data);
if (!bt->cur_controller_.has_value() &&
bt->getControllerProperties(object, info) &&
(!bt->config_["controller-alias"].isString() ||
bt->config_["controller-alias"].asString() == info.alias)) {
bt->cur_controller_ = std::move(info);
bt->dp.emit();
}
}
auto waybar::modules::Bluetooth::onObjectRemoved(GDBusObjectManager* manager,
GDBusObject* object,
gpointer user_data) -> void {
GDBusProxy* proxy_controller =
G_DBUS_PROXY(g_dbus_object_get_interface(object, "org.bluez.Adapter1"));
if (proxy_controller != NULL) {
std::string object_path = g_dbus_object_get_object_path(object);
Bluetooth* bt = static_cast<Bluetooth*>(user_data);
if (object_path == bt->cur_controller_->path) {
bt->cur_controller_ = bt->findCurController();
bt->dp.emit();
}
g_object_unref(proxy_controller);
}
}
// NOTE: only for when the org.bluez.Battery1 interface is added/removed after/before a device is // NOTE: only for when the org.bluez.Battery1 interface is added/removed after/before a device is
// connected/disconnected // connected/disconnected
auto waybar::modules::Bluetooth::onInterfaceAddedOrRemoved(GDBusObjectManager* manager, auto waybar::modules::Bluetooth::onInterfaceAddedOrRemoved(GDBusObjectManager* manager,
@ -292,6 +328,7 @@ auto waybar::modules::Bluetooth::onInterfaceAddedOrRemoved(GDBusObjectManager* m
std::string object_path = g_dbus_proxy_get_object_path(G_DBUS_PROXY(interface)); std::string object_path = g_dbus_proxy_get_object_path(G_DBUS_PROXY(interface));
if (interface_name == "org.bluez.Battery1") { if (interface_name == "org.bluez.Battery1") {
Bluetooth* bt = static_cast<Bluetooth*>(user_data); Bluetooth* bt = static_cast<Bluetooth*>(user_data);
if (bt->cur_controller_.has_value()) {
auto device = std::find_if(bt->connected_devices_.begin(), bt->connected_devices_.end(), auto device = std::find_if(bt->connected_devices_.begin(), bt->connected_devices_.end(),
[object_path](auto d) { return d.path == object_path; }); [object_path](auto d) { return d.path == object_path; });
if (device != bt->connected_devices_.end()) { if (device != bt->connected_devices_.end()) {
@ -299,6 +336,7 @@ auto waybar::modules::Bluetooth::onInterfaceAddedOrRemoved(GDBusObjectManager* m
bt->dp.emit(); bt->dp.emit();
} }
} }
}
} }
auto waybar::modules::Bluetooth::onInterfaceProxyPropertiesChanged( auto waybar::modules::Bluetooth::onInterfaceProxyPropertiesChanged(
@ -309,6 +347,11 @@ auto waybar::modules::Bluetooth::onInterfaceProxyPropertiesChanged(
std::string object_path = g_dbus_object_get_object_path(G_DBUS_OBJECT(object_proxy)); std::string object_path = g_dbus_object_get_object_path(G_DBUS_OBJECT(object_proxy));
Bluetooth* bt = static_cast<Bluetooth*>(user_data); Bluetooth* bt = static_cast<Bluetooth*>(user_data);
if (!bt->cur_controller_.has_value()) {
return;
}
if (interface_name == "org.bluez.Adapter1") { if (interface_name == "org.bluez.Adapter1") {
if (object_path == bt->cur_controller_->path) { if (object_path == bt->cur_controller_->path) {
bt->getControllerProperties(G_DBUS_OBJECT(object_proxy), *bt->cur_controller_); bt->getControllerProperties(G_DBUS_OBJECT(object_proxy), *bt->cur_controller_);