feat: Add dynamic bluetooth buttons

This commit is contained in:
dashie 2023-12-08 23:55:04 +00:00
parent 741d678ffd
commit 286302354e
10 changed files with 123 additions and 153 deletions

View file

@ -37,6 +37,10 @@ impl BluetoothBox {
}
}
// TODO
// handle bonded -> this means saved but not connected
// handle rssi below x -> don't show device
fn setup_callbacks(
listeners: Arc<Listeners>,
bluetooth_box: Arc<BluetoothBox>,
@ -110,6 +114,7 @@ fn setup_callbacks(
}
pub fn populate_conntected_bluetooth_devices(bluetooth_box: Arc<BluetoothBox>) {
// TODO handle saved devices -> they also exist
gio::spawn_blocking(move || {
let ref_box = bluetooth_box.clone();
let devices = get_connected_devices();
@ -177,10 +182,10 @@ pub fn populate_conntected_bluetooth_devices(bluetooth_box: Arc<BluetoothBox>) {
for device in devices {
let path = device.path.clone();
let connected = device.connected;
let bluetooth_entry = BluetoothEntry::new(&device);
let bluetooth_entry = BluetoothEntry::new(device);
imp.available_devices
.borrow_mut()
.insert(path, (bluetooth_entry.clone(), device));
.insert(path, bluetooth_entry.clone());
if connected {
imp.reset_bluetooth_connected_devices.add(&*bluetooth_entry);
} else {
@ -195,10 +200,8 @@ pub fn populate_conntected_bluetooth_devices(bluetooth_box: Arc<BluetoothBox>) {
pub fn start_bluetooth_listener(listeners: Arc<Listeners>, bluetooth_box: Arc<BluetoothBox>) {
gio::spawn_blocking(move || {
if listeners.bluetooth_listener.load(Ordering::SeqCst) {
println!("bluetooth listener was active");
return;
}
println!("starting bluetooth listener");
let conn = Connection::new_session().unwrap();
let proxy = conn.with_proxy(
@ -230,17 +233,15 @@ pub fn start_bluetooth_listener(listeners: Arc<Listeners>, bluetooth_box: Arc<Bl
let res = conn.add_match(device_added, move |ir: BluetoothDeviceAdded, _, _| {
let bluetooth_box = device_added_box.clone();
println!("added");
glib::spawn_future(async move {
glib::idle_add_once(move || {
println!("{}", ir.bluetooth_device.icon);
let imp = bluetooth_box.imp();
let path = ir.bluetooth_device.path.clone();
let connected = ir.bluetooth_device.connected;
let bluetooth_entry = BluetoothEntry::new(&ir.bluetooth_device);
let bluetooth_entry = BluetoothEntry::new(ir.bluetooth_device);
imp.available_devices
.borrow_mut()
.insert(path, (bluetooth_entry.clone(), ir.bluetooth_device));
.insert(path, bluetooth_entry.clone());
if connected {
imp.reset_bluetooth_connected_devices.add(&*bluetooth_entry);
} else {
@ -251,70 +252,73 @@ pub fn start_bluetooth_listener(listeners: Arc<Listeners>, bluetooth_box: Arc<Bl
true
});
if res.is_err() {
println!("fail on bluetooth device add");
println!("fail on bluetooth device add event");
return;
}
let res = conn.add_match(device_removed, move |ir: BluetoothDeviceRemoved, _, _| {
let bluetooth_box = device_removed_box.clone();
println!("removed");
glib::spawn_future(async move {
glib::idle_add_once(move || {
let imp = bluetooth_box.imp();
let map = imp.available_devices.borrow_mut();
if let Some(list_entry) = map.get(&ir.bluetooth_device) {
imp.reset_bluetooth_connected_devices.remove(&*list_entry.0);
let mut map = imp.available_devices.borrow_mut();
if let Some(list_entry) = map.remove(&ir.bluetooth_device) {
if list_entry.imp().bluetooth_device.borrow().connected {
imp.reset_bluetooth_connected_devices.remove(&*list_entry);
} else {
imp.reset_bluetooth_available_devices.remove(&*list_entry);
}
}
});
});
true
});
if res.is_err() {
println!("fail on bluetooth device remove");
println!("fail on bluetooth device remove event");
return;
}
let res = conn.add_match(device_changed, move |ir: BluetoothDeviceChanged, _, _| {
let bluetooth_box = device_changed_box.clone();
println!("changed");
glib::spawn_future(async move {
glib::idle_add_once(move || {
let imp = bluetooth_box.imp();
let map = imp.available_devices.borrow_mut();
if let Some(list_entry) = map.get(&ir.bluetooth_device.path) {
if list_entry.1.connected != ir.bluetooth_device.connected {
let mut map = imp.available_devices.borrow_mut();
if let Some(list_entry) = map.get_mut(&ir.bluetooth_device.path) {
let mut existing_bluetooth_device =
list_entry.imp().bluetooth_device.borrow_mut();
if existing_bluetooth_device.connected != ir.bluetooth_device.connected {
if ir.bluetooth_device.connected {
imp.reset_bluetooth_connected_devices.add(&*list_entry.0);
imp.reset_bluetooth_available_devices.remove(&*list_entry.0);
imp.reset_bluetooth_connected_devices.add(&**list_entry);
imp.reset_bluetooth_available_devices.remove(&**list_entry);
} else {
imp.reset_bluetooth_available_devices.add(&*list_entry.0);
imp.reset_bluetooth_connected_devices.remove(&*list_entry.0);
imp.reset_bluetooth_available_devices.add(&**list_entry);
imp.reset_bluetooth_connected_devices.remove(&**list_entry);
}
}
if list_entry.1.paired != ir.bluetooth_device.paired {
if ir.bluetooth_device.paired {
if existing_bluetooth_device.bonded != ir.bluetooth_device.bonded {
if ir.bluetooth_device.bonded {
list_entry
.0
.imp()
.remove_device_button
.borrow()
.set_sensitive(true);
} else {
list_entry
.0
.imp()
.remove_device_button
.borrow()
.set_sensitive(false);
}
}
*existing_bluetooth_device = ir.bluetooth_device;
}
});
});
true
});
if res.is_err() {
println!("fail on bluetooth device remove");
println!("fail on bluetooth device remove event");
return;
}
@ -325,25 +329,23 @@ pub fn start_bluetooth_listener(listeners: Arc<Listeners>, bluetooth_box: Arc<Bl
loop {
let _ = conn.process(Duration::from_millis(1000));
if !listeners.bluetooth_listener.load(Ordering::SeqCst) {
println!("stopping bluetooth listener");
let _: Result<(), Error> =
proxy.method_call("org.Xetibo.ReSetBluetooth", "StopBluetoothListener", ());
break;
}
if listener_active && time.elapsed().unwrap() > Duration::from_millis(25000) {
if listener_active && time.elapsed().unwrap() > Duration::from_millis(10000) {
listener_active = false;
let instance_ref = loop_box.clone();
glib::spawn_future(async move {
glib::idle_add_once(move || {
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);
}
entries.clear();
imp.reset_bluetooth_refresh_button.set_sensitive(true);
instance_ref
.imp()
.reset_bluetooth_refresh_button
.set_sensitive(true);
});
});
let _: Result<(), Error> =
proxy.method_call("org.Xetibo.ReSetBluetooth", "StopBluetoothListener", ());
proxy.method_call("org.Xetibo.ReSetBluetooth", "StopBluetoothScan", ());
}
if !listener_active && listeners.bluetooth_scan_requested.load(Ordering::SeqCst) {
listeners

View file

@ -3,7 +3,7 @@ use dbus::Path;
use gtk::subclass::prelude::*;
use gtk::{glib, Button, CompositeTemplate, Switch};
use gtk::{prelude::*, StringList};
use re_set_lib::bluetooth::bluetooth_structures::{BluetoothAdapter, BluetoothDevice};
use re_set_lib::bluetooth::bluetooth_structures::BluetoothAdapter;
use std::cell::RefCell;
use std::collections::HashMap;
use std::sync::{Arc, RwLock};
@ -12,8 +12,7 @@ use crate::components::base::list_entry::ListEntry;
use crate::components::bluetooth::bluetooth_box;
use crate::components::bluetooth::bluetooth_entry::BluetoothEntry;
type BluetoothMap =
RefCell<HashMap<Path<'static>, (Arc<BluetoothEntry>, BluetoothDevice)>>;
type BluetoothMap = RefCell<HashMap<Path<'static>, Arc<BluetoothEntry>>>;
#[derive(Default, CompositeTemplate)]
#[template(resource = "/org/Xetibo/ReSet/resetBluetooth.ui")]

View file

@ -23,10 +23,11 @@ unsafe impl Send for BluetoothEntry {}
unsafe impl Sync for BluetoothEntry {}
impl BluetoothEntry {
pub fn new(device: &BluetoothDevice) -> Arc<Self> {
pub fn new(device: BluetoothDevice) -> Arc<Self> {
let entry: Arc<BluetoothEntry> = Arc::new(Object::builder().build());
let entry_imp = entry.imp();
let entry_ref = entry.clone();
let entry_ref_remove = entry.clone();
entry.set_title(&device.alias);
entry.set_subtitle(&device.address);
entry.set_activatable(true);
@ -37,53 +38,44 @@ impl BluetoothEntry {
.valign(Align::Center)
.build(),
);
entry_imp.connecting_label.replace(
Label::builder()
.label("")
.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"));
} else {
entry.add_prefix(&Image::from_icon_name(&device.icon));
}
if device.connected || device.paired {
if device.connected || device.bonded {
entry_imp.remove_device_button.borrow().set_sensitive(true);
} else {
entry_imp.remove_device_button.borrow().set_sensitive(false);
}
let path = Arc::new(device.path.clone());
entry_imp.bluetooth_device.replace(device);
entry_imp
.remove_device_button
.borrow()
.connect_clicked(move |_| {
remove_device_pairing((*path).clone());
let imp = entry_ref_remove.imp();
remove_device_pairing(imp.bluetooth_device.borrow().path.clone());
});
let gesture = GestureClick::new();
let connected = device.connected;
// let paired = device.paired;
// paired is not what we think
// TODO implement paired
let path = device.path.clone();
gesture.connect_released(move |_, _, _, _| {
if connected {
let imp = entry_ref.imp();
let borrow = imp.bluetooth_device.borrow();
if borrow.connected {
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());
imp.connecting_label.borrow().set_text("Disconnecting...");
disconnect_from_device(entry_ref.clone(), borrow.path.clone());
} else {
entry_ref.set_sensitive(false);
entry_ref
.imp()
.connecting_label
.borrow()
.set_text("Connecting...");
connect_to_device(entry_ref.clone(), path.clone());
imp.connecting_label.borrow().set_text("Connecting...");
connect_to_device(entry_ref.clone(), borrow.path.clone());
}
});
entry.add_controller(gesture);

View file

@ -4,6 +4,7 @@ use adw::subclass::preferences_row::PreferencesRowImpl;
use adw::ActionRow;
use gtk::subclass::prelude::*;
use gtk::{glib, Button, CompositeTemplate, Label};
use re_set_lib::bluetooth::bluetooth_structures::BluetoothDevice;
use std::cell::RefCell;
#[derive(Default, CompositeTemplate)]
@ -12,6 +13,7 @@ pub struct BluetoothEntry {
pub remove_device_button: RefCell<Button>,
pub connecting_label: RefCell<Label>,
pub device_name: RefCell<String>,
pub bluetooth_device: RefCell<BluetoothDevice>
}
#[glib::object_subclass]