refact virtual display
Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
parent
042a4e575f
commit
9d8e7745e2
4
build.py
4
build.py
@ -41,8 +41,8 @@ def get_version():
|
|||||||
def parse_rc_features(feature):
|
def parse_rc_features(feature):
|
||||||
available_features = {
|
available_features = {
|
||||||
'IddDriver': {
|
'IddDriver': {
|
||||||
'zip_url': 'https://github.com/fufesou/RustDeskIddDriver/releases/download/v0.1/RustDeskIddDriver_x64.zip',
|
'zip_url': 'https://github.com/fufesou/RustDeskIddDriver/releases/download/v0.3/RustDeskIddDriver_x64.zip',
|
||||||
'checksum_url': 'https://github.com/fufesou/RustDeskIddDriver/releases/download/v0.1/checksum_md5',
|
'checksum_url': 'https://github.com/fufesou/RustDeskIddDriver/releases/download/v0.3/checksum_md5',
|
||||||
'exclude': ['README.md', 'certmgr.exe', 'install_cert_runas_admin.bat'],
|
'exclude': ['README.md', 'certmgr.exe', 'install_cert_runas_admin.bat'],
|
||||||
},
|
},
|
||||||
'PrivacyMode': {
|
'PrivacyMode': {
|
||||||
|
@ -1141,8 +1141,6 @@ pub struct LocalConfig {
|
|||||||
// Various data for flutter ui
|
// Various data for flutter ui
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
ui_flutter: HashMap<String, String>,
|
ui_flutter: HashMap<String, String>,
|
||||||
#[serde(default)]
|
|
||||||
virtual_display_num: usize,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LocalConfig {
|
impl LocalConfig {
|
||||||
@ -1245,19 +1243,6 @@ impl LocalConfig {
|
|||||||
config.store();
|
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)]
|
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
|
||||||
|
@ -3,7 +3,7 @@ use virtual_display;
|
|||||||
|
|
||||||
fn prompt_input() -> u8 {
|
fn prompt_input() -> u8 {
|
||||||
println!("Press key execute:");
|
println!("Press key execute:");
|
||||||
println!(" 1. 'x' 1. exit");
|
println!(" 1. 'q' 1. quit");
|
||||||
println!(" 2. 'i' 2. install or update driver");
|
println!(" 2. 'i' 2. install or update driver");
|
||||||
println!(" 3. 'u' 3. uninstall driver");
|
println!(" 3. 'u' 3. uninstall driver");
|
||||||
println!(" 4. 'c' 4. create device");
|
println!(" 4. 'c' 4. create device");
|
||||||
@ -40,7 +40,7 @@ fn main() {
|
|||||||
loop {
|
loop {
|
||||||
let chr = prompt_input();
|
let chr = prompt_input();
|
||||||
match chr as char {
|
match chr as char {
|
||||||
'x' => break,
|
'q' => break,
|
||||||
'i' => {
|
'i' => {
|
||||||
println!("Install or update driver begin");
|
println!("Install or update driver begin");
|
||||||
let mut reboot_required = false;
|
let mut reboot_required = false;
|
||||||
|
@ -47,7 +47,10 @@ macro_rules! make_lib_wrapper {
|
|||||||
|
|
||||||
$(let $field = if let Some(lib) = &lib {
|
$(let $field = if let Some(lib) = &lib {
|
||||||
match unsafe { lib.symbol::<$tp>(stringify!($field)) } {
|
match unsafe { lib.symbol::<$tp>(stringify!($field)) } {
|
||||||
Ok(m) => Some(*m),
|
Ok(m) => {
|
||||||
|
log::info!("method found {}", stringify!($field));
|
||||||
|
Some(*m)
|
||||||
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::warn!("Failed to load func {}, {}", stringify!($field), e);
|
log::warn!("Failed to load func {}, {}", stringify!($field), e);
|
||||||
None
|
None
|
||||||
|
@ -69,3 +69,6 @@ pub mod rc;
|
|||||||
|
|
||||||
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
#[cfg(not(any(target_os = "android", target_os = "ios")))]
|
||||||
pub mod privacy_win_mag;
|
pub mod privacy_win_mag;
|
||||||
|
|
||||||
|
#[cfg(all(windows, feature = "virtual_display_driver"))]
|
||||||
|
pub mod virtual_display_manager;
|
||||||
|
@ -19,10 +19,10 @@
|
|||||||
// https://slhck.info/video/2017/03/01/rate-control.html
|
// https://slhck.info/video/2017/03/01/rate-control.html
|
||||||
|
|
||||||
use super::{video_qos::VideoQoS, *};
|
use super::{video_qos::VideoQoS, *};
|
||||||
|
#[cfg(all(windows, feature = "virtual_display_driver"))]
|
||||||
|
use crate::virtual_display_manager;
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
use crate::{platform::windows::is_process_consent_running, privacy_win_mag};
|
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)]
|
#[cfg(windows)]
|
||||||
use hbb_common::get_version_number;
|
use hbb_common::get_version_number;
|
||||||
use hbb_common::tokio::sync::{
|
use hbb_common::tokio::sync::{
|
||||||
@ -45,11 +45,6 @@ use std::{
|
|||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
time::{self, Duration, Instant},
|
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_UBUNTU_HIGHER_REQUIRED: &str = "Wayland requires Ubuntu 21.04 or higher version.";
|
||||||
pub const SCRAP_OTHER_VERSION_OR_X11_REQUIRED: &str =
|
pub const SCRAP_OTHER_VERSION_OR_X11_REQUIRED: &str =
|
||||||
@ -284,15 +279,8 @@ fn create_capturer(
|
|||||||
#[cfg(all(windows, feature = "virtual_display_driver"))]
|
#[cfg(all(windows, feature = "virtual_display_driver"))]
|
||||||
fn ensure_close_virtual_device() -> ResultType<()> {
|
fn ensure_close_virtual_device() -> ResultType<()> {
|
||||||
let num_displays = Display::all()?.len();
|
let num_displays = Display::all()?.len();
|
||||||
if num_displays == 0 {
|
if num_displays > 1 {
|
||||||
// Device may sometimes be uninstalled by user in "Device Manager" Window.
|
virtual_display_manager::plug_out_headless();
|
||||||
// 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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -938,46 +926,14 @@ fn try_get_displays() -> ResultType<Vec<Display>> {
|
|||||||
let mut displays = Display::all()?;
|
let mut displays = Display::all()?;
|
||||||
if displays.len() == 0 {
|
if displays.len() == 0 {
|
||||||
log::debug!("no displays, create virtual display");
|
log::debug!("no displays, create virtual display");
|
||||||
// Try plugin monitor
|
if let Err(e) = virtual_display_manager::plug_in_headless() {
|
||||||
if LocalConfig::get_virtual_display_num() > 0 {
|
log::error!("plug in headless failed {}", e);
|
||||||
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 {
|
} 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
displays = Display::all()?;
|
displays = Display::all()?;
|
||||||
}
|
}
|
||||||
} else if displays.len() > 1 {
|
} else if displays.len() > 1 {
|
||||||
// to-do: do not close if in idd privacy mode.
|
|
||||||
|
|
||||||
// If more than one displays exists, close RustDeskVirtualDisplay
|
// If more than one displays exists, close RustDeskVirtualDisplay
|
||||||
if virtual_display::is_device_created() {
|
let _res = virtual_display_manager::plug_in_headless();
|
||||||
virtual_display::close_device()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Ok(displays)
|
Ok(displays)
|
||||||
}
|
}
|
||||||
|
106
src/virtual_display_manager.rs
Normal file
106
src/virtual_display_manager.rs
Normal file
@ -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<Mutex<VirtualDisplayManager>> =
|
||||||
|
Arc::new(Mutex::new(VirtualDisplayManager::default()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
struct VirtualDisplayManager {
|
||||||
|
headless_index: Option<u32>,
|
||||||
|
peer_required_indices: HashSet<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
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<Vec<virtual_display::MonitorMode>>,
|
||||||
|
) -> ResultType<Vec<u32>> {
|
||||||
|
let mut manager = VIRTUAL_DISPLAY_MANAGER.lock().unwrap();
|
||||||
|
VirtualDisplayManager::prepare_driver()?;
|
||||||
|
|
||||||
|
let mut indices: Vec<u32> = 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(())
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user