#include "bluetooth.h" #include "../util.h" #include #include 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 (err) { qtb_log("checking bluetooth adapter power state failed\n-> %s", err->message); g_error_free(err); err = NULL; qtb_die(); } 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; }