From a1d3b9684df4bccec3b741e86ad659bb103c716b Mon Sep 17 00:00:00 2001 From: galister <22305755+galister@users.noreply.github.com> Date: Sat, 23 Mar 2024 15:35:01 +0100 Subject: [PATCH] fix: end async work on soft-shutdown --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- src/backend/notifications.rs | 22 +++++++++++++++++++--- src/overlays/mirror.rs | 35 ++++++++++++++++++++++------------- 4 files changed, 44 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0f76fb5..0d847a9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3602,8 +3602,8 @@ dependencies = [ [[package]] name = "wlx-capture" -version = "0.3.0" -source = "git+https://github.com/galister/wlx-capture?tag=v0.3.0#bbe232c207c7d6cfca26efe02e8bc6ce85ee764a" +version = "0.3.1" +source = "git+https://github.com/galister/wlx-capture?tag=v0.3.1#f9c9c98e0752bfbdaa2af69b59376c697c223915" dependencies = [ "ashpd", "drm-fourcc", diff --git a/Cargo.toml b/Cargo.toml index ee92739..ba29f67 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,7 +43,7 @@ strum = { version = "0.25.0", features = ["derive"] } thiserror = "1.0.56" vulkano = { git = "https://github.com/vulkano-rs/vulkano", rev = "94f50f1" } vulkano-shaders = { git = "https://github.com/vulkano-rs/vulkano", rev = "94f50f1" } -wlx-capture = { git = "https://github.com/galister/wlx-capture", tag = "v0.3.0", default-features = false } +wlx-capture = { git = "https://github.com/galister/wlx-capture", tag = "v0.3.1", default-features = false } xdg = "2.5.2" [features] diff --git a/src/backend/notifications.rs b/src/backend/notifications.rs index cc30f84..2064f3f 100644 --- a/src/backend/notifications.rs +++ b/src/backend/notifications.rs @@ -2,7 +2,10 @@ use dbus::{blocking::Connection, channel::MatchingReceiver, message::MatchRule}; use serde::{Deserialize, Serialize}; use std::{ path::PathBuf, - sync::{mpsc, Arc}, + sync::{ + atomic::{AtomicBool, Ordering}, + mpsc, Arc, + }, time::Duration, }; @@ -12,6 +15,7 @@ pub struct NotificationManager { rx_toast: mpsc::Receiver, tx_toast: mpsc::SyncSender, dbus_data: Option, + running: Arc, } impl NotificationManager { @@ -21,6 +25,7 @@ impl NotificationManager { rx_toast, tx_toast, dbus_data: None, + running: Arc::new(AtomicBool::new(true)), } } @@ -125,7 +130,7 @@ impl NotificationManager { pub fn run_udp(&mut self) { let sender = self.tx_toast.clone(); - // NOTE: We're detaching the thread, as there's no simple way to gracefully stop it other than app shutdown. + let running = self.running.clone(); let _ = std::thread::spawn(move || { let addr = "127.0.0.1:42069"; let socket = match std::net::UdpSocket::bind(addr) { @@ -135,9 +140,13 @@ impl NotificationManager { return; } }; + if let Err(err) = socket.set_read_timeout(Some(Duration::from_millis(200))) { + log::error!("Failed to set read timeout: {:?}", err); + } + let mut buf = [0u8; 1024 * 16]; // vrcx embeds icons as b64 - loop { + while running.load(Ordering::Relaxed) { if let Ok((num_bytes, _)) = socket.recv_from(&mut buf) { let json_str = match std::str::from_utf8(&buf[..num_bytes]) { Ok(s) => s, @@ -170,10 +179,17 @@ impl NotificationManager { } } } + log::info!("Notification listener stopped."); }); } } +impl Drop for NotificationManager { + fn drop(&mut self) { + self.running.store(false, Ordering::Relaxed); + } +} + fn parse_dbus(msg: &dbus::Message) -> anyhow::Result { let mut args = msg.iter_init(); let app_name: String = args.read()?; diff --git a/src/overlays/mirror.rs b/src/overlays/mirror.rs index 094161b..ddd4419 100644 --- a/src/overlays/mirror.rs +++ b/src/overlays/mirror.rs @@ -1,6 +1,9 @@ -use std::{sync::Arc, thread::JoinHandle}; +use std::{ + sync::Arc, + task::{Context, Poll}, +}; -use futures::executor; +use futures::{Future, FutureExt}; use glam::vec3a; use wlx_capture::pipewire::{pipewire_select_screen, PipewireCapture, PipewireSelectScreenResult}; @@ -15,21 +18,23 @@ use crate::{ }; use super::screen::ScreenRenderer; +type PinnedSelectorFuture = core::pin::Pin< + Box>>, +>; pub struct MirrorRenderer { name: Arc, renderer: Option, - selector: Option>>, + selector: Option, last_extent: [u32; 3], } impl MirrorRenderer { pub fn new(name: Arc) -> Self { + let selector = Box::pin(pipewire_select_screen(None, false, false, false)); Self { name, renderer: None, - selector: Some(std::thread::spawn(|| { - executor::block_on(pipewire_select_screen(None, false, false, false)).ok() - })), + selector: Some(selector), last_extent: [0; 3], } } @@ -40,14 +45,18 @@ impl OverlayRenderer for MirrorRenderer { Ok(()) } fn render(&mut self, app: &mut AppState) -> anyhow::Result<()> { - if let Some(selector) = self.selector.take() { - if !selector.is_finished() { - self.selector = Some(selector); - return Ok(()); - } + if let Some(mut selector) = self.selector.take() { + let maybe_pw_result = match selector + .poll_unpin(&mut Context::from_waker(futures::task::noop_waker_ref())) + { + Poll::Ready(result) => result, + Poll::Pending => { + self.selector = Some(selector); + return Ok(()); + } + }; - // safe unwrap because we know it's finished - if let Some(pw_result) = selector.join().unwrap() { + if let Ok(pw_result) = maybe_pw_result { log::info!( "{}: PipeWire node selected: {}", self.name.clone(),