summaryrefslogtreecommitdiff
path: root/lib/bluetooth/bluetooth.vala
diff options
context:
space:
mode:
authorAylur <[email protected]>2024-09-01 14:17:36 +0200
committerAylur <[email protected]>2024-09-01 14:17:36 +0200
commit3e3f045d650a839d21f7b649da7aa5c19bd2e38b (patch)
tree9a974eb0d38932d474940288c662bd1f01ea3088 /lib/bluetooth/bluetooth.vala
parent408faee16911ccfaa3e7dad69f9938fd4a696704 (diff)
monorepo structuring
Diffstat (limited to 'lib/bluetooth/bluetooth.vala')
-rw-r--r--lib/bluetooth/bluetooth.vala181
1 files changed, 181 insertions, 0 deletions
diff --git a/lib/bluetooth/bluetooth.vala b/lib/bluetooth/bluetooth.vala
new file mode 100644
index 0000000..ce086ba
--- /dev/null
+++ b/lib/bluetooth/bluetooth.vala
@@ -0,0 +1,181 @@
+namespace AstalBluetooth {
+public Bluetooth get_default() {
+ return Bluetooth.get_default();
+}
+
+public class Bluetooth : Object {
+ private static Bluetooth _instance;
+
+ public static Bluetooth get_default() {
+ if (_instance == null)
+ _instance = new Bluetooth();
+
+ return _instance;
+ }
+
+ private DBusObjectManagerClient manager;
+
+ private HashTable<string, Adapter> _adapters =
+ new HashTable<string, Adapter>(str_hash, str_equal);
+
+ private HashTable<string, Device> _devices =
+ new HashTable<string, Device>(str_hash, str_equal);
+
+ public signal void device_added (Device device) {
+ notify_property("devices");
+ }
+
+ public signal void device_removed (Device device) {
+ notify_property("devices");
+ }
+
+ public signal void adapter_added (Adapter adapter) {
+ notify_property("adapters");
+ }
+
+ public signal void adapter_removed (Adapter adapter) {
+ notify_property("adapters");
+ }
+
+ public bool is_powered { get; private set; default = false; }
+ public bool is_connected { get; private set; default = false; }
+ public Adapter? adapter { get { return adapters.nth_data(0); } }
+
+ public List<weak Adapter> adapters {
+ owned get { return _adapters.get_values(); }
+ }
+
+ public List<weak Device> devices {
+ owned get { return _devices.get_values(); }
+ }
+
+ construct {
+ try {
+ manager = new DBusObjectManagerClient.for_bus_sync(
+ BusType.SYSTEM,
+ DBusObjectManagerClientFlags.NONE,
+ "org.bluez",
+ "/",
+ manager_proxy_get_type,
+ null
+ );
+
+ foreach (var object in manager.get_objects()) {
+ foreach (var iface in object.get_interfaces()) {
+ on_interface_added(object, iface);
+ }
+ }
+
+ manager.interface_added.connect(on_interface_added);
+ manager.interface_removed.connect(on_interface_removed);
+
+ manager.object_added.connect((object) => {
+ foreach (var iface in object.get_interfaces()) {
+ on_interface_added(object, iface);
+ }
+ });
+
+ manager.object_removed.connect((object) => {
+ foreach (var iface in object.get_interfaces()) {
+ on_interface_removed(object, iface);
+ }
+ });
+ } catch (Error err) {
+ critical(err.message);
+ }
+ }
+
+ public void toggle() {
+ adapter.powered = !adapter.powered;
+ }
+
+ [CCode (cname="astal_bluetooth_idevice_proxy_get_type")]
+ extern static GLib.Type get_idevice_proxy_type();
+
+ [CCode (cname="astal_bluetooth_iadapter_proxy_get_type")]
+ extern static GLib.Type get_iadapter_proxy_type();
+
+ private Type manager_proxy_get_type(DBusObjectManagerClient _, string object_path, string? interface_name) {
+ if (interface_name == null)
+ return typeof(DBusObjectProxy);
+
+ switch (interface_name) {
+ case "org.bluez.Device1":
+ return get_idevice_proxy_type();
+ case "org.bluez.Adapter1":
+ return get_iadapter_proxy_type();
+ default:
+ return typeof(DBusProxy);
+ }
+ }
+
+ private void on_interface_added(DBusObject object, DBusInterface iface) {
+ if (iface is IDevice) {
+ var device = new Device((IDevice)iface);
+ _devices.set(device.object_path, device);
+ device_added(device);
+ device.notify.connect(sync);
+ sync();
+ }
+
+ if (iface is IAdapter) {
+ var adapter = new Adapter((IAdapter)iface);
+ _adapters.set(adapter.object_path, adapter);
+ adapter_added(adapter);
+ adapter.notify.connect(sync);
+ sync();
+ }
+ }
+
+ private void on_interface_removed (DBusObject object, DBusInterface iface) {
+ if (iface is IDevice) {
+ unowned var device = (IDevice)iface;
+ device_removed(_devices.get(device.g_object_path));
+ _devices.remove(device.g_object_path);
+ }
+
+ if (iface is IAdapter) {
+ unowned var adapter = (IAdapter)iface;
+ adapter_removed(_adapters.get(adapter.g_object_path));
+ _adapters.remove(adapter.g_object_path);
+ }
+
+ sync();
+ }
+
+ private void sync() {
+ var powered = get_powered();
+ var connected = get_connected();
+
+ if (powered != is_powered || connected != is_connected) {
+ if (powered != is_powered) {
+ is_powered = powered;
+ }
+
+ if (connected != is_connected) {
+ is_connected = connected;
+ }
+ }
+ }
+
+ private bool get_powered() {
+ foreach (var adapter in adapters) {
+ if (adapter.powered) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private bool get_connected() {
+ foreach (var device in devices) {
+ if (device.connected) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
+}