fix(bluetooth): other devices not initially appearing

This commit is contained in:
Michael Aaron Murphy 2025-04-17 17:30:19 +02:00
parent e7f24828f1
commit 4f1ef57fe2
No known key found for this signature in database
GPG key ID: B2732D4240C9212C

View file

@ -27,8 +27,8 @@ use tokio::{
Mutex, Mutex,
}, },
task::JoinHandle, task::JoinHandle,
time::timeout,
}; };
// Copied from https://github.com/bluez/bluez/blob/39467578207889fd015775cbe81a3db9dd26abea/src/dbus-common.c#L53 // Copied from https://github.com/bluez/bluez/blob/39467578207889fd015775cbe81a3db9dd26abea/src/dbus-common.c#L53
#[inline] #[inline]
fn device_type_to_icon(device_type: &str) -> &'static str { fn device_type_to_icon(device_type: &str) -> &'static str {
@ -299,7 +299,6 @@ pub enum BluerSessionEvent {
err_msg: Option<String>, err_msg: Option<String>,
}, },
ChangesProcessed(BluerState), ChangesProcessed(BluerState),
ChangeStreamEnded, // TODO can we just restart the stream in a new task?
AgentEvent(BluerAgentEvent), AgentEvent(BluerAgentEvent),
} }
@ -567,69 +566,57 @@ impl BluerSessionState {
return; return;
}; };
let adapter_clone = self.adapter.clone(); let adapter_clone = self.adapter.clone();
let _monitor_devices: tokio::task::JoinHandle<Result<(), anyhow::Error>> = spawn( let _monitor_devices: tokio::task::JoinHandle<Result<(), anyhow::Error>> =
async move { spawn(async move {
let mut change_stream = { let mut devices: Vec<BluerDevice> = Vec::new();
let mut milli_timeout = 10;
let mut res = adapter_clone.discover_devices_with_changes().await;
while res.is_err() {
_ = tokio::time::timeout(
Duration::from_millis(milli_timeout),
wake_up.recv(),
)
.await;
res = adapter_clone.discover_devices_with_changes().await;
milli_timeout = milli_timeout.saturating_mul(5);
}
res.unwrap()
};
let mut interval = tokio::time::interval(Duration::from_secs(1));
loop { loop {
let mut milli_timeout = 10; let wakeup_fut = wake_up.recv();
let mut devices: Vec<BluerDevice> = Vec::new();
let mut new_devices = Vec::new(); // Listens for process changes and builds edvice lists.
'outer: loop { let listener_fut = async {
tokio::select! { let mut new_devices = Vec::new();
change = timeout(Duration::from_millis(milli_timeout), change_stream.next()) => { let mut interval = tokio::time::interval(Duration::from_secs(1));
if let Ok(e) = change { let mut change_stream =
if e.is_none() { match adapter_clone.discover_devices_with_changes().await {
break 'outer; Ok(stream) => stream,
} Err(_) => {
} else { interval.tick().await;
milli_timeout = milli_timeout.saturating_mul(2); return;
continue;
} }
} };
_wake = wake_up.recv() => {
}
};
new_devices = build_device_list(new_devices, &adapter_clone).await; while let Some(_) = change_stream.next().await {
for d in new_devices new_devices = build_device_list(new_devices, &adapter_clone).await;
.iter() for d in new_devices
.filter(|d| !devices.contains(d) && d.paired_and_trusted()) .iter()
{ .filter(|d| !devices.contains(d) && d.paired_and_trusted())
_ = req_tx.send(BluerRequest::ConnectDevice(d.address)).await; {
_ = req_tx.send(BluerRequest::ConnectDevice(d.address)).await;
}
let _ = tx
.send(BluerSessionEvent::ChangesProcessed(BluerState {
devices: new_devices.clone(),
bluetooth_enabled: adapter_clone
.is_powered()
.await
.unwrap_or_default(),
}))
.await;
devices.clear();
mem::swap(&mut new_devices, &mut devices);
interval.tick().await;
} }
};
mem::swap(&mut new_devices, &mut devices); futures::pin_mut!(listener_fut);
let _ = tx futures::pin_mut!(wakeup_fut);
.send(BluerSessionEvent::ChangesProcessed(BluerState {
devices: devices.clone(), futures::future::select(listener_fut, wakeup_fut).await;
bluetooth_enabled: adapter_clone
.is_powered()
.await
.unwrap_or_default(),
}))
.await;
interval.tick().await;
}
let _ = tx.send(BluerSessionEvent::ChangeStreamEnded).await;
} }
}, });
);
} }
#[inline] #[inline]