185 lines
4.9 KiB
C++
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);
|
|
}
|
|
} |