From 94816a490adc91ead929d5cc45c1d2b38fd7c436 Mon Sep 17 00:00:00 2001 From: Philipp Urlbauer Date: Thu, 25 Nov 2021 19:28:10 +0100 Subject: [PATCH 01/52] Use WinAPI to simulate pointermovements --- Cargo.toml | 2 + src/input/autopilot_device.rs | 122 +++++++++++++++++++++++++++++----- 2 files changed, 107 insertions(+), 17 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7b3fc22c..afcbd472 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,8 @@ percent-encoding = "2.1.0" toml = "^0.5" structopt = { version = "^0.3", features = ["color", "suggestions"], default-features = false } dirs = "^3.0" +[target.'cfg(windows)'.dependencies] +winapi = { version = "0.3", features = ["winuser"] } [build-dependencies] cc = "^1.0" diff --git a/src/input/autopilot_device.rs b/src/input/autopilot_device.rs index e5a3542d..20483020 100644 --- a/src/input/autopilot_device.rs +++ b/src/input/autopilot_device.rs @@ -3,20 +3,32 @@ use autopilot::mouse; use autopilot::mouse::ScrollDirection; use autopilot::screen::size as screen_size; +use winapi::shared::windef::{HWND, POINT}; +use winapi::um::winuser::*; + use tracing::warn; use crate::input::device::{InputDevice, InputDeviceType}; -use crate::protocol::{Button, KeyboardEvent, KeyboardEventType, PointerEvent, WheelEvent}; +use crate::protocol::{ + Button, KeyboardEvent, KeyboardEventType, PointerEvent, PointerEventType, PointerType, + WheelEvent, +}; use crate::capturable::Capturable; pub struct AutoPilotDevice { capturable: Box, + pointer_device_handle: *mut HSYNTHETICPOINTERDEVICE__, } impl AutoPilotDevice { pub fn new(capturable: Box) -> Self { - Self { capturable } + unsafe { + Self { + capturable, + pointer_device_handle: CreateSyntheticPointerDevice(PT_PEN, 1, 1), + } + } } } @@ -53,23 +65,99 @@ impl InputDevice for AutoPilotDevice { return; } }; - if let Err(err) = mouse::move_to(autopilot::geometry::Point::new( - (event.x * width_rel + x_rel) * width, - (event.y * height_rel + y_rel) * height, - )) { - warn!("Could not move mouse: {}", err); - } - match event.button { - Button::PRIMARY => { - mouse::toggle(mouse::Button::Left, event.buttons.contains(event.button)) - } - Button::AUXILARY => { - mouse::toggle(mouse::Button::Middle, event.buttons.contains(event.button)) + let (x, y) = ( + ((event.x * width_rel + x_rel) * width) as i32, + ((event.y * height_rel + y_rel) * height) as i32, + ); + match event.pointer_type { + PointerType::Pen => { + unsafe { + let mut pointer_type_info = POINTER_TYPE_INFO { + type_: PT_PEN, + u: std::mem::zeroed(), + }; + //| POINTER_FLAG_FIRSTBUTTON + let pointer_flags; + let button_change_type; + match event.event_type { + PointerEventType::DOWN => { + pointer_flags = POINTER_FLAG_INRANGE + | POINTER_FLAG_INCONTACT + | POINTER_FLAG_PRIMARY + | POINTER_FLAG_DOWN; + button_change_type = POINTER_CHANGE_FIRSTBUTTON_DOWN; + } + + PointerEventType::UP => { + pointer_flags = POINTER_FLAG_PRIMARY | POINTER_FLAG_UP; + button_change_type = POINTER_CHANGE_FIRSTBUTTON_UP; + } + PointerEventType::MOVE => { + pointer_flags = POINTER_FLAG_INRANGE + | POINTER_FLAG_INCONTACT + | POINTER_FLAG_PRIMARY; + button_change_type = POINTER_CHANGE_NONE; + } + + PointerEventType::CANCEL => { + pointer_flags = POINTER_FLAG_PRIMARY | POINTER_FLAG_CANCELED; + button_change_type = POINTER_CHANGE_NONE; + } + }; + *pointer_type_info.u.penInfo_mut() = POINTER_PEN_INFO { + pointerInfo: POINTER_INFO { + pointerType: PT_PEN, + pointerId: event.pointer_id as u32, + frameId: 0, + pointerFlags: pointer_flags, + sourceDevice: 0 as *mut winapi::ctypes::c_void, //maybe use syntheticPointerDeviceHandle here but works with 0 + hwndTarget: 0 as HWND, + ptPixelLocation: POINT { x: x, y: y }, + ptHimetricLocation: POINT { x: 0, y: 0 }, + ptPixelLocationRaw: POINT { x: x, y: y }, + ptHimetricLocationRaw: POINT { x: 0, y: 0 }, + dwTime: 0, + historyCount: 1, + InputData: 0, + dwKeyStates: 0, + PerformanceCount: 0, + ButtonChangeType: button_change_type, + }, + penFlags: PEN_FLAG_NONE, + penMask: PEN_MASK_PRESSURE + | PEN_MASK_ROTATION + | PEN_MASK_TILT_X + | PEN_MASK_TILT_Y, + pressure: (event.pressure * 100f64) as u32, + rotation: event.twist as u32, + tiltX: event.tilt_x, + tiltY: event.tilt_y, + }; + InjectSyntheticPointerInput(self.pointer_device_handle, &pointer_type_info, 1); + } } - Button::SECONDARY => { - mouse::toggle(mouse::Button::Right, event.buttons.contains(event.button)) + PointerType::Mouse => { + if let Err(err) = mouse::move_to(autopilot::geometry::Point::new( + (event.x * width_rel + x_rel) * width, + (event.y * height_rel + y_rel) * height, + )) { + warn!("Could not move mouse: {}", err); + } + match event.button { + Button::PRIMARY => { + mouse::toggle(mouse::Button::Left, event.buttons.contains(event.button)) + } + Button::AUXILARY => { + mouse::toggle(mouse::Button::Middle, event.buttons.contains(event.button)) + } + Button::SECONDARY => { + mouse::toggle(mouse::Button::Right, event.buttons.contains(event.button)) + } + _ => (), + } } - _ => (), + PointerType::Touch => todo!(), + PointerType::Unknown => todo!(), } } From a21f5a7f8c0e7212fb0695690f29611fb35ffa51 Mon Sep 17 00:00:00 2001 From: Philipp Urlbauer Date: Fri, 26 Nov 2021 01:55:42 +0100 Subject: [PATCH 02/52] Move windows implementation to own file --- src/input/autopilot_device.rs | 122 ++----------- src/input/autopilot_device_win.rs | 284 ++++++++++++++++++++++++++++++ src/input/device.rs | 3 +- src/input/mod.rs | 7 +- 4 files changed, 307 insertions(+), 109 deletions(-) create mode 100644 src/input/autopilot_device_win.rs diff --git a/src/input/autopilot_device.rs b/src/input/autopilot_device.rs index 20483020..e5a3542d 100644 --- a/src/input/autopilot_device.rs +++ b/src/input/autopilot_device.rs @@ -3,32 +3,20 @@ use autopilot::mouse; use autopilot::mouse::ScrollDirection; use autopilot::screen::size as screen_size; -use winapi::shared::windef::{HWND, POINT}; -use winapi::um::winuser::*; - use tracing::warn; use crate::input::device::{InputDevice, InputDeviceType}; -use crate::protocol::{ - Button, KeyboardEvent, KeyboardEventType, PointerEvent, PointerEventType, PointerType, - WheelEvent, -}; +use crate::protocol::{Button, KeyboardEvent, KeyboardEventType, PointerEvent, WheelEvent}; use crate::capturable::Capturable; pub struct AutoPilotDevice { capturable: Box, - pointer_device_handle: *mut HSYNTHETICPOINTERDEVICE__, } impl AutoPilotDevice { pub fn new(capturable: Box) -> Self { - unsafe { - Self { - capturable, - pointer_device_handle: CreateSyntheticPointerDevice(PT_PEN, 1, 1), - } - } + Self { capturable } } } @@ -65,99 +53,23 @@ impl InputDevice for AutoPilotDevice { return; } }; - let (x, y) = ( - ((event.x * width_rel + x_rel) * width) as i32, - ((event.y * height_rel + y_rel) * height) as i32, - ); - match event.pointer_type { - PointerType::Pen => { - unsafe { - let mut pointer_type_info = POINTER_TYPE_INFO { - type_: PT_PEN, - u: std::mem::zeroed(), - }; - //| POINTER_FLAG_FIRSTBUTTON - let pointer_flags; - let button_change_type; - match event.event_type { - PointerEventType::DOWN => { - pointer_flags = POINTER_FLAG_INRANGE - | POINTER_FLAG_INCONTACT - | POINTER_FLAG_PRIMARY - | POINTER_FLAG_DOWN; - button_change_type = POINTER_CHANGE_FIRSTBUTTON_DOWN; - } - - PointerEventType::UP => { - pointer_flags = POINTER_FLAG_PRIMARY | POINTER_FLAG_UP; - button_change_type = POINTER_CHANGE_FIRSTBUTTON_UP; - } - PointerEventType::MOVE => { - pointer_flags = POINTER_FLAG_INRANGE - | POINTER_FLAG_INCONTACT - | POINTER_FLAG_PRIMARY; - button_change_type = POINTER_CHANGE_NONE; - } - - PointerEventType::CANCEL => { - pointer_flags = POINTER_FLAG_PRIMARY | POINTER_FLAG_CANCELED; - button_change_type = POINTER_CHANGE_NONE; - } - }; - *pointer_type_info.u.penInfo_mut() = POINTER_PEN_INFO { - pointerInfo: POINTER_INFO { - pointerType: PT_PEN, - pointerId: event.pointer_id as u32, - frameId: 0, - pointerFlags: pointer_flags, - sourceDevice: 0 as *mut winapi::ctypes::c_void, //maybe use syntheticPointerDeviceHandle here but works with 0 - hwndTarget: 0 as HWND, - ptPixelLocation: POINT { x: x, y: y }, - ptHimetricLocation: POINT { x: 0, y: 0 }, - ptPixelLocationRaw: POINT { x: x, y: y }, - ptHimetricLocationRaw: POINT { x: 0, y: 0 }, - dwTime: 0, - historyCount: 1, - InputData: 0, - dwKeyStates: 0, - PerformanceCount: 0, - ButtonChangeType: button_change_type, - }, - penFlags: PEN_FLAG_NONE, - penMask: PEN_MASK_PRESSURE - | PEN_MASK_ROTATION - | PEN_MASK_TILT_X - | PEN_MASK_TILT_Y, - pressure: (event.pressure * 100f64) as u32, - rotation: event.twist as u32, - tiltX: event.tilt_x, - tiltY: event.tilt_y, - }; - InjectSyntheticPointerInput(self.pointer_device_handle, &pointer_type_info, 1); - } + if let Err(err) = mouse::move_to(autopilot::geometry::Point::new( + (event.x * width_rel + x_rel) * width, + (event.y * height_rel + y_rel) * height, + )) { + warn!("Could not move mouse: {}", err); + } + match event.button { + Button::PRIMARY => { + mouse::toggle(mouse::Button::Left, event.buttons.contains(event.button)) } - PointerType::Mouse => { - if let Err(err) = mouse::move_to(autopilot::geometry::Point::new( - (event.x * width_rel + x_rel) * width, - (event.y * height_rel + y_rel) * height, - )) { - warn!("Could not move mouse: {}", err); - } - match event.button { - Button::PRIMARY => { - mouse::toggle(mouse::Button::Left, event.buttons.contains(event.button)) - } - Button::AUXILARY => { - mouse::toggle(mouse::Button::Middle, event.buttons.contains(event.button)) - } - Button::SECONDARY => { - mouse::toggle(mouse::Button::Right, event.buttons.contains(event.button)) - } - _ => (), - } + Button::AUXILARY => { + mouse::toggle(mouse::Button::Middle, event.buttons.contains(event.button)) + } + Button::SECONDARY => { + mouse::toggle(mouse::Button::Right, event.buttons.contains(event.button)) } - PointerType::Touch => todo!(), - PointerType::Unknown => todo!(), + _ => (), } } diff --git a/src/input/autopilot_device_win.rs b/src/input/autopilot_device_win.rs new file mode 100644 index 00000000..b03cf9c1 --- /dev/null +++ b/src/input/autopilot_device_win.rs @@ -0,0 +1,284 @@ +use autopilot::geometry::Size; +use autopilot::mouse; +use autopilot::mouse::ScrollDirection; +use autopilot::screen::size as screen_size; + +use winapi::shared::windef::{HWND, POINT, RECT}; +use winapi::um::winuser::*; + +use tracing::warn; + +use crate::input::device::{InputDevice, InputDeviceType}; +use crate::protocol::{ + Button, KeyboardEvent, KeyboardEventType, PointerEvent, PointerEventType, PointerType, + WheelEvent, +}; + +use crate::capturable::Capturable; + +pub struct WindowsInput { + capturable: Box, + pointer_device_handle: *mut HSYNTHETICPOINTERDEVICE__, + touch_device_handle: *mut HSYNTHETICPOINTERDEVICE__, +} + +impl WindowsInput { + pub fn new(capturable: Box) -> Self { + unsafe { + Self { + capturable, + pointer_device_handle: CreateSyntheticPointerDevice(PT_PEN, 1, 1), + touch_device_handle: CreateSyntheticPointerDevice(PT_TOUCH, 5, 1), + } + } + } +} + +impl InputDevice for WindowsInput { + fn send_wheel_event(&mut self, event: &WheelEvent) { + match event.dy { + 1..=i32::MAX => mouse::scroll(ScrollDirection::Up, 1), + i32::MIN..=-1 => mouse::scroll(ScrollDirection::Down, 1), + 0 => {} + } + } + + fn send_pointer_event(&mut self, event: &PointerEvent) { + if !event.is_primary { + return; + } + if let Err(err) = self.capturable.before_input() { + warn!("Failed to activate window, sending no input ({})", err); + return; + } + let geometry = self.capturable.geometry_relative(); + if let Err(err) = geometry { + warn!("Failed to get window geometry, sending no input ({})", err); + return; + } + let (x_rel, y_rel, width_rel, height_rel) = geometry.unwrap(); + let Size { width, height } = screen_size(); + let (x, y) = ( + ((event.x * width_rel + x_rel) * width) as i32, + ((event.y * height_rel + y_rel) * height) as i32, + ); + let mut pointer_type_info = POINTER_TYPE_INFO { + type_: PT_PEN, + u: unsafe { std::mem::zeroed() }, + }; + let pointer_flags; + let button_change_type; + match event.event_type { + PointerEventType::DOWN => { + pointer_flags = POINTER_FLAG_INRANGE + | POINTER_FLAG_INCONTACT + | POINTER_FLAG_PRIMARY + | POINTER_FLAG_DOWN; + button_change_type = POINTER_CHANGE_FIRSTBUTTON_DOWN; + } + + PointerEventType::UP => { + pointer_flags = POINTER_FLAG_PRIMARY | POINTER_FLAG_UP; + button_change_type = POINTER_CHANGE_FIRSTBUTTON_UP; + } + PointerEventType::MOVE => { + pointer_flags = + POINTER_FLAG_INRANGE | POINTER_FLAG_INCONTACT | POINTER_FLAG_PRIMARY; + button_change_type = POINTER_CHANGE_NONE; + } + + PointerEventType::CANCEL => { + pointer_flags = POINTER_FLAG_PRIMARY | POINTER_FLAG_CANCELED; + button_change_type = POINTER_CHANGE_NONE; + } + }; + match event.pointer_type { + PointerType::Pen => { + unsafe { + *pointer_type_info.u.penInfo_mut() = POINTER_PEN_INFO { + pointerInfo: POINTER_INFO { + pointerType: PT_PEN, + pointerId: event.pointer_id as u32, + frameId: 0, + pointerFlags: pointer_flags, + sourceDevice: 0 as *mut winapi::ctypes::c_void, //maybe use syntheticPointerDeviceHandle here but works with 0 + hwndTarget: 0 as HWND, + ptPixelLocation: POINT { x: x, y: y }, + ptHimetricLocation: POINT { x: 0, y: 0 }, + ptPixelLocationRaw: POINT { x: x, y: y }, + ptHimetricLocationRaw: POINT { x: 0, y: 0 }, + dwTime: 0, + historyCount: 1, + InputData: 0, + dwKeyStates: 0, + PerformanceCount: 0, + ButtonChangeType: button_change_type, + }, + penFlags: PEN_FLAG_NONE, + penMask: PEN_MASK_PRESSURE + | PEN_MASK_ROTATION + | PEN_MASK_TILT_X + | PEN_MASK_TILT_Y, + pressure: (event.pressure * 100f64) as u32, + rotation: event.twist as u32, + tiltX: event.tilt_x, + tiltY: event.tilt_y, + }; + InjectSyntheticPointerInput(self.pointer_device_handle, &pointer_type_info, 1); + } + } + PointerType::Touch => { + unsafe { + *pointer_type_info.u.touchInfo_mut() = POINTER_TOUCH_INFO { + pointerInfo: POINTER_INFO { + pointerType: PT_TOUCH, + pointerId: event.pointer_id as u32, + frameId: 0, + pointerFlags: pointer_flags, + sourceDevice: 0 as *mut winapi::ctypes::c_void, //maybe use syntheticPointerDeviceHandle here but works with 0 + hwndTarget: 0 as HWND, + ptPixelLocation: POINT { x: x, y: y }, + ptHimetricLocation: POINT { x: 0, y: 0 }, + ptPixelLocationRaw: POINT { x: x, y: y }, + ptHimetricLocationRaw: POINT { x: 0, y: 0 }, + dwTime: 0, + historyCount: 1, + InputData: 0, + dwKeyStates: 0, + PerformanceCount: 0, + ButtonChangeType: button_change_type, + }, + touchFlags: TOUCH_FLAG_NONE, + touchMask: TOUCH_MASK_PRESSURE, + orientation: 0, + pressure: (event.pressure * 100f64) as u32, + rcContact: RECT { + left: x, + top: y, + right: x, + bottom: y, + }, + rcContactRaw: RECT { + left: x, + top: y, + right: x, + bottom: y, + }, + }; + InjectSyntheticPointerInput(self.touch_device_handle, &pointer_type_info, 1); + } + } + PointerType::Mouse => { + if let Err(err) = mouse::move_to(autopilot::geometry::Point::new( + (event.x * width_rel + x_rel) * width, + (event.y * height_rel + y_rel) * height, + )) { + warn!("Could not move mouse: {}", err); + } + match event.button { + Button::PRIMARY => { + mouse::toggle(mouse::Button::Left, event.buttons.contains(event.button)) + } + Button::AUXILARY => { + mouse::toggle(mouse::Button::Middle, event.buttons.contains(event.button)) + } + Button::SECONDARY => { + mouse::toggle(mouse::Button::Right, event.buttons.contains(event.button)) + } + _ => (), + } + } + PointerType::Unknown => todo!(), + } + } + + fn send_keyboard_event(&mut self, event: &KeyboardEvent) { + use autopilot::key::{Character, Code, KeyCode}; + + let state = match event.event_type { + KeyboardEventType::UP => false, + KeyboardEventType::DOWN => true, + // autopilot doesn't handle this, so just do nothing + KeyboardEventType::REPEAT => return, + }; + + fn map_key(code: &str) -> Option { + match code { + "Escape" => Some(KeyCode::Escape), + "Enter" => Some(KeyCode::Return), + "Backspace" => Some(KeyCode::Backspace), + "Tab" => Some(KeyCode::Tab), + "Space" => Some(KeyCode::Space), + "CapsLock" => Some(KeyCode::CapsLock), + "F1" => Some(KeyCode::F1), + "F2" => Some(KeyCode::F2), + "F3" => Some(KeyCode::F3), + "F4" => Some(KeyCode::F4), + "F5" => Some(KeyCode::F5), + "F6" => Some(KeyCode::F6), + "F7" => Some(KeyCode::F7), + "F8" => Some(KeyCode::F8), + "F9" => Some(KeyCode::F9), + "F10" => Some(KeyCode::F10), + "F11" => Some(KeyCode::F11), + "F12" => Some(KeyCode::F12), + "F13" => Some(KeyCode::F13), + "F14" => Some(KeyCode::F14), + "F15" => Some(KeyCode::F15), + "F16" => Some(KeyCode::F16), + "F17" => Some(KeyCode::F17), + "F18" => Some(KeyCode::F18), + "F19" => Some(KeyCode::F19), + "F20" => Some(KeyCode::F20), + "F21" => Some(KeyCode::F21), + "F22" => Some(KeyCode::F22), + "F23" => Some(KeyCode::F23), + "F24" => Some(KeyCode::F24), + "Home" => Some(KeyCode::Home), + "ArrowUp" => Some(KeyCode::UpArrow), + "PageUp" => Some(KeyCode::PageUp), + "ArrowLeft" => Some(KeyCode::LeftArrow), + "ArrowRight" => Some(KeyCode::RightArrow), + "End" => Some(KeyCode::End), + "ArrowDown" => Some(KeyCode::DownArrow), + "PageDown" => Some(KeyCode::PageDown), + "Delete" => Some(KeyCode::Delete), + "ControlLeft" | "ControlRight" => Some(KeyCode::Control), + "AltLeft" | "AltRight" => Some(KeyCode::Alt), + "MetaLeft" | "MetaRight" => Some(KeyCode::Meta), + "ShiftLeft" | "ShiftRight" => Some(KeyCode::Shift), + _ => None, + } + } + let key = map_key(&event.code); + let mut flags = Vec::new(); + if event.ctrl { + flags.push(autopilot::key::Flag::Control); + } + if event.alt { + flags.push(autopilot::key::Flag::Alt); + } + if event.meta { + flags.push(autopilot::key::Flag::Meta); + } + if event.shift { + flags.push(autopilot::key::Flag::Shift); + } + match key { + Some(key) => autopilot::key::toggle(&Code(key), state, &flags, 0), + None => { + for c in event.key.chars() { + autopilot::key::toggle(&Character(c), state, &flags, 0); + } + } + } + } + + fn set_capturable(&mut self, capturable: Box) { + self.capturable = capturable; + } + + fn device_type(&self) -> InputDeviceType { + InputDeviceType::WindowsInput + } +} diff --git a/src/input/device.rs b/src/input/device.rs index ed7a672f..424eebdf 100644 --- a/src/input/device.rs +++ b/src/input/device.rs @@ -1,10 +1,11 @@ -use crate::protocol::{WheelEvent, PointerEvent, KeyboardEvent}; use crate::capturable::Capturable; +use crate::protocol::{KeyboardEvent, PointerEvent, WheelEvent}; #[derive(PartialEq, Eq)] pub enum InputDeviceType { AutoPilotDevice, UInputDevice, + WindowsInput, } pub trait InputDevice { diff --git a/src/input/mod.rs b/src/input/mod.rs index 5cbe2d66..21ca2da1 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -1,8 +1,9 @@ -pub mod device; pub mod autopilot_device; +pub mod autopilot_device_win; +pub mod device; +#[cfg(target_os = "linux")] +pub mod uinput_device; #[cfg(target_os = "linux")] #[allow(dead_code)] pub mod uinput_keys; -#[cfg(target_os = "linux")] -pub mod uinput_device; From 327375da572d6f84714b72a9459ae75939ec95ed Mon Sep 17 00:00:00 2001 From: Philipp Urlbauer Date: Fri, 26 Nov 2021 02:04:40 +0100 Subject: [PATCH 03/52] Use windows device only on windows --- src/input/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/input/mod.rs b/src/input/mod.rs index 21ca2da1..5091d2fa 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -1,7 +1,9 @@ pub mod autopilot_device; -pub mod autopilot_device_win; pub mod device; +#[cfg(target_os = "windows")] +pub mod autopilot_device_win; + #[cfg(target_os = "linux")] pub mod uinput_device; #[cfg(target_os = "linux")] From 3b6e9f0d23dfb050d3b66758849957b67de98662 Mon Sep 17 00:00:00 2001 From: Philipp Urlbauer Date: Fri, 26 Nov 2021 02:06:02 +0100 Subject: [PATCH 04/52] Use WindowsInput in websocket --- src/websocket.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/websocket.rs b/src/websocket.rs index b050b474..10adc44e 100644 --- a/src/websocket.rs +++ b/src/websocket.rs @@ -510,7 +510,7 @@ impl WsHandler { d.set_capturable(capturable.clone()); } - #[cfg(not(target_os = "linux"))] + #[cfg(target_os = "macos")] if self.input_device.is_none() { self.input_device = Some(Box::new( crate::input::autopilot_device::AutoPilotDevice::new(capturable.clone()), @@ -520,6 +520,16 @@ impl WsHandler { .as_mut() .map(|d| d.set_capturable(capturable.clone())); } + #[cfg(target_os = "windows")] + if self.input_device.is_none() { + self.input_device = Some(Box::new( + crate::input::autopilot_device_win::WindowsInput::new(capturable.clone()), + )); + } else { + self.input_device + .as_mut() + .map(|d| d.set_capturable(capturable.clone())); + } self.video_sender .send(VideoCommands::Start(VideoConfig { From dae725e240a5e084dab9b5b86d0fb9c38288f7dd Mon Sep 17 00:00:00 2001 From: Philipp Urlbauer Date: Sat, 27 Nov 2021 17:04:44 +0100 Subject: [PATCH 05/52] Working with multiple monitors --- src/capturable/autopilot.rs | 6 ++ src/capturable/captrs_capture.rs | 70 +++++++++++++++++++++++ src/capturable/mod.rs | 27 ++++++++- src/capturable/testsrc.rs | 6 ++ src/capturable/win_ctx.rs | 93 +++++++++++++++++++++++++++++++ src/input/autopilot_device_win.rs | 11 ++-- src/websocket.rs | 1 + 7 files changed, 206 insertions(+), 8 deletions(-) create mode 100644 src/capturable/captrs_capture.rs create mode 100644 src/capturable/win_ctx.rs diff --git a/src/capturable/autopilot.rs b/src/capturable/autopilot.rs index 719daad6..68defc8c 100644 --- a/src/capturable/autopilot.rs +++ b/src/capturable/autopilot.rs @@ -27,6 +27,12 @@ impl Capturable for AutoPilotCapturable { fn recorder(&self, _capture_cursor: bool) -> Result, Box> { Ok(Box::new(RecorderAutoPilot::new())) } + fn geometry(&self) -> Result<(u32, u32), Box> { + Ok((0, 0)) + } + fn geometry_offset(&self) -> Result<(i32, i32), Box> { + Ok((0, 0)) + } } pub struct RecorderAutoPilot { diff --git a/src/capturable/captrs_capture.rs b/src/capturable/captrs_capture.rs new file mode 100644 index 00000000..fdbc8415 --- /dev/null +++ b/src/capturable/captrs_capture.rs @@ -0,0 +1,70 @@ +use crate::capturable::{Capturable, Recorder}; +use captrs::Capturer; +use std::boxed::Box; +use std::error::Error; + +#[derive(Clone)] +pub struct CaptrsCapturable { + id: u8, + width: u32, + height: u32, + offset_x: i32, + offset_y: i32, +} + +impl CaptrsCapturable { + pub fn new(id: u8, width: u32, height: u32, offset_x: i32, offset_y: i32) -> CaptrsCapturable { + CaptrsCapturable { + id, + width, + height, + offset_x, + offset_y, + } + } +} + +impl Capturable for CaptrsCapturable { + fn name(&self) -> String { + format!("Desktop {} (captrs)", self.id).into() + } + fn geometry_relative(&self) -> Result<(f64, f64, f64, f64), Box> { + Ok((0.0, 0.0, 1.0, 1.0)) + } + fn before_input(&mut self) -> Result<(), Box> { + Ok(()) + } + fn recorder(&self, _capture_cursor: bool) -> Result, Box> { + Ok(Box::new(CaptrsRecorder::new(self.id))) + } + fn geometry(&self) -> Result<(u32, u32), Box> { + Ok((self.width, self.height)) + } + fn geometry_offset(&self) -> Result<(i32, i32), Box> { + Ok((self.offset_x, self.offset_y)) + } +} + +pub struct CaptrsRecorder { + capturer: Capturer, +} + +impl CaptrsRecorder { + pub fn new(id: u8) -> CaptrsRecorder { + CaptrsRecorder { + capturer: Capturer::new(id.into()).unwrap(), + } + } +} + +impl Recorder for CaptrsRecorder { + fn capture(&mut self) -> Result> { + let _ = self.capturer.capture_store_frame(); + let (w, h) = self.capturer.geometry(); + Ok(crate::video::PixelProvider::BGR0( + w as usize, + h as usize, + unsafe { std::mem::transmute(self.capturer.get_stored_frame().unwrap()) }, + )) + } +} diff --git a/src/capturable/mod.rs b/src/capturable/mod.rs index 7cfaa011..bdb8582a 100644 --- a/src/capturable/mod.rs +++ b/src/capturable/mod.rs @@ -1,4 +1,5 @@ pub mod autopilot; + use std::boxed::Box; use std::error::Error; use tracing::warn; @@ -10,9 +11,13 @@ pub mod pipewire; #[cfg(target_os = "linux")] pub mod pipewire_dbus; pub mod testsrc; + +#[cfg(target_os = "windows")] +pub mod captrs_capture; +#[cfg(target_os = "windows")] +pub mod win_ctx; #[cfg(target_os = "linux")] pub mod x11; - pub trait Recorder { fn capture(&mut self) -> Result>; } @@ -44,6 +49,8 @@ pub trait Capturable: Send + BoxCloneCapturable { /// Return a Recorder that can record the current capturable. fn recorder(&self, capture_cursor: bool) -> Result, Box>; + fn geometry(&self) -> Result<(u32, u32), Box>; + fn geometry_offset(&self) -> Result<(i32, i32), Box>; } impl Clone for Box { @@ -111,8 +118,22 @@ pub fn get_capturables( } } - use crate::capturable::autopilot::AutoPilotCapturable; - capturables.push(Box::new(AutoPilotCapturable::new())); + #[cfg(target_os = "windows")] + { + use crate::capturable::captrs_capture::CaptrsCapturable; + use crate::capturable::win_ctx::WinCtx; + let winctx = WinCtx::new(); + for (i, o) in winctx.get_outputs().iter().enumerate() { + let captr = CaptrsCapturable::new( + i as u8, + (o.right - o.left) as u32, + (o.bottom - o.top) as u32, + o.left - winctx.get_union_rect().left, + o.top - winctx.get_union_rect().top, + ); + capturables.push(Box::new(captr)); + } + } if crate::log::get_log_level() >= tracing::Level::DEBUG { for (width, height) in [ diff --git a/src/capturable/testsrc.rs b/src/capturable/testsrc.rs index e9c630f0..784fc746 100644 --- a/src/capturable/testsrc.rs +++ b/src/capturable/testsrc.rs @@ -52,6 +52,12 @@ impl Capturable for TestCapturable { fn recorder(&self, _: bool) -> Result, Box> { Ok(Box::new(TestRecorder::new(*self))) } + fn geometry(&self) -> Result<(u32, u32), Box> { + Ok((0, 0)) + } + fn geometry_offset(&self) -> Result<(i32, i32), Box> { + Ok((0, 0)) + } } impl Recorder for TestRecorder { diff --git a/src/capturable/win_ctx.rs b/src/capturable/win_ctx.rs new file mode 100644 index 00000000..b1e4b88c --- /dev/null +++ b/src/capturable/win_ctx.rs @@ -0,0 +1,93 @@ +use std::mem::zeroed; +use std::{mem, ptr}; +use winapi::shared::dxgi::{ + CreateDXGIFactory1, IDXGIAdapter1, IDXGIFactory1, IDXGIOutput, IID_IDXGIFactory1, + DXGI_OUTPUT_DESC, +}; + +use winapi::shared::windef::*; +use winapi::shared::winerror::*; +use winapi::um::winuser::*; +use wio::com::ComPtr; + +use super::captrs_capture::CaptrsCapturable; + +// from https://github.com/bryal/dxgcap-rs/blob/009b746d1c19c4c10921dd469eaee483db6aa002/src/lib.r +fn hr_failed(hr: HRESULT) -> bool { + hr < 0 +} + +fn create_dxgi_factory_1() -> ComPtr { + unsafe { + let mut factory = ptr::null_mut(); + let hr = CreateDXGIFactory1(&IID_IDXGIFactory1, &mut factory); + if hr_failed(hr) { + panic!("Failed to create DXGIFactory1, {:x}", hr) + } else { + ComPtr::from_raw(factory as *mut IDXGIFactory1) + } + } +} + +fn get_adapter_outputs(adapter: &IDXGIAdapter1) -> Vec> { + let mut outputs = Vec::new(); + for i in 0.. { + unsafe { + let mut output = ptr::null_mut(); + if hr_failed(adapter.EnumOutputs(i, &mut output)) { + break; + } else { + let mut out_desc = zeroed(); + (*output).GetDesc(&mut out_desc); + if out_desc.AttachedToDesktop != 0 { + outputs.push(ComPtr::from_raw(output)) + } else { + break; + } + } + } + } + outputs +} + +#[derive(Clone)] +pub struct WinCtx { + outputs: Vec, + union_rect: RECT, +} + +impl WinCtx { + pub fn new() -> WinCtx { + let mut rects: Vec = Vec::new(); + let mut union: RECT; + unsafe { + union = mem::zeroed(); + let factory = create_dxgi_factory_1(); + let mut adapter = ptr::null_mut(); + if factory.EnumAdapters1(0, &mut adapter) != DXGI_ERROR_NOT_FOUND { + let adp = ComPtr::from_raw(adapter); + let outputs = get_adapter_outputs(&adp); + for o in outputs { + let mut desc: DXGI_OUTPUT_DESC = mem::zeroed(); + o.GetDesc(ptr::addr_of_mut!(desc)); + rects.push(desc.DesktopCoordinates); + UnionRect( + ptr::addr_of_mut!(union), + ptr::addr_of!(union), + ptr::addr_of!(desc.DesktopCoordinates), + ); + } + } + } + WinCtx { + outputs: rects, + union_rect: union, + } + } + pub fn get_outputs(&self) -> &Vec { + &self.outputs + } + pub fn get_union_rect(&self) -> &RECT { + &self.union_rect + } +} diff --git a/src/input/autopilot_device_win.rs b/src/input/autopilot_device_win.rs index b03cf9c1..b86e9123 100644 --- a/src/input/autopilot_device_win.rs +++ b/src/input/autopilot_device_win.rs @@ -57,10 +57,11 @@ impl InputDevice for WindowsInput { return; } let (x_rel, y_rel, width_rel, height_rel) = geometry.unwrap(); - let Size { width, height } = screen_size(); + let (width, height) = self.capturable.geometry().unwrap(); + let (offset_x, offset_y) = self.capturable.geometry_offset().unwrap(); let (x, y) = ( - ((event.x * width_rel + x_rel) * width) as i32, - ((event.y * height_rel + y_rel) * height) as i32, + ((event.x * width_rel + x_rel) * width as f64) as i32 + offset_x, + ((event.y * height_rel + y_rel) * height as f64) as i32 + offset_y, ); let mut pointer_type_info = POINTER_TYPE_INFO { type_: PT_PEN, @@ -170,8 +171,8 @@ impl InputDevice for WindowsInput { } PointerType::Mouse => { if let Err(err) = mouse::move_to(autopilot::geometry::Point::new( - (event.x * width_rel + x_rel) * width, - (event.y * height_rel + y_rel) * height, + (event.x * width_rel + x_rel) * width as f64, + (event.y * height_rel + y_rel) * height as f64, )) { warn!("Could not move mouse: {}", err); } diff --git a/src/websocket.rs b/src/websocket.rs index 10adc44e..5f51ea17 100644 --- a/src/websocket.rs +++ b/src/websocket.rs @@ -13,6 +13,7 @@ use websocket::server::upgrade::{sync::Buffer as WsBuffer, WsUpgrade}; use websocket::sync::Server; use websocket::{Message, OwnedMessage, WebSocketError}; +use crate::capturable::captrs_capture::CaptrsCapturable; use crate::capturable::{get_capturables, Capturable, Recorder}; use crate::input::device::{InputDevice, InputDeviceType}; use crate::protocol::{ From f2fad32d37ca4515fdea5e8ecc0dc7c0ffc26e91 Mon Sep 17 00:00:00 2001 From: Philipp Urlbauer Date: Sat, 27 Nov 2021 17:05:13 +0100 Subject: [PATCH 06/52] Additional dependencies --- Cargo.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index afcbd472..6c12fb9b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,9 @@ toml = "^0.5" structopt = { version = "^0.3", features = ["color", "suggestions"], default-features = false } dirs = "^3.0" [target.'cfg(windows)'.dependencies] -winapi = { version = "0.3", features = ["winuser"] } +winapi = { version = "0.3.8", features = ["d3d11", "d3dcommon", "dxgi", "dxgi1_2", "dxgitype", "ntdef", "unknwnbase", "windef", "winerror", "winuser"] } +wio = "0.2.2" +captrs = "^0.3.1" [build-dependencies] cc = "^1.0" From 94c1baa290a8ade25c4040a5a9b5a06c2ff22309 Mon Sep 17 00:00:00 2001 From: Philipp Urlbauer Date: Sat, 27 Nov 2021 17:56:14 +0100 Subject: [PATCH 07/52] Remove unused imports --- src/capturable/win_ctx.rs | 2 -- src/input/autopilot_device_win.rs | 2 -- src/websocket.rs | 1 - 3 files changed, 5 deletions(-) diff --git a/src/capturable/win_ctx.rs b/src/capturable/win_ctx.rs index b1e4b88c..50dbdf02 100644 --- a/src/capturable/win_ctx.rs +++ b/src/capturable/win_ctx.rs @@ -10,8 +10,6 @@ use winapi::shared::winerror::*; use winapi::um::winuser::*; use wio::com::ComPtr; -use super::captrs_capture::CaptrsCapturable; - // from https://github.com/bryal/dxgcap-rs/blob/009b746d1c19c4c10921dd469eaee483db6aa002/src/lib.r fn hr_failed(hr: HRESULT) -> bool { hr < 0 diff --git a/src/input/autopilot_device_win.rs b/src/input/autopilot_device_win.rs index b86e9123..37db808e 100644 --- a/src/input/autopilot_device_win.rs +++ b/src/input/autopilot_device_win.rs @@ -1,7 +1,5 @@ -use autopilot::geometry::Size; use autopilot::mouse; use autopilot::mouse::ScrollDirection; -use autopilot::screen::size as screen_size; use winapi::shared::windef::{HWND, POINT, RECT}; use winapi::um::winuser::*; diff --git a/src/websocket.rs b/src/websocket.rs index 5f51ea17..10adc44e 100644 --- a/src/websocket.rs +++ b/src/websocket.rs @@ -13,7 +13,6 @@ use websocket::server::upgrade::{sync::Buffer as WsBuffer, WsUpgrade}; use websocket::sync::Server; use websocket::{Message, OwnedMessage, WebSocketError}; -use crate::capturable::captrs_capture::CaptrsCapturable; use crate::capturable::{get_capturables, Capturable, Recorder}; use crate::input::device::{InputDevice, InputDeviceType}; use crate::protocol::{ From 77f0d6d34478c3ca65617772ff9fb6e57f04618e Mon Sep 17 00:00:00 2001 From: Philipp Urlbauer Date: Sat, 27 Nov 2021 18:05:11 +0100 Subject: [PATCH 08/52] Might build on linux and mac now --- src/capturable/pipewire.rs | 12 +++++++++++- src/capturable/x11.rs | 8 ++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/capturable/pipewire.rs b/src/capturable/pipewire.rs index 17391b21..fe16173e 100644 --- a/src/capturable/pipewire.rs +++ b/src/capturable/pipewire.rs @@ -107,6 +107,14 @@ impl Capturable for PipeWireCapturable { fn recorder(&self, capture_cursor: bool) -> Result, Box> { Ok(Box::new(PipeWireRecorder::new(self.clone())?)) } + + fn geometry(&self) -> Result<(u32, u32), Box> { + Ok((0, 0)) + } + + fn geometry_offset(&self) -> Result<(i32, i32), Box> { + Ok((0, 0)) + } } pub struct PipeWireRecorder { @@ -327,7 +335,9 @@ fn streams_from_response(response: OrgFreedesktopPortalRequestResponse) -> Vec

>(); Some(PwStreamInfo { path, - source_type: attributes.get("source_type").map_or(Some(0), |v| v.as_u64())?, + source_type: attributes + .get("source_type") + .map_or(Some(0), |v| v.as_u64())?, }) }) .collect::>(), diff --git a/src/capturable/x11.rs b/src/capturable/x11.rs index 454c0221..168e5a3f 100644 --- a/src/capturable/x11.rs +++ b/src/capturable/x11.rs @@ -136,6 +136,14 @@ impl Capturable for X11Capturable { Err(err) => Err(Box::new(err)), } } + + fn geometry(&self) -> Result<(u32, u32), Box> { + Ok((0, 0)) + } + + fn geometry_offset(&self) -> Result<(i32, i32), Box> { + Ok((0, 0)) + } } impl fmt::Display for X11Capturable { From 2937b2ee576e5087beb7313a70837aba7f7bab39 Mon Sep 17 00:00:00 2001 From: Philipp Urlbauer Date: Sat, 27 Nov 2021 18:08:13 +0100 Subject: [PATCH 09/52] add missing geometry, geometry_offset in implementation CGDisplayCapturable --- src/capturable/core_graphics.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/capturable/core_graphics.rs b/src/capturable/core_graphics.rs index 222a1e7d..8fda401b 100644 --- a/src/capturable/core_graphics.rs +++ b/src/capturable/core_graphics.rs @@ -71,6 +71,14 @@ impl Capturable for CGDisplayCapturable { capture_cursor, ))) } + + fn geometry(&self) -> Result<(u32, u32), Box> { + Ok((0, 0)) + } + + fn geometry_offset(&self) -> Result<(i32, i32), Box> { + Ok((0, 0)) + } } pub struct RecorderCGDisplay { From 2a2c06f99dc064569372572692c22b59d41db81a Mon Sep 17 00:00:00 2001 From: Philipp Urlbauer Date: Mon, 29 Nov 2021 15:27:03 +0100 Subject: [PATCH 10/52] Fix the capturable trait, add Geometry enum that is retruned by capturable.geometry --- src/capturable/autopilot.rs | 12 +++--------- src/capturable/captrs_capture.rs | 17 +++++++++-------- src/capturable/core_graphics.rs | 18 +++++------------- src/capturable/mod.rs | 10 +++++++--- src/capturable/pipewire.rs | 12 ++---------- src/capturable/testsrc.rs | 12 +++--------- src/capturable/x11.rs | 17 +++++++---------- src/input/autopilot_device.rs | 9 ++++++--- src/input/autopilot_device_win.rs | 24 +++++++++++------------- src/input/uinput_device.rs | 9 ++++++--- 10 files changed, 59 insertions(+), 81 deletions(-) diff --git a/src/capturable/autopilot.rs b/src/capturable/autopilot.rs index 68defc8c..3eb51d21 100644 --- a/src/capturable/autopilot.rs +++ b/src/capturable/autopilot.rs @@ -3,7 +3,7 @@ use std::error::Error; use image_autopilot::GenericImageView; -use crate::capturable::{Capturable, Recorder}; +use crate::capturable::{Capturable, Geometry, Recorder}; #[derive(Clone)] pub struct AutoPilotCapturable {} @@ -18,8 +18,8 @@ impl Capturable for AutoPilotCapturable { fn name(&self) -> String { "Desktop (autopilot)".into() } - fn geometry_relative(&self) -> Result<(f64, f64, f64, f64), Box> { - Ok((0.0, 0.0, 1.0, 1.0)) + fn geometry(&self) -> Result> { + Ok(Geometry::Relative(0.0, 0.0, 1.0, 1.0)) } fn before_input(&mut self) -> Result<(), Box> { Ok(()) @@ -27,12 +27,6 @@ impl Capturable for AutoPilotCapturable { fn recorder(&self, _capture_cursor: bool) -> Result, Box> { Ok(Box::new(RecorderAutoPilot::new())) } - fn geometry(&self) -> Result<(u32, u32), Box> { - Ok((0, 0)) - } - fn geometry_offset(&self) -> Result<(i32, i32), Box> { - Ok((0, 0)) - } } pub struct RecorderAutoPilot { diff --git a/src/capturable/captrs_capture.rs b/src/capturable/captrs_capture.rs index fdbc8415..d5e4b7e6 100644 --- a/src/capturable/captrs_capture.rs +++ b/src/capturable/captrs_capture.rs @@ -3,6 +3,8 @@ use captrs::Capturer; use std::boxed::Box; use std::error::Error; +use super::Geometry; + #[derive(Clone)] pub struct CaptrsCapturable { id: u8, @@ -28,20 +30,19 @@ impl Capturable for CaptrsCapturable { fn name(&self) -> String { format!("Desktop {} (captrs)", self.id).into() } - fn geometry_relative(&self) -> Result<(f64, f64, f64, f64), Box> { - Ok((0.0, 0.0, 1.0, 1.0)) - } fn before_input(&mut self) -> Result<(), Box> { Ok(()) } fn recorder(&self, _capture_cursor: bool) -> Result, Box> { Ok(Box::new(CaptrsRecorder::new(self.id))) } - fn geometry(&self) -> Result<(u32, u32), Box> { - Ok((self.width, self.height)) - } - fn geometry_offset(&self) -> Result<(i32, i32), Box> { - Ok((self.offset_x, self.offset_y)) + fn geometry(&self) -> Result> { + Ok(Geometry::VirtualScreen( + self.offset_x, + self.offset_y, + self.width, + self.height, + )) } } diff --git a/src/capturable/core_graphics.rs b/src/capturable/core_graphics.rs index 8fda401b..d56fb870 100644 --- a/src/capturable/core_graphics.rs +++ b/src/capturable/core_graphics.rs @@ -19,7 +19,7 @@ use core_graphics::{ window::CGWindowID, }; -use crate::capturable::{Capturable, Recorder}; +use crate::capturable::{Capturable, Geometry, Recorder}; #[derive(Debug)] pub struct CGError(String); @@ -52,10 +52,10 @@ impl Capturable for CGDisplayCapturable { self.display.pixels_high() ) } - fn geometry_relative(&self) -> Result<(f64, f64, f64, f64), Box> { + fn geometry(&self) -> Result> { let bounds = self.display.bounds(); let (x0, y0, w, h) = screen_coordsys()?; - Ok(( + Ok(Geometry::Relative( (bounds.origin.x - x0) / w, (bounds.origin.y - y0) / h, bounds.size.width / w, @@ -71,14 +71,6 @@ impl Capturable for CGDisplayCapturable { capture_cursor, ))) } - - fn geometry(&self) -> Result<(u32, u32), Box> { - Ok((0, 0)) - } - - fn geometry_offset(&self) -> Result<(i32, i32), Box> { - Ok((0, 0)) - } } pub struct RecorderCGDisplay { @@ -183,8 +175,8 @@ impl Capturable for CGWindowCapturable { fn name(&self) -> String { self.name.clone() } - fn geometry_relative(&self) -> Result<(f64, f64, f64, f64), Box> { - Ok(self.geometry_relative) + fn geometry(&self) -> Result> { + Ok(Geometry::Relative(self.geometry_relative)) } fn before_input(&mut self) -> Result<(), Box> { self.update_geometry() diff --git a/src/capturable/mod.rs b/src/capturable/mod.rs index bdb8582a..bb51e196 100644 --- a/src/capturable/mod.rs +++ b/src/capturable/mod.rs @@ -35,13 +35,19 @@ where } } +pub enum Geometry { + Relative(f64, f64, f64, f64), + VirtualScreen(i32, i32, u32, u32), +} + pub trait Capturable: Send + BoxCloneCapturable { /// Name of the Capturable, for example the window title, if it is a window. fn name(&self) -> String; /// Return x, y, width, height of the Capturable as floats relative to the absolute size of the /// screen. For example x=0.5, y=0.0, width=0.5, height=1.0 means the right half of the screen. - fn geometry_relative(&self) -> Result<(f64, f64, f64, f64), Box>; + /// Or offset_x, offset_y, width, height for a capturable using a virtual screen. (Windows) + fn geometry(&self) -> Result>; /// Callback that is called right before input is simulated. /// Useful to focus the window on input. @@ -49,8 +55,6 @@ pub trait Capturable: Send + BoxCloneCapturable { /// Return a Recorder that can record the current capturable. fn recorder(&self, capture_cursor: bool) -> Result, Box>; - fn geometry(&self) -> Result<(u32, u32), Box>; - fn geometry_offset(&self) -> Result<(i32, i32), Box>; } impl Clone for Box { diff --git a/src/capturable/pipewire.rs b/src/capturable/pipewire.rs index fe16173e..2d0a1085 100644 --- a/src/capturable/pipewire.rs +++ b/src/capturable/pipewire.rs @@ -96,8 +96,8 @@ impl Capturable for PipeWireCapturable { format!("Pipewire {}, path: {}", type_str, self.path) } - fn geometry_relative(&self) -> Result<(f64, f64, f64, f64), Box> { - Ok((0.0, 0.0, 1.0, 1.0)) + fn geometry(&self) -> Result> { + Ok(Geometry::Relative(0.0, 0.0, 1.0, 1.0)) } fn before_input(&mut self) -> Result<(), Box> { @@ -107,14 +107,6 @@ impl Capturable for PipeWireCapturable { fn recorder(&self, capture_cursor: bool) -> Result, Box> { Ok(Box::new(PipeWireRecorder::new(self.clone())?)) } - - fn geometry(&self) -> Result<(u32, u32), Box> { - Ok((0, 0)) - } - - fn geometry_offset(&self) -> Result<(i32, i32), Box> { - Ok((0, 0)) - } } pub struct PipeWireRecorder { diff --git a/src/capturable/testsrc.rs b/src/capturable/testsrc.rs index 784fc746..9e86491a 100644 --- a/src/capturable/testsrc.rs +++ b/src/capturable/testsrc.rs @@ -1,4 +1,4 @@ -use crate::capturable::{Capturable, Recorder}; +use crate::capturable::{Capturable, Geometry, Recorder}; use crate::video::PixelProvider; use std::error::Error; @@ -43,8 +43,8 @@ impl Capturable for TestCapturable { fn name(&self) -> String { format!("Test Source {}x{}", self.width, self.height) } - fn geometry_relative(&self) -> Result<(f64, f64, f64, f64), Box> { - Ok((1.0, 1.0, 1.0, 1.0)) + fn geometry(&self) -> Result> { + Ok(Geometry::Relative(0.0, 0.0, 1.0, 1.0)) } fn before_input(&mut self) -> Result<(), Box> { Ok(()) @@ -52,12 +52,6 @@ impl Capturable for TestCapturable { fn recorder(&self, _: bool) -> Result, Box> { Ok(Box::new(TestRecorder::new(*self))) } - fn geometry(&self) -> Result<(u32, u32), Box> { - Ok((0, 0)) - } - fn geometry_offset(&self) -> Result<(i32, i32), Box> { - Ok((0, 0)) - } } impl Recorder for TestRecorder { diff --git a/src/capturable/x11.rs b/src/capturable/x11.rs index 168e5a3f..e287720b 100644 --- a/src/capturable/x11.rs +++ b/src/capturable/x11.rs @@ -94,7 +94,7 @@ impl Capturable for X11Capturable { } } - fn geometry_relative(&self) -> Result<(f64, f64, f64, f64), Box> { + fn geometry(&self) -> Result<(Geometry), Box> { let mut x: c_float = 0.0; let mut y: c_float = 0.0; let mut width: c_float = 0.0; @@ -115,7 +115,12 @@ impl Capturable for X11Capturable { if err.is_err() { return Err(Box::new(err)); } - Ok((x.into(), y.into(), width.into(), height.into())) + Ok(Geometry::Relative( + x.into(), + y.into(), + width.into(), + height.into(), + )) } fn before_input(&mut self) -> Result<(), Box> { @@ -136,14 +141,6 @@ impl Capturable for X11Capturable { Err(err) => Err(Box::new(err)), } } - - fn geometry(&self) -> Result<(u32, u32), Box> { - Ok((0, 0)) - } - - fn geometry_offset(&self) -> Result<(i32, i32), Box> { - Ok((0, 0)) - } } impl fmt::Display for X11Capturable { diff --git a/src/input/autopilot_device.rs b/src/input/autopilot_device.rs index e5a3542d..e51d6911 100644 --- a/src/input/autopilot_device.rs +++ b/src/input/autopilot_device.rs @@ -8,7 +8,7 @@ use tracing::warn; use crate::input::device::{InputDevice, InputDeviceType}; use crate::protocol::{Button, KeyboardEvent, KeyboardEventType, PointerEvent, WheelEvent}; -use crate::capturable::Capturable; +use crate::capturable::{Capturable, Geometry}; pub struct AutoPilotDevice { capturable: Box, @@ -37,12 +37,15 @@ impl InputDevice for AutoPilotDevice { warn!("Failed to activate window, sending no input ({})", err); return; } - let geometry = self.capturable.geometry_relative(); + let geometry = self.capturable.geometry(); if let Err(err) = geometry { warn!("Failed to get window geometry, sending no input ({})", err); return; } - let (x_rel, y_rel, width_rel, height_rel) = geometry.unwrap(); + let (x_rel, y_rel, width_rel, height_rel) = match geometry.unwrap() { + Geometry::Relative(x, y, width, height) => (x, y, width, height), + _ => unreachable!(), + }; #[cfg(not(target_os = "macos"))] let Size { width, height } = screen_size(); #[cfg(target_os = "macos")] diff --git a/src/input/autopilot_device_win.rs b/src/input/autopilot_device_win.rs index 37db808e..2a510db1 100644 --- a/src/input/autopilot_device_win.rs +++ b/src/input/autopilot_device_win.rs @@ -12,7 +12,7 @@ use crate::protocol::{ WheelEvent, }; -use crate::capturable::Capturable; +use crate::capturable::{Capturable, Geometry}; pub struct WindowsInput { capturable: Box, @@ -49,17 +49,15 @@ impl InputDevice for WindowsInput { warn!("Failed to activate window, sending no input ({})", err); return; } - let geometry = self.capturable.geometry_relative(); - if let Err(err) = geometry { - warn!("Failed to get window geometry, sending no input ({})", err); - return; - } - let (x_rel, y_rel, width_rel, height_rel) = geometry.unwrap(); - let (width, height) = self.capturable.geometry().unwrap(); - let (offset_x, offset_y) = self.capturable.geometry_offset().unwrap(); + let (offset_x, offset_y, width, height) = match self.capturable.geometry().unwrap() { + Geometry::VirtualScreen(offset_x, offset_y, width, height) => { + (offset_x, offset_y, width, height) + } + _ => unreachable!(), + }; let (x, y) = ( - ((event.x * width_rel + x_rel) * width as f64) as i32 + offset_x, - ((event.y * height_rel + y_rel) * height as f64) as i32 + offset_y, + (event.x * width as f64) as i32 + offset_x, + (event.y * height as f64) as i32 + offset_y, ); let mut pointer_type_info = POINTER_TYPE_INFO { type_: PT_PEN, @@ -169,8 +167,8 @@ impl InputDevice for WindowsInput { } PointerType::Mouse => { if let Err(err) = mouse::move_to(autopilot::geometry::Point::new( - (event.x * width_rel + x_rel) * width as f64, - (event.y * height_rel + y_rel) * height as f64, + event.x * width as f64, + event.y * height as f64, )) { warn!("Could not move mouse: {}", err); } diff --git a/src/input/uinput_device.rs b/src/input/uinput_device.rs index 2faf37a6..fdb16373 100644 --- a/src/input/uinput_device.rs +++ b/src/input/uinput_device.rs @@ -3,7 +3,7 @@ use std::ffi::CString; use std::os::raw::{c_char, c_int}; use crate::capturable::x11::X11Context; -use crate::capturable::Capturable; +use crate::capturable::{Capturable, Geometry}; use crate::input::device::{InputDevice, InputDeviceType}; use crate::protocol::{ Button, KeyboardEvent, KeyboardEventType, KeyboardLocation, PointerEvent, PointerEventType, @@ -278,12 +278,15 @@ impl InputDevice for UInputDevice { warn!("Failed to activate window, sending no input ({})", err); return; } - let geometry = self.capturable.geometry_relative(); + let geometry = self.capturable.geometry(); if let Err(err) = geometry { warn!("Failed to get window geometry, sending no input ({})", err); return; } - let (x, y, width, height) = geometry.unwrap(); + let (x, y, width, height) = match geometry.unwrap() { + Geometry::Relative(x, y, width, height) => (x, y, width, height), + _ => unreachable!(), + }; self.x = x; self.y = y; self.width = width; From dbfd1697d9fb2b517b10bd88465d396608fa6904 Mon Sep 17 00:00:00 2001 From: Philipp Urlbauer Date: Mon, 29 Nov 2021 16:18:33 +0100 Subject: [PATCH 11/52] Add missing import for linux --- src/capturable/pipewire.rs | 2 +- src/capturable/x11.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/capturable/pipewire.rs b/src/capturable/pipewire.rs index 2d0a1085..d05d5cca 100644 --- a/src/capturable/pipewire.rs +++ b/src/capturable/pipewire.rs @@ -16,7 +16,7 @@ use gstreamer as gst; use gstreamer::prelude::*; use gstreamer_app::AppSink; -use crate::capturable::{Capturable, Recorder}; +use crate::capturable::{Capturable, Geometry, Recorder}; use crate::video::PixelProvider; use crate::capturable::pipewire_dbus::{ diff --git a/src/capturable/x11.rs b/src/capturable/x11.rs index e287720b..0e2626be 100644 --- a/src/capturable/x11.rs +++ b/src/capturable/x11.rs @@ -1,4 +1,4 @@ -use crate::capturable::{Capturable, Recorder}; +use crate::capturable::{Capturable, Geometry, Recorder}; use crate::cerror::CError; use crate::video::PixelProvider; use std::ffi::{CStr, CString}; From c0bd199f83668ccff9f52b69ec9a4df2f7def43b Mon Sep 17 00:00:00 2001 From: Philipp Urlbauer Date: Mon, 29 Nov 2021 16:32:50 +0100 Subject: [PATCH 12/52] unpack geometry_relative struct --- src/capturable/core_graphics.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/capturable/core_graphics.rs b/src/capturable/core_graphics.rs index d56fb870..2d2bb906 100644 --- a/src/capturable/core_graphics.rs +++ b/src/capturable/core_graphics.rs @@ -176,7 +176,8 @@ impl Capturable for CGWindowCapturable { self.name.clone() } fn geometry(&self) -> Result> { - Ok(Geometry::Relative(self.geometry_relative)) + let (x, y, w, h) = self.geometry_relative; + Ok(Geometry::Relative(x, y, w, h)) } fn before_input(&mut self) -> Result<(), Box> { self.update_geometry() From 3e5cbb3def66900df8cbad7d9339aed53be3b822 Mon Sep 17 00:00:00 2001 From: Philipp Urlbauer Date: Mon, 29 Nov 2021 19:29:46 +0100 Subject: [PATCH 13/52] Resolve review issues --- src/capturable/captrs_capture.rs | 13 +++- src/capturable/mod.rs | 17 ++--- src/capturable/win_ctx.rs | 10 +-- src/capturable/x11.rs | 2 +- src/input/autopilot_device_win.rs | 115 ++++++------------------------ 5 files changed, 47 insertions(+), 110 deletions(-) diff --git a/src/capturable/captrs_capture.rs b/src/capturable/captrs_capture.rs index d5e4b7e6..80b34798 100644 --- a/src/capturable/captrs_capture.rs +++ b/src/capturable/captrs_capture.rs @@ -8,6 +8,7 @@ use super::Geometry; #[derive(Clone)] pub struct CaptrsCapturable { id: u8, + name: String, width: u32, height: u32, offset_x: i32, @@ -15,9 +16,17 @@ pub struct CaptrsCapturable { } impl CaptrsCapturable { - pub fn new(id: u8, width: u32, height: u32, offset_x: i32, offset_y: i32) -> CaptrsCapturable { + pub fn new( + id: u8, + name: String, + width: u32, + height: u32, + offset_x: i32, + offset_y: i32, + ) -> CaptrsCapturable { CaptrsCapturable { id, + name, width, height, offset_x, @@ -28,7 +37,7 @@ impl CaptrsCapturable { impl Capturable for CaptrsCapturable { fn name(&self) -> String { - format!("Desktop {} (captrs)", self.id).into() + format!("Desktop {} (captrs)", self.name).into() } fn before_input(&mut self) -> Result<(), Box> { Ok(()) diff --git a/src/capturable/mod.rs b/src/capturable/mod.rs index bb51e196..01331b66 100644 --- a/src/capturable/mod.rs +++ b/src/capturable/mod.rs @@ -34,7 +34,9 @@ where Box::new(self.clone()) } } - +/// Relative: x, y, width, height of the Capturable as floats relative to the absolute size of the +/// screen. For example x=0.5, y=0.0, width=0.5, height=1.0 means the right half of the screen. +/// VirtualScreen: offset_x, offset_y, width, height for a capturable using a virtual screen. (Windows) pub enum Geometry { Relative(f64, f64, f64, f64), VirtualScreen(i32, i32, u32, u32), @@ -44,9 +46,7 @@ pub trait Capturable: Send + BoxCloneCapturable { /// Name of the Capturable, for example the window title, if it is a window. fn name(&self) -> String; - /// Return x, y, width, height of the Capturable as floats relative to the absolute size of the - /// screen. For example x=0.5, y=0.0, width=0.5, height=1.0 means the right half of the screen. - /// Or offset_x, offset_y, width, height for a capturable using a virtual screen. (Windows) + /// Return Geometry of the Capturable. fn geometry(&self) -> Result>; /// Callback that is called right before input is simulated. @@ -130,10 +130,11 @@ pub fn get_capturables( for (i, o) in winctx.get_outputs().iter().enumerate() { let captr = CaptrsCapturable::new( i as u8, - (o.right - o.left) as u32, - (o.bottom - o.top) as u32, - o.left - winctx.get_union_rect().left, - o.top - winctx.get_union_rect().top, + String::from_utf16_lossy(o.DeviceName.as_ref()), + (o.DesktopCoordinates.right - o.DesktopCoordinates.left) as u32, + (o.DesktopCoordinates.bottom - o.DesktopCoordinates.top) as u32, + o.DesktopCoordinates.left - winctx.get_union_rect().left, + o.DesktopCoordinates.top - winctx.get_union_rect().top, ); capturables.push(Box::new(captr)); } diff --git a/src/capturable/win_ctx.rs b/src/capturable/win_ctx.rs index 50dbdf02..2b16d987 100644 --- a/src/capturable/win_ctx.rs +++ b/src/capturable/win_ctx.rs @@ -50,13 +50,13 @@ fn get_adapter_outputs(adapter: &IDXGIAdapter1) -> Vec> { #[derive(Clone)] pub struct WinCtx { - outputs: Vec, + outputs: Vec, union_rect: RECT, } impl WinCtx { pub fn new() -> WinCtx { - let mut rects: Vec = Vec::new(); + let mut desktops: Vec = Vec::new(); let mut union: RECT; unsafe { union = mem::zeroed(); @@ -68,7 +68,7 @@ impl WinCtx { for o in outputs { let mut desc: DXGI_OUTPUT_DESC = mem::zeroed(); o.GetDesc(ptr::addr_of_mut!(desc)); - rects.push(desc.DesktopCoordinates); + desktops.push(desc); UnionRect( ptr::addr_of_mut!(union), ptr::addr_of!(union), @@ -78,11 +78,11 @@ impl WinCtx { } } WinCtx { - outputs: rects, + outputs: desktops, union_rect: union, } } - pub fn get_outputs(&self) -> &Vec { + pub fn get_outputs(&self) -> &Vec { &self.outputs } pub fn get_union_rect(&self) -> &RECT { diff --git a/src/capturable/x11.rs b/src/capturable/x11.rs index 0e2626be..4a320a48 100644 --- a/src/capturable/x11.rs +++ b/src/capturable/x11.rs @@ -94,7 +94,7 @@ impl Capturable for X11Capturable { } } - fn geometry(&self) -> Result<(Geometry), Box> { + fn geometry(&self) -> Result> { let mut x: c_float = 0.0; let mut y: c_float = 0.0; let mut width: c_float = 0.0; diff --git a/src/input/autopilot_device_win.rs b/src/input/autopilot_device_win.rs index 2a510db1..3e908373 100644 --- a/src/input/autopilot_device_win.rs +++ b/src/input/autopilot_device_win.rs @@ -6,16 +6,17 @@ use winapi::um::winuser::*; use tracing::warn; +use crate::input::autopilot_device::AutoPilotDevice; use crate::input::device::{InputDevice, InputDeviceType}; use crate::protocol::{ - Button, KeyboardEvent, KeyboardEventType, PointerEvent, PointerEventType, PointerType, - WheelEvent, + Button, KeyboardEvent, PointerEvent, PointerEventType, PointerType, WheelEvent, }; use crate::capturable::{Capturable, Geometry}; pub struct WindowsInput { capturable: Box, + autopilot_device: AutoPilotDevice, pointer_device_handle: *mut HSYNTHETICPOINTERDEVICE__, touch_device_handle: *mut HSYNTHETICPOINTERDEVICE__, } @@ -24,7 +25,8 @@ impl WindowsInput { pub fn new(capturable: Box) -> Self { unsafe { Self { - capturable, + capturable: capturable.clone(), + autopilot_device: AutoPilotDevice::new(capturable.clone()), pointer_device_handle: CreateSyntheticPointerDevice(PT_PEN, 1, 1), touch_device_handle: CreateSyntheticPointerDevice(PT_TOUCH, 5, 1), } @@ -70,7 +72,8 @@ impl InputDevice for WindowsInput { pointer_flags = POINTER_FLAG_INRANGE | POINTER_FLAG_INCONTACT | POINTER_FLAG_PRIMARY - | POINTER_FLAG_DOWN; + | POINTER_FLAG_DOWN + | POINTER_FLAG_UPDATE; button_change_type = POINTER_CHANGE_FIRSTBUTTON_DOWN; } @@ -79,8 +82,10 @@ impl InputDevice for WindowsInput { button_change_type = POINTER_CHANGE_FIRSTBUTTON_UP; } PointerEventType::MOVE => { - pointer_flags = - POINTER_FLAG_INRANGE | POINTER_FLAG_INCONTACT | POINTER_FLAG_PRIMARY; + pointer_flags = POINTER_FLAG_INRANGE + | POINTER_FLAG_INCONTACT + | POINTER_FLAG_PRIMARY + | POINTER_FLAG_UPDATE; button_change_type = POINTER_CHANGE_NONE; } @@ -132,7 +137,7 @@ impl InputDevice for WindowsInput { pointerId: event.pointer_id as u32, frameId: 0, pointerFlags: pointer_flags, - sourceDevice: 0 as *mut winapi::ctypes::c_void, //maybe use syntheticPointerDeviceHandle here but works with 0 + sourceDevice: self.touch_device_handle as *mut winapi::ctypes::c_void, //maybe use syntheticPointerDeviceHandle here but works with 0 hwndTarget: 0 as HWND, ptPixelLocation: POINT { x: x, y: y }, ptHimetricLocation: POINT { x: 0, y: 0 }, @@ -150,16 +155,16 @@ impl InputDevice for WindowsInput { orientation: 0, pressure: (event.pressure * 100f64) as u32, rcContact: RECT { - left: x, - top: y, - right: x, - bottom: y, + left: 0, + top: 0, + right: event.width as i32, + bottom: event.height as i32, }, rcContactRaw: RECT { - left: x, - top: y, - right: x, - bottom: y, + left: 0, + top: 0, + right: event.width as i32, + bottom: event.height as i32, }, }; InjectSyntheticPointerInput(self.touch_device_handle, &pointer_type_info, 1); @@ -190,85 +195,7 @@ impl InputDevice for WindowsInput { } fn send_keyboard_event(&mut self, event: &KeyboardEvent) { - use autopilot::key::{Character, Code, KeyCode}; - - let state = match event.event_type { - KeyboardEventType::UP => false, - KeyboardEventType::DOWN => true, - // autopilot doesn't handle this, so just do nothing - KeyboardEventType::REPEAT => return, - }; - - fn map_key(code: &str) -> Option { - match code { - "Escape" => Some(KeyCode::Escape), - "Enter" => Some(KeyCode::Return), - "Backspace" => Some(KeyCode::Backspace), - "Tab" => Some(KeyCode::Tab), - "Space" => Some(KeyCode::Space), - "CapsLock" => Some(KeyCode::CapsLock), - "F1" => Some(KeyCode::F1), - "F2" => Some(KeyCode::F2), - "F3" => Some(KeyCode::F3), - "F4" => Some(KeyCode::F4), - "F5" => Some(KeyCode::F5), - "F6" => Some(KeyCode::F6), - "F7" => Some(KeyCode::F7), - "F8" => Some(KeyCode::F8), - "F9" => Some(KeyCode::F9), - "F10" => Some(KeyCode::F10), - "F11" => Some(KeyCode::F11), - "F12" => Some(KeyCode::F12), - "F13" => Some(KeyCode::F13), - "F14" => Some(KeyCode::F14), - "F15" => Some(KeyCode::F15), - "F16" => Some(KeyCode::F16), - "F17" => Some(KeyCode::F17), - "F18" => Some(KeyCode::F18), - "F19" => Some(KeyCode::F19), - "F20" => Some(KeyCode::F20), - "F21" => Some(KeyCode::F21), - "F22" => Some(KeyCode::F22), - "F23" => Some(KeyCode::F23), - "F24" => Some(KeyCode::F24), - "Home" => Some(KeyCode::Home), - "ArrowUp" => Some(KeyCode::UpArrow), - "PageUp" => Some(KeyCode::PageUp), - "ArrowLeft" => Some(KeyCode::LeftArrow), - "ArrowRight" => Some(KeyCode::RightArrow), - "End" => Some(KeyCode::End), - "ArrowDown" => Some(KeyCode::DownArrow), - "PageDown" => Some(KeyCode::PageDown), - "Delete" => Some(KeyCode::Delete), - "ControlLeft" | "ControlRight" => Some(KeyCode::Control), - "AltLeft" | "AltRight" => Some(KeyCode::Alt), - "MetaLeft" | "MetaRight" => Some(KeyCode::Meta), - "ShiftLeft" | "ShiftRight" => Some(KeyCode::Shift), - _ => None, - } - } - let key = map_key(&event.code); - let mut flags = Vec::new(); - if event.ctrl { - flags.push(autopilot::key::Flag::Control); - } - if event.alt { - flags.push(autopilot::key::Flag::Alt); - } - if event.meta { - flags.push(autopilot::key::Flag::Meta); - } - if event.shift { - flags.push(autopilot::key::Flag::Shift); - } - match key { - Some(key) => autopilot::key::toggle(&Code(key), state, &flags, 0), - None => { - for c in event.key.chars() { - autopilot::key::toggle(&Character(c), state, &flags, 0); - } - } - } + self.autopilot_device.send_keyboard_event(event); } fn set_capturable(&mut self, capturable: Box) { From d7f4dc227959fa21a3c2fd7e830a9f0bb57f4584 Mon Sep 17 00:00:00 2001 From: Philipp Urlbauer Date: Mon, 29 Nov 2021 19:32:42 +0100 Subject: [PATCH 14/52] Removed unused features --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 6c12fb9b..68b9e489 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ toml = "^0.5" structopt = { version = "^0.3", features = ["color", "suggestions"], default-features = false } dirs = "^3.0" [target.'cfg(windows)'.dependencies] -winapi = { version = "0.3.8", features = ["d3d11", "d3dcommon", "dxgi", "dxgi1_2", "dxgitype", "ntdef", "unknwnbase", "windef", "winerror", "winuser"] } +winapi = { version = "0.3.8", features = ["d3d11", "d3dcommon", "dxgi", "dxgi1_2", "dxgitype"] } wio = "0.2.2" captrs = "^0.3.1" From 076d5b4b193e92a3f7135096fa2e057dbb9334f7 Mon Sep 17 00:00:00 2001 From: Philipp Urlbauer Date: Mon, 29 Nov 2021 19:38:15 +0100 Subject: [PATCH 15/52] Dont ignore nonprimary events --- src/input/autopilot_device_win.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/input/autopilot_device_win.rs b/src/input/autopilot_device_win.rs index 3e908373..47e26666 100644 --- a/src/input/autopilot_device_win.rs +++ b/src/input/autopilot_device_win.rs @@ -44,9 +44,6 @@ impl InputDevice for WindowsInput { } fn send_pointer_event(&mut self, event: &PointerEvent) { - if !event.is_primary { - return; - } if let Err(err) = self.capturable.before_input() { warn!("Failed to activate window, sending no input ({})", err); return; From bc342708573068860ca416e23883849632f59aca Mon Sep 17 00:00:00 2001 From: Philipp Urlbauer Date: Mon, 29 Nov 2021 20:03:22 +0100 Subject: [PATCH 16/52] Add Error wrapper for Captrs --- src/capturable/captrs_capture.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/capturable/captrs_capture.rs b/src/capturable/captrs_capture.rs index 80b34798..73229184 100644 --- a/src/capturable/captrs_capture.rs +++ b/src/capturable/captrs_capture.rs @@ -54,7 +54,17 @@ impl Capturable for CaptrsCapturable { )) } } +#[derive(Debug)] +pub struct CaptrsError(String); +impl std::fmt::Display for CaptrsError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let Self(s) = self; + write!(f, "{}", s) + } +} + +impl Error for CaptrsError {} pub struct CaptrsRecorder { capturer: Capturer, } @@ -69,7 +79,9 @@ impl CaptrsRecorder { impl Recorder for CaptrsRecorder { fn capture(&mut self) -> Result> { - let _ = self.capturer.capture_store_frame(); + self.capturer + .capture_store_frame() + .map_err(|e| CaptrsError("Captrs failed to capture frame".into()))?; let (w, h) = self.capturer.geometry(); Ok(crate::video::PixelProvider::BGR0( w as usize, From 05da252a46c8beffe5ce0596e5a08065a7abf21b Mon Sep 17 00:00:00 2001 From: Philipp Urlbauer Date: Mon, 29 Nov 2021 20:07:10 +0100 Subject: [PATCH 17/52] Remove unneccesary clone --- src/input/autopilot_device_win.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/input/autopilot_device_win.rs b/src/input/autopilot_device_win.rs index 47e26666..daeb6f98 100644 --- a/src/input/autopilot_device_win.rs +++ b/src/input/autopilot_device_win.rs @@ -26,7 +26,7 @@ impl WindowsInput { unsafe { Self { capturable: capturable.clone(), - autopilot_device: AutoPilotDevice::new(capturable.clone()), + autopilot_device: AutoPilotDevice::new(capturable), pointer_device_handle: CreateSyntheticPointerDevice(PT_PEN, 1, 1), touch_device_handle: CreateSyntheticPointerDevice(PT_TOUCH, 5, 1), } From bcabb77ddc09671f1c234a6cd8f61cece87b16b9 Mon Sep 17 00:00:00 2001 From: Philipp Urlbauer Date: Mon, 29 Nov 2021 20:18:10 +0100 Subject: [PATCH 18/52] CaptrsRecorder::new returns result --- src/capturable/captrs_capture.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/capturable/captrs_capture.rs b/src/capturable/captrs_capture.rs index 73229184..bf87850c 100644 --- a/src/capturable/captrs_capture.rs +++ b/src/capturable/captrs_capture.rs @@ -43,7 +43,7 @@ impl Capturable for CaptrsCapturable { Ok(()) } fn recorder(&self, _capture_cursor: bool) -> Result, Box> { - Ok(Box::new(CaptrsRecorder::new(self.id))) + Ok(Box::new(CaptrsRecorder::new(self.id)?)) } fn geometry(&self) -> Result> { Ok(Geometry::VirtualScreen( @@ -70,10 +70,10 @@ pub struct CaptrsRecorder { } impl CaptrsRecorder { - pub fn new(id: u8) -> CaptrsRecorder { - CaptrsRecorder { + pub fn new(id: u8) -> Result> { + Ok(CaptrsRecorder { capturer: Capturer::new(id.into()).unwrap(), - } + }) } } From edd5f3ae5527f08f47cadd320ef9504bb4e326e5 Mon Sep 17 00:00:00 2001 From: Philipp Urlbauer Date: Mon, 29 Nov 2021 20:19:36 +0100 Subject: [PATCH 19/52] dont unwrap here --- src/capturable/captrs_capture.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/capturable/captrs_capture.rs b/src/capturable/captrs_capture.rs index bf87850c..48d52a2a 100644 --- a/src/capturable/captrs_capture.rs +++ b/src/capturable/captrs_capture.rs @@ -72,7 +72,7 @@ pub struct CaptrsRecorder { impl CaptrsRecorder { pub fn new(id: u8) -> Result> { Ok(CaptrsRecorder { - capturer: Capturer::new(id.into()).unwrap(), + capturer: Capturer::new(id.into())?, }) } } From 4b340dec45c4c17534e4b5c65b06a2a16d9e3746 Mon Sep 17 00:00:00 2001 From: Philipp Urlbauer Date: Tue, 30 Nov 2021 20:32:48 +0100 Subject: [PATCH 20/52] Add myself to contributors --- CONTRIBUTORS | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 1558fa84..27a6910d 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -7,6 +7,7 @@ List of Contributors: ************************** Robert Schroll Daniel Rutz +Philipp Urlbauer ************************** 3-Clause BSD License From 0f9362e0fe79608d47e34ce0ac822edc987bd96d Mon Sep 17 00:00:00 2001 From: Philipp Urlbauer Date: Thu, 2 Dec 2021 19:08:13 +0100 Subject: [PATCH 21/52] add _ to error variable to prevent compilerwarning --- src/capturable/captrs_capture.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/capturable/captrs_capture.rs b/src/capturable/captrs_capture.rs index 48d52a2a..e7c2b27b 100644 --- a/src/capturable/captrs_capture.rs +++ b/src/capturable/captrs_capture.rs @@ -81,7 +81,7 @@ impl Recorder for CaptrsRecorder { fn capture(&mut self) -> Result> { self.capturer .capture_store_frame() - .map_err(|e| CaptrsError("Captrs failed to capture frame".into()))?; + .map_err(|_e| CaptrsError("Captrs failed to capture frame".into()))?; let (w, h) = self.capturer.geometry(); Ok(crate::video::PixelProvider::BGR0( w as usize, From 2f3064b6b86c73282b0b76270582c78bb93aebe0 Mon Sep 17 00:00:00 2001 From: Philipp Urlbauer Date: Thu, 2 Dec 2021 19:10:29 +0100 Subject: [PATCH 22/52] working touchinput via InjectSyntheticPointerInput --- src/input/autopilot_device_win.rs | 99 ++++++++++++------------------- 1 file changed, 38 insertions(+), 61 deletions(-) diff --git a/src/input/autopilot_device_win.rs b/src/input/autopilot_device_win.rs index daeb6f98..262dd42e 100644 --- a/src/input/autopilot_device_win.rs +++ b/src/input/autopilot_device_win.rs @@ -1,7 +1,7 @@ use autopilot::mouse; use autopilot::mouse::ScrollDirection; -use winapi::shared::windef::{HWND, POINT, RECT}; +use winapi::shared::windef::{HWND, POINT}; use winapi::um::winuser::*; use tracing::warn; @@ -24,6 +24,7 @@ pub struct WindowsInput { impl WindowsInput { pub fn new(capturable: Box) -> Self { unsafe { + InitializeTouchInjection(5, TOUCH_FEEDBACK_DEFAULT); Self { capturable: capturable.clone(), autopilot_device: AutoPilotDevice::new(capturable), @@ -58,42 +59,35 @@ impl InputDevice for WindowsInput { (event.x * width as f64) as i32 + offset_x, (event.y * height as f64) as i32 + offset_y, ); - let mut pointer_type_info = POINTER_TYPE_INFO { - type_: PT_PEN, - u: unsafe { std::mem::zeroed() }, + let button_change_type = match event.buttons { + Button::PRIMARY => POINTER_CHANGE_FIRSTBUTTON_DOWN, + Button::SECONDARY => POINTER_CHANGE_SECONDBUTTON_DOWN, + Button::AUXILARY => POINTER_CHANGE_THIRDBUTTON_DOWN, + Button::NONE => POINTER_CHANGE_NONE, + _ => POINTER_CHANGE_NONE, }; - let pointer_flags; - let button_change_type; - match event.event_type { + let mut pointer_flags = match event.event_type { PointerEventType::DOWN => { - pointer_flags = POINTER_FLAG_INRANGE - | POINTER_FLAG_INCONTACT - | POINTER_FLAG_PRIMARY - | POINTER_FLAG_DOWN - | POINTER_FLAG_UPDATE; - button_change_type = POINTER_CHANGE_FIRSTBUTTON_DOWN; - } - - PointerEventType::UP => { - pointer_flags = POINTER_FLAG_PRIMARY | POINTER_FLAG_UP; - button_change_type = POINTER_CHANGE_FIRSTBUTTON_UP; + POINTER_FLAG_INRANGE | POINTER_FLAG_INCONTACT | POINTER_FLAG_DOWN } PointerEventType::MOVE => { - pointer_flags = POINTER_FLAG_INRANGE - | POINTER_FLAG_INCONTACT - | POINTER_FLAG_PRIMARY - | POINTER_FLAG_UPDATE; - button_change_type = POINTER_CHANGE_NONE; + POINTER_FLAG_INRANGE | POINTER_FLAG_INCONTACT | POINTER_FLAG_UPDATE } - + PointerEventType::UP => POINTER_FLAG_UP, PointerEventType::CANCEL => { - pointer_flags = POINTER_FLAG_PRIMARY | POINTER_FLAG_CANCELED; - button_change_type = POINTER_CHANGE_NONE; + POINTER_FLAG_INRANGE | POINTER_FLAG_UPDATE | POINTER_FLAG_CANCELED } }; + if event.is_primary { + pointer_flags |= POINTER_FLAG_PRIMARY; + } match event.pointer_type { PointerType::Pen => { unsafe { + let mut pointer_type_info = POINTER_TYPE_INFO { + type_: PT_PEN, + u: std::mem::zeroed(), + }; *pointer_type_info.u.penInfo_mut() = POINTER_PEN_INFO { pointerInfo: POINTER_INFO { pointerType: PT_PEN, @@ -127,43 +121,26 @@ impl InputDevice for WindowsInput { } } PointerType::Touch => { + println!("touch event\n\n"); unsafe { - *pointer_type_info.u.touchInfo_mut() = POINTER_TOUCH_INFO { - pointerInfo: POINTER_INFO { - pointerType: PT_TOUCH, - pointerId: event.pointer_id as u32, - frameId: 0, - pointerFlags: pointer_flags, - sourceDevice: self.touch_device_handle as *mut winapi::ctypes::c_void, //maybe use syntheticPointerDeviceHandle here but works with 0 - hwndTarget: 0 as HWND, - ptPixelLocation: POINT { x: x, y: y }, - ptHimetricLocation: POINT { x: 0, y: 0 }, - ptPixelLocationRaw: POINT { x: x, y: y }, - ptHimetricLocationRaw: POINT { x: 0, y: 0 }, - dwTime: 0, - historyCount: 1, - InputData: 0, - dwKeyStates: 0, - PerformanceCount: 0, - ButtonChangeType: button_change_type, - }, - touchFlags: TOUCH_FLAG_NONE, - touchMask: TOUCH_MASK_PRESSURE, - orientation: 0, - pressure: (event.pressure * 100f64) as u32, - rcContact: RECT { - left: 0, - top: 0, - right: event.width as i32, - bottom: event.height as i32, - }, - rcContactRaw: RECT { - left: 0, - top: 0, - right: event.width as i32, - bottom: event.height as i32, - }, + let mut pointer_type_info = POINTER_TYPE_INFO { + type_: PT_TOUCH, + u: std::mem::zeroed(), }; + + let mut pointer_touch_info: POINTER_TOUCH_INFO = std::mem::zeroed(); + pointer_touch_info.pointerInfo = std::mem::zeroed(); + pointer_touch_info.pointerInfo.pointerType = PT_TOUCH; + pointer_touch_info.pointerInfo.pointerFlags = pointer_flags; + pointer_touch_info.pointerInfo.pointerId = event.pointer_id as u32; //event.pointer_id as u32; Using the actual pointer id causes errors in the touch injection + pointer_touch_info.pointerInfo.ptPixelLocation = POINT { x, y }; + pointer_touch_info.touchFlags = TOUCH_FLAG_NONE; + pointer_touch_info.touchMask = TOUCH_MASK_PRESSURE; + pointer_touch_info.pressure = (event.pressure * 1024f64) as u32; + + pointer_touch_info.pointerInfo.ButtonChangeType = button_change_type; + + *pointer_type_info.u.touchInfo_mut() = pointer_touch_info; InjectSyntheticPointerInput(self.touch_device_handle, &pointer_type_info, 1); } } From 023af0254753495ecf161bfe8636662435c9ad42 Mon Sep 17 00:00:00 2001 From: Philipp Urlbauer Date: Tue, 7 Dec 2021 20:46:29 +0100 Subject: [PATCH 23/52] Simulate Mouse via WinAPI --- src/capturable/captrs_capture.rs | 32 +++++-------- src/capturable/mod.rs | 8 ++-- src/input/autopilot_device_win.rs | 80 ++++++++++++++++++++----------- 3 files changed, 66 insertions(+), 54 deletions(-) diff --git a/src/capturable/captrs_capture.rs b/src/capturable/captrs_capture.rs index e7c2b27b..244f60d6 100644 --- a/src/capturable/captrs_capture.rs +++ b/src/capturable/captrs_capture.rs @@ -2,6 +2,7 @@ use crate::capturable::{Capturable, Recorder}; use captrs::Capturer; use std::boxed::Box; use std::error::Error; +use winapi::shared::windef::RECT; use super::Geometry; @@ -9,28 +10,17 @@ use super::Geometry; pub struct CaptrsCapturable { id: u8, name: String, - width: u32, - height: u32, - offset_x: i32, - offset_y: i32, + screen: RECT, + virtual_screen: RECT, } impl CaptrsCapturable { - pub fn new( - id: u8, - name: String, - width: u32, - height: u32, - offset_x: i32, - offset_y: i32, - ) -> CaptrsCapturable { + pub fn new(id: u8, name: String, screen: RECT, virtual_screen: RECT) -> CaptrsCapturable { CaptrsCapturable { id, name, - width, - height, - offset_x, - offset_y, + screen, + virtual_screen, } } } @@ -47,10 +37,12 @@ impl Capturable for CaptrsCapturable { } fn geometry(&self) -> Result> { Ok(Geometry::VirtualScreen( - self.offset_x, - self.offset_y, - self.width, - self.height, + self.screen.left - self.virtual_screen.left, + self.screen.top - self.virtual_screen.top, + (self.screen.right - self.screen.left) as u32, + (self.screen.bottom - self.screen.top) as u32, + self.screen.left, + self.screen.top, )) } } diff --git a/src/capturable/mod.rs b/src/capturable/mod.rs index 01331b66..17f5568e 100644 --- a/src/capturable/mod.rs +++ b/src/capturable/mod.rs @@ -39,7 +39,7 @@ where /// VirtualScreen: offset_x, offset_y, width, height for a capturable using a virtual screen. (Windows) pub enum Geometry { Relative(f64, f64, f64, f64), - VirtualScreen(i32, i32, u32, u32), + VirtualScreen(i32, i32, u32, u32, i32, i32), } pub trait Capturable: Send + BoxCloneCapturable { @@ -131,10 +131,8 @@ pub fn get_capturables( let captr = CaptrsCapturable::new( i as u8, String::from_utf16_lossy(o.DeviceName.as_ref()), - (o.DesktopCoordinates.right - o.DesktopCoordinates.left) as u32, - (o.DesktopCoordinates.bottom - o.DesktopCoordinates.top) as u32, - o.DesktopCoordinates.left - winctx.get_union_rect().left, - o.DesktopCoordinates.top - winctx.get_union_rect().top, + o.DesktopCoordinates, + winctx.get_union_rect().clone(), ); capturables.push(Box::new(captr)); } diff --git a/src/input/autopilot_device_win.rs b/src/input/autopilot_device_win.rs index 262dd42e..f31093a9 100644 --- a/src/input/autopilot_device_win.rs +++ b/src/input/autopilot_device_win.rs @@ -1,6 +1,4 @@ -use autopilot::mouse; -use autopilot::mouse::ScrollDirection; - +use winapi::shared::minwindef::DWORD; use winapi::shared::windef::{HWND, POINT}; use winapi::um::winuser::*; @@ -37,11 +35,7 @@ impl WindowsInput { impl InputDevice for WindowsInput { fn send_wheel_event(&mut self, event: &WheelEvent) { - match event.dy { - 1..=i32::MAX => mouse::scroll(ScrollDirection::Up, 1), - i32::MIN..=-1 => mouse::scroll(ScrollDirection::Down, 1), - 0 => {} - } + unsafe { mouse_event(MOUSEEVENTF_WHEEL, 0, 0, event.dy as DWORD, 0) }; } fn send_pointer_event(&mut self, event: &PointerEvent) { @@ -49,12 +43,17 @@ impl InputDevice for WindowsInput { warn!("Failed to activate window, sending no input ({})", err); return; } - let (offset_x, offset_y, width, height) = match self.capturable.geometry().unwrap() { - Geometry::VirtualScreen(offset_x, offset_y, width, height) => { - (offset_x, offset_y, width, height) - } - _ => unreachable!(), - }; + let (offset_x, offset_y, width, height, left, top) = + match self.capturable.geometry().unwrap() { + Geometry::VirtualScreen(offset_x, offset_y, width, height, left, top) => { + (offset_x, offset_y, width, height, left, top) + } + _ => unreachable!(), + }; + print!( + "offset_x {} offset_y {} width {} height {}", + offset_x, offset_y, width, height + ); let (x, y) = ( (event.x * width as f64) as i32 + offset_x, (event.y * height as f64) as i32 + offset_y, @@ -145,24 +144,47 @@ impl InputDevice for WindowsInput { } } PointerType::Mouse => { - if let Err(err) = mouse::move_to(autopilot::geometry::Point::new( - event.x * width as f64, - event.y * height as f64, - )) { - warn!("Could not move mouse: {}", err); - } - match event.button { - Button::PRIMARY => { - mouse::toggle(mouse::Button::Left, event.buttons.contains(event.button)) - } - Button::AUXILARY => { - mouse::toggle(mouse::Button::Middle, event.buttons.contains(event.button)) + let mut dw_flags = 0; + + let (screen_x, screen_y) = ( + (event.x * width as f64) as i32 + left, + (event.y * height as f64) as i32 + top, + ); + + match event.event_type { + PointerEventType::DOWN => match event.buttons { + Button::PRIMARY => { + dw_flags |= MOUSEEVENTF_LEFTDOWN; + } + Button::SECONDARY => { + dw_flags |= MOUSEEVENTF_RIGHTDOWN; + } + Button::AUXILARY => { + dw_flags |= MOUSEEVENTF_MIDDLEDOWN; + } + _ => {} + }, + PointerEventType::MOVE => { + unsafe { SetCursorPos(screen_x, screen_y) }; } - Button::SECONDARY => { - mouse::toggle(mouse::Button::Right, event.buttons.contains(event.button)) + PointerEventType::UP => match event.button { + Button::PRIMARY => { + dw_flags |= MOUSEEVENTF_LEFTUP; + } + Button::SECONDARY => { + dw_flags |= MOUSEEVENTF_RIGHTUP; + } + Button::AUXILARY => { + dw_flags |= MOUSEEVENTF_MIDDLEUP; + } + _ => {} + }, + PointerEventType::CANCEL => { + dw_flags |= MOUSEEVENTF_LEFTUP; } - _ => (), } + unsafe { mouse_event(dw_flags, 0 as u32, 0 as u32, 0, 0) }; + print!("mouse event {} {}", screen_x, screen_y); } PointerType::Unknown => todo!(), } From 5c56128d19a2db7a5e22a06dd884025a8f903c49 Mon Sep 17 00:00:00 2001 From: Philipp Urlbauer Date: Tue, 7 Dec 2021 20:48:06 +0100 Subject: [PATCH 24/52] Remove prints --- src/input/autopilot_device_win.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/input/autopilot_device_win.rs b/src/input/autopilot_device_win.rs index f31093a9..396213ee 100644 --- a/src/input/autopilot_device_win.rs +++ b/src/input/autopilot_device_win.rs @@ -50,10 +50,6 @@ impl InputDevice for WindowsInput { } _ => unreachable!(), }; - print!( - "offset_x {} offset_y {} width {} height {}", - offset_x, offset_y, width, height - ); let (x, y) = ( (event.x * width as f64) as i32 + offset_x, (event.y * height as f64) as i32 + offset_y, @@ -120,7 +116,6 @@ impl InputDevice for WindowsInput { } } PointerType::Touch => { - println!("touch event\n\n"); unsafe { let mut pointer_type_info = POINTER_TYPE_INFO { type_: PT_TOUCH, @@ -184,7 +179,6 @@ impl InputDevice for WindowsInput { } } unsafe { mouse_event(dw_flags, 0 as u32, 0 as u32, 0, 0) }; - print!("mouse event {} {}", screen_x, screen_y); } PointerType::Unknown => todo!(), } From c716d4785faf2fab3692587c3511e1cb14241936 Mon Sep 17 00:00:00 2001 From: qdlmcfresh Date: Thu, 9 Dec 2021 11:29:15 +0100 Subject: [PATCH 25/52] Fix pressure factor again --- src/input/autopilot_device_win.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/input/autopilot_device_win.rs b/src/input/autopilot_device_win.rs index 396213ee..6f12cbaf 100644 --- a/src/input/autopilot_device_win.rs +++ b/src/input/autopilot_device_win.rs @@ -107,7 +107,7 @@ impl InputDevice for WindowsInput { | PEN_MASK_ROTATION | PEN_MASK_TILT_X | PEN_MASK_TILT_Y, - pressure: (event.pressure * 100f64) as u32, + pressure: (event.pressure * 1024f64) as u32, rotation: event.twist as u32, tiltX: event.tilt_x, tiltY: event.tilt_y, From 574c37ae50fa5badaad1257cdcf78f4b406e7ac2 Mon Sep 17 00:00:00 2001 From: Philipp Urlbauer Date: Tue, 14 Dec 2021 16:15:18 +0100 Subject: [PATCH 26/52] POINTER_FLAG_INCONTACT only with primary button --- src/input/autopilot_device_win.rs | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/input/autopilot_device_win.rs b/src/input/autopilot_device_win.rs index 6f12cbaf..fdf0d9b2 100644 --- a/src/input/autopilot_device_win.rs +++ b/src/input/autopilot_device_win.rs @@ -54,25 +54,26 @@ impl InputDevice for WindowsInput { (event.x * width as f64) as i32 + offset_x, (event.y * height as f64) as i32 + offset_y, ); - let button_change_type = match event.buttons { - Button::PRIMARY => POINTER_CHANGE_FIRSTBUTTON_DOWN, - Button::SECONDARY => POINTER_CHANGE_SECONDBUTTON_DOWN, - Button::AUXILARY => POINTER_CHANGE_THIRDBUTTON_DOWN, - Button::NONE => POINTER_CHANGE_NONE, - _ => POINTER_CHANGE_NONE, - }; let mut pointer_flags = match event.event_type { PointerEventType::DOWN => { POINTER_FLAG_INRANGE | POINTER_FLAG_INCONTACT | POINTER_FLAG_DOWN } - PointerEventType::MOVE => { - POINTER_FLAG_INRANGE | POINTER_FLAG_INCONTACT | POINTER_FLAG_UPDATE - } + PointerEventType::MOVE => POINTER_FLAG_INRANGE | POINTER_FLAG_UPDATE, PointerEventType::UP => POINTER_FLAG_UP, PointerEventType::CANCEL => { POINTER_FLAG_INRANGE | POINTER_FLAG_UPDATE | POINTER_FLAG_CANCELED } }; + let button_change_type = match event.buttons { + Button::PRIMARY => { + pointer_flags |= POINTER_FLAG_INCONTACT; + POINTER_CHANGE_FIRSTBUTTON_DOWN + } + Button::SECONDARY => POINTER_CHANGE_SECONDBUTTON_DOWN, + Button::AUXILARY => POINTER_CHANGE_THIRDBUTTON_DOWN, + Button::NONE => POINTER_CHANGE_NONE, + _ => POINTER_CHANGE_NONE, + }; if event.is_primary { pointer_flags |= POINTER_FLAG_PRIMARY; } From f0adf61a094ae9ff721bb787964ea5051145258a Mon Sep 17 00:00:00 2001 From: Philipp Urlbauer Date: Sat, 28 May 2022 13:09:52 +0200 Subject: [PATCH 27/52] Update cargo.lock --- Cargo.lock | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 00a84391..3156534c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -151,6 +151,16 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +[[package]] +name = "captrs" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dad312f1be0ea3cce9ad0cdbace33350ea0781f138d7b49bfe191df0aa83db1b" +dependencies = [ + "dxgcap", + "x11cap", +] + [[package]] name = "cc" version = "1.0.73" @@ -414,6 +424,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "dxgcap" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18a3f3df51c509e7c8d2807c63abfecdea1a83def81baec83d68c6f5bb8ac654" +dependencies = [ + "winapi", + "wio", +] + [[package]] name = "either" version = "1.6.1" @@ -2288,6 +2308,7 @@ version = "0.11.4" dependencies = [ "autopilot", "bitflags", + "captrs", "cc", "core-foundation 0.9.3", "core-graphics 0.22.3", @@ -2314,6 +2335,8 @@ dependencies = [ "tracing-subscriber", "url 2.2.2", "websocket", + "winapi", + "wio", ] [[package]] @@ -2381,6 +2404,15 @@ version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +[[package]] +name = "wio" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d129932f4644ac2396cb456385cbf9e63b5b30c6e8dc4820bdca4eb082037a5" +dependencies = [ + "winapi", +] + [[package]] name = "x11" version = "2.19.1" @@ -2390,3 +2422,13 @@ dependencies = [ "libc", "pkg-config", ] + +[[package]] +name = "x11cap" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16ccedf556cb1f784d462dd8f24a7804f766d57c0051439d3e4052465263c399" +dependencies = [ + "libc", + "x11", +] From 34dd80ef92b55bae8656065e71f3cf823062cadf Mon Sep 17 00:00:00 2001 From: Philipp Urlbauer Date: Sat, 28 May 2022 13:38:16 +0200 Subject: [PATCH 28/52] Integrate changes by @Ph-Fr-One to fix multitouch --- src/input/autopilot_device_win.rs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/input/autopilot_device_win.rs b/src/input/autopilot_device_win.rs index fdf0d9b2..8a2c79ff 100644 --- a/src/input/autopilot_device_win.rs +++ b/src/input/autopilot_device_win.rs @@ -17,6 +17,7 @@ pub struct WindowsInput { autopilot_device: AutoPilotDevice, pointer_device_handle: *mut HSYNTHETICPOINTERDEVICE__, touch_device_handle: *mut HSYNTHETICPOINTERDEVICE__, + multitouch_map: std::collections::HashMap, } impl WindowsInput { @@ -28,6 +29,7 @@ impl WindowsInput { autopilot_device: AutoPilotDevice::new(capturable), pointer_device_handle: CreateSyntheticPointerDevice(PT_PEN, 1, 1), touch_device_handle: CreateSyntheticPointerDevice(PT_TOUCH, 5, 1), + multitouch_map: std::collections::HashMap::new(), } } } @@ -136,7 +138,26 @@ impl InputDevice for WindowsInput { pointer_touch_info.pointerInfo.ButtonChangeType = button_change_type; *pointer_type_info.u.touchInfo_mut() = pointer_touch_info; - InjectSyntheticPointerInput(self.touch_device_handle, &pointer_type_info, 1); + self.multitouch_map + .insert(event.pointer_id, pointer_type_info); + let len = self.multitouch_map.len(); + + let mut pointer_type_info_vec: Vec = Vec::new(); + for (_i, info) in self.multitouch_map.iter().enumerate() { + pointer_type_info_vec.push(*info.1); + } + let b: Box<[POINTER_TYPE_INFO]> = pointer_type_info_vec.into_boxed_slice(); + let m: *mut POINTER_TYPE_INFO = Box::into_raw(b) as _; + + InjectSyntheticPointerInput(self.touch_device_handle, m, len as u32); + + match event.event_type { + PointerEventType::DOWN | PointerEventType::MOVE => {} + + PointerEventType::UP | PointerEventType::CANCEL => { + self.multitouch_map.remove(&event.pointer_id); + } + } } } PointerType::Mouse => { From 1d0c91747e9647a502f3d965f07681e6ff45642d Mon Sep 17 00:00:00 2001 From: erentar Date: Thu, 2 Feb 2023 07:28:35 +0100 Subject: [PATCH 29/52] Add fedora command to install required libs --- Readme.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Readme.md b/Readme.md index b381caac..769596a0 100644 --- a/Readme.md +++ b/Readme.md @@ -270,6 +270,19 @@ libxfixes-dev libxtst-dev libxrandr-dev libxcomposite-dev libxi-dev libxv-dev au nvidia-cuda-dev pkg-config libdrm-dev libpango1.0-dev libgstreamer1.0-dev \ libgstreamer-plugins-base1.0-dev libdbus-1-dev ``` + +On Fedora, they can be installed via: +```sh +sudo dnf install libXext-devel libXft-devel libXinerama-devel libXcursor-devel libXrender-devel \ +libXfixes-devel libXtst-devel libXrandr-devel libXcomposite-devel libXi-devel libXv-devel autoconf libtool \ +pkg-config libdrm-devel pango-devel gstreamer1-devel \ +gstreamer1-plugins-base-devel dbus-devel nasm npm +``` +After npm is installed, typescript must be installed by: +```sh +sudo npm install typescript -g +``` + Note that building for the first time may take a while as by default ffmpeg needs to be build. On Windows only msvc is supported as C compiler; it is, however, possible to cross compile on Linux for Windows using minGW. From 9bf257188381543f739669752bbd2f6efa7afbe7 Mon Sep 17 00:00:00 2001 From: OmegaRogue Date: Thu, 16 Mar 2023 15:00:37 +0100 Subject: [PATCH 30/52] fix scroll direction problems in uinput closes #214 --- CONTRIBUTORS | 1 + src/input/uinput_device.rs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 1558fa84..252b08b0 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -7,6 +7,7 @@ List of Contributors: ************************** Robert Schroll Daniel Rutz +OmegaRogue ************************** 3-Clause BSD License diff --git a/src/input/uinput_device.rs b/src/input/uinput_device.rs index 52de374d..30a7e5ac 100644 --- a/src/input/uinput_device.rs +++ b/src/input/uinput_device.rs @@ -262,9 +262,9 @@ impl InputDevice for UInputDevice { self.mouse_fd, ET_RELATIVE, EC_REL_HWHEEL, - direction(event.dy), + direction(event.dx), ); - self.send(self.mouse_fd, ET_RELATIVE, EC_REL_WHEEL_HI_RES, event.dx); + self.send(self.mouse_fd, ET_RELATIVE, EC_REL_WHEEL_HI_RES, event.dy); self.send(self.mouse_fd, ET_RELATIVE, EC_REL_HWHEEL_HI_RES, event.dx); self.send( From dec0909cee7c27a960e7760f8dfbadcf2a5e3f8c Mon Sep 17 00:00:00 2001 From: scribblemaniac Date: Fri, 4 Aug 2023 20:41:03 -0600 Subject: [PATCH 31/52] Always render square QR code so it can be read --- src/gui.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/gui.rs b/src/gui.rs index 84ff3463..47e7de5c 100644 --- a/src/gui.rs +++ b/src/gui.rs @@ -1,3 +1,4 @@ +use std::cmp::min; use std::iter::Iterator; use std::net::{IpAddr, SocketAddr}; @@ -305,11 +306,8 @@ pub fn run(config: &Config, log_receiver: mpsc::Receiver) { let code = QrCode::new(&url_string).unwrap(); let img_buf = code.render::>().build(); let image = image::DynamicImage::ImageLuma8(img_buf); - let image = image.resize_exact( - qr_frame.width() as u32, - qr_frame.height() as u32, - image::imageops::FilterType::Nearest, - ); + let dims = min(qr_frame.width(), qr_frame.height()) as u32; + let image = image.resize_exact(dims, dims, image::imageops::FilterType::Nearest); let mut buf = vec![]; image .write_to(&mut buf, image::ImageOutputFormat::Png) From d92867ec229ecf080f96ff53978bdf3c1c5e45e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Cadilhac?= Date: Mon, 9 Sep 2024 13:54:56 -0500 Subject: [PATCH 32/52] Create helper window in main thread. This is required by the latest fltk, see: https://docs.rs/fltk/1.4.33/fltk/window/index.html --- src/gui.rs | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/src/gui.rs b/src/gui.rs index 84ff3463..cfe212a2 100644 --- a/src/gui.rs +++ b/src/gui.rs @@ -5,7 +5,7 @@ use std::sync::{mpsc, Arc, Mutex}; use tracing::{error, info}; use fltk::{ - app::App, + app::{App, awake_callback}, button::{Button, CheckButton}, frame::Frame, input::{Input, IntInput}, @@ -223,24 +223,26 @@ pub fn run(config: &Config, log_receiver: mpsc::Receiver) { |_| {}, |message| match message { Ws2UiMessage::UInputInaccessible => { - let w = 500; - let h = 300; - let mut pop_up = Window::default() - .with_size(w, h) - .center_screen() - .with_label("Weylus - UInput inaccessible!"); - pop_up.set_xclass("weylus"); - - let buf = TextBuffer::default(); - let mut pop_up_text = TextDisplay::default().with_size(w, h); - pop_up_text.set_buffer(buf); - pop_up_text.wrap_mode(fltk::text::WrapMode::AtBounds, 5); - let mut buf = pop_up_text.buffer().unwrap(); - buf.set_text(std::include_str!("strings/uinput_error.txt")); - - pop_up.end(); - pop_up.make_modal(true); - pop_up.show(); + awake_callback(move || { + let w = 500; + let h = 300; + let mut pop_up = Window::default() + .with_size(w, h) + .center_screen() + .with_label("Weylus - UInput inaccessible!"); + pop_up.set_xclass("weylus"); + + let buf = TextBuffer::default(); + let mut pop_up_text = TextDisplay::default().with_size(w, h); + pop_up_text.set_buffer(buf); + pop_up_text.wrap_mode(fltk::text::WrapMode::AtBounds, 5); + let mut buf = pop_up_text.buffer().unwrap(); + buf.set_text(std::include_str!("strings/uinput_error.txt")); + + pop_up.end(); + pop_up.make_modal(true); + pop_up.show(); + }); } _ => {} }, From 005001245a444c6868c6e75461e3a73f94acabb8 Mon Sep 17 00:00:00 2001 From: HMH Date: Thu, 6 Apr 2023 19:37:41 +0200 Subject: [PATCH 33/52] Fix handling of KeyboardEvents. --- ts/lib.ts | 28 +++++++++++++++++++++++----- www/templates/index.html | 2 +- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/ts/lib.ts b/ts/lib.ts index 75fb8e50..744b7c00 100644 --- a/ts/lib.ts +++ b/ts/lib.ts @@ -687,19 +687,37 @@ class KeyboardHandler { constructor(webSocket: WebSocket) { this.webSocket = webSocket; - let m = document.getElementById("main"); + let d = document; + let s = document.getElementById("settings") - m.onkeydown = (e) => { + // Consume all KeyboardEvents, except the settings menu is open. + // this avoids making the main/video/canvas element focusable by using + // a tabindex which interferes with PointerEvent than can be considered + // hovering. + + function settings_hidden() { + return s.classList.contains("hide") || s.classList.contains("vanish"); + } + + d.onkeydown = (e) => { + if (!settings_hidden()) + return true; if (e.repeat) return this.onEvent(e, "repeat"); return this.onEvent(e, "down"); }; - m.onkeyup = (e) => { return this.onEvent(e, "up") }; - m.onkeypress = (e) => { + d.onkeyup = (e) => { + if (!settings_hidden()) + return true; + return this.onEvent(e, "up"); + }; + d.onkeypress = (e) => { + if (!settings_hidden()) + return true; e.preventDefault(); e.stopPropagation(); return false; - } + }; } onEvent(event: KeyboardEvent, event_type: string) { diff --git a/www/templates/index.html b/www/templates/index.html index 411ef40c..6c734456 100644 --- a/www/templates/index.html +++ b/www/templates/index.html @@ -14,7 +14,7 @@ -

+
From 80c1e2755c8b46492f76d51f9e7437611b340e0f Mon Sep 17 00:00:00 2001 From: HMH Date: Thu, 6 Apr 2023 19:39:41 +0200 Subject: [PATCH 34/52] Sanitize pressure of pen. If the pen is not touching the screen, set pressure to 0. --- src/input/uinput_device.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/input/uinput_device.rs b/src/input/uinput_device.rs index 52de374d..45d6f729 100644 --- a/src/input/uinput_device.rs +++ b/src/input/uinput_device.rs @@ -34,6 +34,7 @@ pub struct UInputDevice { touch_fd: c_int, touches: [Option; 5], tool_pen_active: bool, + pen_touching: bool, capturable: Box, x: f64, y: f64, @@ -100,6 +101,7 @@ impl UInputDevice { touch_fd, touches: Default::default(), tool_pen_active: false, + pen_touching: false, capturable, x: 0.0, y: 0.0, @@ -445,6 +447,7 @@ impl InputDevice for UInputDevice { match event.event_type { PointerEventType::DOWN | PointerEventType::MOVE => { if let PointerEventType::DOWN = event.event_type { + self.pen_touching = true; self.send(self.stylus_fd, ET_KEY, EC_KEY_TOUCH, 1); } if !self.tool_pen_active && !event.buttons.contains(Button::ERASER) { @@ -473,7 +476,11 @@ impl InputDevice for UInputDevice { self.stylus_fd, ET_ABSOLUTE, EC_ABSOLUTE_PRESSURE, - self.transform_pressure(event.pressure), + if self.pen_touching { + self.transform_pressure(event.pressure) + } else { + 0 + }, ); self.send( self.stylus_fd, @@ -494,6 +501,7 @@ impl InputDevice for UInputDevice { self.send(self.stylus_fd, ET_KEY, EC_KEY_TOOL_RUBBER, 0); self.send(self.stylus_fd, ET_ABSOLUTE, EC_ABSOLUTE_PRESSURE, 0); self.tool_pen_active = false; + self.pen_touching = false; } } self.send( From 0ae4c8dff77787367127eb4923c154ef8b155e5f Mon Sep 17 00:00:00 2001 From: HMH Date: Sat, 25 Nov 2023 01:00:40 +0100 Subject: [PATCH 35/52] Debian Stretch -> Buster for Docker. --- docker/Dockerfile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index b464ccff..60c8edaa 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,4 +1,4 @@ -FROM debian:stretch +FROM debian:buster ENV RUSTUP_HOME="/usr/local/rustup" CARGO_HOME="/usr/local/cargo" PATH="/usr/local/cargo/bin:$PATH" RUN apt-get update && \ apt-get install -y libx11-dev libxext-dev libxft-dev libxinerama-dev libxcursor-dev \ @@ -9,13 +9,13 @@ RUN apt-get update && \ RUN apt-add-repository contrib RUN apt-add-repository non-free RUN apt-get update && apt-get install -y nvidia-cuda-dev -RUN curl -Lo cmake.tar.gz https://github.com/Kitware/CMake/releases/download/v3.23.3/cmake-3.23.3.tar.gz && tar xf cmake.tar.gz +RUN curl -Lo cmake.tar.gz https://github.com/Kitware/CMake/releases/download/v3.27.8/cmake-3.27.8.tar.gz && tar xf cmake.tar.gz RUN cd cmake-3.* && cmake . && make -j$(nproc) && make install RUN rm -rf cmake* -RUN curl -LO "https://www.nasm.us/pub/nasm/releasebuilds/2.15.05/nasm-2.15.05.tar.xz" && \ - tar xf "nasm-2.15.05.tar.xz" && cd "nasm-2.15.05" && \ - ./configure --prefix=/usr && make -j$(nproc) && make install && cd .. && rm -rf "nasm-2.15.05*" -RUN curl -sL https://deb.nodesource.com/setup_16.x | bash - && \ +RUN curl -LO "https://www.nasm.us/pub/nasm/releasebuilds/2.16.01/nasm-2.16.01.tar.xz" && \ + tar xf "nasm-2.16.01.tar.xz" && cd "nasm-2.16.01" && \ + ./configure --prefix=/usr && make -j$(nproc) && make install && cd .. && rm -rf "nasm-2.16.01*" +RUN curl -sL https://deb.nodesource.com/setup_20.x | bash - && \ apt-get install -y nodejs && \ npm install -g typescript RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | \ From 0ca094cd1194bc5872dbd46dc013f168f7fded49 Mon Sep 17 00:00:00 2001 From: HMH Date: Sat, 25 Nov 2023 01:14:35 +0100 Subject: [PATCH 36/52] Update dependencies. --- .gitignore | 1 + Cargo.lock | 979 ++++++++++++++++++++++-------------- build.rs | 3 + build_in_local_container.sh | 14 + deps/build.sh | 2 +- deps/download.sh | 4 +- docker/Dockerfile | 14 +- 7 files changed, 626 insertions(+), 391 deletions(-) create mode 100755 build_in_local_container.sh diff --git a/.gitignore b/.gitignore index e4c2d70d..5df7906c 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ c_helper/target c_helper/Cargo.lock *.js *.js.map +*.tar.gz diff --git a/Cargo.lock b/Cargo.lock index 8b1cbc05..f89a4797 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,21 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "adler32" version = "1.2.0" @@ -19,9 +34,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.59" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c91f1f46651137be86f3a2b9a8359f9ab421d04d941c62b5982e1ca21113adf9" +checksum = "10f00e1f6e58a40e807377c75c6a7f97bf9044fab57816f2414e6f5f4499d7b8" [[package]] name = "atty" @@ -29,7 +44,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi", ] @@ -40,14 +55,14 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" dependencies = [ - "autocfg 1.1.0", + "autocfg 1.3.0", ] [[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "autopilot" @@ -66,6 +81,21 @@ dependencies = [ "x11", ] +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide 0.8.0", + "object", + "rustc-demangle", + "windows-targets", +] + [[package]] name = "base64" version = "0.9.3" @@ -91,6 +121,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + [[package]] name = "block" version = "0.1.6" @@ -111,11 +147,11 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.10.2" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array 0.14.6", + "generic-array 0.14.7", ] [[package]] @@ -135,35 +171,39 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "bytemuck" -version = "1.11.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5377c8865e74a160d21f29c2d40669f53286db6eab59b88540cbb12ffc8b835" +checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.2.1" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "cc" -version = "1.0.73" +version = "1.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +checksum = "b62ac837cdb5cb22e10a256099b4fc502b1dfe560cb282963a974d7abd80e476" +dependencies = [ + "shlex", +] [[package]] name = "cfg-expr" -version = "0.10.3" +version = "0.15.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aacacf4d96c24b2ad6eb8ee6df040e4f27b0d0b39a5710c30091baa830485db" +checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" dependencies = [ "smallvec", + "target-lexicon", ] [[package]] @@ -186,7 +226,7 @@ checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ "ansi_term", "atty", - "bitflags", + "bitflags 1.3.2", "strsim", "textwrap", "unicode-width", @@ -198,14 +238,14 @@ version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] name = "cmake" -version = "0.1.48" +version = "0.1.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8ad8cef104ac57b68b89df3208164d228503abbdce70f6880ffa3d970e7443a" +checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a" dependencies = [ "cc", ] @@ -216,7 +256,7 @@ version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c49e86fc36d5704151f5996b7b3795385f50ce09e3be0f47a0cfde869681cf8" dependencies = [ - "bitflags", + "bitflags 1.3.2", "block", "core-foundation 0.7.0", "core-graphics 0.19.2", @@ -243,11 +283,11 @@ dependencies = [ [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ - "core-foundation-sys 0.8.3", + "core-foundation-sys 0.8.7", "libc", ] @@ -259,9 +299,9 @@ checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" [[package]] name = "core-foundation-sys" -version = "0.8.3" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "core-graphics" @@ -269,7 +309,7 @@ version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3889374e6ea6ab25dba90bb5d96202f61108058361f6dc72e8b03e6f8bbe923" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation 0.7.0", "foreign-types", "libc", @@ -281,8 +321,8 @@ version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" dependencies = [ - "bitflags", - "core-foundation 0.9.3", + "bitflags 1.3.2", + "core-foundation 0.9.4", "core-graphics-types", "foreign-types", "libc", @@ -290,78 +330,66 @@ dependencies = [ [[package]] name = "core-graphics-types" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" dependencies = [ - "bitflags", - "core-foundation 0.9.3", - "foreign-types", + "bitflags 1.3.2", + "core-foundation 0.9.4", "libc", ] [[package]] name = "cpufeatures" -version = "0.2.2" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-channel" -version = "0.5.6" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.2" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.10" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg 1.1.0", - "cfg-if", "crossbeam-utils", - "memoffset", - "once_cell", - "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.11" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc" -dependencies = [ - "cfg-if", - "once_cell", -] +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crypto-common" @@ -369,15 +397,15 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array 0.14.6", + "generic-array 0.14.7", "typenum", ] [[package]] name = "dbus" -version = "0.9.6" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f8bcdd56d2e5c4ed26a529c5a9029f5db8290d433497506f958eae3be148eb6" +checksum = "1bb21987b9fb1613058ba3843121dd18b163b254d8a6e797e144cbac14d96d1b" dependencies = [ "libc", "libdbus-sys", @@ -415,11 +443,11 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.3" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer 0.10.2", + "block-buffer 0.10.4", "crypto-common", ] @@ -445,9 +473,15 @@ dependencies = [ [[package]] name = "either" -version = "1.7.0" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "equivalent" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "fake-simd" @@ -457,23 +491,23 @@ checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" [[package]] name = "fltk" -version = "1.3.12" +version = "1.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b23e9952a97c05f16980e9e4c8f1947a446e2f73f6dea9a1635284b4b865f184" +checksum = "282d3f9b20cb53f0d468790cdaf7ae28d9128ad52caea5ba1e57fd63e571c081" dependencies = [ - "bitflags", + "bitflags 2.6.0", "crossbeam-channel", "fltk-sys", - "lazy_static", + "once_cell", "paste", "ttf-parser", ] [[package]] name = "fltk-sys" -version = "1.3.12" +version = "1.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc98ac94df90651d5ca5082b2990ce817422e046078d5c3906a046823c52802a" +checksum = "8cab52e0e3abc6be8c9ea81bb7aa7887f1650198c3fc4464c5a59ac996d126d3" dependencies = [ "cmake", ] @@ -501,12 +535,11 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.0.1" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ - "matches", - "percent-encoding 2.1.0", + "percent-encoding 2.3.1", ] [[package]] @@ -517,24 +550,24 @@ checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" [[package]] name = "futures-channel" -version = "0.3.21" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", ] [[package]] name = "futures-core" -version = "0.3.21" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" -version = "0.3.21" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" dependencies = [ "futures-core", "futures-task", @@ -543,21 +576,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.21" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.21" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.21" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-core", "futures-task", @@ -577,12 +610,12 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.6" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", - "version_check 0.9.4", + "version_check 0.9.5", ] [[package]] @@ -598,9 +631,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.7" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -617,13 +650,19 @@ dependencies = [ "lzw", ] +[[package]] +name = "gimli" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" + [[package]] name = "glib" version = "0.15.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edb0306fbad0ab5428b0ca674a23893db909a98582969c9b537be4ced78c505d" dependencies = [ - "bitflags", + "bitflags 1.3.2", "futures-channel", "futures-core", "futures-executor", @@ -639,17 +678,17 @@ dependencies = [ [[package]] name = "glib-macros" -version = "0.15.11" +version = "0.15.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25a68131a662b04931e71891fb14aaf65ee4b44d08e8abc10f49e77418c86c64" +checksum = "10c6ae9f6fa26f4fb2ac16b528d138d971ead56141de489f8111e259b9df3c4a" dependencies = [ "anyhow", - "heck 0.4.0", + "heck 0.4.1", "proc-macro-crate", "proc-macro-error", - "proc-macro2 1.0.42", - "quote 1.0.20", - "syn 1.0.98", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 1.0.109", ] [[package]] @@ -679,7 +718,7 @@ version = "0.18.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d66363bacf5e4f6eb281564adc2902e44c52ae5c45082423e7439e9012b75456" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if", "futures-channel", "futures-core", @@ -689,7 +728,7 @@ dependencies = [ "libc", "muldiv", "num-integer", - "num-rational 0.4.1", + "num-rational 0.4.2", "once_cell", "option-operations", "paste", @@ -703,7 +742,7 @@ version = "0.18.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "664adf6abc6546c1ad54492a067dcbc605032c9c789ce8f6f78cb9ddeef4b684" dependencies = [ - "bitflags", + "bitflags 1.3.2", "futures-core", "futures-sink", "glib", @@ -733,7 +772,7 @@ version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "224f35f36582407caf58ded74854526beeecc23d0cf64b8d1c3e00584ed6863f" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if", "glib", "gstreamer", @@ -772,7 +811,7 @@ version = "0.18.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9418adfc72dafa1ad9eb106527ce4804887d101027c4528ec28c7d29cc899519" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cfg-if", "futures-channel", "glib", @@ -799,9 +838,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.13" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37a82c6d637fc9515a4694bbf1cb2457b79d81ce52b3108bdeea58b07dd34a57" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", @@ -818,11 +857,11 @@ dependencies = [ [[package]] name = "handlebars" -version = "4.3.3" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "360d9740069b2f6cbb63ce2dbaa71a20d3185350cbb990d7bebeb9318415eb17" +checksum = "faa67bab9ff362228eb3d00bd024a4965d8231bbb7921167f0cfa66c6626b225" dependencies = [ - "log 0.4.17", + "log 0.4.22", "pest", "pest_derive", "serde", @@ -832,9 +871,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.12.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "heck" @@ -847,9 +886,15 @@ dependencies = [ [[package]] name = "heck" -version = "0.4.0" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "heck" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" @@ -860,11 +905,17 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + [[package]] name = "http" -version = "0.2.8" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", @@ -873,9 +924,9 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", "http", @@ -884,15 +935,15 @@ dependencies = [ [[package]] name = "httparse" -version = "1.7.1" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" [[package]] name = "httpdate" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" @@ -915,9 +966,9 @@ dependencies = [ [[package]] name = "hyper" -version = "0.14.20" +version = "0.14.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" +checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" dependencies = [ "bytes", "futures-channel", @@ -950,11 +1001,10 @@ dependencies = [ [[package]] name = "idna" -version = "0.2.3" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ - "matches", "unicode-bidi", "unicode-normalization", ] @@ -993,11 +1043,11 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.9.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" dependencies = [ - "autocfg 1.1.0", + "equivalent", "hashbrown", ] @@ -1021,9 +1071,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.2" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jpeg-decoder" @@ -1042,42 +1092,49 @@ checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.126" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "libdbus-sys" -version = "0.2.2" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c185b5b7ad900923ef3a8ff594083d4d9b5aea80bb4f32b8342363138c0d456b" +checksum = "06085512b750d640299b79be4bad3d2fa90a9c00b1fd9e1b46364f66f0485c72" dependencies = [ "pkg-config", ] +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.6.0", + "libc", +] + [[package]] name = "log" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" dependencies = [ - "log 0.4.17", + "log 0.4.22", ] [[package]] name = "log" -version = "0.4.17" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "lzw" @@ -1096,24 +1153,15 @@ dependencies = [ [[package]] name = "matches" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" [[package]] name = "memchr" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" - -[[package]] -name = "memoffset" -version = "0.6.5" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" -dependencies = [ - "autocfg 1.1.0", -] +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "mime" @@ -1133,23 +1181,32 @@ dependencies = [ "adler32", ] +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + [[package]] name = "mio" -version = "0.8.4" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ + "hermit-abi 0.3.9", "libc", - "log 0.4.17", "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys", ] [[package]] name = "muldiv" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5136edda114182728ccdedb9f5eda882781f35fa6e80cc360af12a8932507f3" +checksum = "956787520e75e9bd233246045d19f42fb73242759cc57fba9611d940ae96d4b0" [[package]] name = "no-std-net" @@ -1157,6 +1214,16 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65" +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + [[package]] name = "num-derive" version = "0.2.5" @@ -1170,21 +1237,20 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg 1.1.0", "num-traits", ] [[package]] name = "num-iter" -version = "0.1.43" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ - "autocfg 1.1.0", + "autocfg 1.3.0", "num-integer", "num-traits", ] @@ -1195,7 +1261,7 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" dependencies = [ - "autocfg 1.1.0", + "autocfg 1.3.0", "num-integer", "num-traits", ] @@ -1206,38 +1272,37 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" dependencies = [ - "autocfg 1.1.0", + "autocfg 1.3.0", "num-integer", "num-traits", ] [[package]] name = "num-rational" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "autocfg 1.1.0", "num-integer", "num-traits", ] [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ - "autocfg 1.1.0", + "autocfg 1.3.0", ] [[package]] name = "num_cpus" -version = "1.13.1" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", ] @@ -1250,11 +1315,20 @@ dependencies = [ "malloc_buf", ] +[[package]] +name = "object" +version = "0.36.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" -version = "1.13.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "opaque-debug" @@ -1271,11 +1345,17 @@ dependencies = [ "paste", ] +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + [[package]] name = "paste" -version = "1.0.7" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "percent-encoding" @@ -1285,25 +1365,26 @@ checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" [[package]] name = "percent-encoding" -version = "2.1.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.2.1" +version = "2.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69486e2b8c2d2aeb9762db7b4e00b0331156393555cff467f4163ff06821eef8" +checksum = "9c73c26c01b8c87956cea613c907c9d6ecffd8d18a2a5908e5de0adfaa185cea" dependencies = [ + "memchr", "thiserror", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.2.1" +version = "2.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b13570633aff33c6d22ce47dd566b10a3b9122c2fe9d8e7501895905be532b91" +checksum = "664d22978e2815783adbdd2c588b455b1bd625299ce36b2a99881ac9627e6d8d" dependencies = [ "pest", "pest_generator", @@ -1311,33 +1392,33 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.2.1" +version = "2.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3c567e5702efdc79fb18859ea74c3eb36e14c43da7b8c1f098a4ed6514ec7a0" +checksum = "a2d5487022d5d33f4c30d91c22afa240ce2a644e87fe08caad974d4eab6badbe" dependencies = [ "pest", "pest_meta", - "proc-macro2 1.0.42", - "quote 1.0.20", - "syn 1.0.98", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] name = "pest_meta" -version = "2.2.1" +version = "2.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eb32be5ee3bbdafa8c7a18b0a8a8d962b66cfa2ceee4037f49267a50ee821fe" +checksum = "0091754bbd0ea592c4deb3a122ce8ecbb0753b738aa82bc055fcc2eccc8d8174" dependencies = [ "once_cell", "pest", - "sha-1 0.10.0", + "sha2", ] [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -1347,9 +1428,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.25" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "pnet_base" @@ -1389,7 +1470,7 @@ version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef859a23054bbfee7811284275ae522f0434a3c8e7f4b74bd4a35ae7e1c4a283" dependencies = [ - "bitflags", + "bitflags 1.3.2", "crc32fast", "deflate 0.7.20", "inflate", @@ -1401,17 +1482,20 @@ version = "0.16.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6" dependencies = [ - "bitflags", + "bitflags 1.3.2", "crc32fast", "deflate 0.8.6", - "miniz_oxide", + "miniz_oxide 0.3.7", ] [[package]] name = "ppv-lite86" -version = "0.2.16" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "pretty-hex" @@ -1421,13 +1505,12 @@ checksum = "c6fa0831dd7cc608c38a5e323422a0077678fa5744aa2be4ad91c4ece8eec8d5" [[package]] name = "proc-macro-crate" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d50bfb8c23f23915855a00d98b5a35ef2e0b871bb52937bacadb798fbb66c8" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ "once_cell", - "thiserror", - "toml", + "toml_edit 0.19.15", ] [[package]] @@ -1437,10 +1520,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.42", - "quote 1.0.20", - "syn 1.0.98", - "version_check 0.9.4", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 1.0.109", + "version_check 0.9.5", ] [[package]] @@ -1449,9 +1532,9 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.42", - "quote 1.0.20", - "version_check 0.9.4", + "proc-macro2 1.0.86", + "quote 1.0.37", + "version_check 0.9.5", ] [[package]] @@ -1465,9 +1548,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.42" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c278e965f1d8cf32d6e0e96de3d3e79712178ae67986d9cf9151f51e95aac89b" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -1493,11 +1576,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.20" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ - "proc-macro2 1.0.42", + "proc-macro2 1.0.86", ] [[package]] @@ -1649,26 +1732,22 @@ dependencies = [ [[package]] name = "rayon" -version = "1.5.3" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ - "autocfg 1.1.0", - "crossbeam-deque", "either", "rayon-core", ] [[package]] name = "rayon-core" -version = "1.9.3" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "num_cpus", ] [[package]] @@ -1681,30 +1760,27 @@ dependencies = [ ] [[package]] -name = "redox_syscall" -version = "0.2.16" +name = "redox_users" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "bitflags", + "getrandom 0.2.15", + "libredox", + "thiserror", ] [[package]] -name = "redox_users" -version = "0.4.3" +name = "rustc-demangle" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" -dependencies = [ - "getrandom 0.2.7", - "redox_syscall", - "thiserror", -] +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "ryu" -version = "1.0.10" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "safemem" @@ -1720,41 +1796,51 @@ checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.141" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7af873f2c95b99fcb0bd0fe622a43e29514658873c8ceba88c4cb88833a22500" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.141" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75743a150d003dd863b51dc809bcad0d73f2102c53632f1e954e738192a3413f" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ - "proc-macro2 1.0.42", - "quote 1.0.20", - "syn 1.0.98", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] name = "serde_json" -version = "1.0.82" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +dependencies = [ + "serde", +] + [[package]] name = "sha-1" version = "0.8.2" @@ -1768,48 +1854,54 @@ dependencies = [ ] [[package]] -name = "sha-1" -version = "0.10.0" +name = "sha2" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.3", + "digest 0.10.7", ] [[package]] name = "sharded-slab" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ "lazy_static", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "slab" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ - "autocfg 1.1.0", + "autocfg 1.3.0", ] [[package]] name = "smallvec" -version = "1.9.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.4.4" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", - "winapi", + "windows-sys", ] [[package]] @@ -1837,9 +1929,9 @@ checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" dependencies = [ "heck 0.3.3", "proc-macro-error", - "proc-macro2 1.0.42", - "quote 1.0.20", - "syn 1.0.98", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 1.0.109", ] [[package]] @@ -1855,28 +1947,45 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.98" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ - "proc-macro2 1.0.42", - "quote 1.0.20", + "proc-macro2 1.0.86", + "quote 1.0.37", "unicode-ident", ] [[package]] name = "system-deps" -version = "6.0.2" +version = "6.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a45a1c4c9015217e12347f2a411b57ce2c4fc543913b14b6fe40483328e709" +checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" dependencies = [ "cfg-expr", - "heck 0.4.0", + "heck 0.5.0", "pkg-config", - "toml", + "toml 0.8.19", "version-compare", ] +[[package]] +name = "target-lexicon" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + [[package]] name = "textwrap" version = "0.11.0" @@ -1888,30 +1997,31 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.31" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.31" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ - "proc-macro2 1.0.42", - "quote 1.0.20", - "syn 1.0.98", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] name = "thread_local" -version = "1.1.4" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ + "cfg-if", "once_cell", ] @@ -1929,9 +2039,9 @@ dependencies = [ [[package]] name = "time" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" dependencies = [ "libc", "wasi 0.10.0+wasi-snapshot-preview1", @@ -1940,85 +2050,125 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] [[package]] name = "tinyvec_macros" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.20.1" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a8325f63a7d4774dd041e363b2409ed1c5cbbd0f867795e661df066b2b0a581" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ - "autocfg 1.1.0", + "backtrace", "bytes", "libc", - "memchr", "mio", - "num_cpus", - "once_cell", "pin-project-lite", "socket2", "tokio-macros", - "winapi", + "windows-sys", ] [[package]] name = "tokio-macros" -version = "1.8.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ - "proc-macro2 1.0.42", - "quote 1.0.20", - "syn 1.0.98", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] name = "tokio-util" -version = "0.7.3" +version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] name = "toml" -version = "0.5.9" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "toml" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.22.20", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ + "indexmap", + "toml_datetime", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.22.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" +dependencies = [ + "indexmap", "serde", + "serde_spanned", + "toml_datetime", + "winnow 0.6.18", ] [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.36" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fce9567bd60a67d08a16488756721ba392f24f29006402881e43b19aac64307" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -2026,20 +2176,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.22" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11c75893af559bc8e10716548bdef5cb2b983f8e637db9d0e15126b61b484ee2" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ - "proc-macro2 1.0.42", - "quote 1.0.20", - "syn 1.0.98", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] name = "tracing-core" -version = "0.1.29" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aeea4303076558a00714b823f9ad67d58a3bbda1df83d8827d21193156e22f7" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", @@ -2057,11 +2207,11 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.15" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60db860322da191b40952ad9affe65ea23e7dd6a5c442c2c42865810c6ab8e6b" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ - "ansi_term", + "nu-ansi-term", "serde", "serde_json", "sharded-slab", @@ -2078,15 +2228,15 @@ checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" [[package]] name = "try-lock" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "ttf-parser" -version = "0.15.2" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b3e06c9b9d80ed6b745c7159c40b311ad2916abb34a49e9be2653b90db0d8dd" +checksum = "5be21190ff5d38e8b4a2d3b6a3ae57f612cc39c96e83cedeaf7abc338a8bac4a" [[package]] name = "typeable" @@ -2096,15 +2246,15 @@ checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" [[package]] name = "typenum" -version = "1.15.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "ucd-trie" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89570599c4fe5585de2b388aab47e99f7fa4e9238a1399f707a02e356058141c" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" [[package]] name = "unicase" @@ -2117,36 +2267,36 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.8" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" -version = "1.0.2" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.21" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.9.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-width" -version = "0.1.9" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "unicode-xid" @@ -2167,14 +2317,13 @@ dependencies = [ [[package]] name = "url" -version = "2.2.2" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", - "idna 0.2.3", - "matches", - "percent-encoding 2.1.0", + "idna 0.5.0", + "percent-encoding 2.3.1", ] [[package]] @@ -2185,9 +2334,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "version-compare" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe88247b92c1df6b6de80ddc290f3976dbdf2f5f5d3fd049a9fb598c6dd5ca73" +checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" [[package]] name = "version_check" @@ -2197,17 +2346,16 @@ checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "want" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" dependencies = [ - "log 0.4.17", "try-lock", ] @@ -2249,10 +2397,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49aec794b07318993d1db16156d5a9c750120597a5ee40c6b928d416186cb138" dependencies = [ "base64 0.10.1", - "bitflags", + "bitflags 1.3.2", "byteorder", "rand 0.6.5", - "sha-1 0.8.2", + "sha-1", ] [[package]] @@ -2260,9 +2408,9 @@ name = "weylus" version = "0.11.4" dependencies = [ "autopilot", - "bitflags", + "bitflags 1.3.2", "cc", - "core-foundation 0.9.3", + "core-foundation 0.9.4", "core-graphics 0.22.3", "dbus", "dirs", @@ -2271,21 +2419,21 @@ dependencies = [ "gstreamer-app", "gstreamer-video", "handlebars", - "hyper 0.14.20", + "hyper 0.14.30", "image 0.22.5", "image 0.23.14", "num_cpus", - "percent-encoding 2.1.0", + "percent-encoding 2.3.1", "pnet_datalink", "qrcode", "serde", "serde_json", "structopt", "tokio", - "toml", + "toml 0.5.11", "tracing", "tracing-subscriber", - "url 2.2.2", + "url 2.5.2", "websocket", ] @@ -2313,53 +2461,122 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" -version = "0.36.1" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ + "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", + "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", + "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + [[package]] name = "windows_aarch64_msvc" -version = "0.36.1" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.36.1" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" -version = "0.36.1" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" -version = "0.36.1" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" -version = "0.36.1" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +dependencies = [ + "memchr", +] [[package]] name = "x11" -version = "2.19.1" +version = "2.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd0565fa8bfba8c5efe02725b14dff114c866724eff2cfd44d76cea74bcd87a" +checksum = "502da5464ccd04011667b11c435cb992822c2c0dbde1770c988480d312a0db2e" dependencies = [ "libc", "pkg-config", ] + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", +] diff --git a/build.rs b/build.rs index 35787941..e63ee819 100644 --- a/build.rs +++ b/build.rs @@ -169,4 +169,7 @@ fn linux() { println!("cargo:rustc-link-lib={}=va-drm", va_link_kind); println!("cargo:rustc-link-lib={}=va-x11", va_link_kind); println!("cargo:rustc-link-lib=drm"); + println!("cargo:rustc-link-lib=xcb-dri3"); + println!("cargo:rustc-link-lib=X11-xcb"); + println!("cargo:rustc-link-lib=xcb"); } diff --git a/build_in_local_container.sh b/build_in_local_container.sh new file mode 100755 index 00000000..2e9b1c30 --- /dev/null +++ b/build_in_local_container.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env sh + +set -ex + +rm -f docker/archive.tar.gz +git ls-files | tar Tczf - docker/archive.tar.gz + +podman run --replace -d --name weylus_build hhmhh/weylus_build:latest sleep infinity +podman cp docker/archive.tar.gz weylus_build:/ +podman exec weylus_build sh -c "mkdir /weylus && tar xf archive.tar.gz --directory=/weylus && cd weylus && ./docker_build.sh" + +podman run --replace -d --name weylus_build_alpine hhmhh/weylus_build_alpine:latest sleep infinity +podman cp docker/archive.tar.gz weylus_build_alpine:/ +podman exec weylus_build_alpine sh -c "mkdir /weylus && tar xf archive.tar.gz --directory=/weylus && cd weylus && RUSTFLAGS='-C target-feature=-crt-static' cargo build --release" diff --git a/deps/build.sh b/deps/build.sh index a1bfee8c..e8cc6b5b 100755 --- a/deps/build.sh +++ b/deps/build.sh @@ -16,7 +16,7 @@ if [ "$OS" == "Windows_NT" ]; then export HOST_OS="windows" fi -[ -z "$DIST" ] && export DIST="dist" +[ -z "$DIST" ] && export DIST="$PWD/dist" [ -z "$TARGET_OS" ] && export TARGET_OS="$HOST_OS" export NPROCS="$(nproc || echo 4)" diff --git a/deps/download.sh b/deps/download.sh index ab45dcd2..28916047 100755 --- a/deps/download.sh +++ b/deps/download.sh @@ -3,10 +3,10 @@ set -ex test -d x264 || git clone --depth 1 -b stable https://code.videolan.org/videolan/x264.git x264 -test -d ffmpeg || git clone --depth 1 -b n5.1 https://git.ffmpeg.org/ffmpeg.git ffmpeg +test -d ffmpeg || git clone --depth 1 -b n7.0.2 https://git.ffmpeg.org/ffmpeg.git ffmpeg if [ "$TARGET_OS" == "linux" ]; then test -d nv-codec-headers || git clone --depth 1 https://git.videolan.org/git/ffmpeg/nv-codec-headers.git - test -d libva || git clone --depth 1 -b 2.15.0 https://github.com/intel/libva + test -d libva || git clone --depth 1 -b 2.22.0 https://github.com/intel/libva fi if [ "$TARGET_OS" == "windows" ]; then test -d nv-codec-headers || git clone --depth 1 https://git.videolan.org/git/ffmpeg/nv-codec-headers.git diff --git a/docker/Dockerfile b/docker/Dockerfile index 60c8edaa..ed4763bd 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,20 +1,20 @@ -FROM debian:buster +FROM debian:bullseye ENV RUSTUP_HOME="/usr/local/rustup" CARGO_HOME="/usr/local/cargo" PATH="/usr/local/cargo/bin:$PATH" RUN apt-get update && \ apt-get install -y libx11-dev libxext-dev libxft-dev libxinerama-dev libxcursor-dev \ libxrender-dev libxfixes-dev libgl1-mesa-dev libglu1-mesa-dev libxtst-dev cmake git curl \ software-properties-common zip libssl-dev libxrandr-dev libxcomposite-dev libxi-dev \ - gcc g++ autoconf libtool-bin libxv-dev libdrm-dev libpango1.0-dev pkg-config \ - libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libdbus-1-dev mingw-w64 + gcc g++ autoconf libtool-bin libxv-dev libdrm-dev libpango1.0-dev pkg-config mingw-w64 \ + libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libdbus-1-dev libxcb-dri3-dev RUN apt-add-repository contrib RUN apt-add-repository non-free RUN apt-get update && apt-get install -y nvidia-cuda-dev -RUN curl -Lo cmake.tar.gz https://github.com/Kitware/CMake/releases/download/v3.27.8/cmake-3.27.8.tar.gz && tar xf cmake.tar.gz +RUN curl -Lo cmake.tar.gz https://github.com/Kitware/CMake/releases/download/v3.30.3/cmake-3.30.3.tar.gz && tar xf cmake.tar.gz RUN cd cmake-3.* && cmake . && make -j$(nproc) && make install RUN rm -rf cmake* -RUN curl -LO "https://www.nasm.us/pub/nasm/releasebuilds/2.16.01/nasm-2.16.01.tar.xz" && \ - tar xf "nasm-2.16.01.tar.xz" && cd "nasm-2.16.01" && \ - ./configure --prefix=/usr && make -j$(nproc) && make install && cd .. && rm -rf "nasm-2.16.01*" +RUN curl -LO "https://www.nasm.us/pub/nasm/releasebuilds/2.16.03/nasm-2.16.03.tar.xz" && \ + tar xf "nasm-2.16.03.tar.xz" && cd "nasm-2.16.03" && \ + ./configure --prefix=/usr && make -j$(nproc) && make install && cd .. && rm -rf "nasm-2.16.03*" RUN curl -sL https://deb.nodesource.com/setup_20.x | bash - && \ apt-get install -y nodejs && \ npm install -g typescript From 3a131f4987071f9559becb4108109e4e668316b2 Mon Sep 17 00:00:00 2001 From: HMH Date: Tue, 10 Sep 2024 23:45:45 +0200 Subject: [PATCH 37/52] Fix const in signature of `write_video_packet`. --- lib/encode_video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/encode_video.c b/lib/encode_video.c index 8a30639b..2299552e 100644 --- a/lib/encode_video.c +++ b/lib/encode_video.c @@ -59,7 +59,7 @@ typedef struct VideoContext } VideoContext; // this is a rust function and lives in src/video.rs -int write_video_packet(void* rust_ctx, uint8_t* buf, int buf_size); +int write_video_packet(void* rust_ctx, const uint8_t* buf, int buf_size); #if defined(__clang__) || defined(__GNUC__) void log_callback(__attribute__((unused)) void* _ptr, int level, const char* fmt_orig, va_list args) From 14d8002aa9abc8380733c7e2fc4ae777481c257c Mon Sep 17 00:00:00 2001 From: HMH Date: Thu, 12 Sep 2024 21:56:21 +0200 Subject: [PATCH 38/52] Remove cargo deb workaround cargo deb has fixed this issue --- Cargo.toml | 3 --- 1 file changed, 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e80fdae5..52bb4785 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,9 +55,6 @@ identifier = "io.github.h-m-h.weylus" [package.metadata.deb] name = "Weylus" -# Until https://github.com/mmstick/cargo-deb/issues/170 is resolved -# specify depends manually. -depends = "libc6 (>= 2.18), libdbus-1-3 (>= 1.9.14), libdrm2 (>= 2.4.60), libfontconfig1 (>= 2.11), libgcc1 (>= 1:4.2), libglib2.0-0 (>= 2.18.0), libgstreamer-plugins-base1.0-0 (>= 1.10.0), libgstreamer1.0-0 (>= 1.0.0), libx11-6 (>= 2:1.4.99.1), libxcomposite1 (>= 1:0.3-1), libxcursor1 (>> 1.1.2), libxext6, libxfixes3, libxft2 (>> 2.1.1), libxi6 (>= 2:1.2.99.4), libxinerama1, libxrandr2 (>= 2:1.5.0), libxrender1, libxtst6" section = "graphics" priority = "optional" assets = [ From 0b94934fd9b2f7c8f026b64db6e0b8dcbcc5d7f9 Mon Sep 17 00:00:00 2001 From: HMH Date: Fri, 13 Sep 2024 15:26:22 +0200 Subject: [PATCH 39/52] Add some signal handling, improve shutting down. --- Cargo.lock | 20 ++++++++++++++++++++ Cargo.toml | 1 + src/main.rs | 29 ++++++++++++++++++++++++----- src/weylus.rs | 2 +- 4 files changed, 46 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f89a4797..e0d3af8b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1879,6 +1879,25 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "signal-hook" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + [[package]] name = "slab" version = "0.4.9" @@ -2428,6 +2447,7 @@ dependencies = [ "qrcode", "serde", "serde_json", + "signal-hook", "structopt", "tokio", "toml 0.5.11", diff --git a/Cargo.toml b/Cargo.toml index 52bb4785..090c5e0d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ percent-encoding = "2.1.0" qrcode = "0.12.0" serde = { version = "^1.0", features = ["derive"] } serde_json = "^1.0" +signal-hook = "0.3.17" structopt = { version = "^0.3", features = ["color", "suggestions"], default-features = false } tokio = { version = "^1", features = ["macros", "rt-multi-thread", "sync"] } toml = "^0.5" diff --git a/src/main.rs b/src/main.rs index c9b07696..98e46ae6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,12 @@ extern crate test; #[macro_use] extern crate bitflags; -use tracing::{error, warn}; +#[cfg(unix)] +use signal_hook::{ + consts::{SIGINT, SIGTERM}, + iterator::Signals, +}; +use tracing::{error, info, warn}; use std::sync::mpsc; @@ -67,9 +72,7 @@ fn main() { } } - if !conf.no_gui { - gui::run(&conf, receiver); - } else { + if conf.no_gui { let mut weylus = crate::weylus::Weylus::new(); weylus.start( &conf, @@ -80,7 +83,23 @@ fn main() { } }, ); - weylus.wait(); + #[cfg(unix)] + { + let mut signals = Signals::new(&[SIGINT, SIGTERM]).unwrap(); + for sig in signals.forever() { + weylus.stop(); + info!("Shutting down after receiving signal ({sig})."); + break; + } + } + #[cfg(not(unix))] + { + loop { + std::thread::park(); + } + } + } else { + gui::run(&conf, receiver); } } diff --git a/src/weylus.rs b/src/weylus.rs index f4233f60..d81acf35 100644 --- a/src/weylus.rs +++ b/src/weylus.rs @@ -176,7 +176,7 @@ impl Weylus { self.channels = None; } - pub fn wait(&mut self) { + fn wait(&mut self) { if let Some(t) = self.ws_thread.take() { if t.join().is_err() { error!("Websocket thread panicked."); From 06b1f24af0040061f906764e8dc0f3e8c82ebef9 Mon Sep 17 00:00:00 2001 From: HMH Date: Tue, 24 Sep 2024 17:40:45 +0200 Subject: [PATCH 40/52] Improve signal handling. --- src/main.rs | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/main.rs b/src/main.rs index 98e46ae6..d8958446 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,10 +6,8 @@ extern crate test; extern crate bitflags; #[cfg(unix)] -use signal_hook::{ - consts::{SIGINT, SIGTERM}, - iterator::Signals, -}; +use signal_hook::iterator::Signals; +use signal_hook::{consts::TERM_SIGNALS, low_level::signal_name}; use tracing::{error, info, warn}; use std::sync::mpsc; @@ -85,10 +83,23 @@ fn main() { ); #[cfg(unix)] { - let mut signals = Signals::new(&[SIGINT, SIGTERM]).unwrap(); + let mut signals = Signals::new(TERM_SIGNALS).unwrap(); for sig in signals.forever() { + info!( + "Shutting down after receiving signal {signame} ({sig})...", + signame = signal_name(sig).unwrap_or("UNKNOWN SIGNAL") + ); + std::thread::spawn(move || { + for sig in signals.forever() { + warn!( + "Received second signal {signame} ({sig}) while shutting down \ + gracefully, proceeding with forceful shutdown...", + signame = signal_name(sig).unwrap_or("UNKNOWN SIGNAL") + ); + std::process::exit(1); + } + }); weylus.stop(); - info!("Shutting down after receiving signal ({sig})."); break; } } From cd3d91f9b9f50ed90e8a115d03e90a0e5a76c1e5 Mon Sep 17 00:00:00 2001 From: HMH Date: Tue, 24 Sep 2024 20:25:35 +0200 Subject: [PATCH 41/52] Replace websockets with fastwebsockets. This includes an update of hyper, and a change of the protocol. Specifically, the websocket connection does not require a separate port but instead is done via /ws. Furthermore, the client does not poll for frames anymore, instead it sets a preferred frame rate. --- Cargo.lock | 600 +++++++++---------------------- Cargo.toml | 9 +- src/config.rs | 10 +- src/gui.rs | 56 +-- src/main.rs | 14 +- src/protocol.rs | 18 +- src/video.rs | 4 +- src/web.rs | 332 +++++++++++------ src/websocket.rs | 744 +++++++++++++++++++-------------------- src/weylus.rs | 142 ++------ ts/lib.ts | 91 ++--- www/templates/index.html | 140 ++++---- 12 files changed, 954 insertions(+), 1206 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e0d3af8b..6333268f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -34,9 +34,15 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.87" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f00e1f6e58a40e807377c75c6a7f97bf9044fab57816f2414e6f5f4499d7b8" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "atty" @@ -49,15 +55,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "autocfg" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" -dependencies = [ - "autocfg 1.3.0", -] - [[package]] name = "autocfg" version = "1.3.0" @@ -98,22 +95,9 @@ dependencies = [ [[package]] name = "base64" -version = "0.9.3" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" -dependencies = [ - "byteorder", - "safemem", -] - -[[package]] -name = "base64" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" -dependencies = [ - "byteorder", -] +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "bitflags" @@ -133,42 +117,15 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" -[[package]] -name = "block-buffer" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -dependencies = [ - "block-padding", - "byte-tools", - "byteorder", - "generic-array 0.12.4", -] - [[package]] name = "block-buffer" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array 0.14.7", + "generic-array", ] -[[package]] -name = "block-padding" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" -dependencies = [ - "byte-tools", -] - -[[package]] -name = "byte-tools" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" - [[package]] name = "bytemuck" version = "1.18.0" @@ -183,15 +140,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "cc" -version = "1.1.18" +version = "1.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62ac837cdb5cb22e10a256099b4fc502b1dfe560cb282963a974d7abd80e476" +checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0" dependencies = [ "shlex", ] @@ -232,15 +189,6 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "cloudabi" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "cmake" version = "0.1.51" @@ -397,7 +345,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array 0.14.7", + "generic-array", "typenum", ] @@ -432,22 +380,13 @@ dependencies = [ "byteorder", ] -[[package]] -name = "digest" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" -dependencies = [ - "generic-array 0.12.4", -] - [[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "block-buffer 0.10.4", + "block-buffer", "crypto-common", ] @@ -484,16 +423,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] -name = "fake-simd" -version = "0.1.2" +name = "fastwebsockets" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" +checksum = "26da0c7b5cef45c521a6f9cdfffdfeb6c9f5804fbac332deb5ae254634c7a6be" +dependencies = [ + "base64", + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "pin-project", + "rand 0.8.5", + "sha1", + "simdutf8", + "thiserror", + "tokio", + "utf-8", +] [[package]] name = "fltk" -version = "1.4.33" +version = "1.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282d3f9b20cb53f0d468790cdaf7ae28d9128ad52caea5ba1e57fd63e571c081" +checksum = "f8f81f9ebf85aeaad76e43362cc2bb1d926e5daca1327dc0a094d00c86a95ebb" dependencies = [ "bitflags 2.6.0", "crossbeam-channel", @@ -505,9 +458,9 @@ dependencies = [ [[package]] name = "fltk-sys" -version = "1.4.33" +version = "1.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cab52e0e3abc6be8c9ea81bb7aa7887f1650198c3fc4464c5a59ac996d126d3" +checksum = "30bbe32c3f9f72469e2cf2a62edc74ef990b81c2caf082f53fd67060ce0c9893" dependencies = [ "cmake", ] @@ -539,15 +492,9 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ - "percent-encoding 2.3.1", + "percent-encoding", ] -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" - [[package]] name = "futures-channel" version = "0.3.30" @@ -599,15 +546,6 @@ dependencies = [ "slab", ] -[[package]] -name = "generic-array" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" -dependencies = [ - "typenum", -] - [[package]] name = "generic-array" version = "0.14.7" @@ -615,7 +553,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", - "version_check 0.9.5", + "version_check", ] [[package]] @@ -838,15 +776,15 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.26" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" dependencies = [ + "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "futures-util", "http", "indexmap", "slab", @@ -861,7 +799,7 @@ version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "faa67bab9ff362228eb3d00bd024a4965d8231bbb7921167f0cfa66c6626b225" dependencies = [ - "log 0.4.22", + "log", "pest", "pest_derive", "serde", @@ -913,9 +851,9 @@ checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "http" -version = "0.2.12" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ "bytes", "fnv", @@ -924,12 +862,24 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.6" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", + "futures-util", "http", + "http-body", "pin-project-lite", ] @@ -947,32 +897,12 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.10.16" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a0652d9a2609a968c14be1a9ea00bf4b1d64e2e1f53a1b51b6fff3a6e829273" -dependencies = [ - "base64 0.9.3", - "httparse", - "language-tags", - "log 0.3.9", - "mime", - "num_cpus", - "time", - "traitobject", - "typeable", - "unicase", - "url 1.7.2", -] - -[[package]] -name = "hyper" -version = "0.14.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" dependencies = [ "bytes", "futures-channel", - "futures-core", "futures-util", "h2", "http", @@ -981,22 +911,24 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2", + "smallvec", "tokio", - "tower-service", - "tracing", "want", ] [[package]] -name = "idna" -version = "0.1.5" +name = "hyper-util" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", + "bytes", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "tokio", ] [[package]] @@ -1084,12 +1016,6 @@ dependencies = [ "rayon", ] -[[package]] -name = "language-tags" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" - [[package]] name = "lazy_static" version = "1.5.0" @@ -1098,9 +1024,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.158" +version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" [[package]] name = "libdbus-sys" @@ -1121,15 +1047,6 @@ dependencies = [ "libc", ] -[[package]] -name = "log" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" -dependencies = [ - "log 0.4.22", -] - [[package]] name = "log" version = "0.4.22" @@ -1151,27 +1068,12 @@ dependencies = [ "libc", ] -[[package]] -name = "matches" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" - [[package]] name = "memchr" version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" -[[package]] -name = "mime" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" -dependencies = [ - "log 0.3.9", -] - [[package]] name = "miniz_oxide" version = "0.3.7" @@ -1250,7 +1152,7 @@ version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ - "autocfg 1.3.0", + "autocfg", "num-integer", "num-traits", ] @@ -1261,7 +1163,7 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" dependencies = [ - "autocfg 1.3.0", + "autocfg", "num-integer", "num-traits", ] @@ -1272,7 +1174,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" dependencies = [ - "autocfg 1.3.0", + "autocfg", "num-integer", "num-traits", ] @@ -1293,7 +1195,7 @@ version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ - "autocfg 1.3.0", + "autocfg", ] [[package]] @@ -1330,12 +1232,6 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" -[[package]] -name = "opaque-debug" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" - [[package]] name = "option-operations" version = "0.4.1" @@ -1357,12 +1253,6 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" -[[package]] -name = "percent-encoding" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" - [[package]] name = "percent-encoding" version = "2.3.1" @@ -1371,9 +1261,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.12" +version = "2.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c73c26c01b8c87956cea613c907c9d6ecffd8d18a2a5908e5de0adfaa185cea" +checksum = "fdbef9d1d47087a895abd220ed25eb4ad973a5e26f6a4367b038c25e28dfc2d9" dependencies = [ "memchr", "thiserror", @@ -1382,9 +1272,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.12" +version = "2.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "664d22978e2815783adbdd2c588b455b1bd625299ce36b2a99881ac9627e6d8d" +checksum = "4d3a6e3394ec80feb3b6393c725571754c6188490265c61aaf260810d6b95aa0" dependencies = [ "pest", "pest_generator", @@ -1392,9 +1282,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.12" +version = "2.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2d5487022d5d33f4c30d91c22afa240ce2a644e87fe08caad974d4eab6badbe" +checksum = "94429506bde1ca69d1b5601962c73f4172ab4726571a59ea95931218cb0e930e" dependencies = [ "pest", "pest_meta", @@ -1405,15 +1295,35 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.7.12" +version = "2.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0091754bbd0ea592c4deb3a122ce8ecbb0753b738aa82bc055fcc2eccc8d8174" +checksum = "ac8a071862e93690b6e34e9a5fb8e33ff3734473ac0245b27232222c4906a33f" dependencies = [ "once_cell", "pest", "sha2", ] +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", +] + [[package]] name = "pin-project-lite" version = "0.2.14" @@ -1428,9 +1338,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "pnet_base" @@ -1523,7 +1433,7 @@ dependencies = [ "proc-macro2 1.0.86", "quote 1.0.37", "syn 1.0.109", - "version_check 0.9.5", + "version_check", ] [[package]] @@ -1534,7 +1444,7 @@ checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ "proc-macro2 1.0.86", "quote 1.0.37", - "version_check 0.9.5", + "version_check", ] [[package]] @@ -1583,25 +1493,6 @@ dependencies = [ "proc-macro2 1.0.86", ] -[[package]] -name = "rand" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -dependencies = [ - "autocfg 0.1.8", - "libc", - "rand_chacha 0.1.1", - "rand_core 0.4.2", - "rand_hc 0.1.0", - "rand_isaac", - "rand_jitter", - "rand_os", - "rand_pcg", - "rand_xorshift", - "winapi", -] - [[package]] name = "rand" version = "0.7.3" @@ -1612,17 +1503,18 @@ dependencies = [ "libc", "rand_chacha 0.2.2", "rand_core 0.5.1", - "rand_hc 0.2.0", + "rand_hc", ] [[package]] -name = "rand_chacha" -version = "0.1.1" +name = "rand" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "autocfg 0.1.8", - "rand_core 0.3.1", + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", ] [[package]] @@ -1636,20 +1528,15 @@ dependencies = [ ] [[package]] -name = "rand_core" +name = "rand_chacha" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ - "rand_core 0.4.2", + "ppv-lite86", + "rand_core 0.6.4", ] -[[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" - [[package]] name = "rand_core" version = "0.5.1" @@ -1660,12 +1547,12 @@ dependencies = [ ] [[package]] -name = "rand_hc" -version = "0.1.0" +name = "rand_core" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "rand_core 0.3.1", + "getrandom 0.2.15", ] [[package]] @@ -1677,59 +1564,6 @@ dependencies = [ "rand_core 0.5.1", ] -[[package]] -name = "rand_isaac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "rand_jitter" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" -dependencies = [ - "libc", - "rand_core 0.4.2", - "winapi", -] - -[[package]] -name = "rand_os" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -dependencies = [ - "cloudabi", - "fuchsia-cprng", - "libc", - "rand_core 0.4.2", - "rdrand", - "winapi", -] - -[[package]] -name = "rand_pcg" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" -dependencies = [ - "autocfg 0.1.8", - "rand_core 0.4.2", -] - -[[package]] -name = "rand_xorshift" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -dependencies = [ - "rand_core 0.3.1", -] - [[package]] name = "rayon" version = "1.10.0" @@ -1750,15 +1584,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "rdrand" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -dependencies = [ - "rand_core 0.3.1", -] - [[package]] name = "redox_users" version = "0.4.6" @@ -1782,12 +1607,6 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" -[[package]] -name = "safemem" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" - [[package]] name = "scoped_threadpool" version = "0.1.9" @@ -1842,15 +1661,14 @@ dependencies = [ ] [[package]] -name = "sha-1" -version = "0.8.2" +name = "sha1" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ - "block-buffer 0.7.3", - "digest 0.8.1", - "fake-simd", - "opaque-debug", + "cfg-if", + "cpufeatures", + "digest", ] [[package]] @@ -1861,7 +1679,7 @@ checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.7", + "digest", ] [[package]] @@ -1898,13 +1716,19 @@ dependencies = [ "libc", ] +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + [[package]] name = "slab" version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ - "autocfg 1.3.0", + "autocfg", ] [[package]] @@ -2016,18 +1840,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.63" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2 1.0.86", "quote 1.0.37", @@ -2056,17 +1880,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "time" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi", -] - [[package]] name = "tinyvec" version = "1.8.0" @@ -2140,7 +1953,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.20", + "toml_edit 0.22.22", ] [[package]] @@ -2165,23 +1978,17 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.20" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ "indexmap", "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.18", + "winnow 0.6.19", ] -[[package]] -name = "tower-service" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" - [[package]] name = "tracing" version = "0.1.40" @@ -2239,12 +2046,6 @@ dependencies = [ "tracing-serde", ] -[[package]] -name = "traitobject" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079" - [[package]] name = "try-lock" version = "0.2.5" @@ -2257,12 +2058,6 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5be21190ff5d38e8b4a2d3b6a3ae57f612cc39c96e83cedeaf7abc338a8bac4a" -[[package]] -name = "typeable" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1410f6f91f21d1612654e7cc69193b0334f909dcf2c790c4826254fbb86f8887" - [[package]] name = "typenum" version = "1.17.0" @@ -2275,15 +2070,6 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" -[[package]] -name = "unicase" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" -dependencies = [ - "version_check 0.1.5", -] - [[package]] name = "unicode-bidi" version = "0.3.15" @@ -2292,30 +2078,30 @@ checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-normalization" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-width" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "unicode-xid" @@ -2323,17 +2109,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -[[package]] -name = "url" -version = "1.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" -dependencies = [ - "idna 0.1.5", - "matches", - "percent-encoding 1.0.1", -] - [[package]] name = "url" version = "2.5.2" @@ -2341,10 +2116,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", - "idna 0.5.0", - "percent-encoding 2.3.1", + "idna", + "percent-encoding", ] +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + [[package]] name = "valuable" version = "0.1.0" @@ -2357,12 +2138,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" -[[package]] -name = "version_check" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" - [[package]] name = "version_check" version = "0.9.5" @@ -2384,65 +2159,37 @@ version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" -[[package]] -name = "websocket" -version = "0.26.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92aacab060eea423e4036820ddd28f3f9003b2c4d8048cbda985e5a14e18038d" -dependencies = [ - "hyper 0.10.16", - "rand 0.6.5", - "unicase", - "url 1.7.2", - "websocket-base", -] - -[[package]] -name = "websocket-base" -version = "0.26.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49aec794b07318993d1db16156d5a9c750120597a5ee40c6b928d416186cb138" -dependencies = [ - "base64 0.10.1", - "bitflags 1.3.2", - "byteorder", - "rand 0.6.5", - "sha-1", -] - [[package]] name = "weylus" version = "0.11.4" dependencies = [ "autopilot", "bitflags 1.3.2", + "bytes", "cc", "core-foundation 0.9.4", "core-graphics 0.22.3", "dbus", "dirs", + "fastwebsockets", "fltk", "gstreamer", "gstreamer-app", "gstreamer-video", "handlebars", - "hyper 0.14.30", + "http-body-util", + "hyper", + "hyper-util", "image 0.22.5", "image 0.23.14", "num_cpus", - "percent-encoding 2.3.1", + "percent-encoding", "pnet_datalink", "qrcode", "serde", @@ -2453,8 +2200,7 @@ dependencies = [ "toml 0.5.11", "tracing", "tracing-subscriber", - "url 2.5.2", - "websocket", + "url", ] [[package]] @@ -2563,9 +2309,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.18" +version = "0.6.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +checksum = "c52ac009d615e79296318c1bcce2d422aaca15ad08515e344feeda07df67a587" dependencies = [ "memchr", ] diff --git a/Cargo.toml b/Cargo.toml index 090c5e0d..1dc45eed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,10 +9,14 @@ description = "Use your iPad or Android tablet as graphic tablet." [dependencies] autopilot = { git = "https://github.com/H-M-H/autopilot-rs.git", rev = "63eed09c715bfb665bb23172a3930a528e11691c" } bitflags = "^1.3" +bytes = "1.7.1" dirs = "^4.0" +fastwebsockets = { version = "0.8.0", features = ["upgrade", "unstable-split"] } fltk = { version = "^1", features = ["no-pango"] } handlebars = "^4.1" -hyper = { version = "^0.14", features = ["server", "tcp", "http1", "http2"] } +http-body-util = "0.1.2" +hyper = { version = "^1.4", features = ["server", "http1", "http2"] } +hyper-util = { version = "0.1.8", features = ["tokio"] } image = { version = "^0.23", features = ["png"], default-features = false } image_autopilot = { package = "image", version = "0.22.5", features = [], default-features = false } percent-encoding = "2.1.0" @@ -21,12 +25,11 @@ serde = { version = "^1.0", features = ["derive"] } serde_json = "^1.0" signal-hook = "0.3.17" structopt = { version = "^0.3", features = ["color", "suggestions"], default-features = false } -tokio = { version = "^1", features = ["macros", "rt-multi-thread", "sync"] } +tokio = { version = "^1", features = ["fs", "macros", "rt-multi-thread", "sync"] } toml = "^0.5" tracing = "^0.1" tracing-subscriber = { version = "^0.3", features = ["ansi", "json"], default-features = false } url = "^2.2" -websocket = { version = "=0.26.5", features = ["sync"], default-features = false } [build-dependencies] cc = "^1.0" diff --git a/src/config.rs b/src/config.rs index 52d16c21..34879c39 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,5 +1,5 @@ -use std::fs; use std::net::IpAddr; +use std::{fs, path::PathBuf}; use serde::{Deserialize, Serialize}; use structopt::StructOpt; @@ -69,16 +69,16 @@ pub struct Config { help = "Use custom template of index.html to be served by Weylus." )] #[serde(skip)] - pub custom_index_html: Option, + pub custom_index_html: Option, #[structopt(long, help = "Use custom access.html to be served by Weylus.")] #[serde(skip)] - pub custom_access_html: Option, + pub custom_access_html: Option, #[structopt(long, help = "Use custom style.css to be served by Weylus.")] #[serde(skip)] - pub custom_style_css: Option, + pub custom_style_css: Option, #[structopt(long, help = "Use custom lib.js to be served by Weylus.")] #[serde(skip)] - pub custom_lib_js: Option, + pub custom_lib_js: Option, #[structopt(long, help = "Print shell completions for given shell.")] #[serde(skip)] diff --git a/src/gui.rs b/src/gui.rs index 84ff3463..328fb5ff 100644 --- a/src/gui.rs +++ b/src/gui.rs @@ -19,7 +19,7 @@ use fltk::{ use pnet_datalink as datalink; use crate::config::{write_config, Config}; -use crate::websocket::Ws2UiMessage; +use crate::web::Web2UiMessage::UInputInaccessible; pub fn run(config: &Config, log_receiver: mpsc::Receiver) { let width = 200; @@ -218,33 +218,29 @@ pub fn run(config: &Config, log_receiver: mpsc::Receiver) { config.try_mediafoundation = check_native_hw_accel.is_checked(); } } - if !weylus.start( - &config, - |_| {}, - |message| match message { - Ws2UiMessage::UInputInaccessible => { - let w = 500; - let h = 300; - let mut pop_up = Window::default() - .with_size(w, h) - .center_screen() - .with_label("Weylus - UInput inaccessible!"); - pop_up.set_xclass("weylus"); - - let buf = TextBuffer::default(); - let mut pop_up_text = TextDisplay::default().with_size(w, h); - pop_up_text.set_buffer(buf); - pop_up_text.wrap_mode(fltk::text::WrapMode::AtBounds, 5); - let mut buf = pop_up_text.buffer().unwrap(); - buf.set_text(std::include_str!("strings/uinput_error.txt")); - - pop_up.end(); - pop_up.make_modal(true); - pop_up.show(); - } - _ => {} - }, - ) { + if !weylus.start(&config, |message| match message { + UInputInaccessible => { + let w = 500; + let h = 300; + let mut pop_up = Window::default() + .with_size(w, h) + .center_screen() + .with_label("Weylus - UInput inaccessible!"); + pop_up.set_xclass("weylus"); + + let buf = TextBuffer::default(); + let mut pop_up_text = TextDisplay::default().with_size(w, h); + pop_up_text.set_buffer(buf); + pop_up_text.wrap_mode(fltk::text::WrapMode::AtBounds, 5); + let mut buf = pop_up_text.buffer().unwrap(); + buf.set_text(std::include_str!("strings/uinput_error.txt")); + + pop_up.end(); + pop_up.make_modal(true); + pop_up.show(); + } + _ => {} + }) { return Ok(()); } is_server_running = true; @@ -349,4 +345,8 @@ pub fn run(config: &Config, log_receiver: mpsc::Receiver) { but_toggle.set_callback(toggle_server); app.run().expect("Failed to run Gui!"); + + // TODO: Remove when https://github.com/fltk-rs/fltk-rs/issues/1480 is fixed + // this is required to drop the callback and do a graceful shutdown of the web server + but_toggle.set_callback(|_| ()); } diff --git a/src/main.rs b/src/main.rs index d8958446..9595858c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -72,15 +72,11 @@ fn main() { if conf.no_gui { let mut weylus = crate::weylus::Weylus::new(); - weylus.start( - &conf, - |_| {}, - |msg| { - if let crate::websocket::Ws2UiMessage::UInputInaccessible = msg { - warn!(std::include_str!("strings/uinput_error.txt")); - } - }, - ); + weylus.start(&conf, |msg| { + if let crate::web::Web2UiMessage::UInputInaccessible = msg { + warn!(std::include_str!("strings/uinput_error.txt")); + } + }); #[cfg(unix)] { let mut signals = Signals::new(TERM_SIGNALS).unwrap(); diff --git a/src/protocol.rs b/src/protocol.rs index d15e130c..d578b169 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -9,6 +9,7 @@ pub struct ClientConfiguration { pub max_width: usize, pub max_height: usize, pub client_name: Option, + pub frame_rate: f64, } #[derive(Serialize, Deserialize, Debug)] @@ -16,10 +17,6 @@ pub enum MessageInbound { PointerEvent(PointerEvent), WheelEvent(WheelEvent), KeyboardEvent(KeyboardEvent), - // request a video frame from the server - // like this the client can partially control the framerate by sending requests at some given - // rate. However, the server may drop a request if encoding is too slow. - TryGetFrame, GetCapturableList, Config(ClientConfiguration), } @@ -151,3 +148,16 @@ pub struct WheelEvent { pub dy: i32, pub timestamp: u64, } + +pub trait WeylusSender { + type Error: std::error::Error; + fn send_message(&mut self, message: MessageOutbound) -> Result<(), Self::Error>; + fn send_video(&mut self, bytes: &[u8]) -> Result<(), Self::Error>; +} + +pub trait WeylusReceiver: Iterator> { + type Error: std::error::Error; + fn recv_message(&mut self) -> Option> { + self.next() + } +} diff --git a/src/video.rs b/src/video.rs index 731812f4..984ded95 100644 --- a/src/video.rs +++ b/src/video.rs @@ -70,7 +70,7 @@ pub struct VideoEncoder { height_in: usize, width_out: usize, height_out: usize, - write_data: Box, + write_data: Box, start_time: Instant, } @@ -80,7 +80,7 @@ impl VideoEncoder { height_in: usize, width_out: usize, height_out: usize, - write_data: impl Fn(&[u8]) + 'static, + mut write_data: impl FnMut(&[u8]) + 'static, options: EncoderOptions, ) -> Result, CError> { let mut video_encoder = Box::new(Self { diff --git a/src/web.rs b/src/web.rs index c343f4ae..5fef7eb7 100644 --- a/src/web.rs +++ b/src/web.rs @@ -1,30 +1,51 @@ +use bytes::Bytes; +use fastwebsockets::upgrade; use handlebars::Handlebars; -use hyper::service::{make_service_fn, service_fn}; -use hyper::{server::conn::AddrStream, Body, Method, Request, Response, Server, StatusCode}; +use http_body_util::combinators::BoxBody; +use http_body_util::{BodyExt, Full}; +use hyper::body::Incoming; +use hyper::server::conn::http1; +use hyper::service::service_fn; +use hyper::{Method, Request, Response, StatusCode}; +use hyper_util::rt::TokioIo; use serde::Serialize; use std::collections::HashMap; +use std::convert::Infallible; use std::net::SocketAddr; -use std::sync::mpsc; -use std::sync::mpsc::SendError; +use std::path::PathBuf; +use std::sync::atomic::{AtomicUsize, Ordering}; use std::sync::Arc; -use tokio::sync::mpsc as mpsc_tokio; +use std::time::Duration; +use tokio::net::TcpListener; +use tokio::sync::{mpsc, oneshot}; use tracing::{debug, error, info, warn}; +use crate::websocket::{weylus_websocket_channel, WeylusClientConfig, WeylusClientHandler}; + +#[derive(Debug)] +pub enum WebStartUpMessage { + Start, + Error, +} + +pub enum Web2UiMessage { + UInputInaccessible, +} + pub const INDEX_HTML: &str = std::include_str!("../www/templates/index.html"); pub const ACCESS_HTML: &str = std::include_str!("../www/static/access_code.html"); pub const STYLE_CSS: &str = std::include_str!("../www/static/style.css"); pub const LIB_JS: &str = std::include_str!("../www/static/lib.js"); #[derive(Serialize)] -struct WebConfig { +struct IndexTemplateContext { access_code: Option, - websocket_port: u16, uinput_enabled: bool, capture_cursor_enabled: bool, log_level: String, } -fn response_from_str(s: &str, content_type: &str) -> Response { +fn response_from_str(s: &str, content_type: &str) -> Response> { Response::builder() .status(StatusCode::OK) .header("content-type", content_type) @@ -32,7 +53,7 @@ fn response_from_str(s: &str, content_type: &str) -> Response { .unwrap() } -fn response_not_found() -> Response { +fn response_not_found() -> Response> { Response::builder() .status(StatusCode::NOT_FOUND) .header("content-type", "text/html; charset=utf-8") @@ -40,13 +61,13 @@ fn response_not_found() -> Response { .unwrap() } -fn response_from_path_or_default( - path: Option<&String>, +async fn response_from_path_or_default( + path: Option<&PathBuf>, default: &str, content_type: &str, -) -> Response { +) -> Response> { match path { - Some(path) => match std::fs::read_to_string(path) { + Some(path) => match tokio::fs::read_to_string(path).await { Ok(s) => response_from_str(&s, content_type), Err(err) => { warn!("Failed to load file: {}", err); @@ -59,14 +80,17 @@ fn response_from_path_or_default( async fn serve( addr: SocketAddr, - req: Request, + mut req: Request, context: Arc>, - _sender: mpsc::Sender, -) -> Result, hyper::Error> { + sender_ui: mpsc::Sender, + num_clients: Arc, + semaphore_websocket_shutdown: Arc, + notify_disconnect: Arc, +) -> Result>, hyper::Error> { debug!("Got request: {:?}", req); let mut authed = false; - if let Some(access_code) = &context.access_code { - if req.method() == Method::GET && req.uri().path() == "/" { + if let Some(access_code) = &context.web_config.access_code { + if req.method() == Method::GET && (req.uri().path() == "/" || req.uri().path() == "/ws") { use url::form_urlencoded; if let Some(query) = req.uri().query() { let params = form_urlencoded::parse(query.as_bytes()) @@ -84,27 +108,27 @@ async fn serve( authed = true; } if req.method() != Method::GET { - return Ok(response_not_found()); + return Ok(response_not_found().map(|r| r.boxed())); } match req.uri().path() { "/" => { if !authed { return Ok(response_from_path_or_default( - context.custom_access_html.as_ref(), + context.web_config.custom_access_html.as_ref(), ACCESS_HTML, "text/html; charset=utf-8", - )); + ) + .await + .map(|r| r.boxed())); } - debug!(address = ?addr, "Client connected."); - let config = WebConfig { - access_code: context.access_code.clone(), - websocket_port: context.ws_port, + let config = IndexTemplateContext { + access_code: context.web_config.access_code.clone(), uinput_enabled: cfg!(target_os = "linux"), capture_cursor_enabled: cfg!(not(target_os = "windows")), log_level: crate::log::get_log_level().to_string(), }; - let html = if let Some(path) = context.custom_index_html.as_ref() { + let html = if let Some(path) = context.web_config.custom_index_html.as_ref() { let mut reg = Handlebars::new(); if let Err(err) = reg.register_template_file("index", path) { warn!("Failed to register template from path: {}", err); @@ -117,63 +141,102 @@ async fn serve( }; match html { - Ok(html) => Ok(response_from_str(&html, "text/html; charset=utf-8")), + Ok(html) => { + Ok(response_from_str(&html, "text/html; charset=utf-8").map(|r| r.boxed())) + } Err(err) => { error!("Failed to render index template: {}", err); - Ok(response_not_found()) + Ok(response_not_found().map(|r| r.boxed())) } } } + "/ws" => { + if !authed { + return Ok(Response::builder() + .status(StatusCode::UNAUTHORIZED) + .body("unauthorized".to_string().boxed()) + .unwrap()); + } + + let (response, fut) = upgrade::upgrade(&mut req).unwrap(); + num_clients.fetch_add(1, Ordering::Relaxed); + + let config = context.weylus_client_config.clone(); + tokio::spawn(async move { + match fut.await { + Ok(ws) => { + let (sender, receiver) = + weylus_websocket_channel(ws, semaphore_websocket_shutdown); + std::thread::spawn(move || { + let client = WeylusClientHandler::new( + sender, + receiver, + || { + if let Err(err) = + sender_ui.blocking_send(Web2UiMessage::UInputInaccessible) + { + warn!( + "Failed to send message 'UInputInaccessible': {err}." + ); + } + }, + config, + ); + client.run(); + num_clients.fetch_sub(1, Ordering::Relaxed); + notify_disconnect.notify_waiters(); + }); + } + Err(err) => { + eprintln!("Error in websocket connection: {}", err); + num_clients.fetch_sub(1, Ordering::Relaxed); + notify_disconnect.notify_waiters(); + } + } + }); + + Ok(response.map(|r| r.boxed())) + } "/style.css" => Ok(response_from_path_or_default( - context.custom_style_css.as_ref(), + context.web_config.custom_style_css.as_ref(), STYLE_CSS, "text/css; charset=utf-8", - )), + ) + .await + .map(|r| r.boxed())), "/lib.js" => Ok(response_from_path_or_default( - context.custom_lib_js.as_ref(), + context.web_config.custom_lib_js.as_ref(), LIB_JS, "text/javascript; charset=utf-8", - )), - _ => Ok(response_not_found()), + ) + .await + .map(|r| r.boxed())), + _ => Ok(response_not_found().map(|r| r.boxed())), } } -#[derive(Debug)] -pub enum Ui2WebMessage { - Shutdown, -} -pub enum Web2UiMessage { - Start, - Error(String), -} - -fn log_send_error(res: Result<(), SendError>) { - if let Err(err) = res { - warn!("Webserver: Failed to send message to gui: {}", err); - } +#[derive(Clone)] +pub struct WebServerConfig { + pub bind_addr: SocketAddr, + pub access_code: Option, + pub custom_index_html: Option, + pub custom_access_html: Option, + pub custom_style_css: Option, + pub custom_lib_js: Option, } struct Context<'a> { - bind_addr: SocketAddr, - ws_port: u16, - access_code: Option, - custom_index_html: Option, - custom_access_html: Option, - custom_style_css: Option, - custom_lib_js: Option, + web_config: WebServerConfig, + weylus_client_config: WeylusClientConfig, templates: Handlebars<'a>, } pub fn run( - sender: mpsc::Sender, - receiver: mpsc_tokio::Receiver, - bind_addr: SocketAddr, - ws_port: u16, - access_code: Option, - custom_index_html: Option, - custom_access_html: Option, - custom_style_css: Option, - custom_lib_js: Option, + sender_ui: tokio::sync::mpsc::Sender, + sender_startup: oneshot::Sender, + notify_shutdown: Arc, + web_server_config: WebServerConfig, + weylus_client_config: WeylusClientConfig, ) -> std::thread::JoinHandle<()> { let mut templates = Handlebars::new(); templates @@ -181,61 +244,122 @@ pub fn run( .unwrap(); let context = Context { - bind_addr, - ws_port, - access_code, - custom_index_html, - custom_access_html, - custom_style_css, - custom_lib_js, + web_config: web_server_config, + weylus_client_config, templates, }; - std::thread::spawn(move || run_server(context, sender, receiver)) + std::thread::spawn(move || run_server(context, sender_ui, sender_startup, notify_shutdown)) } #[tokio::main] async fn run_server( context: Context<'static>, - sender: mpsc::Sender, - mut receiver: mpsc_tokio::Receiver, + sender_ui: tokio::sync::mpsc::Sender, + sender_startup: oneshot::Sender, + notify_shutdown: Arc, ) { - let addr = context.bind_addr; - let context = Arc::new(context); + let addr = context.web_config.bind_addr; - let sender = sender.clone(); - let sender2 = sender.clone(); - let service = make_service_fn(move |s: &AddrStream| { - let addr = s.remote_addr(); - let context = context.clone(); - let sender = sender.clone(); - async move { - Ok::<_, hyper::Error>(service_fn(move |req| { - let context = context.clone(); - serve(addr, req, context, sender.clone()) - })) - } - }); - let server = match Server::try_bind(&addr) { - Ok(builder) => builder.serve(service), + let listener = match TcpListener::bind(addr).await { + Ok(listener) => listener, Err(err) => { - log_send_error(sender2.send(Web2UiMessage::Error(format!( - "Failed to start webserver: {}", - err - )))); + error!("Failed to bind to socket: {err}."); + sender_startup.send(WebStartUpMessage::Error).unwrap(); return; } }; - let server = server.with_graceful_shutdown(async move { - loop { - match receiver.recv().await { - Some(Ui2WebMessage::Shutdown) => break, - None => break, + + sender_startup.send(WebStartUpMessage::Start).unwrap(); + + let context = Arc::new(context); + + let broadcast_shutdown = Arc::new(tokio::sync::Notify::new()); + + let num_clients = Arc::new(AtomicUsize::new(0)); + let notify_disconnect = Arc::new(tokio::sync::Notify::new()); + let semaphore_websocket_shutdown = Arc::new(tokio::sync::Semaphore::new(0)); + + loop { + let (tcp, remote_address) = tokio::select! { + res = listener.accept() => { + match res { + Ok(conn) => conn, + Err(err) => { + warn!("Connection failed: {err}."); + continue; + } + } + }, + _ = notify_shutdown.notified() => { + info!("Webserver is shutting down."); + broadcast_shutdown.notify_waiters(); + break; } + }; + + debug!(address = ?remote_address, "Client connected."); + + let io = TokioIo::new(tcp); + + let sender_ui = sender_ui.clone(); + let broadcast_shutdown = broadcast_shutdown.clone(); + let context = context.clone(); + let num_clients = num_clients.clone(); + let semaphore_websocket_shutdown = semaphore_websocket_shutdown.clone(); + let notify_disconnect = notify_disconnect.clone(); + + tokio::task::spawn(async move { + let conn = http1::Builder::new().serve_connection( + io, + service_fn({ + move |req| { + let context = context.clone(); + let num_clients = num_clients.clone(); + let semaphore_websocket_shutdown = semaphore_websocket_shutdown.clone(); + let notify_disconnect = notify_disconnect.clone(); + serve( + remote_address, + req, + context, + sender_ui.clone(), + num_clients, + semaphore_websocket_shutdown, + notify_disconnect, + ) + } + }), + ); + + let conn = conn.with_upgrades(); + + tokio::select! { + conn = conn => match conn { + Ok(_) => (), + Err(err) => { + warn!("Error polling connection ({remote_address}): {err}.") + } + }, + _ = broadcast_shutdown.notified() => { + info!("Closing connection to: {remote_address}."); + } + } + }); + } + + semaphore_websocket_shutdown.add_permits(num_clients.load(Ordering::Relaxed)); + + loop { + let remaining_clients = num_clients.load(Ordering::Relaxed); + if remaining_clients == 0 { + break; + } else { + debug!("Waiting for remaining clients ({remaining_clients}) to disconnect."); } - }); - info!("Webserver listening at {}...", addr); - log_send_error(sender2.send(Web2UiMessage::Start)); - if let Err(err) = server.await { - error!("Webserver exited error: {}", err) - }; + tokio::select! { + _ = notify_disconnect.notified() => (), + _ = tokio::time::sleep(Duration::from_secs(1)) => { + semaphore_websocket_shutdown.add_permits(num_clients.load(Ordering::Relaxed)); + }, + } + } } diff --git a/src/websocket.rs b/src/websocket.rs index 3fd7e1d7..c4060ab1 100644 --- a/src/websocket.rs +++ b/src/websocket.rs @@ -1,405 +1,141 @@ -use std::collections::HashMap; -use std::net::{SocketAddr, TcpStream}; -use std::sync::mpsc::{SendError, TryRecvError}; -use std::sync::{mpsc, Arc, Mutex}; -use std::thread::spawn; -use tracing::{debug, error, info, warn}; - -use websocket::sender::Writer; -use websocket::server::upgrade::{sync::Buffer as WsBuffer, WsUpgrade}; -use websocket::sync::Server; -use websocket::{Message, OwnedMessage, WebSocketError}; +use fastwebsockets::{FragmentCollectorRead, Frame, OpCode, WebSocket, WebSocketError}; +use hyper::upgrade::Upgraded; +use hyper_util::rt::TokioIo; +use std::convert::Infallible; +use std::sync::mpsc::{RecvTimeoutError, SendError}; +use std::sync::{mpsc, Arc}; +use std::thread::{spawn, JoinHandle}; +use std::time::{Duration, Instant}; +use tokio::sync::mpsc::channel; +use tracing::{debug, error, warn}; use crate::capturable::{get_capturables, Capturable, Recorder}; use crate::input::device::{InputDevice, InputDeviceType}; use crate::protocol::{ - ClientConfiguration, KeyboardEvent, MessageInbound, MessageOutbound, PointerEvent, WheelEvent, + ClientConfiguration, KeyboardEvent, MessageInbound, MessageOutbound, PointerEvent, + WeylusReceiver, WeylusSender, WheelEvent, }; use crate::cerror::CErrorCode; use crate::video::{EncoderOptions, VideoEncoder}; -type WsWriter = Arc>>; -type WsClients = Arc>>; - -pub enum Ws2UiMessage { - Start, - UInputInaccessible, - Error(String), -} - -pub enum Ui2WsMessage { - Shutdown, -} - -#[derive(Clone)] -pub struct WsConfig { - pub address: SocketAddr, - pub access_code: Option, - pub encoder_options: EncoderOptions, - #[cfg(target_os = "linux")] - pub wayland_support: bool, -} - fn log_send_error(res: Result<(), SendError>) { if let Err(err) = res { warn!("Websocket: Failed to send message to ui: {}", err); } } -pub fn run( - sender: mpsc::Sender, - receiver: mpsc::Receiver, - config: WsConfig, -) -> std::thread::JoinHandle<()> { - spawn(move || { - let clients: WsClients = Arc::new(Mutex::new(HashMap::new())); - - let mut server = match Server::bind(config.address) { - Ok(s) => s, - Err(e) => { - log_send_error(sender.send(Ws2UiMessage::Error(format!( - "Failed binding to socket: {}", - e - )))); - return; - } - }; - - if let Err(err) = server.set_nonblocking(true) { - warn!( - "Could not set websocket to non-blocking, graceful shutdown may be impossible now: {}", - err - ); - } - - log_send_error(sender.send(Ws2UiMessage::Start)); - - loop { - std::thread::sleep(std::time::Duration::from_millis(10)); - - match receiver.try_recv() { - Err(TryRecvError::Disconnected) | Ok(Ui2WsMessage::Shutdown) => { - let clients = clients.lock().unwrap(); - for client in clients.values() { - let client = client.lock().unwrap(); - if let Err(err) = client.shutdown_all() { - error!("Could not shutdown websocket client: {}", err); - } - } - info!("Shutting down websocket: {}", config.address); - return; - } - _ => {} - } - match server.accept() { - Ok(request) => { - let clients = clients.clone(); - let config = config.clone(); - let sender = sender.clone(); - spawn(move || handle_connection(request, clients, config, sender)); - } - _ => {} - }; - } - }) -} - -fn handle_connection( - request: WsUpgrade>, - clients: WsClients, - config: WsConfig, - gui_sender: mpsc::Sender, -) { - let client = match request.accept() { - Ok(c) => c, - Err((_, err)) => { - warn!("Failed to accept client: {}", err); - return; - } - }; - - if let Err(err) = client.set_nonblocking(false) { - warn!("Failed to set client to blocking mode: {}", err); - } - - let peer_addr = match client.peer_addr() { - Ok(p) => p, - Err(err) => { - warn!("Failed to retrieve client address: {}", err); - return; - } - }; - - let (mut ws_receiver, ws_sender) = match client.split() { - Ok(s) => s, - Err(err) => { - warn!("Failed to setup connection: {}", err); - return; - } - }; - - let ws_sender = Arc::new(Mutex::new(ws_sender)); - - { - let mut clients = clients.lock().unwrap(); - clients.insert(peer_addr, ws_sender.clone()); - info!(address = ?peer_addr, "Client connected."); - } - - let mut ws_handler = WsHandler::new(ws_sender, config.clone(), gui_sender, peer_addr); - - let mut authed = config.access_code.is_none(); - let access_code = config.access_code.unwrap_or_else(|| "".into()); - for msg in ws_receiver.incoming_messages() { - match msg { - Ok(msg) => { - if !authed { - if let OwnedMessage::Text(pw) = &msg { - if pw == &access_code { - authed = true; - info!(address = ?peer_addr, "WS-Client authenticated!"); - } else { - warn!( - address = ?peer_addr, - access_code = %pw, - "Authentication failed, wrong access code", - ); - let mut clients = clients.lock().unwrap(); - clients.remove(&peer_addr); - return; - } - } - } else { - ws_handler.process(&msg); - } - if msg.is_close() { - let mut clients = clients.lock().unwrap(); - info!(address = ?peer_addr, "Client disconnected."); - clients.remove(&peer_addr); - return; - } - } - Err(err) => { - match err { - // this happens on calling shutdown, no need to log this - WebSocketError::NoDataAvailable => (), - _ => warn!("Error reading message from websocket, closing ({})", err), - } - - let mut clients = clients.lock().unwrap(); - clients.remove(&peer_addr); - return; - } - } - } -} - -fn send_msg(sender: &WsWriter, msg: &MessageOutbound) { - if let Err(err) = sender - .lock() - .unwrap() - .send_message(&Message::text(serde_json::to_string(msg).unwrap())) - { - warn!("Failed to send message to websocket: {}", err); - } -} - struct VideoConfig { capturable: Box, capture_cursor: bool, max_width: usize, max_height: usize, + frame_rate: f64, } enum VideoCommands { Start(VideoConfig), - TryGetFrame, } -fn handle_video(receiver: mpsc::Receiver, sender: WsWriter, config: WsConfig) { - let mut recorder: Option> = None; - let mut video_encoder: Option> = None; - - let mut max_width = 1920; - let mut max_height = 1080; - - loop { - // stop thread once the channel is closed - let mut msg = match receiver.recv() { - Ok(m) => m, - Err(_) => return, - }; - - // drop frames if the client is requesting frames at a higher rate than they can be - // produced here - if let VideoCommands::TryGetFrame = msg { - loop { - match receiver.try_recv() { - Err(mpsc::TryRecvError::Empty) => break, - Err(mpsc::TryRecvError::Disconnected) => return, - Ok(VideoCommands::TryGetFrame) => continue, - Ok(tmp_msg) => { - msg = tmp_msg; - break; - } - } - } - } - match msg { - VideoCommands::TryGetFrame => { - if recorder.is_none() { - warn!("Screen capture not initalized, can not send video frame!"); - continue; - } - let pixel_data = recorder.as_mut().unwrap().capture(); - if let Err(err) = pixel_data { - warn!("Error capturing screen: {}", err); - continue; - } - let pixel_data = pixel_data.unwrap(); - let (width_in, height_in) = pixel_data.size(); - let scale = - (max_width as f64 / width_in as f64).min(max_height as f64 / height_in as f64); - // limit video to 4K - let scale_max = (3840.0 / width_in as f64).min(2160.0 / height_in as f64); - let scale = scale.min(scale_max); - let mut width_out = width_in; - let mut height_out = height_in; - if scale < 1.0 { - width_out = (width_out as f64 * scale) as usize; - height_out = (height_out as f64 * scale) as usize; - } - // video encoder is not setup or setup for encoding the wrong size: restart it - if video_encoder.is_none() - || !video_encoder - .as_ref() - .unwrap() - .check_size(width_in, height_in, width_out, height_out) - { - send_msg(&sender, &MessageOutbound::NewVideo); - let sender = sender.clone(); - let res = VideoEncoder::new( - width_in, - height_in, - width_out, - height_out, - move |data| { - let msg = Message::binary(data); - if let Err(err) = sender.lock().unwrap().send_message(&msg) { - match err { - WebSocketError::IoError(err) => { - // ignore broken pipe errors as those are caused by - // intentionally shutting down the websocket - if err.kind() == std::io::ErrorKind::BrokenPipe { - debug!("Error sending video: {}", err); - } else { - warn!("Error sending video: {}", err); - } - } - _ => warn!("Error sending video: {}", err), - } - } - }, - config.encoder_options, - ); - match res { - Ok(r) => video_encoder = Some(r), - Err(e) => { - warn!("{}", e); - continue; - } - }; - } - let video_encoder = video_encoder.as_mut().unwrap(); - video_encoder.encode(pixel_data); - } - VideoCommands::Start(config) => { - #[allow(unused_assignments)] - { - // gstpipewire can not handle setting a pipeline's state to Null after another - // pipeline has been created and its state has been set to Play. - // This line makes sure that there always is only a single recorder and thus - // single pipeline in this thread by forcing rust to call the destructor of the - // current pipeline here, right before creating a new pipeline. - // See: https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/986 - // - // This shouldn't affect other Recorder trait objects. - recorder = None; - } - match config.capturable.recorder(config.capture_cursor) { - Ok(r) => { - recorder = Some(r); - max_width = config.max_width; - max_height = config.max_height; - send_msg(&sender, &MessageOutbound::ConfigOk); - } - Err(err) => { - warn!("Failed to init screen cast: {}!", err); - send_msg( - &sender, - &MessageOutbound::Error("Failed to init screen cast!".into()), - ) - } - } - } - } +fn send_message(sender: &mut S, message: MessageOutbound) +where + S: WeylusSender, +{ + if let Err(err) = sender.send_message(message) { + warn!("Failed to send message to client: {err}"); } } -struct WsHandler { - sender: WsWriter, +pub struct WeylusClientHandler { + sender: S, + receiver: Option, video_sender: mpsc::Sender, input_device: Option>, capturables: Vec>, - gui_sender: mpsc::Sender, - ws_config: WsConfig, + on_uinput_inaccessible: FnUInput, + config: WeylusClientConfig, #[cfg(target_os = "linux")] capture_cursor: bool, client_name: Option, - client_address: SocketAddr, + video_thread: JoinHandle<()>, +} + +#[derive(Clone, Copy)] +pub struct WeylusClientConfig { + pub encoder_options: EncoderOptions, + #[cfg(target_os = "linux")] + pub wayland_support: bool, } -impl WsHandler { - fn new( - sender: WsWriter, - config: WsConfig, - gui_sender: mpsc::Sender, - client_address: SocketAddr, - ) -> Self { +impl WeylusClientHandler { + pub fn new( + sender: S, + receiver: R, + on_uinput_inaccessible: FnUInput, + config: WeylusClientConfig, + ) -> Self + where + R: WeylusReceiver, + S: WeylusSender + Clone + Send + Sync + 'static, + { let (video_sender, video_receiver) = mpsc::channel::(); - { + let video_thread = { let sender = sender.clone(); - let config = config.clone(); // offload creating the videostream to another thread to avoid blocking the thread that // is receiving messages from the websocket - spawn(move || handle_video(video_receiver, sender, config)); - } + spawn(move || handle_video(video_receiver, sender, config.encoder_options)) + }; Self { sender, + receiver: Some(receiver), video_sender, input_device: None, capturables: vec![], - gui_sender, - ws_config: config, + on_uinput_inaccessible, + config, #[cfg(target_os = "linux")] capture_cursor: false, client_name: None, - client_address, + video_thread, } } - fn send_msg(&self, msg: &MessageOutbound) { - send_msg(&self.sender, msg) + pub fn run(mut self) + where + R: WeylusReceiver, + S: WeylusSender + Clone + Send + Sync + 'static, + FnUInput: Fn(), + { + for message in self.receiver.take().unwrap() { + match message { + Ok(message) => match message { + MessageInbound::PointerEvent(event) => self.process_pointer_event(&event), + MessageInbound::WheelEvent(event) => self.process_wheel_event(&event), + MessageInbound::KeyboardEvent(event) => self.process_keyboard_event(&event), + MessageInbound::GetCapturableList => self.send_capturable_list(), + MessageInbound::Config(config) => self.update_config(config), + }, + Err(err) => { + warn!("Failed to read message {err}!"); + self.send_message(MessageOutbound::Error( + "Failed to read message!".to_string(), + )); + } + } + } + + drop(self.video_sender); + if let Err(err) = self.video_thread.join() { + warn!("Failed to join video thread: {err:?}"); + } } - // Enqueue a request to send a new video frame. - // - // This does not do any further work in order not to block receiving messages. `handle_video` - // is resposible to do the actual work. - fn queue_try_send_video_frame(&mut self) { - self.video_sender.send(VideoCommands::TryGetFrame).unwrap(); + fn send_message(&mut self, message: MessageOutbound) + where + S: WeylusSender, + { + send_message(&mut self.sender, message) } fn process_wheel_event(&mut self, event: &WheelEvent) { @@ -431,21 +167,28 @@ impl WsHandler { } } - fn send_capturable_list(&mut self) { + fn send_capturable_list(&mut self) + where + S: WeylusSender, + { let mut windows = Vec::::new(); self.capturables = get_capturables( #[cfg(target_os = "linux")] - self.ws_config.wayland_support, + self.config.wayland_support, #[cfg(target_os = "linux")] self.capture_cursor, ); self.capturables.iter().for_each(|c| { windows.push(c.name()); }); - self.send_msg(&MessageOutbound::CapturableList(windows)); + self.send_message(MessageOutbound::CapturableList(windows)); } - fn setup(&mut self, config: ClientConfiguration) { + fn update_config(&mut self, config: ClientConfiguration) + where + S: WeylusSender, + FnUInput: Fn(), + { let client_name_changed = if self.client_name != config.client_name { self.client_name = config.client_name; true @@ -474,13 +217,9 @@ impl WsHandler { Err(e) => { error!("Failed to create uinput device: {}", e); if let CErrorCode::UInputNotAccessible = e.to_enum() { - if let Err(err) = - self.gui_sender.send(Ws2UiMessage::UInputInaccessible) - { - warn!("Failed to send message to gui thread: {}!", err); - } + (self.on_uinput_inaccessible)(); } - self.send_msg(&MessageOutbound::ConfigError( + self.send_message(MessageOutbound::ConfigError( "Failed to create uinput device!".to_string(), )); return; @@ -516,54 +255,279 @@ impl WsHandler { capture_cursor: config.capture_cursor, max_width: config.max_width, max_height: config.max_height, + frame_rate: config.frame_rate, })) .unwrap(); } else { error!("Got invalid id for capturable: {}", config.capturable_id); - self.send_msg(&MessageOutbound::ConfigError( + self.send_message(MessageOutbound::ConfigError( "Invalid id for capturable!".to_string(), )); } } +} - fn process(&mut self, message: &OwnedMessage) { - match message { - OwnedMessage::Text(s) => { - let message: Result = serde_json::from_str(s); - match message { - Ok(message) => { - if let MessageInbound::TryGetFrame = message { - } else { - debug!( - client_message = %s, - address = ?self.client_address, - "Got message from client." - ); - } - match message { - MessageInbound::WheelEvent(event) => { - self.process_wheel_event(&event); - } - MessageInbound::PointerEvent(event) => { - self.process_pointer_event(&event); +fn handle_video( + receiver: mpsc::Receiver, + mut sender: S, + encoder_options: EncoderOptions, +) { + const EFFECTIVE_INIFINIT: Duration = Duration::from_secs(3600 * 24 * 365 * 200); + + let mut recorder: Option> = None; + let mut video_encoder: Option> = None; + + let mut max_width = 1920; + let mut max_height = 1080; + let mut frame_duration = EFFECTIVE_INIFINIT; + let mut last_frame = Instant::now(); + + loop { + let now = Instant::now(); + let elapsed = now - last_frame; + let frames_passed = (elapsed.as_secs_f64() / frame_duration.as_secs_f64()) as u32; + let next_frame = last_frame + (frames_passed + 1) * frame_duration; + let timeout = next_frame - now; + last_frame = next_frame; + + if frames_passed > 0 { + debug!("Dropped {frames_passed} frame(s)!"); + } + + match receiver.recv_timeout(timeout) { + Ok(VideoCommands::Start(config)) => { + #[allow(unused_assignments)] + { + // gstpipewire can not handle setting a pipeline's state to Null after another + // pipeline has been created and its state has been set to Play. + // This line makes sure that there always is only a single recorder and thus + // single pipeline in this thread by forcing rust to call the destructor of the + // current pipeline here, right before creating a new pipeline. + // See: https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/986 + // + // This shouldn't affect other Recorder trait objects. + recorder = None; + } + match config.capturable.recorder(config.capture_cursor) { + Ok(r) => { + recorder = Some(r); + max_width = config.max_width; + max_height = config.max_height; + send_message(&mut sender, MessageOutbound::ConfigOk); + } + Err(err) => { + warn!("Failed to init screen cast: {}!", err); + send_message( + &mut sender, + MessageOutbound::Error("Failed to init screen cast!".into()), + ) + } + } + last_frame = Instant::now(); + + // The Duration type can not handle infinity, if the frame rate is set to 0 we just + // set the duration between two frames to a very long one, which is effectively + // infinity. + let d = 1.0 / config.frame_rate; + frame_duration = if d.is_finite() { + Duration::from_secs_f64(d) + } else { + EFFECTIVE_INIFINIT + }; + frame_duration = frame_duration.min(EFFECTIVE_INIFINIT); + } + Err(RecvTimeoutError::Timeout) => { + if recorder.is_none() { + warn!("Screen capture not initalized, can not send video frame!"); + continue; + } + let pixel_data = recorder.as_mut().unwrap().capture(); + if let Err(err) = pixel_data { + warn!("Error capturing screen: {}", err); + continue; + } + let pixel_data = pixel_data.unwrap(); + let (width_in, height_in) = pixel_data.size(); + let scale = + (max_width as f64 / width_in as f64).min(max_height as f64 / height_in as f64); + // limit video to 4K + let scale_max = (3840.0 / width_in as f64).min(2160.0 / height_in as f64); + let scale = scale.min(scale_max); + let mut width_out = width_in; + let mut height_out = height_in; + if scale < 1.0 { + width_out = (width_out as f64 * scale) as usize; + height_out = (height_out as f64 * scale) as usize; + } + // video encoder is not setup or setup for encoding the wrong size: restart it + if video_encoder.is_none() + || !video_encoder + .as_ref() + .unwrap() + .check_size(width_in, height_in, width_out, height_out) + { + send_message(&mut sender, MessageOutbound::NewVideo); + let mut sender = sender.clone(); + let res = VideoEncoder::new( + width_in, + height_in, + width_out, + height_out, + move |data| { + if let Err(err) = sender.send_video(data) { + warn!("Failed to send video frame: {err}!"); } - MessageInbound::KeyboardEvent(event) => { - self.process_keyboard_event(&event); + }, + encoder_options, + ); + match res { + Ok(r) => video_encoder = Some(r), + Err(e) => { + warn!("{}", e); + continue; + } + }; + } + let video_encoder = video_encoder.as_mut().unwrap(); + video_encoder.encode(pixel_data); + } + // stop thread once the channel is closed + Err(RecvTimeoutError::Disconnected) => return, + }; + } +} + +pub struct WsWeylusReceiver { + recv: tokio::sync::mpsc::Receiver, +} + +impl Iterator for WsWeylusReceiver { + type Item = Result; + + fn next(&mut self) -> Option { + self.recv.blocking_recv().map(Ok) + } +} + +impl WeylusReceiver for WsWeylusReceiver { + type Error = Infallible; +} + +pub enum WsMessage { + Frame(Frame<'static>), + Video(Vec), + MessageOutbound(MessageOutbound), +} + +unsafe impl Send for WsMessage {} + +#[derive(Clone)] +pub struct WsWeylusSender { + sender: tokio::sync::mpsc::Sender, +} + +impl WeylusSender for WsWeylusSender { + type Error = tokio::sync::mpsc::error::SendError; + + fn send_message(&mut self, message: MessageOutbound) -> Result<(), Self::Error> { + self.sender + .blocking_send(WsMessage::MessageOutbound(message)) + } + + fn send_video(&mut self, bytes: &[u8]) -> Result<(), Self::Error> { + self.sender.blocking_send(WsMessage::Video(bytes.to_vec())) + } +} + +pub fn weylus_websocket_channel( + websocket: WebSocket>, + semaphore_shutdown: Arc, +) -> (WsWeylusSender, WsWeylusReceiver) { + let (rx, mut tx) = websocket.split(|ws| tokio::io::split(ws)); + + let mut rx = FragmentCollectorRead::new(rx); + + let (sender_inbound, receiver_inbound) = channel::(32); + let (sender_outbound, mut receiver_outbound) = channel::(32); + + { + let sender_outbound = sender_outbound.clone(); + tokio::spawn(async move { + let mut send_fn = |frame| async { + if let Err(err) = sender_outbound.send(WsMessage::Frame(frame)).await { + warn!("Failed to send websocket frame while receiving fragmented frame: {err}.") + }; + Ok(()) + }; + + loop { + let fut = rx.read_frame::<_, WebSocketError>(&mut send_fn); + + let frame = tokio::select! { + _ = semaphore_shutdown.acquire() => break, + frame = fut => frame.unwrap(), + }; + match frame.opcode { + OpCode::Close => break, + OpCode::Text => match serde_json::from_slice(&frame.payload) { + Ok(msg) => { + if let Err(err) = sender_inbound.send(msg).await { + warn!("Failed to forward inbound message to WeylusClientHandler: {err}."); } - MessageInbound::TryGetFrame => self.queue_try_send_video_frame(), - MessageInbound::GetCapturableList => self.send_capturable_list(), - MessageInbound::Config(config) => self.setup(config), } + Err(err) => warn!("Failed to parse message: {err}"), + }, + _ => {} + } + } + }); + } + + tokio::spawn(async move { + loop { + let msg = if let Some(msg) = receiver_outbound.recv().await { + msg + } else { + break; + }; + + match msg { + WsMessage::Frame(frame) => { + if let Err(err) = tx.write_frame(frame).await { + if let WebSocketError::ConnectionClosed = err { + break; + } + warn!("Failed to send frame: {err}"); } - Err(err) => { - warn!("Unable to parse message: {} ({})", s, err); - self.send_msg(&MessageOutbound::Error( - "Failed to parse message!".to_string(), - )); + } + WsMessage::Video(data) => { + if let Err(err) = tx.write_frame(Frame::binary(data.into())).await { + if let WebSocketError::ConnectionClosed = err { + break; + } + warn!("Failed to send video frame: {err}"); + } + } + WsMessage::MessageOutbound(msg) => { + let json_string = serde_json::to_string(&msg).unwrap(); + let data = json_string.as_bytes(); + if let Err(err) = tx.write_frame(Frame::text(data.into())).await { + if let WebSocketError::ConnectionClosed = err { + break; + } + warn!("Failed to send outbound message: {err}"); } } } - _ => (), } - } + }); + + ( + WsWeylusSender { + sender: sender_outbound, + }, + WsWeylusReceiver { + recv: receiver_inbound, + }, + ) } diff --git a/src/weylus.rs b/src/weylus.rs index d81acf35..96125ab6 100644 --- a/src/weylus.rs +++ b/src/weylus.rs @@ -1,29 +1,21 @@ use std::net::SocketAddr; -use std::sync::mpsc; -use tokio::sync::mpsc as mpsc_tokio; -use tracing::{error, warn}; +use std::sync::{mpsc, Arc}; +use tracing::error; use crate::config::Config; use crate::video::EncoderOptions; -use crate::web::{Ui2WebMessage, Web2UiMessage}; -use crate::websocket::{Ui2WsMessage, Ws2UiMessage, WsConfig}; - -struct Channels { - sender_ui2ws: mpsc::Sender, - sender_ui2web: mpsc_tokio::Sender, -} +use crate::web::{Web2UiMessage, WebServerConfig, WebStartUpMessage}; +use crate::websocket::WeylusClientConfig; pub struct Weylus { - channels: Option, - ws_thread: Option>, + notify_shutdown: Arc, web_thread: Option>, } impl Weylus { pub fn new() -> Self { Self { - channels: None, - ws_thread: None, + notify_shutdown: Arc::new(tokio::sync::Notify::new()), web_thread: None, } } @@ -32,11 +24,7 @@ impl Weylus { &mut self, config: &Config, mut on_web_message: impl FnMut(Web2UiMessage) + Send + 'static, - mut on_ws_message: impl FnMut(Ws2UiMessage) + Send + 'static, ) -> bool { - if self.channels.is_some() { - return false; - } let encoder_options = EncoderOptions { #[cfg(target_os = "linux")] try_vaapi: config.try_vaapi, @@ -59,68 +47,34 @@ impl Weylus { try_mediafoundation: false, }; - let ws_config = WsConfig { - address: SocketAddr::new(config.bind_address, config.websocket_port), - access_code: config.access_code.clone(), - encoder_options, - #[cfg(target_os = "linux")] - wayland_support: config.wayland_support, - }; - - let (sender_ui2ws, receiver_ui2ws) = mpsc::channel(); - let (sender_ui2web, receiver_ui2web) = mpsc_tokio::channel(100); - - let (sender_ws2ui, receiver_ws2ui) = mpsc::channel(); - let (sender_web2ui, receiver_web2ui) = mpsc::channel(); - - let ws_thread = crate::websocket::run(sender_ws2ui, receiver_ui2ws, ws_config); - match receiver_ws2ui.recv() { - Ok(Ws2UiMessage::Start) => {} - Ok(Ws2UiMessage::Error(err)) => { - error!("Failed to start websocket server: {}", err); - if ws_thread.join().is_err() { - error!("Websocketserver thread panicked."); - } - return false; - } - Ok(Ws2UiMessage::UInputInaccessible) => unreachable!(), - Err(err) => { - error!("Error communicating with websocketserver thread: {}", err); - if ws_thread.join().is_err() { - error!("Websocketserver thread panicked."); - } - return false; - } - } + let (sender_ui, mut receiver_ui) = tokio::sync::mpsc::channel(100); + let (sender_startup, receiver_startup) = tokio::sync::oneshot::channel(); let web_thread = crate::web::run( - sender_web2ui, - receiver_ui2web, - SocketAddr::new(config.bind_address, config.web_port), - config.websocket_port, - config.access_code.clone(), - config.custom_index_html.clone(), - config.custom_access_html.clone(), - config.custom_style_css.clone(), - config.custom_lib_js.clone(), + sender_ui, + sender_startup, + self.notify_shutdown.clone(), + WebServerConfig { + bind_addr: SocketAddr::new(config.bind_address, config.web_port), + access_code: config.access_code.clone(), + custom_index_html: config.custom_index_html.clone(), + custom_access_html: config.custom_access_html.clone(), + custom_style_css: config.custom_style_css.clone(), + custom_lib_js: config.custom_lib_js.clone(), + }, + WeylusClientConfig { + encoder_options, + #[cfg(target_os = "linux")] + wayland_support: config.wayland_support, + }, ); - match receiver_web2ui.recv() { - Ok(Web2UiMessage::Start) => (), - Ok(Web2UiMessage::Error(err)) => { - error!("Webserver error: {}", err); + + match receiver_startup.blocking_recv() { + Ok(WebStartUpMessage::Start) => (), + Ok(WebStartUpMessage::Error) => { if web_thread.join().is_err() { error!("Webserver thread panicked."); } - - if let Err(err) = sender_ui2ws.send(Ui2WsMessage::Shutdown) { - warn!( - "Failed to send shutdown command to websocketserver: {}", - err - ); - } - if ws_thread.join().is_err() { - error!("Websocketserver thread panicked."); - } return false; } Err(err) => { @@ -128,60 +82,24 @@ impl Weylus { if web_thread.join().is_err() { error!("Webserver thread panicked."); } - - if let Err(err) = sender_ui2ws.send(Ui2WsMessage::Shutdown) { - warn!( - "Failed to send shutdown command to websocketserver: {}", - err - ); - } - if ws_thread.join().is_err() { - error!("Websocketserver thread panicked."); - } return false; } } - self.ws_thread = Some(ws_thread); self.web_thread = Some(web_thread); - self.channels = Some(Channels { - sender_ui2ws, - sender_ui2web, - }); std::thread::spawn(move || { - for msg in receiver_web2ui.iter() { + while let Some(msg) = receiver_ui.blocking_recv() { on_web_message(msg); } }); - std::thread::spawn(move || { - for msg in receiver_ws2ui.iter() { - on_ws_message(msg); - } - }); true } pub fn stop(&mut self) { - if let Some(channels) = self.channels.as_mut() { - if let Err(err) = channels.sender_ui2ws.send(Ui2WsMessage::Shutdown) { - warn!( - "Failed to send shutdown command to websocketserver: {}", - err - ); - } - if let Err(err) = channels.sender_ui2web.try_send(Ui2WebMessage::Shutdown) { - warn!("Failed to send shutdown command to webserver: {}", err); - } - } + self.notify_shutdown.notify_one(); self.wait(); - self.channels = None; } fn wait(&mut self) { - if let Some(t) = self.ws_thread.take() { - if t.join().is_err() { - error!("Websocket thread panicked."); - } - } if let Some(t) = self.web_thread.take() { if t.join().is_err() { error!("Web thread panicked."); diff --git a/ts/lib.ts b/ts/lib.ts index 744b7c00..ebef111a 100644 --- a/ts/lib.ts +++ b/ts/lib.ts @@ -16,7 +16,7 @@ let last_fps_calc: number = performance.now(); let check_video: HTMLInputElement; -function run(access_code: string, websocket_port: number, level: string) { +function run(level: string) { window.onload = () => { log_pre = document.getElementById("log") as HTMLPreElement; log_pre.textContent = ""; @@ -39,7 +39,7 @@ function run(access_code: string, websocket_port: number, level: string) { } return false; }, true) - init(access_code, websocket_port) + init(); }; } @@ -53,12 +53,12 @@ function log(level: LogLevel, msg: string) { log_pre.textContent += LogLevel[level] + ": " + msg + "\n"; } -function frame_update_scale(x: number) { - return Math.pow(x / 100, 3); +function frame_rate_scale(x: number) { + return Math.pow(x / 100, 1.5); } -function frame_update_scale_inv(x: number) { - return 100 * Math.pow(x, 1 / 3); +function frame_rate_scale_inv(x: number) { + return 100 * Math.pow(x, 2 / 3); } @@ -101,8 +101,8 @@ class Settings { webSocket: WebSocket; checks: Map; capturable_select: HTMLSelectElement; - frame_update_limit_input: HTMLInputElement; - frame_update_limit_output: HTMLOutputElement; + frame_rate_input: HTMLInputElement; + frame_rate_output: HTMLOutputElement; scale_video_input: HTMLInputElement; scale_video_output: HTMLOutputElement; range_min_pressure: HTMLInputElement; @@ -115,16 +115,16 @@ class Settings { this.webSocket = webSocket; this.checks = new Map(); this.capturable_select = document.getElementById("window") as HTMLSelectElement; - this.frame_update_limit_input = document.getElementById("frame_update_limit") as HTMLInputElement; - this.frame_update_limit_input.min = frame_update_scale_inv(1).toString(); - this.frame_update_limit_input.max = frame_update_scale_inv(1000).toString(); - this.frame_update_limit_output = this.frame_update_limit_input.nextElementSibling as HTMLOutputElement; + this.frame_rate_input = document.getElementById("frame_rate") as HTMLInputElement; + this.frame_rate_input.min = frame_rate_scale_inv(0).toString(); + this.frame_rate_input.max = frame_rate_scale_inv(120).toString(); + this.frame_rate_output = this.frame_rate_input.nextElementSibling as HTMLOutputElement; this.scale_video_input = document.getElementById("scale_video") as HTMLInputElement; this.scale_video_output = this.scale_video_input.nextElementSibling as HTMLOutputElement; this.range_min_pressure = document.getElementById("min_pressure") as HTMLInputElement; this.client_name_input = document.getElementById("client_name") as HTMLInputElement; - this.frame_update_limit_input.oninput = (e) => { - this.frame_update_limit_output.value = Math.round(frame_update_scale(this.frame_update_limit_input.valueAsNumber)).toString(); + this.frame_rate_input.oninput = (e) => { + this.frame_rate_output.value = Math.round(frame_rate_scale(this.frame_rate_input.valueAsNumber)).toString(); } this.scale_video_input.oninput = (e) => { let [w, h] = calc_max_video_resolution(this.scale_video_input.valueAsNumber) @@ -189,7 +189,7 @@ class Settings { toggle_energysaving((e.target as HTMLInputElement).checked); }; - this.frame_update_limit_input.onchange = () => this.save_settings(); + this.frame_rate_input.onchange = () => this.save_settings(); this.range_min_pressure.onchange = () => this.save_settings(); // server @@ -198,6 +198,7 @@ class Settings { this.checks.get("capture_cursor").onchange = upd_server_config; this.scale_video_input.onchange = upd_server_config; this.client_name_input.onchange = upd_server_config; + this.frame_rate_input.onchange = upd_server_config; document.getElementById("refresh").onclick = () => this.webSocket.send('"GetCapturableList"'); this.capturable_select.onchange = () => this.send_server_config(); @@ -213,6 +214,7 @@ class Settings { let [w, h] = calc_max_video_resolution(this.scale_video_input.valueAsNumber); config["max_width"] = w; config["max_height"] = h; + config["frame_rate"] = frame_rate_scale(this.frame_rate_input.valueAsNumber); if (this.client_name_input.value) config["client_name"] = this.client_name_input.value; this.webSocket.send(JSON.stringify({ "Config": config })); @@ -222,7 +224,7 @@ class Settings { let settings = Object(null); for (const [key, elem] of this.checks.entries()) settings[key] = elem.checked; - settings["frame_update_limit"] = frame_update_scale(this.frame_update_limit_input.valueAsNumber).toString(); + settings["frame_rate"] = frame_rate_scale(this.frame_rate_input.valueAsNumber).toString(); settings["scale_video"] = this.scale_video_input.value; settings["min_pressure"] = this.range_min_pressure.value; settings["client_name"] = this.client_name_input.value; @@ -232,8 +234,8 @@ class Settings { load_settings() { let settings_string = localStorage.getItem("settings"); if (settings_string === null) { - this.frame_update_limit_input.value = frame_update_scale_inv(33).toString(); - this.frame_update_limit_output.value = (33).toString(); + this.frame_rate_input.value = frame_rate_scale_inv(30).toString(); + this.frame_rate_output.value = (30).toString(); let [w, h] = calc_max_video_resolution(this.scale_video_input.valueAsNumber) this.scale_video_output.value = w + "x" + h; return; @@ -244,12 +246,12 @@ class Settings { if (typeof settings[key] === "boolean") elem.checked = settings[key]; } - let upd_limit = settings["frame_update_limit"]; + let upd_limit = settings["frame_rate"]; if (upd_limit) - this.frame_update_limit_input.value = frame_update_scale_inv(upd_limit).toString(); + this.frame_rate_input.value = frame_rate_scale_inv(upd_limit).toString(); else - this.frame_update_limit_input.value = frame_update_scale_inv(33).toString(); - this.frame_update_limit_output.value = Math.round(frame_update_scale(this.frame_update_limit_input.valueAsNumber)).toString(); + this.frame_rate_input.value = frame_rate_scale_inv(30).toString(); + this.frame_rate_output.value = Math.round(frame_rate_scale(this.frame_rate_input.valueAsNumber)).toString(); let scale_video = settings["scale_video"]; if (scale_video) @@ -302,10 +304,6 @@ class Settings { return ptrs; } - frame_update_limit() { - return frame_update_scale(this.frame_update_limit_input.valueAsNumber) - } - toggle() { this.settings.classList.toggle("hide"); this.visible = !this.visible; @@ -315,7 +313,7 @@ class Settings { let current_selection = undefined; if (this.capturable_select.selectedOptions[0]) current_selection = this.capturable_select.selectedOptions[0].textContent; - let new_index; + let new_index: number; this.capturable_select.innerText = ""; window_names.forEach((name, i) => { let option = document.createElement("option"); @@ -728,27 +726,13 @@ class KeyboardHandler { } } -function frame_timer(webSocket: WebSocket) { - // Closing or closed, so no more frames - if (webSocket.readyState > webSocket.OPEN) - return; - +function frame_rate_stats() { let t = performance.now(); - if (t - last_fps_calc > 1500) { - let fps = Math.round(frame_count / (t - last_fps_calc) * 10000) / 10; - fps_out.value = fps.toString(); - frame_count = 0; - last_fps_calc = t; - } - - if (document.hidden) { - requestAnimationFrame(() => frame_timer(webSocket)); - return; - } - - if (webSocket.readyState === webSocket.OPEN && check_video.checked) - webSocket.send('"TryGetFrame"'); - setTimeout(() => frame_timer(webSocket), settings.frame_update_limit()); + let fps = Math.round(frame_count / (t - last_fps_calc) * 10000) / 10; + fps_out.value = fps.toString(); + frame_count = 0; + last_fps_calc = t; + setTimeout(() => frame_rate_stats(), 1500); } function handle_messages( @@ -854,12 +838,11 @@ function check_apis() { } } -function init(access_code: string, websocket_port: number) { +function init() { check_apis(); - let authed = false; let protocol = document.location.protocol == "https:" ? "wss://" : "ws://"; - let webSocket = new WebSocket(protocol + window.location.hostname + ":" + websocket_port); + let webSocket = new WebSocket(protocol + window.location.hostname + ":" + window.location.port + "/ws"); webSocket.binaryType = "arraybuffer"; settings = new Settings(webSocket); @@ -904,8 +887,7 @@ function init(access_code: string, websocket_port: number) { canvas.height = window.innerHeight * window.devicePixelRatio; let [w, h] = calc_max_video_resolution(settings.scale_video_input.valueAsNumber); settings.scale_video_output.value = w + "x" + h; - if (authed) - settings.send_server_config(); + settings.send_server_config(); } video.controls = false; video.onloadeddata = () => stretch_video(); @@ -914,7 +896,6 @@ function init(access_code: string, websocket_port: number) { if (!is_connected) { new KeyboardHandler(webSocket); new PointerHandler(webSocket); - frame_timer(webSocket); is_connected = true; } }, @@ -923,12 +904,10 @@ function init(access_code: string, websocket_port: number) { ); window.onunload = () => { webSocket.close(); } webSocket.onopen = function(event) { - if (access_code) - webSocket.send(access_code); - authed = true; webSocket.send('"GetCapturableList"'); settings.send_server_config(); } + frame_rate_stats(); } // object-fit: fill; <-- this is unfortunately not supported on iOS, so we use the following diff --git a/www/templates/index.html b/www/templates/index.html index 6c734456..83d8396d 100644 --- a/www/templates/index.html +++ b/www/templates/index.html @@ -1,72 +1,80 @@ - - - - - - Weylus - - - - - -
- - -
-
-
â ¿
-
-

Settings

-
- - - -
-

Video

-
- - - - - - - - -
-

Input

-
- - - - - -
-
- -
-
- - -
-
- -
-
-
-
+ + + + + + Weylus + + + + + + +
+ + +
+
+
â ¿
+
+

Settings

+
+ + + +
+

Video

+
+ + + + + + + + +
+

Input

+
+ + + + + +
+
+ +
+
+ + +
+
+ +
+
+
- +
+ From 9e5376c9d2398003ba215175c396d931ed820967 Mon Sep 17 00:00:00 2001 From: HMH Date: Tue, 24 Sep 2024 20:53:06 +0200 Subject: [PATCH 42/52] Update various dependencies. --- Cargo.lock | 231 +++++++++++++++++++++++++++++++---------------- Cargo.toml | 14 +-- src/gui.rs | 4 +- src/protocol.rs | 2 +- src/websocket.rs | 6 -- src/weylus.rs | 2 +- 6 files changed, 165 insertions(+), 94 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6333268f..45e11c9c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,6 +11,12 @@ dependencies = [ "gimli", ] +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "adler2" version = "2.0.0" @@ -90,7 +96,7 @@ dependencies = [ "miniz_oxide 0.8.0", "object", "rustc-demangle", - "windows-targets", + "windows-targets 0.52.6", ] [[package]] @@ -110,6 +116,9 @@ name = "bitflags" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +dependencies = [ + "serde", +] [[package]] name = "block" @@ -138,6 +147,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + [[package]] name = "bytes" version = "1.7.2" @@ -169,12 +184,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "checked_int_cast" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17cc5e6b5ab06331c33589842070416baa137e8b0eb912b008cfd4a78ada7919" - [[package]] name = "clap" version = "2.34.0" @@ -370,16 +379,6 @@ dependencies = [ "byteorder", ] -[[package]] -name = "deflate" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174" -dependencies = [ - "adler32", - "byteorder", -] - [[package]] name = "digest" version = "0.10.7" @@ -392,22 +391,23 @@ dependencies = [ [[package]] name = "dirs" -version = "4.0.0" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" dependencies = [ "dirs-sys", ] [[package]] name = "dirs-sys" -version = "0.3.7" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" dependencies = [ "libc", + "option-ext", "redox_users", - "winapi", + "windows-sys 0.48.0", ] [[package]] @@ -442,6 +442,25 @@ dependencies = [ "utf-8", ] +[[package]] +name = "fdeflate" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "flate2" +version = "1.0.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" +dependencies = [ + "crc32fast", + "miniz_oxide 0.8.0", +] + [[package]] name = "fltk" version = "1.4.34" @@ -795,9 +814,9 @@ dependencies = [ [[package]] name = "handlebars" -version = "4.5.0" +version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faa67bab9ff362228eb3d00bd024a4965d8231bbb7921167f0cfa66c6626b225" +checksum = "ce25b617d1375ef96eeb920ae717e3da34a02fc979fe632c75128350f9e1f74a" dependencies = [ "log", "pest", @@ -960,17 +979,14 @@ dependencies = [ [[package]] name = "image" -version = "0.23.14" +version = "0.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1" +checksum = "99314c8a2152b8ddb211f924cdae532d8c5e4c8bb54728e12fff1b0cd5963a10" dependencies = [ "bytemuck", - "byteorder", - "color_quant", - "num-iter", - "num-rational 0.3.2", + "byteorder-lite", "num-traits", - "png 0.16.8", + "png 0.17.13", ] [[package]] @@ -1076,11 +1092,12 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "miniz_oxide" -version = "0.3.7" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ - "adler32", + "adler", + "simd-adler32", ] [[package]] @@ -1101,7 +1118,7 @@ dependencies = [ "hermit-abi 0.3.9", "libc", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -1168,17 +1185,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-rational" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - [[package]] name = "num-rational" version = "0.4.2" @@ -1232,6 +1238,12 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "option-operations" version = "0.4.1" @@ -1382,20 +1394,21 @@ checksum = "ef859a23054bbfee7811284275ae522f0434a3c8e7f4b74bd4a35ae7e1c4a283" dependencies = [ "bitflags 1.3.2", "crc32fast", - "deflate 0.7.20", + "deflate", "inflate", ] [[package]] name = "png" -version = "0.16.8" +version = "0.17.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6" +checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" dependencies = [ "bitflags 1.3.2", "crc32fast", - "deflate 0.8.6", - "miniz_oxide 0.3.7", + "fdeflate", + "flate2", + "miniz_oxide 0.7.4", ] [[package]] @@ -1467,12 +1480,11 @@ dependencies = [ [[package]] name = "qrcode" -version = "0.12.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16d2f1455f3630c6e5107b4f2b94e74d76dea80736de0981fd27644216cff57f" +checksum = "d68782463e408eb1e668cf6152704bd856c78c5b6417adaee3203d8f4c1fc9ec" dependencies = [ - "checked_int_cast", - "image 0.23.14", + "image 0.25.2", ] [[package]] @@ -1716,6 +1728,12 @@ dependencies = [ "libc", ] +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + [[package]] name = "simdutf8" version = "0.1.5" @@ -1744,7 +1762,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -1819,7 +1837,7 @@ dependencies = [ "cfg-expr", "heck 0.5.0", "pkg-config", - "toml 0.8.19", + "toml", "version-compare", ] @@ -1908,7 +1926,7 @@ dependencies = [ "pin-project-lite", "socket2", "tokio-macros", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -1935,15 +1953,6 @@ dependencies = [ "tokio", ] -[[package]] -name = "toml" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" -dependencies = [ - "serde", -] - [[package]] name = "toml" version = "0.8.19" @@ -2170,7 +2179,7 @@ name = "weylus" version = "0.11.4" dependencies = [ "autopilot", - "bitflags 1.3.2", + "bitflags 2.6.0", "bytes", "cc", "core-foundation 0.9.4", @@ -2187,7 +2196,7 @@ dependencies = [ "hyper", "hyper-util", "image 0.22.5", - "image 0.23.14", + "image 0.25.2", "num_cpus", "percent-encoding", "pnet_datalink", @@ -2197,7 +2206,7 @@ dependencies = [ "signal-hook", "structopt", "tokio", - "toml 0.5.11", + "toml", "tracing", "tracing-subscriber", "url", @@ -2225,13 +2234,37 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -2240,28 +2273,46 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -2274,24 +2325,48 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" diff --git a/Cargo.toml b/Cargo.toml index 1dc45eed..68d6f1db 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,28 +8,28 @@ description = "Use your iPad or Android tablet as graphic tablet." [dependencies] autopilot = { git = "https://github.com/H-M-H/autopilot-rs.git", rev = "63eed09c715bfb665bb23172a3930a528e11691c" } -bitflags = "^1.3" +bitflags = { version = "^2.6", features = ["serde"] } bytes = "1.7.1" -dirs = "^4.0" +dirs = "^5.0" fastwebsockets = { version = "0.8.0", features = ["upgrade", "unstable-split"] } fltk = { version = "^1", features = ["no-pango"] } -handlebars = "^4.1" +handlebars = "^6.1" http-body-util = "0.1.2" hyper = { version = "^1.4", features = ["server", "http1", "http2"] } hyper-util = { version = "0.1.8", features = ["tokio"] } -image = { version = "^0.23", features = ["png"], default-features = false } +image = { version = "^0.25", features = ["png"], default-features = false } image_autopilot = { package = "image", version = "0.22.5", features = [], default-features = false } percent-encoding = "2.1.0" -qrcode = "0.12.0" +qrcode = "0.14.0" serde = { version = "^1.0", features = ["derive"] } serde_json = "^1.0" signal-hook = "0.3.17" structopt = { version = "^0.3", features = ["color", "suggestions"], default-features = false } tokio = { version = "^1", features = ["fs", "macros", "rt-multi-thread", "sync"] } -toml = "^0.5" +toml = "^0.8" tracing = "^0.1" tracing-subscriber = { version = "^0.3", features = ["ansi", "json"], default-features = false } -url = "^2.2" +url = "^2.5" [build-dependencies] cc = "^1.0" diff --git a/src/gui.rs b/src/gui.rs index 328fb5ff..472a4c86 100644 --- a/src/gui.rs +++ b/src/gui.rs @@ -1,3 +1,4 @@ +use std::io::Cursor; use std::iter::Iterator; use std::net::{IpAddr, SocketAddr}; @@ -307,8 +308,9 @@ pub fn run(config: &Config, log_receiver: mpsc::Receiver) { image::imageops::FilterType::Nearest, ); let mut buf = vec![]; + let mut cursor = Cursor::new(&mut buf); image - .write_to(&mut buf, image::ImageOutputFormat::Png) + .write_to(&mut cursor, image::ImageFormat::Png) .unwrap(); let png = fltk::image::PngImage::from_data(&buf).unwrap(); diff --git a/src/protocol.rs b/src/protocol.rs index d578b169..ecf452aa 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -86,7 +86,7 @@ fn location_from<'de, D: Deserializer<'de>>(deserializer: D) -> Result(res: Result<(), SendError>) { - if let Err(err) = res { - warn!("Websocket: Failed to send message to ui: {}", err); - } -} - struct VideoConfig { capturable: Box, capture_cursor: bool, diff --git a/src/weylus.rs b/src/weylus.rs index 96125ab6..9c4dc6aa 100644 --- a/src/weylus.rs +++ b/src/weylus.rs @@ -1,5 +1,5 @@ use std::net::SocketAddr; -use std::sync::{mpsc, Arc}; +use std::sync::Arc; use tracing::error; use crate::config::Config; From 0ee8be2182a6db76639d37199acff3c1dfcf406c Mon Sep 17 00:00:00 2001 From: HMH Date: Tue, 24 Sep 2024 21:33:40 +0200 Subject: [PATCH 43/52] Update GitHub actions. --- .github/workflows/build.yml | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bf9089df..f4a47d4d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,12 +13,12 @@ jobs: runs-on: ubuntu-latest container: docker://hhmhh/weylus_build:latest steps: - - uses: actions/checkout@v3 - - uses: actions/cache@v3 + - uses: actions/checkout@v4 + - uses: actions/cache@v4 with: path: deps/dist* key: ${{ runner.os }}-deps-${{ hashFiles('deps/*') }} - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: | ~/.cargo/registry @@ -29,22 +29,22 @@ jobs: run: ./docker_build.sh shell: bash - name: Artifacts1 - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: linux path: packages/weylus-linux.zip - name: Artifacts2 - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: linux-deb path: packages/Weylus*.deb - name: Artifacts3 - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: windows path: packages/weylus-windows.zip - name: Publish - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v2 if: startsWith(github.ref, 'refs/tags/') with: files: | @@ -59,12 +59,12 @@ jobs: runs-on: ubuntu-latest container: docker://hhmhh/weylus_build_alpine:latest steps: - - uses: actions/checkout@v3 - - uses: actions/cache@v3 + - uses: actions/checkout@v4 + - uses: actions/cache@v4 with: path: deps/dist* key: ${{ runner.os }}-alpine-deps-${{ hashFiles('deps/*') }} - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: | ~/.cargo/registry @@ -75,12 +75,12 @@ jobs: run: cargo build --release && cd target/release && tar czf weylus-linux-alpine-musl.tar.gz weylus shell: bash - name: Artifacts1 - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: linux-alpine-musl path: target/release/weylus-linux-alpine-musl.tar.gz - name: Publish - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v2 if: startsWith(github.ref, 'refs/tags/') with: files: | @@ -92,12 +92,12 @@ jobs: build-macos: runs-on: macOS-latest steps: - - uses: actions/checkout@v3 - - uses: actions/cache@v3 + - uses: actions/checkout@v4 + - uses: actions/cache@v4 with: path: deps/dist key: ${{ runner.os }}-deps-${{ hashFiles('deps/*') }} - - uses: actions/cache@v3 + - uses: actions/cache@v4 with: path: | ~/.cargo/registry @@ -116,14 +116,14 @@ jobs: - name: Package run: cd target/release/bundle/osx/ && zip -r macOS.zip Weylus.app - name: Artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: ${{ runner.os }} path: | target/release/bundle/osx/macOS.zip - name: ArtifactsDebug if: failure() - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: ${{ runner.os }}-ffbuild path: | @@ -136,7 +136,7 @@ jobs: SSH_PASS: ${{ secrets.SSH_PASS }} NGROK_REGION: eu - name: Publish - uses: softprops/action-gh-release@v1 + uses: softprops/action-gh-release@v2 if: startsWith(github.ref, 'refs/tags/') with: files: | From 6bd33d9285d206edf589a33bf40133dcd21571c6 Mon Sep 17 00:00:00 2001 From: HMH Date: Tue, 24 Sep 2024 22:49:59 +0200 Subject: [PATCH 44/52] Change nvenc preset to p1. --- lib/encode_video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/encode_video.c b/lib/encode_video.c index 2299552e..9e5a07c4 100644 --- a/lib/encode_video.c +++ b/lib/encode_video.c @@ -310,7 +310,7 @@ void open_video(VideoContext* ctx, Error* err) if (ctx->c) { ctx->sw_pix_fmt = ctx->c->pix_fmt = AV_PIX_FMT_BGR0; - av_opt_set(ctx->c->priv_data, "preset", "fast", 0); + av_opt_set(ctx->c->priv_data, "preset", "p1", 0); av_opt_set(ctx->c->priv_data, "zerolatency", "1", 0); av_opt_set(ctx->c->priv_data, "tune", "ull", 0); av_opt_set(ctx->c->priv_data, "rc", "vbr", 0); From e1c05277fb912e6b61c2ae3b2ea52cac21d053d6 Mon Sep 17 00:00:00 2001 From: HMH Date: Tue, 24 Sep 2024 22:50:37 +0200 Subject: [PATCH 45/52] Handle XFixesGetCursorImage returning NULL. --- lib/linux/xcapture.c | 71 +++++++++++++++++++++++++------------------- 1 file changed, 40 insertions(+), 31 deletions(-) diff --git a/lib/linux/xcapture.c b/lib/linux/xcapture.c index cff81da6..743021e4 100644 --- a/lib/linux/xcapture.c +++ b/lib/linux/xcapture.c @@ -13,6 +13,7 @@ #include #include "../error.h" +#include "../log.h" #include "xhelper.h" int clamp(int x, int lb, int ub) @@ -226,43 +227,51 @@ void capture_screen(CaptureContext* ctx, struct Image* img, int capture_cursor, if (capture_cursor && ctx->has_xfixes) { XFixesCursorImage* cursor_img = XFixesGetCursorImage(ctx->cap.disp); - uint32_t* data = (uint32_t*)ctx->ximg->data; + if (cursor_img != NULL) + { + uint32_t* data = (uint32_t*)ctx->ximg->data; - // coordinates of cursor inside ximg - int x0 = cursor_img->x - cursor_img->xhot - x; - int y0 = cursor_img->y - cursor_img->yhot - y; + // coordinates of cursor inside ximg + int x0 = cursor_img->x - cursor_img->xhot - x; + int y0 = cursor_img->y - cursor_img->yhot - y; - // clamp part of cursor image to draw to the part of the cursor that is inside - // the captured area - int i0 = clamp(0, -x0, width - x0); - int i1 = clamp(cursor_img->width, -x0, width - x0); - int j0 = clamp(0, -y0, height - y0); - int j1 = clamp(cursor_img->height, -y0, height - y0); - // paint cursor image into captured image - for (int j = j0; j < j1; ++j) - for (int i = i0; i < i1; ++i) - { - uint32_t c_pixel = cursor_img->pixels[j * cursor_img->width + i]; - unsigned char a = (c_pixel & 0xff000000) >> 24; - if (a) + // clamp part of cursor image to draw to the part of the cursor that is inside + // the captured area + int i0 = clamp(0, -x0, width - x0); + int i1 = clamp(cursor_img->width, -x0, width - x0); + int j0 = clamp(0, -y0, height - y0); + int j1 = clamp(cursor_img->height, -y0, height - y0); + // paint cursor image into captured image + for (int j = j0; j < j1; ++j) + for (int i = i0; i < i1; ++i) { - uint32_t d_pixel = data[(j + y0) * width + i + x0]; + uint32_t c_pixel = cursor_img->pixels[j * cursor_img->width + i]; + unsigned char a = (c_pixel & 0xff000000) >> 24; + if (a) + { + uint32_t d_pixel = data[(j + y0) * width + i + x0]; - unsigned char c1 = (c_pixel & 0x00ff0000) >> 16; - unsigned char c2 = (c_pixel & 0x0000ff00) >> 8; - unsigned char c3 = (c_pixel & 0x000000ff) >> 0; - unsigned char d1 = (d_pixel & 0x00ff0000) >> 16; - unsigned char d2 = (d_pixel & 0x0000ff00) >> 8; - unsigned char d3 = (d_pixel & 0x000000ff) >> 0; - // colors from the cursor image are premultiplied with the alpha channel - unsigned char f1 = c1 + d1 * (255 - a) / 255; - unsigned char f2 = c2 + d2 * (255 - a) / 255; - unsigned char f3 = c3 + d3 * (255 - a) / 255; - data[(j + y0) * width + i + x0] = (f1 << 16) | (f2 << 8) | (f3 << 0); + unsigned char c1 = (c_pixel & 0x00ff0000) >> 16; + unsigned char c2 = (c_pixel & 0x0000ff00) >> 8; + unsigned char c3 = (c_pixel & 0x000000ff) >> 0; + unsigned char d1 = (d_pixel & 0x00ff0000) >> 16; + unsigned char d2 = (d_pixel & 0x0000ff00) >> 8; + unsigned char d3 = (d_pixel & 0x000000ff) >> 0; + // colors from the cursor image are premultiplied with the alpha channel + unsigned char f1 = c1 + d1 * (255 - a) / 255; + unsigned char f2 = c2 + d2 * (255 - a) / 255; + unsigned char f3 = c3 + d3 * (255 - a) / 255; + data[(j + y0) * width + i + x0] = (f1 << 16) | (f2 << 8) | (f3 << 0); + } } - } - XFree(cursor_img); + XFree(cursor_img); + } + else + { + log_warn( + "Failed to obtain cursor image, XFixesGetCursorImage has returned a null pointer."); + } } img->width = ctx->ximg->width; From f06a564504e823de0324f77742578c2916630222 Mon Sep 17 00:00:00 2001 From: HMH Date: Tue, 24 Sep 2024 22:51:59 +0200 Subject: [PATCH 46/52] Link crt (musl) dynamically on Alpine. --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f4a47d4d..d261324d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -72,7 +72,7 @@ jobs: target key: ${{ runner.os }}-alpine-cargo-${{ hashFiles('Cargo.lock') }} - name: Build - run: cargo build --release && cd target/release && tar czf weylus-linux-alpine-musl.tar.gz weylus + run: RUSTFLAGS='-C target-feature=-crt-static' cargo build --release && cd target/release && tar czf weylus-linux-alpine-musl.tar.gz weylus shell: bash - name: Artifacts1 uses: actions/upload-artifact@v4 From b50f1519857d8250343aec36a510b1053591ca9b Mon Sep 17 00:00:00 2001 From: HMH Date: Tue, 24 Sep 2024 23:18:08 +0200 Subject: [PATCH 47/52] Improve nvenc options. --- lib/encode_video.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/encode_video.c b/lib/encode_video.c index 9e5a07c4..68b96ab3 100644 --- a/lib/encode_video.c +++ b/lib/encode_video.c @@ -313,8 +313,9 @@ void open_video(VideoContext* ctx, Error* err) av_opt_set(ctx->c->priv_data, "preset", "p1", 0); av_opt_set(ctx->c->priv_data, "zerolatency", "1", 0); av_opt_set(ctx->c->priv_data, "tune", "ull", 0); - av_opt_set(ctx->c->priv_data, "rc", "vbr", 0); + av_opt_set(ctx->c->priv_data, "rc", "cbr", 0); av_opt_set(ctx->c->priv_data, "cq", "21", 0); + av_opt_set(ctx->c->priv_data, "delay", "0", 0); set_codec_params(ctx); int ret = avcodec_open2(ctx->c, codec, NULL); if (ret == 0) From 0ab42d5b3eb358ac2d309a061bbdd88e69fd9ad6 Mon Sep 17 00:00:00 2001 From: HMH Date: Wed, 25 Sep 2024 00:16:08 +0200 Subject: [PATCH 48/52] Remove websocket port from gui. --- src/config.rs | 2 -- src/gui.rs | 12 ++---------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/src/config.rs b/src/config.rs index 34879c39..1e582f82 100644 --- a/src/config.rs +++ b/src/config.rs @@ -14,8 +14,6 @@ pub struct Config { pub bind_address: IpAddr, #[structopt(long, default_value = "1701", help = "Web port")] pub web_port: u16, - #[structopt(long, default_value = "9001", help = "Websocket port")] - pub websocket_port: u16, #[cfg(target_os = "linux")] #[structopt( long, diff --git a/src/gui.rs b/src/gui.rs index 38fbec1c..5c476991 100644 --- a/src/gui.rs +++ b/src/gui.rs @@ -30,7 +30,7 @@ pub fn run(config: &Config, log_receiver: mpsc::Receiver) { let app = App::default().with_scheme(fltk::app::AppScheme::Gtk); let mut wind = Window::default() - .with_size(660, 620) + .with_size(660, 600) .center_screen() .with_label(&format!("Weylus - {}", env!("CARGO_PKG_VERSION"))); wind.set_xclass("weylus"); @@ -61,15 +61,9 @@ pub fn run(config: &Config, log_receiver: mpsc::Receiver) { .with_label("Port"); input_port.set_value(&config.web_port.to_string()); - let mut input_ws_port = IntInput::default() - .with_size(width, height) - .below_of(&input_port, padding) - .with_label("Websocket Port"); - input_ws_port.set_value(&config.websocket_port.to_string()); - let mut check_auto_start = CheckButton::default() .with_size(70, height) - .below_of(&input_ws_port, padding) + .below_of(&input_port, padding + 5) .with_label("Auto Start"); check_auto_start.set_tooltip("Start Weylus server immediately on program start."); check_auto_start.set_checked(config.auto_start); @@ -195,11 +189,9 @@ pub fn run(config: &Config, log_receiver: mpsc::Receiver) { }; let bind_addr: IpAddr = input_bind_addr.value().parse()?; let web_port: u16 = input_port.value().parse()?; - let ws_port: u16 = input_ws_port.value().parse()?; config.access_code = access_code.map(|s| s.to_string()); config.web_port = web_port; - config.websocket_port = ws_port; config.bind_address = bind_addr; config.auto_start = check_auto_start.is_checked(); #[cfg(target_os = "linux")] From 4c5dca5048911843857dacb2d9f5bd7661ecb63c Mon Sep 17 00:00:00 2001 From: HMH Date: Wed, 25 Sep 2024 13:51:52 +0200 Subject: [PATCH 49/52] Replace structopt with clap derive. --- Cargo.lock | 200 +++++++++++++++++++++++++++----------------------- Cargo.toml | 3 +- src/config.rs | 70 +++++++++--------- src/main.rs | 10 ++- 4 files changed, 157 insertions(+), 126 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a1df0af9..a0d35d58 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -30,12 +30,52 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" [[package]] -name = "ansi_term" -version = "0.12.1" +name = "anstream" +version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" dependencies = [ - "winapi", + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" + +[[package]] +name = "anstyle-parse" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", ] [[package]] @@ -50,17 +90,6 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", -] - [[package]] name = "autocfg" version = "1.3.0" @@ -196,18 +225,53 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "2.34.0" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +checksum = "b0956a43b323ac1afaffc053ed5c4b7c1f1800bacd1683c353aabbb752515dd3" dependencies = [ - "ansi_term", - "atty", - "bitflags 1.3.2", + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d72166dd41634086d5803a47eb71ae740e61d84709c36f3c34110173db3961b" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", "strsim", - "textwrap", - "unicode-width", ] +[[package]] +name = "clap_complete" +version = "4.5.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8937760c3f4c60871870b8c3ee5f9b30771f792a7045c48bcbba999d7d6b3b8e" +dependencies = [ + "clap", +] + +[[package]] +name = "clap_derive" +version = "4.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +dependencies = [ + "heck 0.5.0", + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", +] + +[[package]] +name = "clap_lex" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" + [[package]] name = "cmake" version = "0.1.51" @@ -238,6 +302,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" +[[package]] +name = "colorchoice" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" + [[package]] name = "core-foundation" version = "0.7.0" @@ -852,15 +922,6 @@ version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -[[package]] -name = "heck" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] - [[package]] name = "heck" version = "0.4.1" @@ -873,15 +934,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - [[package]] name = "hermit-abi" version = "0.3.9" @@ -1037,6 +1089,12 @@ dependencies = [ "serde", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + [[package]] name = "itoa" version = "1.0.11" @@ -1135,7 +1193,7 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ - "hermit-abi 0.3.9", + "hermit-abi", "libc", "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.52.0", @@ -1230,7 +1288,7 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.3.9", + "hermit-abi", "libc", ] @@ -1787,33 +1845,9 @@ dependencies = [ [[package]] name = "strsim" -version = "0.8.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - -[[package]] -name = "structopt" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" -dependencies = [ - "clap", - "lazy_static", - "structopt-derive", -] - -[[package]] -name = "structopt-derive" -version = "0.4.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" -dependencies = [ - "heck 0.3.3", - "proc-macro-error", - "proc-macro2 1.0.86", - "quote 1.0.37", - "syn 1.0.109", -] +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" @@ -1867,15 +1901,6 @@ version = "0.12.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - [[package]] name = "thiserror" version = "1.0.64" @@ -2120,18 +2145,6 @@ dependencies = [ "tinyvec", ] -[[package]] -name = "unicode-segmentation" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" - -[[package]] -name = "unicode-width" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" - [[package]] name = "unicode-xid" version = "0.1.0" @@ -2155,6 +2168,12 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "valuable" version = "0.1.0" @@ -2203,6 +2222,8 @@ dependencies = [ "bytes", "captrs", "cc", + "clap", + "clap_complete", "core-foundation 0.9.4", "core-graphics 0.22.3", "dbus", @@ -2225,7 +2246,6 @@ dependencies = [ "serde", "serde_json", "signal-hook", - "structopt", "tokio", "toml", "tracing", diff --git a/Cargo.toml b/Cargo.toml index 32ba39fe..4b30a73e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,8 @@ description = "Use your iPad or Android tablet as graphic tablet." autopilot = { git = "https://github.com/H-M-H/autopilot-rs.git", rev = "63eed09c715bfb665bb23172a3930a528e11691c" } bitflags = { version = "^2.6", features = ["serde"] } bytes = "1.7.1" +clap = { version = "4.5.18", features = ["derive"] } +clap_complete = "4.5.29" dirs = "^5.0" fastwebsockets = { version = "0.8.0", features = ["upgrade", "unstable-split"] } fltk = { version = "^1", features = ["no-pango"] } @@ -24,7 +26,6 @@ qrcode = "0.14.0" serde = { version = "^1.0", features = ["derive"] } serde_json = "^1.0" signal-hook = "0.3.17" -structopt = { version = "^0.3", features = ["color", "suggestions"], default-features = false } tokio = { version = "^1", features = ["fs", "macros", "rt-multi-thread", "sync"] } toml = "^0.8" tracing = "^0.1" diff --git a/src/config.rs b/src/config.rs index 1e582f82..927ae2a6 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,86 +1,86 @@ use std::net::IpAddr; use std::{fs, path::PathBuf}; +use clap::Parser; use serde::{Deserialize, Serialize}; -use structopt::StructOpt; -use tracing::warn; +use tracing::{debug, warn}; -#[derive(Serialize, Deserialize, StructOpt, Debug, Clone)] -#[structopt(name = "weylus")] +#[derive(Serialize, Deserialize, Parser, Debug, Clone)] +#[command(version, about, long_about = None)] pub struct Config { - #[structopt(long, help = "Access code")] + #[arg(long, help = "Access code")] pub access_code: Option, - #[structopt(long, default_value = "0.0.0.0", help = "Bind address")] + #[arg(long, default_value = "0.0.0.0", help = "Bind address")] pub bind_address: IpAddr, - #[structopt(long, default_value = "1701", help = "Web port")] + #[arg(long, default_value = "1701", help = "Web port")] pub web_port: u16, #[cfg(target_os = "linux")] - #[structopt( + #[arg( long, help = "Try to use hardware acceleration through the Video Acceleration API." )] pub try_vaapi: bool, #[cfg(any(target_os = "linux", target_os = "windows"))] - #[structopt(long, help = "Try to use Nvidia's NVENC to encode the video via GPU.")] + #[arg(long, help = "Try to use Nvidia's NVENC to encode the video via GPU.")] #[serde(default)] pub try_nvenc: bool, #[cfg(target_os = "macos")] - #[structopt( + #[arg( long, help = "Try to use hardware acceleration through the VideoToolbox API." )] #[serde(default)] pub try_videotoolbox: bool, #[cfg(target_os = "windows")] - #[structopt( + #[arg( long, help = "Try to use hardware acceleration through the MediaFoundation API." )] #[serde(default)] pub try_mediafoundation: bool, - #[structopt(long, help = "Start Weylus server immediately on program start.")] + #[arg(long, help = "Start Weylus server immediately on program start.")] #[serde(default)] pub auto_start: bool, - #[structopt(long, help = "Run Weylus without gui and start immediately.")] + #[arg(long, help = "Run Weylus without gui and start immediately.")] #[serde(default)] pub no_gui: bool, #[cfg(target_os = "linux")] - #[structopt(long, help = "Wayland/PipeWire Support.")] + #[arg(long, help = "Wayland/PipeWire Support.")] #[serde(default)] pub wayland_support: bool, - #[structopt(long, help = "Print template of index.html served by Weylus.")] + #[arg(long, help = "Print template of index.html served by Weylus.")] #[serde(skip)] pub print_index_html: bool, - #[structopt(long, help = "Print access.html served by Weylus.")] + #[arg(long, help = "Print access.html served by Weylus.")] #[serde(skip)] pub print_access_html: bool, - #[structopt(long, help = "Print style.css served by Weylus.")] + #[arg(long, help = "Print style.css served by Weylus.")] #[serde(skip)] pub print_style_css: bool, - #[structopt(long, help = "Print lib.js served by Weylus.")] + #[arg(long, help = "Print lib.js served by Weylus.")] #[serde(skip)] pub print_lib_js: bool, - #[structopt( + #[arg( long, help = "Use custom template of index.html to be served by Weylus." )] #[serde(skip)] pub custom_index_html: Option, - #[structopt(long, help = "Use custom access.html to be served by Weylus.")] + #[arg(long, help = "Use custom access.html to be served by Weylus.")] #[serde(skip)] pub custom_access_html: Option, - #[structopt(long, help = "Use custom style.css to be served by Weylus.")] + #[arg(long, help = "Use custom style.css to be served by Weylus.")] #[serde(skip)] pub custom_style_css: Option, - #[structopt(long, help = "Use custom lib.js to be served by Weylus.")] + #[arg(long, help = "Use custom lib.js to be served by Weylus.")] #[serde(skip)] pub custom_lib_js: Option, - #[structopt(long, help = "Print shell completions for given shell.")] + #[arg(long, help = "Print shell completions for given shell.")] #[serde(skip)] - pub completions: Option, + pub completions: Option, } pub fn read_config() -> Option { @@ -96,7 +96,12 @@ pub fn read_config() -> Option { } }, Err(err) => { - warn!("Failed to read configuration file: {}", err); + match err.kind() { + std::io::ErrorKind::NotFound => { + debug!("Failed to read configuration file: {}", err) + } + _ => warn!("Failed to read configuration file: {}", err), + } None } } @@ -130,14 +135,13 @@ pub fn write_config(conf: &Config) { } pub fn get_config() -> Config { - // TODO: once https://github.com/clap-rs/clap/issues/748 is resolved use - // the configfile to provide default values that override hardcoded defaults - - // read config from file if no args are specified - if std::env::args().len() == 1 { - // (ab)use parsing an empty args array to provide a default config - read_config().unwrap_or_else(crate::config::Config::from_args) + let args = std::env::args(); + if let Some(mut config) = read_config() { + if args.len() > 1 { + config.update_from(args); + } + config } else { - crate::config::Config::from_args() + Config::parse() } } diff --git a/src/main.rs b/src/main.rs index 9595858c..4a04d6e0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,6 +5,8 @@ extern crate test; #[macro_use] extern crate bitflags; +use clap::CommandFactory; +use clap_complete::generate; #[cfg(unix)] use signal_hook::iterator::Signals; use signal_hook::{consts::TERM_SIGNALS, low_level::signal_name}; @@ -13,7 +15,6 @@ use tracing::{error, info, warn}; use std::sync::mpsc; use config::{get_config, Config}; -use structopt::StructOpt; mod capturable; mod cerror; @@ -35,7 +36,12 @@ fn main() { let conf = get_config(); if let Some(shell) = conf.completions { - Config::clap().gen_completions_to("weylus", shell, &mut std::io::stdout()); + generate( + shell, + &mut Config::command(), + "weylus", + &mut std::io::stdout(), + ); return; } From 2312881e0011cf34ecd09d1614bc4ed3b1559bc2 Mon Sep 17 00:00:00 2001 From: HMH Date: Wed, 25 Sep 2024 14:24:50 +0200 Subject: [PATCH 50/52] Increase smoothness of pointer events. Sometimes events are merged, `getCoalescedEvents` provides all events in full resolution. --- ts/lib.ts | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/ts/lib.ts b/ts/lib.ts index ebef111a..9277cd3e 100644 --- a/ts/lib.ts +++ b/ts/lib.ts @@ -352,8 +352,7 @@ class PEvent { width: number; height: number; - constructor(eventType: string, event: PointerEvent, target: HTMLElement) { - let targetRect = target.getBoundingClientRect(); + constructor(eventType: string, event: PointerEvent, targetRect: DOMRect) { let diag_len = Math.sqrt(targetRect.width * targetRect.width + targetRect.height * targetRect.height) this.event_type = eventType.toString(); this.pointer_id = event.pointerId; @@ -580,7 +579,9 @@ class Painter { onmove(event: PointerEvent) { if (this.lines_active.has(event.pointerId)) - this.appendEventToLine(event); + for (const e of event.getCoalescedEvents()) { + this.appendEventToLine(e); + } } onstop(event: PointerEvent) { @@ -639,17 +640,21 @@ class PointerHandler { onEvent(event: PointerEvent, event_type: string) { if (this.pointerTypes.includes(event.pointerType)) { - this.webSocket.send( - JSON.stringify( - { - "PointerEvent": new PEvent( - event_type, - event, - event.target as HTMLElement - ) - } - ) - ); + let rect = (event.target as HTMLElement).getBoundingClientRect(); + const events = event_type === "pointermove" ? event.getCoalescedEvents() : [event]; + for (let event of events) { + this.webSocket.send( + JSON.stringify( + { + "PointerEvent": new PEvent( + event_type, + event, + rect + ) + } + ) + ); + } if (settings.visible) { settings.toggle(); } From a5c6be587f7a69f8471b254d9a6e3b1228068a14 Mon Sep 17 00:00:00 2001 From: HMH Date: Wed, 25 Sep 2024 17:26:59 +0200 Subject: [PATCH 51/52] Add theme selection and auto resize qr code. --- Cargo.lock | 10 +++++++ Cargo.toml | 3 ++- src/config.rs | 66 ++++++++++++++++++++++++++++++++++++++++++++++ src/gui.rs | 72 ++++++++++++++++++++++++++++++++++++++------------- ts/lib.ts | 8 +++--- 5 files changed, 137 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a0d35d58..a0881c65 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -574,6 +574,15 @@ dependencies = [ "cmake", ] +[[package]] +name = "fltk-theme" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03302d43154c9c51b4297a96f40c85ea913bb15ea27b6a38665284ddae8ac3d7" +dependencies = [ + "fltk", +] + [[package]] name = "fnv" version = "1.0.7" @@ -2230,6 +2239,7 @@ dependencies = [ "dirs", "fastwebsockets", "fltk", + "fltk-theme", "gstreamer", "gstreamer-app", "gstreamer-video", diff --git a/Cargo.toml b/Cargo.toml index 4b30a73e..93d53087 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,8 @@ clap = { version = "4.5.18", features = ["derive"] } clap_complete = "4.5.29" dirs = "^5.0" fastwebsockets = { version = "0.8.0", features = ["upgrade", "unstable-split"] } -fltk = { version = "^1", features = ["no-pango"] } +fltk = { version = "^1" } +fltk-theme = "0.7.3" handlebars = "^6.1" http-body-util = "0.1.2" hyper = { version = "^1.4", features = ["server", "http1", "http2"] } diff --git a/src/config.rs b/src/config.rs index 927ae2a6..b2b26878 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,10 +1,74 @@ use std::net::IpAddr; +use std::str::FromStr; use std::{fs, path::PathBuf}; use clap::Parser; use serde::{Deserialize, Serialize}; use tracing::{debug, warn}; +#[derive(clap::ValueEnum, Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq)] +pub enum ThemeType { + Aero, + AquaClassic, + Blue, + Classic, + Dark, + Greybird, + HighContrast, + Metro, +} + +const THEME_LIST: [ThemeType; 8] = [ + ThemeType::Aero, + ThemeType::AquaClassic, + ThemeType::Blue, + ThemeType::Classic, + ThemeType::Dark, + ThemeType::Greybird, + ThemeType::HighContrast, + ThemeType::Metro, +]; + +impl Default for ThemeType { + fn default() -> Self { + Self::Greybird + } +} + +impl ThemeType { + pub fn apply(&self) { + let theme = match self { + ThemeType::Classic => fltk_theme::ThemeType::Classic, + ThemeType::Aero => fltk_theme::ThemeType::Aero, + ThemeType::Metro => fltk_theme::ThemeType::Metro, + ThemeType::AquaClassic => fltk_theme::ThemeType::AquaClassic, + ThemeType::Greybird => fltk_theme::ThemeType::Greybird, + ThemeType::Blue => fltk_theme::ThemeType::Blue, + ThemeType::Dark => fltk_theme::ThemeType::Dark, + ThemeType::HighContrast => fltk_theme::ThemeType::HighContrast, + }; + let theme = fltk_theme::WidgetTheme::new(theme); + theme.apply(); + } + + pub fn name(&self) -> String { + format!("{self:?}") + } + + pub fn to_index(&self) -> i32 { + THEME_LIST.iter().position(|th| th == self).unwrap() as i32 + } + + pub fn from_index(i: i32) -> Self { + let i = i.clamp(0, THEME_LIST.len() as i32 - 1) as usize; + THEME_LIST[i] + } + + pub fn themes() -> &'static [ThemeType] { + &THEME_LIST + } +} + #[derive(Serialize, Deserialize, Parser, Debug, Clone)] #[command(version, about, long_about = None)] pub struct Config { @@ -41,6 +105,8 @@ pub struct Config { #[arg(long, help = "Start Weylus server immediately on program start.")] #[serde(default)] pub auto_start: bool, + #[arg(long, help = "Gui Theme")] + pub gui_theme: Option, #[arg(long, help = "Run Weylus without gui and start immediately.")] #[serde(default)] pub no_gui: bool, diff --git a/src/gui.rs b/src/gui.rs index 5c476991..99bbfd42 100644 --- a/src/gui.rs +++ b/src/gui.rs @@ -3,6 +3,8 @@ use std::io::Cursor; use std::iter::Iterator; use std::net::{IpAddr, SocketAddr}; +use fltk::image::PngImage; +use fltk::menu::Choice; use std::sync::{mpsc, Arc, Mutex}; use tracing::{error, info}; @@ -20,7 +22,7 @@ use fltk::{ #[cfg(not(target_os = "windows"))] use pnet_datalink as datalink; -use crate::config::{write_config, Config}; +use crate::config::{write_config, Config, ThemeType}; use crate::web::Web2UiMessage::UInputInaccessible; pub fn run(config: &Config, log_receiver: mpsc::Receiver) { @@ -29,6 +31,7 @@ pub fn run(config: &Config, log_receiver: mpsc::Receiver) { let padding = 10; let app = App::default().with_scheme(fltk::app::AppScheme::Gtk); + config.gui_theme.map(|th| th.apply()); let mut wind = Window::default() .with_size(660, 600) .center_screen() @@ -154,10 +157,19 @@ pub fn run(config: &Config, log_receiver: mpsc::Receiver) { output.set_buffer(output_buf); let output_buf = output.buffer().unwrap(); - let mut qr_frame = Frame::default() - .with_size(240, 240) + let mut choice_theme = Choice::default() + .with_size(width, height) .right_of(&input_access_code, padding); + for theme in ThemeType::themes() { + choice_theme.add_choice(&theme.name()); + } + choice_theme.set_value(config.gui_theme.unwrap_or(ThemeType::default()).to_index()); + + let mut qr_frame = Frame::default() + .with_size(235, 235) + .right_of(&input_bind_addr, padding); + qr_frame.hide(); wind.make_resizable(true); @@ -176,10 +188,23 @@ pub fn run(config: &Config, log_receiver: mpsc::Receiver) { let mut weylus = crate::weylus::Weylus::new(); let mut is_server_running = false; let auto_start = config.auto_start; - let mut config = config.clone(); + let config = Arc::new(Mutex::new(config.clone())); + + { + let config = config.clone(); + choice_theme.set_callback(move |c| { + let v = c.value(); + if v >= 0 { + ThemeType::from_index(v).apply(); + config.lock().unwrap().gui_theme = Some(ThemeType::from_index(v)); + write_config(&config.lock().unwrap()); + } + }); + } let mut toggle_server = move |but: &mut Button| { if let Err(err) = || -> Result<(), Box> { + let mut config = config.lock().unwrap(); if !is_server_running { { let access_code_string = input_access_code.value(); @@ -194,6 +219,7 @@ pub fn run(config: &Config, log_receiver: mpsc::Receiver) { config.web_port = web_port; config.bind_address = bind_addr; config.auto_start = check_auto_start.is_checked(); + config.gui_theme = Some(ThemeType::from_index(choice_theme.value())); #[cfg(target_os = "linux")] { config.try_vaapi = check_native_hw_accel.is_checked(); @@ -291,20 +317,29 @@ pub fn run(config: &Config, log_receiver: mpsc::Receiver) { .to_string(), ); } - let code = QrCode::new(&url_string).unwrap(); - let img_buf = code.render::>().build(); - let image = image::DynamicImage::ImageLuma8(img_buf); - let dims = min(qr_frame.width(), qr_frame.height()) as u32; - let image = - image.resize_exact(dims, dims, image::imageops::FilterType::Nearest); - let mut buf = vec![]; - let mut cursor = Cursor::new(&mut buf); - image - .write_to(&mut cursor, image::ImageFormat::Png) - .unwrap(); - let png = fltk::image::PngImage::from_data(&buf).unwrap(); - - qr_frame.set_image(Some(png)); + + let cb = move |qr_frame: &mut Frame, _, _, w, h| { + let code = QrCode::new(&url_string).unwrap(); + let img_buf = code.render::>().build(); + let image = image::DynamicImage::ImageLuma8(img_buf); + let dims = min(w, h) as u32; + let image = + image.resize_exact(dims, dims, image::imageops::FilterType::Nearest); + let mut buf = vec![]; + let mut cursor = Cursor::new(&mut buf); + image + .write_to(&mut cursor, image::ImageFormat::Png) + .unwrap(); + let png = fltk::image::PngImage::from_data(&buf).unwrap(); + qr_frame.set_image(Some(png)); + }; + + let x = qr_frame.x(); + let y = qr_frame.y(); + let w = qr_frame.width(); + let h = qr_frame.height(); + cb(&mut qr_frame, x, y, w, h); + qr_frame.resize_callback(cb); qr_frame.show(); } #[cfg(target_os = "windows")] @@ -321,6 +356,7 @@ pub fn run(config: &Config, log_receiver: mpsc::Receiver) { weylus.stop(); but.set_label("Start"); output_server_addr.hide(); + qr_frame.resize_callback(|_, _, _, _, _| {}); qr_frame.hide(); is_server_running = false; } diff --git a/ts/lib.ts b/ts/lib.ts index 9277cd3e..28899754 100644 --- a/ts/lib.ts +++ b/ts/lib.ts @@ -578,10 +578,12 @@ class Painter { } onmove(event: PointerEvent) { - if (this.lines_active.has(event.pointerId)) - for (const e of event.getCoalescedEvents()) { + if (this.lines_active.has(event.pointerId)) { + const events = typeof event.getCoalescedEvents === 'function' ? event.getCoalescedEvents() : [event]; + for (const e of events) { this.appendEventToLine(e); } + } } onstop(event: PointerEvent) { @@ -641,7 +643,7 @@ class PointerHandler { onEvent(event: PointerEvent, event_type: string) { if (this.pointerTypes.includes(event.pointerType)) { let rect = (event.target as HTMLElement).getBoundingClientRect(); - const events = event_type === "pointermove" ? event.getCoalescedEvents() : [event]; + const events = event_type === "pointermove" && typeof event.getCoalescedEvents === 'function' ? event.getCoalescedEvents() : [event]; for (let event of events) { this.webSocket.send( JSON.stringify( From 461a73caa4b15ab39536d7fc0079d5813096194f Mon Sep 17 00:00:00 2001 From: HMH Date: Wed, 25 Sep 2024 18:15:34 +0200 Subject: [PATCH 52/52] Update some more deps. --- Cargo.lock | 287 ++++++++++++++++++------------------- Cargo.toml | 16 +-- src/capturable/pipewire.rs | 14 +- 3 files changed, 154 insertions(+), 163 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a0881c65..90adfd5b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -78,18 +78,18 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "anyhow" -version = "1.0.89" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" - [[package]] name = "atomic-waker" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +[[package]] +name = "atomic_refcell" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41e67cd8309bbd06cd603a9e693a784ac2e5d1e955f11286e355089fcab3047c" + [[package]] name = "autocfg" version = "1.3.0" @@ -209,9 +209,9 @@ dependencies = [ [[package]] name = "cfg-expr" -version = "0.15.8" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" +checksum = "d0890061c4d3223e7267f3bad2ec40b997d64faac1c2815a4a9d95018e2b9e9c" dependencies = [ "smallvec", "target-lexicon", @@ -260,7 +260,7 @@ version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ - "heck 0.5.0", + "heck", "proc-macro2 1.0.86", "quote 1.0.37", "syn 2.0.77", @@ -291,7 +291,7 @@ dependencies = [ "block", "core-foundation 0.7.0", "core-graphics 0.19.2", - "foreign-types", + "foreign-types 0.3.2", "libc", "objc", ] @@ -320,9 +320,9 @@ dependencies = [ [[package]] name = "core-foundation" -version = "0.9.4" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" dependencies = [ "core-foundation-sys 0.8.7", "libc", @@ -348,31 +348,31 @@ checksum = "b3889374e6ea6ab25dba90bb5d96202f61108058361f6dc72e8b03e6f8bbe923" dependencies = [ "bitflags 1.3.2", "core-foundation 0.7.0", - "foreign-types", + "foreign-types 0.3.2", "libc", ] [[package]] name = "core-graphics" -version = "0.22.3" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" +checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" dependencies = [ - "bitflags 1.3.2", - "core-foundation 0.9.4", + "bitflags 2.6.0", + "core-foundation 0.10.0", "core-graphics-types", - "foreign-types", + "foreign-types 0.5.0", "libc", ] [[package]] name = "core-graphics-types" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" dependencies = [ - "bitflags 1.3.2", - "core-foundation 0.9.4", + "bitflags 2.6.0", + "core-foundation 0.10.0", "libc", ] @@ -595,7 +595,28 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" dependencies = [ - "foreign-types-shared", + "foreign-types-shared 0.1.1", +] + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared 0.3.1", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", ] [[package]] @@ -604,6 +625,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -639,6 +666,17 @@ dependencies = [ "futures-util", ] +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2 1.0.86", + "quote 1.0.37", + "syn 2.0.77", +] + [[package]] name = "futures-sink" version = "0.3.30" @@ -658,6 +696,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-core", + "futures-macro", "futures-task", "pin-project-lite", "pin-utils", @@ -712,46 +751,58 @@ version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" +[[package]] +name = "gio-sys" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5237611e97e9b86ab5768adc3eef853ae713ea797aa3835404acdfacffc9fb38" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", + "windows-sys 0.52.0", +] + [[package]] name = "glib" -version = "0.15.12" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edb0306fbad0ab5428b0ca674a23893db909a98582969c9b537be4ced78c505d" +checksum = "95648aac01b75503000bb3bcaa5ec7a7a2dd61e43636b8b1814854de94dd80e4" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "futures-channel", "futures-core", "futures-executor", "futures-task", + "futures-util", + "gio-sys", "glib-macros", "glib-sys", "gobject-sys", "libc", - "once_cell", + "memchr", "smallvec", - "thiserror", ] [[package]] name = "glib-macros" -version = "0.15.13" +version = "0.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10c6ae9f6fa26f4fb2ac16b528d138d971ead56141de489f8111e259b9df3c4a" +checksum = "302f1d633c9cdef4350330e7b68fd8016e2834bb106c93fdf9789fcde753c1ab" dependencies = [ - "anyhow", - "heck 0.4.1", + "heck", "proc-macro-crate", - "proc-macro-error", "proc-macro2 1.0.86", "quote 1.0.37", - "syn 1.0.109", + "syn 2.0.77", ] [[package]] name = "glib-sys" -version = "0.15.10" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef4b192f8e65e9cf76cbf4ea71fa8e3be4a0e18ffe3d68b8da6836974cc5bad4" +checksum = "92eee4531c1c9abba945d19378b205031b5890e1f99c319ba0503b6e0c06a163" dependencies = [ "libc", "system-deps", @@ -759,9 +810,9 @@ dependencies = [ [[package]] name = "gobject-sys" -version = "0.15.10" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d57ce44246becd17153bd035ab4d32cfee096a657fc01f2231c9278378d1e0a" +checksum = "fa3d1dcd8a1eb2e7c22be3d5e792b14b186f3524f79b25631730f9a8c169d49a" dependencies = [ "glib-sys", "libc", @@ -770,17 +821,17 @@ dependencies = [ [[package]] name = "gstreamer" -version = "0.18.8" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66363bacf5e4f6eb281564adc2902e44c52ae5c45082423e7439e9012b75456" +checksum = "683e15f8cc3a1a2646d9fe2181a58b7abb4c166256d8d15cce368e420c741140" dependencies = [ - "bitflags 1.3.2", "cfg-if", "futures-channel", "futures-core", "futures-util", "glib", "gstreamer-sys", + "itertools", "libc", "muldiv", "num-integer", @@ -788,17 +839,17 @@ dependencies = [ "once_cell", "option-operations", "paste", - "pretty-hex", + "pin-project-lite", + "smallvec", "thiserror", ] [[package]] name = "gstreamer-app" -version = "0.18.7" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "664adf6abc6546c1ad54492a067dcbc605032c9c789ce8f6f78cb9ddeef4b684" +checksum = "e0c86915cc4cdfa030532301a46c725e0ce0c6c2b57a68c44ce9b34db587e552" dependencies = [ - "bitflags 1.3.2", "futures-core", "futures-sink", "glib", @@ -806,14 +857,13 @@ dependencies = [ "gstreamer-app-sys", "gstreamer-base", "libc", - "once_cell", ] [[package]] name = "gstreamer-app-sys" -version = "0.18.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3b401f21d731b3e5de802487f25507fabd34de2dd007d582f440fb1c66a4fbb" +checksum = "37066c1b93ba57aa070ebc1e0a564bc1a9adda78fb0850e624861fad46fd1448" dependencies = [ "glib-sys", "gstreamer-base-sys", @@ -824,11 +874,11 @@ dependencies = [ [[package]] name = "gstreamer-base" -version = "0.18.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224f35f36582407caf58ded74854526beeecc23d0cf64b8d1c3e00584ed6863f" +checksum = "ed5d73cb5cbf229c8904fba5ff93b1863f186bccc062064c1b2a9000750cc06e" dependencies = [ - "bitflags 1.3.2", + "atomic_refcell", "cfg-if", "glib", "gstreamer", @@ -838,9 +888,9 @@ dependencies = [ [[package]] name = "gstreamer-base-sys" -version = "0.18.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a083493c3c340e71fa7c66eebda016e9fafc03eb1b4804cf9b2bad61994b078e" +checksum = "4a6643ef963c636b8022adc93aa19eac6f356bd174a187c499339fc5d64c1e05" dependencies = [ "glib-sys", "gobject-sys", @@ -851,9 +901,9 @@ dependencies = [ [[package]] name = "gstreamer-sys" -version = "0.18.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3517a65d3c2e6f8905b456eba5d53bda158d664863aef960b44f651cb7d33e2" +checksum = "d9c9005b55dd2b1784645963c1ec409f9d420a56f6348d0ae69c2eaff584bcc3" dependencies = [ "glib-sys", "gobject-sys", @@ -863,11 +913,10 @@ dependencies = [ [[package]] name = "gstreamer-video" -version = "0.18.7" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9418adfc72dafa1ad9eb106527ce4804887d101027c4528ec28c7d29cc899519" +checksum = "57332bca1ae7825a53fe57d993b63389f132d335aed691ac76f0ffe4304548e3" dependencies = [ - "bitflags 1.3.2", "cfg-if", "futures-channel", "glib", @@ -876,13 +925,14 @@ dependencies = [ "gstreamer-video-sys", "libc", "once_cell", + "thiserror", ] [[package]] name = "gstreamer-video-sys" -version = "0.18.3" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33331b1675e73b5b000c796354278eca7fdde9327015971d9f41afe28b96e0dc" +checksum = "0f5c334d143384e8dc714af948c2e5d7d12cb588fdcfb56f3bf37c24daf350ef" dependencies = [ "glib-sys", "gobject-sys", @@ -931,12 +981,6 @@ version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - [[package]] name = "heck" version = "0.5.0" @@ -1091,9 +1135,9 @@ dependencies = [ [[package]] name = "ipnetwork" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f84f1612606f3753f205a4e9a2efd6fe5b4c573a6269b2cc6c3003d44a0d127" +checksum = "bf466541e9d546596ee94f9f69590f89473455f88372423e0008fc1a7daf100e" dependencies = [ "serde", ] @@ -1104,6 +1148,15 @@ version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.11" @@ -1333,9 +1386,9 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "option-operations" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42b01597916c91a493b1e8a2fde64fec1764be3259abc1f06efc99c274f150a2" +checksum = "7c26d27bb1aeab65138e4bf7666045169d1717febcc9ff870166be8348b223d0" dependencies = [ "paste", ] @@ -1443,18 +1496,18 @@ checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "pnet_base" -version = "0.31.0" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d3a993d49e5fd5d4d854d6999d4addca1f72d86c65adf224a36757161c02b6" +checksum = "ffc190d4067df16af3aba49b3b74c469e611cad6314676eaf1157f31aa0fb2f7" dependencies = [ "no-std-net", ] [[package]] name = "pnet_datalink" -version = "0.31.0" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e466faf03a98ad27f6e15cd27a2b7cc89e73e640a43527742977bc503c37f8aa" +checksum = "e79e70ec0be163102a332e1d2d5586d362ad76b01cec86f830241f2b6452a7b7" dependencies = [ "ipnetwork", "libc", @@ -1465,9 +1518,9 @@ dependencies = [ [[package]] name = "pnet_sys" -version = "0.31.0" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "328e231f0add6d247d82421bf3790b4b33b39c8930637f428eef24c4c6a90805" +checksum = "7d4643d3d4db6b08741050c2f3afa9a892c4244c085a72fcda93c9c2c9a00f4b" dependencies = [ "libc", "winapi", @@ -1507,44 +1560,13 @@ dependencies = [ "zerocopy", ] -[[package]] -name = "pretty-hex" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6fa0831dd7cc608c38a5e323422a0077678fa5744aa2be4ad91c4ece8eec8d5" - [[package]] name = "proc-macro-crate" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" -dependencies = [ - "once_cell", - "toml_edit 0.19.15", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2 1.0.86", - "quote 1.0.37", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" dependencies = [ - "proc-macro2 1.0.86", - "quote 1.0.37", - "version_check", + "toml_edit", ] [[package]] @@ -1869,17 +1891,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2 1.0.86", - "quote 1.0.37", - "unicode-ident", -] - [[package]] name = "syn" version = "2.0.77" @@ -1893,12 +1904,12 @@ dependencies = [ [[package]] name = "system-deps" -version = "6.2.2" +version = "7.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" +checksum = "66d23aaf9f331227789a99e8de4c91bf46703add012bdfd45fdecdfb2975a005" dependencies = [ "cfg-expr", - "heck 0.5.0", + "heck", "pkg-config", "toml", "version-compare", @@ -2016,7 +2027,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.22", + "toml_edit", ] [[package]] @@ -2028,17 +2039,6 @@ dependencies = [ "serde", ] -[[package]] -name = "toml_edit" -version = "0.19.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" -dependencies = [ - "indexmap", - "toml_datetime", - "winnow 0.5.40", -] - [[package]] name = "toml_edit" version = "0.22.22" @@ -2049,7 +2049,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.19", + "winnow", ] [[package]] @@ -2233,8 +2233,8 @@ dependencies = [ "cc", "clap", "clap_complete", - "core-foundation 0.9.4", - "core-graphics 0.22.3", + "core-foundation 0.10.0", + "core-graphics 0.24.0", "dbus", "dirs", "fastwebsockets", @@ -2426,15 +2426,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "winnow" -version = "0.5.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" -dependencies = [ - "memchr", -] - [[package]] name = "winnow" version = "0.6.19" diff --git a/Cargo.toml b/Cargo.toml index 93d53087..b3e6c92f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,21 +39,21 @@ wio = "0.2.2" captrs = "^0.3.1" [build-dependencies] -cc = "^1.0" -num_cpus = "^1.13" +cc = "^1.1" +num_cpus = "^1.16" [target.'cfg(target_os = "linux")'.dependencies] dbus = "^0.9" -gstreamer = "^0.18" -gstreamer-app = { version = "^0.18", features = ["v1_10"] } -gstreamer-video = "^0.18" +gstreamer = "^0.23" +gstreamer-app = { version = "^0.23", features = ["v1_16"] } +gstreamer-video = "^0.23" [target.'cfg(not(target_os = "windows"))'.dependencies] -pnet_datalink = "^0.31" +pnet_datalink = "^0.35" [target.'cfg(target_os = "macos")'.dependencies] -core-foundation = "^0.9" -core-graphics = "^0.22" +core-foundation = "^0.10" +core-graphics = "^0.24" [features] bench = [] diff --git a/src/capturable/pipewire.rs b/src/capturable/pipewire.rs index 09a6674e..8acc02d2 100644 --- a/src/capturable/pipewire.rs +++ b/src/capturable/pipewire.rs @@ -122,9 +122,9 @@ pub struct PipeWireRecorder { impl PipeWireRecorder { pub fn new(capturable: PipeWireCapturable) -> Result> { - let pipeline = gst::Pipeline::new(None); + let pipeline = gst::Pipeline::new(); - let src = gst::ElementFactory::make("pipewiresrc", None)?; + let src = gst::ElementFactory::make("pipewiresrc").build()?; src.set_property("fd", &capturable.fd.as_raw_fd()); src.set_property("path", &format!("{}", capturable.path)); @@ -132,7 +132,7 @@ impl PipeWireRecorder { // see: https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/982 src.set_property("always-copy", &true); - let sink = gst::ElementFactory::make("appsink", None)?; + let sink = gst::ElementFactory::make("appsink").build()?; sink.set_property("drop", &true); sink.set_property("max-buffers", &1u32); @@ -142,13 +142,13 @@ impl PipeWireRecorder { .dynamic_cast::() .map_err(|_| GStreamerError("Sink element is expected to be an appsink!".into()))?; let mut caps = gst::Caps::new_empty(); - caps.merge_structure(gst::structure::Structure::new( + caps.merge_structure(gst::structure::Structure::from_iter( "video/x-raw", - &[("format", &"BGRx")], + [("format", "BGRx".into())], )); - caps.merge_structure(gst::structure::Structure::new( + caps.merge_structure(gst::structure::Structure::from_iter( "video/x-raw", - &[("format", &"RGBx")], + [("format", "RGBx".into())], )); appsink.set_caps(Some(&caps));