This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
quick-text-bar/modules/bluetooth.c

119 lines
4.0 KiB
C
Raw Normal View History

2022-08-28 14:27:03 -07:00
#include "bluetooth.h"
#include "../util.h"
#include <dirent.h>
#include <gio/gio.h>
static long long powered_devices = 0;
static GPtrArray *get_bluetooth_device_paths() {
DIR *dir = opendir("/sys/class/bluetooth");
if (!dir) {
return NULL;
}
GPtrArray *arr = g_ptr_array_new();
struct dirent *current;
while ((current = readdir(dir))) {
if (strcmp(current->d_name, ".") != 0 &&
strcmp(current->d_name, "..") != 0) {
char *path = g_strdup_printf("/org/bluez/%s", current->d_name);
g_ptr_array_add(arr, path);
}
}
closedir(dir);
return arr;
}
static void load_initial_device_states(GDBusConnection *dbus,
GPtrArray *devices) {
gsize i;
for (i = 0; i < devices->len; ++i) {
const char *path = g_ptr_array_index(devices, i);
GError *err = NULL;
GVariant *response = g_dbus_connection_call_sync(
dbus, "org.bluez", path, "org.freedesktop.DBus.Properties", "Get",
g_variant_new_parsed("('org.bluez.Adapter1', 'Powered')"),
(GVariantType *)"(v)", G_DBUS_CALL_FLAGS_NONE, -1, NULL, &err);
if (response) {
GVariant *wrapper = g_variant_get_child_value(response, 0);
GVariant *value = g_variant_get_child_value(wrapper, 0);
gboolean powered = g_variant_get_boolean(value);
if (powered) {
++powered_devices;
} /* sice powered_devices is already 0, we dont have to increment it
if the device is not powered */
g_variant_unref(value);
g_variant_unref(wrapper);
g_variant_unref(response);
}
}
qtb_signal_modules(4);
}
static void device_changed_callback(GDBusConnection *dbus,
const char *sender_name,
const char *object_path,
const char *interface_name,
const char *signal_name, GVariant *params,
gpointer user_data) {
GVariant *changed = g_variant_get_child_value(params, 1);
GVariant *value_wrapper = g_variant_lookup_value(changed, "Powered", G_VARIANT_TYPE_BOOLEAN);
if (value_wrapper) {
gboolean powered = g_variant_get_boolean(value_wrapper);
if (powered) {
++powered_devices;
} else {
--powered_devices;
}
g_variant_unref(value_wrapper);
}
g_variant_unref(changed);
qtb_signal_modules(4);
}
static void subscribe_to_events(GDBusConnection *dbus, GPtrArray *devices) {
gsize i;
for (i = 0; i < devices->len; ++i) {
const char *path = g_ptr_array_index(devices, i);
g_dbus_connection_signal_subscribe(
dbus, NULL, "org.freedesktop.DBus.Properties", "PropertiesChanged",
path, "org.bluez.Adapter1", G_DBUS_SIGNAL_FLAGS_NONE,
&device_changed_callback, NULL, NULL);
}
}
static void *thread_action() {
GMainContext *context = g_main_context_new();
g_main_context_push_thread_default(context);
GError *err = NULL;
GDBusConnection *dbus = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &err);
if (err) {
qtb_log("could not connect to bluez on the system bus: %s",
err->message);
qtb_die();
}
GPtrArray *devices = get_bluetooth_device_paths();
load_initial_device_states(dbus, devices);
subscribe_to_events(dbus, devices);
gsize i;
for (i = 0; i < devices->len; ++i) {
g_free(g_ptr_array_index(devices, i));
}
g_ptr_array_free(devices, TRUE);
GMainLoop *main_loop = g_main_loop_new(context, FALSE);
g_main_loop_run(main_loop);
return NULL;
}
void bluetooth_module_init() {
g_thread_new("bluetooth-module", &thread_action, NULL);
}
char *bluetooth_module_poll() {
char *output = NULL;
if (powered_devices != 0) {
output = qtb_strdup("");
}
return output;
}