diff --git a/build.py b/build.py index fb9e213db..cc00c0793 100755 --- a/build.py +++ b/build.py @@ -41,8 +41,8 @@ def get_version(): def parse_rc_features(feature): available_features = { 'IddDriver': { - 'zip_url': 'https://github.com/fufesou/RustDeskIddDriver/releases/download/v0.1/RustDeskIddDriver_x64.zip', - 'checksum_url': 'https://github.com/fufesou/RustDeskIddDriver/releases/download/v0.1/checksum_md5', + 'zip_url': 'https://github.com/fufesou/RustDeskIddDriver/releases/download/v0.3/RustDeskIddDriver_x64.zip', + 'checksum_url': 'https://github.com/fufesou/RustDeskIddDriver/releases/download/v0.3/checksum_md5', 'exclude': ['README.md', 'certmgr.exe', 'install_cert_runas_admin.bat'], }, 'PrivacyMode': { diff --git a/libs/hbb_common/src/config.rs b/libs/hbb_common/src/config.rs index 8786858e2..369920982 100644 --- a/libs/hbb_common/src/config.rs +++ b/libs/hbb_common/src/config.rs @@ -1141,8 +1141,6 @@ pub struct LocalConfig { // Various data for flutter ui #[serde(default)] ui_flutter: HashMap, - #[serde(default)] - virtual_display_num: usize, } impl LocalConfig { @@ -1245,19 +1243,6 @@ impl LocalConfig { config.store(); } } - - pub fn get_virtual_display_num() -> usize { - LOCAL_CONFIG.read().unwrap().virtual_display_num - } - - pub fn set_virtual_display_num(virtual_display_num: usize) { - let mut lock = LOCAL_CONFIG.write().unwrap(); - if lock.virtual_display_num == virtual_display_num { - return; - } - lock.virtual_display_num = virtual_display_num; - lock.store(); - } } #[derive(Debug, Default, Serialize, Deserialize, Clone)] diff --git a/libs/virtual_display/examples/virtual_display_1.rs b/libs/virtual_display/examples/virtual_display_1.rs index 1471e3faf..e5e1ae554 100644 --- a/libs/virtual_display/examples/virtual_display_1.rs +++ b/libs/virtual_display/examples/virtual_display_1.rs @@ -3,7 +3,7 @@ use virtual_display; fn prompt_input() -> u8 { println!("Press key execute:"); - println!(" 1. 'x' 1. exit"); + println!(" 1. 'q' 1. quit"); println!(" 2. 'i' 2. install or update driver"); println!(" 3. 'u' 3. uninstall driver"); println!(" 4. 'c' 4. create device"); @@ -40,7 +40,7 @@ fn main() { loop { let chr = prompt_input(); match chr as char { - 'x' => break, + 'q' => break, 'i' => { println!("Install or update driver begin"); let mut reboot_required = false; diff --git a/libs/virtual_display/src/lib.rs b/libs/virtual_display/src/lib.rs index f7e904537..578ffa2e9 100644 --- a/libs/virtual_display/src/lib.rs +++ b/libs/virtual_display/src/lib.rs @@ -47,7 +47,10 @@ macro_rules! make_lib_wrapper { $(let $field = if let Some(lib) = &lib { match unsafe { lib.symbol::<$tp>(stringify!($field)) } { - Ok(m) => Some(*m), + Ok(m) => { + log::info!("method found {}", stringify!($field)); + Some(*m) + }, Err(e) => { log::warn!("Failed to load func {}, {}", stringify!($field), e); None diff --git a/src/lib.rs b/src/lib.rs index f52fbd1da..52e9fcd5d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -69,3 +69,6 @@ pub mod rc; #[cfg(not(any(target_os = "android", target_os = "ios")))] pub mod privacy_win_mag; + +#[cfg(all(windows, feature = "virtual_display_driver"))] +pub mod virtual_display_manager; diff --git a/src/server/video_service.rs b/src/server/video_service.rs index 4789d4fd6..e6f29a405 100644 --- a/src/server/video_service.rs +++ b/src/server/video_service.rs @@ -19,10 +19,10 @@ // https://slhck.info/video/2017/03/01/rate-control.html use super::{video_qos::VideoQoS, *}; +#[cfg(all(windows, feature = "virtual_display_driver"))] +use crate::virtual_display_manager; #[cfg(windows)] use crate::{platform::windows::is_process_consent_running, privacy_win_mag}; -#[cfg(all(windows, feature = "virtual_display_driver"))] -use hbb_common::config::LocalConfig; #[cfg(windows)] use hbb_common::get_version_number; use hbb_common::tokio::sync::{ @@ -45,11 +45,6 @@ use std::{ ops::{Deref, DerefMut}, time::{self, Duration, Instant}, }; -#[cfg(all(windows, feature = "virtual_display_driver"))] -use virtual_display; - -#[cfg(all(windows, feature = "virtual_display_driver"))] -const VIRTUAL_DISPLAY_INDEX_FOR_HEADLESS: u32 = 0; pub const SCRAP_UBUNTU_HIGHER_REQUIRED: &str = "Wayland requires Ubuntu 21.04 or higher version."; pub const SCRAP_OTHER_VERSION_OR_X11_REQUIRED: &str = @@ -284,15 +279,8 @@ fn create_capturer( #[cfg(all(windows, feature = "virtual_display_driver"))] fn ensure_close_virtual_device() -> ResultType<()> { let num_displays = Display::all()?.len(); - if num_displays == 0 { - // Device may sometimes be uninstalled by user in "Device Manager" Window. - // Closing device will clear the instance data. - virtual_display::close_device(); - } else if num_displays > 1 { - // Try close device, if display device changed. - if virtual_display::is_device_created() { - virtual_display::close_device(); - } + if num_displays > 1 { + virtual_display_manager::plug_out_headless(); } Ok(()) } @@ -938,46 +926,14 @@ fn try_get_displays() -> ResultType> { let mut displays = Display::all()?; if displays.len() == 0 { log::debug!("no displays, create virtual display"); - // Try plugin monitor - if LocalConfig::get_virtual_display_num() > 0 { - let mut device_already_created = false; - if let Err(e) = virtual_display::create_device() { - if e.to_string().contains("Device is already created") { - device_already_created = true; - } else { - log::debug!("Create device failed {}", e); - } - } - if device_already_created || virtual_display::is_device_created() { - // Reboot is not required for this case. - let mut _reboot_required = false; - virtual_display::install_update_driver(&mut _reboot_required)?; - if let Err(e) = virtual_display::plug_in_monitor(VIRTUAL_DISPLAY_INDEX_FOR_HEADLESS) - { - log::debug!("Plug in monitor failed {}", e); - } else { - let modes = [virtual_display::MonitorMode { - width: 1920, - height: 1080, - sync: 60, - }]; - if let Err(e) = virtual_display::update_monitor_modes( - VIRTUAL_DISPLAY_INDEX_FOR_HEADLESS, - &modes, - ) { - log::debug!("Update monitor modes failed {}", e); - } - } - } + if let Err(e) = virtual_display_manager::plug_in_headless() { + log::error!("plug in headless failed {}", e); + } else { displays = Display::all()?; } } else if displays.len() > 1 { - // to-do: do not close if in idd privacy mode. - // If more than one displays exists, close RustDeskVirtualDisplay - if virtual_display::is_device_created() { - virtual_display::close_device() - } + let _res = virtual_display_manager::plug_in_headless(); } Ok(displays) } diff --git a/src/virtual_display_manager.rs b/src/virtual_display_manager.rs new file mode 100644 index 000000000..82328915e --- /dev/null +++ b/src/virtual_display_manager.rs @@ -0,0 +1,106 @@ +use hbb_common::{allow_err, bail, lazy_static, log, ResultType}; +use std::{ + collections::HashSet, + sync::{Arc, Mutex}, +}; + +// virtual display index range: 0 - 2 are reserved for headless and other special uses. +const VIRTUAL_DISPLAY_INDEX_FOR_HEADLESS: u32 = 0; +const VIRTUAL_DISPLAY_START_FOR_PEER: u32 = 3; +const VIRTUAL_DISPLAY_MAX_COUNT: u32 = 10; + +lazy_static::lazy_static! { + static ref VIRTUAL_DISPLAY_MANAGER: Arc> = + Arc::new(Mutex::new(VirtualDisplayManager::default())); +} + +#[derive(Default)] +struct VirtualDisplayManager { + headless_index: Option, + peer_required_indices: HashSet, +} + +impl VirtualDisplayManager { + fn prepare_driver() -> ResultType<()> { + if let Err(e) = virtual_display::create_device() { + if !e.to_string().contains("Device is already created") { + bail!("Create device failed {}", e); + } + } + // Reboot is not required for this case. + let mut _reboot_required = false; + allow_err!(virtual_display::install_update_driver( + &mut _reboot_required + )); + Ok(()) + } + + fn plug_in_monitor(index: u32, modes: &[virtual_display::MonitorMode]) -> ResultType<()> { + if let Err(e) = virtual_display::plug_in_monitor(index) { + bail!("Plug in monitor failed {}", e); + } + if let Err(e) = virtual_display::update_monitor_modes(index, &modes) { + log::error!("Update monitor modes failed {}", e); + } + Ok(()) + } +} + +pub fn plug_in_headless() -> ResultType<()> { + let mut manager = VIRTUAL_DISPLAY_MANAGER.lock().unwrap(); + VirtualDisplayManager::prepare_driver()?; + let modes = [virtual_display::MonitorMode { + width: 1920, + height: 1080, + sync: 60, + }]; + VirtualDisplayManager::plug_in_monitor(VIRTUAL_DISPLAY_INDEX_FOR_HEADLESS, &modes)?; + manager.headless_index = Some(VIRTUAL_DISPLAY_INDEX_FOR_HEADLESS); + Ok(()) +} + +pub fn plug_out_headless() { + let mut manager = VIRTUAL_DISPLAY_MANAGER.lock().unwrap(); + if let Some(index) = manager.headless_index.take() { + if let Err(e) = virtual_display::plug_out_monitor(index) { + log::error!("Plug out monitor failed {}", e); + } + } +} + +pub fn plug_in_peer_required( + modes: Vec>, +) -> ResultType> { + let mut manager = VIRTUAL_DISPLAY_MANAGER.lock().unwrap(); + VirtualDisplayManager::prepare_driver()?; + + let mut indices: Vec = Vec::new(); + for m in modes.iter() { + for idx in VIRTUAL_DISPLAY_START_FOR_PEER..VIRTUAL_DISPLAY_MAX_COUNT { + if !manager.peer_required_indices.contains(&idx) { + match VirtualDisplayManager::plug_in_monitor(idx, m) { + Ok(_) => { + manager.peer_required_indices.insert(idx); + indices.push(idx); + } + Err(e) => { + log::error!("Plug in monitor failed {}", e); + } + } + } + } + } + + Ok(indices) +} + +pub fn plug_out_peer_required(modes: &[u32]) -> ResultType<()> { + let mut manager = VIRTUAL_DISPLAY_MANAGER.lock().unwrap(); + for idx in modes.iter() { + if manager.peer_required_indices.contains(idx) { + allow_err!(virtual_display::plug_out_monitor(*idx)); + manager.peer_required_indices.remove(idx); + } + } + Ok(()) +}