Files
bar/src/services/bluetooth.cpp

185 lines
4.9 KiB
C++

#include "services/bluetooth.hpp"
#include <cassert>
#include <iostream>
#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<BluetoothService *>(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);
}
}