Merge pull request #3360 from lukasfink1/bt-dyn-controller-pr

Add hotplug detection of bluetooth controllers
This commit is contained in:
Alexis Rouillard 2024-06-14 09:06:57 +02:00 committed by GitHub
commit 3f49725834
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 64 additions and 18 deletions

View File

@ -49,6 +49,9 @@ class Bluetooth : public ALabel {
auto update() -> void override;
private:
static auto onObjectAdded(GDBusObjectManager*, GDBusObject*, gpointer) -> void;
static auto onObjectRemoved(GDBusObjectManager*, GDBusObject*, gpointer) -> void;
static auto onInterfaceAddedOrRemoved(GDBusObjectManager*, GDBusObject*, GDBusInterface*,
gpointer) -> void;
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(); });
}
// NOTE: assumption made that the controller that is selected stays unchanged
// for duration of the module
if (cur_controller_ = findCurController(); !cur_controller_) {
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());
} else {
spdlog::error("findCurController() failed: no bluetooth controller found");
spdlog::warn("no bluetooth controller found");
}
update();
} 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_);
}
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_CALLBACK(onInterfaceProxyPropertiesChanged), this);
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
rfkill_.on_update.connect(sigc::hide(sigc::mem_fun(*this, &Bluetooth::update)));
#endif
}
dp.emit();
}
@ -282,6 +283,41 @@ auto waybar::modules::Bluetooth::update() -> void {
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
// connected/disconnected
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));
if (interface_name == "org.bluez.Battery1") {
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(),
[object_path](auto d) { return d.path == object_path; });
if (device != bt->connected_devices_.end()) {
@ -300,6 +337,7 @@ auto waybar::modules::Bluetooth::onInterfaceAddedOrRemoved(GDBusObjectManager* m
}
}
}
}
auto waybar::modules::Bluetooth::onInterfaceProxyPropertiesChanged(
GDBusObjectManagerClient* manager, GDBusObjectProxy* object_proxy, GDBusProxy* interface_proxy,
@ -309,6 +347,11 @@ auto waybar::modules::Bluetooth::onInterfaceProxyPropertiesChanged(
std::string object_path = g_dbus_object_get_object_path(G_DBUS_OBJECT(object_proxy));
Bluetooth* bt = static_cast<Bluetooth*>(user_data);
if (!bt->cur_controller_.has_value()) {
return;
}
if (interface_name == "org.bluez.Adapter1") {
if (object_path == bt->cur_controller_->path) {
bt->getControllerProperties(G_DBUS_OBJECT(object_proxy), *bt->cur_controller_);