diff --git a/Cargo.toml b/Cargo.toml index 09ea560..90245ae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" description = "A wip universal Linux settings application." [dependencies] -reset_daemon = "0.4.2" -re_set-lib = "0.6.4" +reset_daemon = "0.4.3" +re_set-lib = "0.6.5" adw = { version = "0.5.3", package = "libadwaita", features = ["v1_4"] } dbus = "0.9.7" gtk = { version = "0.7.3", package = "gtk4", features = ["v4_12"] } diff --git a/src/components/base/utils.rs b/src/components/base/utils.rs index e640661..a5c1bdb 100644 --- a/src/components/base/utils.rs +++ b/src/components/base/utils.rs @@ -28,6 +28,7 @@ pub struct Listeners { pub wifi_disabled: AtomicBool, pub wifi_listener: AtomicBool, pub bluetooth_listener: AtomicBool, + pub bluetooth_scan_requested: AtomicBool, pub pulse_listener: AtomicBool, } diff --git a/src/components/bluetooth/bluetooth_box.rs b/src/components/bluetooth/bluetooth_box.rs index f234364..6a36b48 100644 --- a/src/components/bluetooth/bluetooth_box.rs +++ b/src/components/bluetooth/bluetooth_box.rs @@ -41,7 +41,6 @@ fn setup_callbacks( listeners: Arc, bluetooth_box: Arc, ) -> Arc { - let bluetooth_box_button_ref = bluetooth_box.clone(); let bluetooth_box_ref = bluetooth_box.clone(); let listeners_ref = listeners.clone(); let imp = bluetooth_box.imp(); @@ -58,7 +57,9 @@ fn setup_callbacks( imp.reset_bluetooth_refresh_button .connect_clicked(move |button| { button.set_sensitive(false); - start_bluetooth_listener(listeners.clone(), bluetooth_box_button_ref.clone()); + listeners + .bluetooth_scan_requested + .store(true, Ordering::SeqCst); }); imp.reset_bluetooth_discoverable_switch @@ -176,7 +177,7 @@ pub fn populate_conntected_bluetooth_devices(bluetooth_box: Arc) { for device in devices { let path = device.path.clone(); let connected = device.connected; - let bluetooth_entry = Arc::new(BluetoothEntry::new(&device)); + let bluetooth_entry = BluetoothEntry::new(&device); imp.available_devices .borrow_mut() .insert(path, (bluetooth_entry.clone(), device)); @@ -236,7 +237,7 @@ pub fn start_bluetooth_listener(listeners: Arc, bluetooth_box: Arc, bluetooth_box: Arc, bluetooth_box: Arc Duration::from_millis(25000) - { - listeners.bluetooth_listener.store(false, Ordering::SeqCst); + if !listeners.bluetooth_listener.load(Ordering::SeqCst) { + println!("stopping bluetooth listener"); + break; + } + if listener_active && time.elapsed().unwrap() > Duration::from_millis(25000) { + listener_active = false; + let instance_ref = loop_box.clone(); glib::spawn_future(async move { glib::idle_add_once(move || { - let imp = loop_box.imp(); + let imp = instance_ref.imp(); let mut entries = imp.available_devices.borrow_mut(); for entry in entries.iter() { imp.reset_bluetooth_available_devices.remove(&*entry.1 .0); @@ -339,8 +344,15 @@ pub fn start_bluetooth_listener(listeners: Arc, bluetooth_box: Arc = proxy.method_call("org.Xetibo.ReSetBluetooth", "StopBluetoothListener", ()); - println!("stopping bluetooth listener"); - break; + } + if !listener_active && listeners.bluetooth_scan_requested.load(Ordering::SeqCst) { + listeners + .bluetooth_scan_requested + .store(false, Ordering::SeqCst); + listener_active = true; + let _: Result<(), Error> = + proxy.method_call("org.Xetibo.ReSetBluetooth", "StartBluetoothListener", ()); + time = SystemTime::now(); } thread::sleep(Duration::from_millis(100)); } diff --git a/src/components/bluetooth/bluetooth_entry.rs b/src/components/bluetooth/bluetooth_entry.rs index 8476012..8d04d18 100644 --- a/src/components/bluetooth/bluetooth_entry.rs +++ b/src/components/bluetooth/bluetooth_entry.rs @@ -4,13 +4,13 @@ use std::time::Duration; use crate::components::bluetooth::bluetooth_entry_impl; use adw::glib::Object; -use adw::{glib, ActionRow}; use adw::prelude::{ActionRowExt, PreferencesRowExt}; +use adw::{glib, ActionRow}; use dbus::blocking::Connection; use dbus::{Error, Path}; use glib::subclass::prelude::ObjectSubclassIsExt; use gtk::prelude::{ButtonExt, ListBoxRowExt, WidgetExt}; -use gtk::{gio, GestureClick, Image, Button, Align}; +use gtk::{gio, Align, Button, GestureClick, Image, Label}; use re_set_lib::bluetooth::bluetooth_structures::BluetoothDevice; glib::wrapper! { @@ -23,15 +23,25 @@ unsafe impl Send for BluetoothEntry {} unsafe impl Sync for BluetoothEntry {} impl BluetoothEntry { - pub fn new(device: &BluetoothDevice) -> Self { - let entry: BluetoothEntry = Object::builder().build(); + pub fn new(device: &BluetoothDevice) -> Arc { + let entry: Arc = Arc::new(Object::builder().build()); let entry_imp = entry.imp(); - + let entry_ref = entry.clone(); entry.set_title(&device.alias); entry.set_subtitle(&device.address); entry.set_activatable(true); - entry_imp.remove_device_button.replace(Button::builder().icon_name("user-trash-symbolic").valign(Align::Center).build()); + entry_imp.remove_device_button.replace( + Button::builder() + .icon_name("user-trash-symbolic") + .valign(Align::Center) + .build(), + ); + entry_imp.connecting_label.replace( + Label::builder() + .label("") + .build(), + ); entry.add_suffix(entry_imp.remove_device_button.borrow().deref()); if device.icon.is_empty() { entry.add_prefix(&Image::from_icon_name("dialog-question-symbolic")); @@ -44,9 +54,12 @@ impl BluetoothEntry { entry_imp.remove_device_button.borrow().set_sensitive(false); } let path = Arc::new(device.path.clone()); - entry_imp.remove_device_button.borrow().connect_clicked(move |_| { - remove_device_pairing((*path).clone()); - }); + entry_imp + .remove_device_button + .borrow() + .connect_clicked(move |_| { + remove_device_pairing((*path).clone()); + }); let gesture = GestureClick::new(); let connected = device.connected; // let paired = device.paired; @@ -54,11 +67,23 @@ impl BluetoothEntry { // TODO implement paired let path = device.path.clone(); gesture.connect_released(move |_, _, _, _| { - connect_to_device(path.clone()); if connected { - disconnect_from_device(path.clone()); + let imp = entry_ref.imp(); + imp.remove_device_button.borrow().set_sensitive(false); + entry_ref + .imp() + .connecting_label + .borrow() + .set_text("Disconnecting..."); + disconnect_from_device(entry_ref.clone(), path.clone()); } else { - connect_to_device(path.clone()); + entry_ref.set_sensitive(false); + entry_ref + .imp() + .connecting_label + .borrow() + .set_text("Connecting..."); + connect_to_device(entry_ref.clone(), path.clone()); } }); entry.add_controller(gesture); @@ -66,7 +91,7 @@ impl BluetoothEntry { } } -fn connect_to_device(path: Path<'static>) { +fn connect_to_device(entry: Arc, path: Path<'static>) { gio::spawn_blocking(move || { let conn = Connection::new_session().unwrap(); let proxy = conn.with_proxy( @@ -74,11 +99,26 @@ fn connect_to_device(path: Path<'static>) { "/org/Xetibo/ReSetDaemon", Duration::from_millis(1000), ); - let _: Result<(bool,), Error> = proxy.method_call( + let res: Result<(bool,), Error> = proxy.method_call( "org.Xetibo.ReSetBluetooth", "ConnectToBluetoothDevice", (path,), ); + glib::spawn_future(async move { + glib::idle_add_once(move || { + if res.is_err() { + entry.set_sensitive(true); + entry + .imp() + .connecting_label + .borrow() + .set_text("Error on connecting"); + } else { + entry.set_sensitive(true); + entry.imp().connecting_label.borrow().set_text(""); + } + }); + }); }); } @@ -98,7 +138,7 @@ fn connect_to_device(path: Path<'static>) { // }); // } -fn disconnect_from_device(path: Path<'static>) { +fn disconnect_from_device(entry: Arc, path: Path<'static>) { gio::spawn_blocking(move || { let conn = Connection::new_session().unwrap(); let proxy = conn.with_proxy( @@ -106,11 +146,25 @@ fn disconnect_from_device(path: Path<'static>) { "/org/Xetibo/ReSetDaemon", Duration::from_millis(1000), ); - let _: Result<(bool,), Error> = proxy.method_call( + let res: Result<(bool,), Error> = proxy.method_call( "org.Xetibo.ReSetBluetooth", "DisconnectFromBluetoothDevice", (path,), ); + glib::spawn_future(async move { + glib::idle_add_once(move || { + let imp = entry.imp(); + if res.is_err() { + imp.remove_device_button.borrow().set_sensitive(true); + imp.connecting_label + .borrow() + .set_text("Error on disconnecting"); + } else { + imp.remove_device_button.borrow().set_sensitive(true); + imp.connecting_label.borrow().set_text(""); + } + }); + }); }); } diff --git a/src/components/bluetooth/bluetooth_entry_impl.rs b/src/components/bluetooth/bluetooth_entry_impl.rs index 6834d48..609c528 100644 --- a/src/components/bluetooth/bluetooth_entry_impl.rs +++ b/src/components/bluetooth/bluetooth_entry_impl.rs @@ -3,13 +3,14 @@ use adw::subclass::action_row::ActionRowImpl; use adw::subclass::preferences_row::PreferencesRowImpl; use adw::ActionRow; use gtk::subclass::prelude::*; -use gtk::{glib, Button, CompositeTemplate}; +use gtk::{glib, Button, CompositeTemplate, Label}; use std::cell::RefCell; #[derive(Default, CompositeTemplate)] #[template(resource = "/org/Xetibo/ReSet/resetBluetoothEntry.ui")] pub struct BluetoothEntry { pub remove_device_button: RefCell