#include "services/bluetooth.hpp" #include #include #include "glib.h" #include "sigc++/signal.h" BluetoothService::BluetoothService() { GError *error = nullptr; this->adapter_proxy = g_dbus_proxy_new_for_bus_sync( G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, nullptr, "org.bluez", "/org/bluez/hci0", "org.bluez.Adapter1", nullptr, &error); if (error) { std::cerr << "Error creating Bluetooth adapter proxy: " << error->message << std::endl; g_error_free(error); assert(false); } else { std::cout << "Bluetooth adapter proxy created successfully." << std::endl; } this->powerState = this->getPowerState(); this->isDiscovering = this->getIsDiscovering(); g_signal_connect( this->adapter_proxy, "g-properties-changed", G_CALLBACK(BluetoothService::onPropertyChangedStatic), this); } bool BluetoothService::getPowerState() { GVariant *result = g_dbus_proxy_get_cached_property( this->adapter_proxy, "Powered"); if (!result) { std::cerr << "Error getting Powered property." << std::endl; return false; } gboolean powered; g_variant_get(result, "b", &powered); g_variant_unref(result); return powered; } bool BluetoothService::getIsDiscovering() { GVariant *result = g_dbus_proxy_get_cached_property( this->adapter_proxy, "Discovering"); if (!result) { std::cerr << "Error getting Discovering property." << std::endl; return false; } gboolean discovering; g_variant_get(result, "b", &discovering); g_variant_unref(result); return discovering; } void BluetoothService::setPowerState(bool state) { GError *error = nullptr; GDBusConnection *connection = g_dbus_proxy_get_connection(this->adapter_proxy); GVariant *reply = g_dbus_connection_call_sync( connection, "org.bluez", "/org/bluez/hci0", "org.freedesktop.DBus.Properties", "Set", g_variant_new( "(ssv)", "org.bluez.Adapter1", "Powered", g_variant_new_boolean(state)), nullptr, G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &error); if (error) { std::cerr << "Error setting Powered property: " << error->message << std::endl; g_error_free(error); } if (reply) { g_variant_unref(reply); } if (!error) { this->powerState = state; } } void BluetoothService::setIsDiscovering(bool state) { const bool currently_discovering = this->getIsDiscovering(); this->isDiscovering = currently_discovering; if (currently_discovering == state) { return; } GError *error = nullptr; const char *method = state ? "StartDiscovery" : "StopDiscovery"; GVariant *reply = g_dbus_proxy_call_sync( this->adapter_proxy, method, nullptr, G_DBUS_CALL_FLAGS_NONE, -1, nullptr, &error); if (error) { std::cerr << "Error calling " << method << ": " << error->message << std::endl; g_error_free(error); if (reply) { g_variant_unref(reply); } return; } this->isDiscovering = state; if (reply) { g_variant_unref(reply); } } void BluetoothService::onPropertyChanged(GDBusProxy *proxy, GVariant *changed_properties, const gchar *const *invalidated_properties, gpointer user_data) { gboolean is_powered = FALSE; gboolean is_discovering = FALSE; if (g_variant_lookup(changed_properties, "Powered", "b", &is_powered)) { this->setIsDiscovering(false); isDiscoveringChangedSignal.emit(isDiscovering); this->powerState = is_powered; powerStateChangedSignal.emit(powerState); } if (g_variant_lookup(changed_properties, "Discovering", "b", &is_discovering)) { this->isDiscovering = is_discovering; isDiscoveringChangedSignal.emit(isDiscovering); } } void BluetoothService::onPropertyChangedStatic(GDBusProxy *proxy, GVariant *changed_properties, const gchar *const *invalidated_properties, gpointer user_data) { BluetoothService *service = static_cast(user_data); if (service) { service->onPropertyChanged(proxy, changed_properties, invalidated_properties, user_data); } else { std::cerr << "Error: BluetoothService instance is null in static callback." << std::endl; assert(false); } }