Merge branch 'master' into dev

This commit is contained in:
xxrl
2022-11-20 13:27:39 +08:00
107 changed files with 5470 additions and 1631 deletions

View File

@@ -18,7 +18,7 @@ fn build_c_impl() {
if build.get_compiler().is_like_msvc() {
build.define("WIN32", "");
// build.define("_AMD64_", "");
build.flag("-Zi");
build.flag("-Z7");
build.flag("-GR-");
// build.flag("-std:c++11");
} else {

View File

@@ -8,8 +8,8 @@ use std::{
};
use anyhow::Result;
use directories_next::ProjectDirs;
use rand::Rng;
use serde as de;
use serde_derive::{Deserialize, Serialize};
use sodiumoxide::crypto::sign;
@@ -80,6 +80,26 @@ pub const RS_PUB_KEY: &'static str = "OeVuKk5nlHiXp+APNn0Y3pC1Iwpwn44JGqrQCsWqmB
pub const RENDEZVOUS_PORT: i32 = 21116;
pub const RELAY_PORT: i32 = 21117;
macro_rules! serde_field_string {
($default_func:ident, $de_func:ident, $default_expr:expr) => {
fn $default_func() -> String {
$default_expr
}
fn $de_func<'de, D>(deserializer: D) -> Result<String, D::Error>
where
D: de::Deserializer<'de>,
{
let s: &str = de::Deserialize::deserialize(deserializer)?;
Ok(if s.is_empty() {
Self::$default_func()
} else {
s.to_owned()
})
}
};
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum NetworkType {
Direct,
@@ -142,9 +162,20 @@ pub struct PeerConfig {
pub size_ft: Size,
#[serde(default)]
pub size_pf: Size,
#[serde(default)]
pub view_style: String, // original (default), scale
#[serde(default)]
#[serde(
default = "PeerConfig::default_view_style",
deserialize_with = "PeerConfig::deserialize_view_style"
)]
pub view_style: String,
#[serde(
default = "PeerConfig::default_scroll_style",
deserialize_with = "PeerConfig::deserialize_scroll_style"
)]
pub scroll_style: String,
#[serde(
default = "PeerConfig::default_image_quality",
deserialize_with = "PeerConfig::deserialize_image_quality"
)]
pub image_quality: String,
#[serde(default)]
pub custom_image_quality: Vec<i32>,
@@ -167,9 +198,15 @@ pub struct PeerConfig {
#[serde(default)]
pub show_quality_monitor: bool,
// the other scalar value must before this
#[serde(default)]
// The other scalar value must before this
#[serde(
default,
deserialize_with = "PeerConfig::deserialize_options"
)]
pub options: HashMap<String, String>,
// Various data for flutter ui
#[serde(default)]
pub ui_flutter: HashMap<String, String>,
#[serde(default)]
pub info: PeerInfoSerde,
#[serde(default)]
@@ -372,12 +409,15 @@ impl Config {
pub fn get_home() -> PathBuf {
#[cfg(any(target_os = "android", target_os = "ios"))]
return Self::path(APP_HOME_DIR.read().unwrap().as_str());
if let Some(path) = dirs_next::home_dir() {
patch(path)
} else if let Ok(path) = std::env::current_dir() {
path
} else {
std::env::temp_dir()
#[cfg(not(any(target_os = "android", target_os = "ios")))]
{
if let Some(path) = dirs_next::home_dir() {
patch(path)
} else if let Ok(path) = std::env::current_dir() {
path
} else {
std::env::temp_dir()
}
}
}
@@ -388,17 +428,22 @@ impl Config {
path.push(p);
return path;
}
#[cfg(not(target_os = "macos"))]
let org = "";
#[cfg(target_os = "macos")]
let org = ORG.read().unwrap().clone();
// /var/root for root
if let Some(project) = ProjectDirs::from("", &org, &*APP_NAME.read().unwrap()) {
let mut path = patch(project.config_dir().to_path_buf());
path.push(p);
return path;
#[cfg(not(any(target_os = "android", target_os = "ios")))]
{
#[cfg(not(target_os = "macos"))]
let org = "";
#[cfg(target_os = "macos")]
let org = ORG.read().unwrap().clone();
// /var/root for root
if let Some(project) =
directories_next::ProjectDirs::from("", &org, &*APP_NAME.read().unwrap())
{
let mut path = patch(project.config_dir().to_path_buf());
path.push(p);
return path;
}
return "".into();
}
return "".into();
}
#[allow(unreachable_code)]
@@ -577,16 +622,19 @@ impl Config {
.to_string(),
);
}
let mut id = 0u32;
#[cfg(not(any(target_os = "android", target_os = "ios")))]
if let Ok(Some(ma)) = mac_address::get_mac_address() {
for x in &ma.bytes()[2..] {
id = (id << 8) | (*x as u32);
{
let mut id = 0u32;
if let Ok(Some(ma)) = mac_address::get_mac_address() {
for x in &ma.bytes()[2..] {
id = (id << 8) | (*x as u32);
}
id = id & 0x1FFFFFFF;
Some(id.to_string())
} else {
None
}
id = id & 0x1FFFFFFF;
Some(id.to_string())
} else {
None
}
}
@@ -885,6 +933,21 @@ impl PeerConfig {
}
Default::default()
}
serde_field_string!(default_view_style, deserialize_view_style, "original".to_owned());
serde_field_string!(default_scroll_style, deserialize_scroll_style, "scrollauto".to_owned());
serde_field_string!(default_image_quality, deserialize_image_quality, "balanced".to_owned());
fn deserialize_options<'de, D>(deserializer: D) -> Result<HashMap<String, String>, D::Error>
where
D: de::Deserializer<'de>,
{
let mut mp: HashMap<String, String> = de::Deserialize::deserialize(deserializer)?;
if !mp.contains_key("codec-preference") {
mp.insert("codec-preference".to_owned(), "auto".to_owned());
}
Ok(mp)
}
}
#[derive(Debug, Default, Serialize, Deserialize, Clone)]
@@ -897,6 +960,9 @@ pub struct LocalConfig {
pub fav: Vec<String>,
#[serde(default)]
options: HashMap<String, String>,
// Various data for flutter ui
#[serde(default)]
ui_flutter: HashMap<String, String>,
}
impl LocalConfig {
@@ -968,6 +1034,27 @@ impl LocalConfig {
config.store();
}
}
pub fn get_flutter_config(k: &str) -> String {
if let Some(v) = LOCAL_CONFIG.read().unwrap().ui_flutter.get(k) {
v.clone()
} else {
"".to_owned()
}
}
pub fn set_flutter_config(k: String, v: String) {
let mut config = LOCAL_CONFIG.write().unwrap();
let v2 = if v.is_empty() { None } else { Some(&v) };
if v2 != config.ui_flutter.get(&k) {
if v2.is_none() {
config.ui_flutter.remove(&k);
} else {
config.ui_flutter.insert(k, v);
}
config.store();
}
}
}
#[derive(Debug, Default, Serialize, Deserialize, Clone)]

View File

@@ -380,7 +380,7 @@ impl TransferJob {
}
}
pub async fn write(&mut self, block: FileTransferBlock, raw: Option<&[u8]>) -> ResultType<()> {
pub async fn write(&mut self, block: FileTransferBlock) -> ResultType<()> {
if block.id != self.id {
bail!("Wrong id");
}
@@ -402,20 +402,15 @@ impl TransferJob {
let path = format!("{}.download", get_string(&path));
self.file = Some(File::create(&path).await?);
}
let data = if let Some(data) = raw {
data
} else {
&block.data
};
if block.compressed {
let tmp = decompress(data);
let tmp = decompress(&block.data);
self.file.as_mut().unwrap().write_all(&tmp).await?;
self.finished_size += tmp.len() as u64;
} else {
self.file.as_mut().unwrap().write_all(data).await?;
self.finished_size += data.len() as u64;
self.file.as_mut().unwrap().write_all(&block.data).await?;
self.finished_size += block.data.len() as u64;
}
self.transferred += data.len() as u64;
self.transferred += block.data.len() as u64;
Ok(())
}

View File

@@ -161,19 +161,23 @@ pub fn get_version_from_url(url: &str) -> String {
}
pub fn gen_version() {
use std::io::prelude::*;
let mut file = File::create("./src/version.rs").unwrap();
for line in read_lines("Cargo.toml").unwrap() {
if let Ok(line) = line {
let ab: Vec<&str> = line.split("=").map(|x| x.trim()).collect();
if ab.len() == 2 && ab[0] == "version" {
use std::io::prelude::*;
file.write_all(format!("pub const VERSION: &str = {};", ab[1]).as_bytes())
file.write_all(format!("pub const VERSION: &str = {};\n", ab[1]).as_bytes())
.ok();
file.sync_all().ok();
break;
}
}
}
// generate build date
let build_date = format!("{}", chrono::Local::now().format("%Y-%m-%d %H:%M"));
file.write_all(format!("pub const BUILD_DATE: &str = \"{}\";", build_date).as_bytes())
.ok();
file.sync_all().ok();
}
fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>>

View File

@@ -51,24 +51,32 @@ fn execute(path: PathBuf, args: Vec<String>) {
.expect(&format!("failed to execute {:?}", exe_name));
}
fn is_setup(name: &str) -> bool {
name.to_lowercase().ends_with("install.exe") || name.to_lowercase().ends_with("安装.exe")
}
fn main() {
let is_setup = is_setup(
&std::env::current_exe()
.unwrap()
.to_string_lossy()
.to_string(),
);
let reader = BinaryReader::default();
if let Some(exe) = setup(reader, None, is_setup) {
let args = if is_setup {
vec!["--install".to_owned()]
let mut args = Vec::new();
let mut arg_exe = Default::default();
let mut i = 0;
for arg in std::env::args() {
if i == 0 {
arg_exe = arg.clone();
} else {
vec![]
};
args.push(arg);
}
i += 1;
}
let click_setup = args.is_empty() && arg_exe.to_lowercase().ends_with("install.exe");
let quick_support = args.is_empty() && arg_exe.to_lowercase().ends_with("qs.exe");
let reader = BinaryReader::default();
if let Some(exe) = setup(
reader,
None,
click_setup || args.contains(&"--silent-install".to_owned()),
) {
if click_setup {
args = vec!["--install".to_owned()];
} else if quick_support {
args = vec!["--quick_support".to_owned()];
}
execute(exe, args);
}
}

View File

@@ -1,6 +1,3 @@
pub mod ffi;
use std::sync::RwLock;
pub use ffi::*;
use lazy_static::lazy_static;

View File

@@ -61,7 +61,7 @@ impl TraitCapturer for Capturer {
}
}
pub struct Frame<'a>(&'a [u8]);
pub struct Frame<'a>(pub &'a [u8]);
impl<'a> ops::Deref for Frame<'a> {
type Target = [u8];

View File

@@ -4,7 +4,7 @@
use hbb_common::anyhow::{anyhow, Context};
use hbb_common::message_proto::{EncodedVideoFrame, EncodedVideoFrames, Message, VideoFrame};
use hbb_common::{ResultType, get_time};
use hbb_common::{get_time, ResultType};
use crate::codec::EncoderApi;
use crate::STRIDE_ALIGN;
@@ -233,7 +233,9 @@ impl EncoderApi for VpxEncoder {
impl VpxEncoder {
pub fn encode(&mut self, pts: i64, data: &[u8], stride_align: usize) -> Result<EncodeFrames> {
assert!(2 * data.len() >= 3 * self.width * self.height);
if 2 * data.len() < 3 * self.width * self.height {
return Err(Error::FailedCall("len not enough".to_string()));
}
let mut image = Default::default();
call_vpx_ptr!(vpx_img_wrap(

1358
libs/virtual_display/Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -5,12 +5,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[build-dependencies]
cc = "1.0"
[dependencies]
thiserror = "1.0.30"
lazy_static = "1.4"
serde = "1.0"
serde_derive = "1.0"
libloading = "0.7"
hbb_common = { path = "../hbb_common" }

View File

@@ -1,32 +1,3 @@
# virtual display
Virtual display may be used on computers that do not have a monitor.
[Development reference](https://github.com/pavlobu/deskreen/discussions/86)
## windows
### win10
Win10 provides [Indirect Display Driver Model](https://msdn.microsoft.com/en-us/library/windows/hardware/mt761968(v=vs.85).aspx).
This lib uses [this project](https://github.com/fufesou/RustDeskIddDriver) as the driver.
**NOTE**: Versions before Win10 1607. Try follow [this method](https://github.com/fanxiushu/xdisp_virt/tree/master/indirect_display).
#### tested platforms
- [x] 19041
- [x] 19043
### win7
TODO
[WDDM](https://docs.microsoft.com/en-us/windows-hardware/drivers/display/windows-vista-display-driver-model-design-guide).
## X11
## OSX
[doc](./dylib/README.md)

View File

@@ -0,0 +1,19 @@
[package]
name = "dylib_virtual_display"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib", "staticlib", "rlib"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[build-dependencies]
cc = "1.0"
[dependencies]
thiserror = "1.0.30"
lazy_static = "1.4"
serde = "1.0"
serde_derive = "1.0"
hbb_common = { path = "../../hbb_common" }

View File

@@ -0,0 +1,32 @@
# virtual display
Virtual display may be used on computers that do not have a monitor.
[Development reference](https://github.com/pavlobu/deskreen/discussions/86)
## windows
### win10
Win10 provides [Indirect Display Driver Model](https://msdn.microsoft.com/en-us/library/windows/hardware/mt761968(v=vs.85).aspx).
This lib uses [this project](https://github.com/fufesou/RustDeskIddDriver) as the driver.
**NOTE**: Versions before Win10 1607. Try follow [this method](https://github.com/fanxiushu/xdisp_virt/tree/master/indirect_display).
#### tested platforms
- [x] 19041
- [x] 19043
### win7
TODO
[WDDM](https://docs.microsoft.com/en-us/windows-hardware/drivers/display/windows-vista-display-driver-model-design-guide).
## X11
## OSX

View File

@@ -13,7 +13,7 @@ fn build_c_impl() {
if build.get_compiler().is_like_msvc() {
build.define("WIN32", "");
build.flag("-Zi");
build.flag("-Z7");
build.flag("-GR-");
// build.flag("-std:c++11");
} else {
@@ -24,7 +24,7 @@ fn build_c_impl() {
}
#[cfg(target_os = "windows")]
build.compile("xxx");
build.compile("win_virtual_display");
#[cfg(target_os = "windows")]
println!("cargo:rerun-if-changed=src/win10/IddController.c");

View File

@@ -1,5 +1,5 @@
#[cfg(windows)]
use virtual_display::win10::{idd, DRIVER_INSTALL_PATH};
use dylib_virtual_display::win10::{idd, DRIVER_INSTALL_PATH};
#[cfg(windows)]
use std::{

View File

@@ -0,0 +1,207 @@
#[cfg(windows)]
pub mod win10;
use hbb_common::{bail, lazy_static, ResultType};
use std::{path::Path, sync::Mutex};
lazy_static::lazy_static! {
// If device is uninstalled though "Device Manager" Window.
// Rustdesk is unable to handle device any more...
static ref H_SW_DEVICE: Mutex<u64> = Mutex::new(0);
static ref MONITOR_PLUGIN: Mutex<Vec<u32>> = Mutex::new(Vec::new());
}
#[no_mangle]
#[cfg(windows)]
pub fn get_dirver_install_path() -> &'static str {
win10::DRIVER_INSTALL_PATH
}
#[no_mangle]
pub fn download_driver() -> ResultType<()> {
#[cfg(windows)]
let _download_url = win10::DRIVER_DOWNLOAD_URL;
#[cfg(target_os = "linux")]
let _download_url = "";
// process download and report progress
Ok(())
}
#[no_mangle]
pub fn install_update_driver(_reboot_required: &mut bool) -> ResultType<()> {
#[cfg(windows)]
let install_path = win10::DRIVER_INSTALL_PATH;
#[cfg(not(windows))]
let install_path = "";
let abs_path = Path::new(install_path).canonicalize()?;
if !abs_path.exists() {
bail!("{} not exists", install_path)
}
#[cfg(windows)]
unsafe {
{
// Device must be created before install driver.
// https://github.com/fufesou/RustDeskIddDriver/issues/1
if let Err(e) = create_device() {
bail!("{}", e);
}
let full_install_path: Vec<u16> = abs_path
.to_string_lossy()
.as_ref()
.encode_utf16()
.chain(Some(0).into_iter())
.collect();
let mut reboot_required_tmp = win10::idd::FALSE;
if win10::idd::InstallUpdate(full_install_path.as_ptr() as _, &mut reboot_required_tmp)
== win10::idd::FALSE
{
bail!("{}", win10::get_last_msg()?);
}
*_reboot_required = reboot_required_tmp == win10::idd::TRUE;
}
}
Ok(())
}
#[no_mangle]
pub fn uninstall_driver(_reboot_required: &mut bool) -> ResultType<()> {
#[cfg(windows)]
let install_path = win10::DRIVER_INSTALL_PATH;
#[cfg(not(windows))]
let install_path = "";
let abs_path = Path::new(install_path).canonicalize()?;
if !abs_path.exists() {
bail!("{} not exists", install_path)
}
#[cfg(windows)]
unsafe {
{
let full_install_path: Vec<u16> = abs_path
.to_string_lossy()
.as_ref()
.encode_utf16()
.chain(Some(0).into_iter())
.collect();
let mut reboot_required_tmp = win10::idd::FALSE;
if win10::idd::Uninstall(full_install_path.as_ptr() as _, &mut reboot_required_tmp)
== win10::idd::FALSE
{
bail!("{}", win10::get_last_msg()?);
}
*_reboot_required = reboot_required_tmp == win10::idd::TRUE;
}
}
Ok(())
}
#[no_mangle]
pub fn is_device_created() -> bool {
#[cfg(windows)]
return *H_SW_DEVICE.lock().unwrap() != 0;
#[cfg(not(windows))]
return false;
}
#[no_mangle]
pub fn create_device() -> ResultType<()> {
if is_device_created() {
return Ok(());
}
#[cfg(windows)]
unsafe {
let mut lock_device = H_SW_DEVICE.lock().unwrap();
let mut h_sw_device = *lock_device as win10::idd::HSWDEVICE;
if win10::idd::DeviceCreate(&mut h_sw_device) == win10::idd::FALSE {
bail!("{}", win10::get_last_msg()?);
} else {
*lock_device = h_sw_device as u64;
}
}
Ok(())
}
#[no_mangle]
pub fn close_device() {
#[cfg(windows)]
unsafe {
win10::idd::DeviceClose(*H_SW_DEVICE.lock().unwrap() as win10::idd::HSWDEVICE);
*H_SW_DEVICE.lock().unwrap() = 0;
MONITOR_PLUGIN.lock().unwrap().clear();
}
}
#[no_mangle]
pub fn plug_in_monitor() -> ResultType<()> {
#[cfg(windows)]
unsafe {
let monitor_index = 0 as u32;
let mut plug_in_monitors = MONITOR_PLUGIN.lock().unwrap();
for i in 0..plug_in_monitors.len() {
if let Some(d) = plug_in_monitors.get(i) {
if *d == monitor_index {
return Ok(());
}
};
}
if win10::idd::MonitorPlugIn(monitor_index, 0, 30) == win10::idd::FALSE {
bail!("{}", win10::get_last_msg()?);
}
(*plug_in_monitors).push(monitor_index);
}
Ok(())
}
#[no_mangle]
pub fn plug_out_monitor() -> ResultType<()> {
#[cfg(windows)]
unsafe {
let monitor_index = 0 as u32;
if win10::idd::MonitorPlugOut(monitor_index) == win10::idd::FALSE {
bail!("{}", win10::get_last_msg()?);
}
let mut plug_in_monitors = MONITOR_PLUGIN.lock().unwrap();
for i in 0..plug_in_monitors.len() {
if let Some(d) = plug_in_monitors.get(i) {
if *d == monitor_index {
plug_in_monitors.remove(i);
break;
}
};
}
}
Ok(())
}
#[no_mangle]
pub fn update_monitor_modes() -> ResultType<()> {
#[cfg(windows)]
unsafe {
let monitor_index = 0 as u32;
let mut modes = vec![win10::idd::MonitorMode {
width: 1920,
height: 1080,
sync: 60,
}];
if win10::idd::FALSE
== win10::idd::MonitorModesUpdate(
monitor_index as win10::idd::UINT,
modes.len() as win10::idd::UINT,
modes.as_mut_ptr(),
)
{
bail!("{}", win10::get_last_msg()?);
}
}
Ok(())
}

View File

@@ -1,192 +1,125 @@
#[cfg(windows)]
pub mod win10;
use hbb_common::{bail, ResultType};
use std::sync::{Arc, Mutex};
use hbb_common::{bail, lazy_static, ResultType};
use std::{path::Path, sync::Mutex};
const LIB_NAME_VIRTUAL_DISPLAY: &str = "dylib_virtual_display";
lazy_static::lazy_static! {
// If device is uninstalled though "Device Manager" Window.
// Rustdesk is unable to handle device any more...
static ref H_SW_DEVICE: Mutex<u64> = Mutex::new(0);
static ref MONITOR_PLUGIN: Mutex<Vec<u32>> = Mutex::new(Vec::new());
static ref LIB_VIRTUAL_DISPLAY: Arc<Mutex<Result<libloading::Library, libloading::Error>>> = {
Arc::new(Mutex::new(unsafe { libloading::Library::new(get_lib_name()) }))
};
}
pub fn download_driver() -> ResultType<()> {
#[cfg(windows)]
let _download_url = win10::DRIVER_DOWNLOAD_URL;
#[cfg(target_os = "linux")]
let _download_url = "";
// process download and report progress
Ok(())
#[cfg(target_os = "windows")]
fn get_lib_name() -> String {
format!("{}.dll", LIB_NAME_VIRTUAL_DISPLAY)
}
pub fn install_update_driver(_reboot_required: &mut bool) -> ResultType<()> {
#[cfg(windows)]
let install_path = win10::DRIVER_INSTALL_PATH;
#[cfg(not(windows))]
let install_path = "";
let abs_path = Path::new(install_path).canonicalize()?;
if !abs_path.exists() {
bail!("{} not exists", install_path)
}
#[cfg(windows)]
unsafe {
{
// Device must be created before install driver.
// https://github.com/fufesou/RustDeskIddDriver/issues/1
if let Err(e) = create_device() {
bail!("{}", e);
}
let full_install_path: Vec<u16> = abs_path
.to_string_lossy()
.as_ref()
.encode_utf16()
.chain(Some(0).into_iter())
.collect();
let mut reboot_required_tmp = win10::idd::FALSE;
if win10::idd::InstallUpdate(full_install_path.as_ptr() as _, &mut reboot_required_tmp)
== win10::idd::FALSE
{
bail!("{}", win10::get_last_msg()?);
}
*_reboot_required = reboot_required_tmp == win10::idd::TRUE;
}
}
Ok(())
#[cfg(target_os = "linux")]
fn get_lib_name() -> String {
format!("lib{}.so", LIB_NAME_VIRTUAL_DISPLAY)
}
pub fn uninstall_driver(_reboot_required: &mut bool) -> ResultType<()> {
#[cfg(windows)]
let install_path = win10::DRIVER_INSTALL_PATH;
#[cfg(not(windows))]
let install_path = "";
#[cfg(target_os = "macos")]
fn get_lib_name() -> String {
format!("lib{}.dylib", LIB_NAME_VIRTUAL_DISPLAY)
}
let abs_path = Path::new(install_path).canonicalize()?;
if !abs_path.exists() {
bail!("{} not exists", install_path)
fn try_reload_lib() {
let mut lock = LIB_VIRTUAL_DISPLAY.lock().unwrap();
if lock.is_err() {
*lock = unsafe { libloading::Library::new(get_lib_name()) };
}
}
#[cfg(windows)]
unsafe {
{
let full_install_path: Vec<u16> = abs_path
.to_string_lossy()
.as_ref()
.encode_utf16()
.chain(Some(0).into_iter())
.collect();
let mut reboot_required_tmp = win10::idd::FALSE;
if win10::idd::Uninstall(full_install_path.as_ptr() as _, &mut reboot_required_tmp)
== win10::idd::FALSE
{
bail!("{}", win10::get_last_msg()?);
#[cfg(windows)]
pub fn get_dirver_install_path() -> ResultType<&'static str> {
try_reload_lib();
match &*LIB_VIRTUAL_DISPLAY.lock().unwrap() {
Ok(lib) => unsafe {
match lib.get::<libloading::Symbol<fn() -> &'static str>>(b"get_dirver_install_path") {
Ok(func) => Ok(func()),
Err(e) => bail!("Failed to load func get_dirver_install_path, {}", e),
}
*_reboot_required = reboot_required_tmp == win10::idd::TRUE;
}
},
Err(e) => bail!("Failed to load library {}, {}", LIB_NAME_VIRTUAL_DISPLAY, e),
}
Ok(())
}
pub fn is_device_created() -> bool {
#[cfg(windows)]
return *H_SW_DEVICE.lock().unwrap() != 0;
#[cfg(not(windows))]
return false;
}
pub fn create_device() -> ResultType<()> {
if is_device_created() {
return Ok(());
try_reload_lib();
match &*LIB_VIRTUAL_DISPLAY.lock().unwrap() {
Ok(lib) => unsafe {
match lib.get::<libloading::Symbol<fn() -> bool>>(b"is_device_created") {
Ok(func) => func(),
Err(..) => false,
}
},
Err(..) => false,
}
#[cfg(windows)]
unsafe {
let mut lock_device = H_SW_DEVICE.lock().unwrap();
let mut h_sw_device = *lock_device as win10::idd::HSWDEVICE;
if win10::idd::DeviceCreate(&mut h_sw_device) == win10::idd::FALSE {
bail!("{}", win10::get_last_msg()?);
} else {
*lock_device = h_sw_device as u64;
}
}
Ok(())
}
pub fn close_device() {
#[cfg(windows)]
unsafe {
win10::idd::DeviceClose(*H_SW_DEVICE.lock().unwrap() as win10::idd::HSWDEVICE);
*H_SW_DEVICE.lock().unwrap() = 0;
MONITOR_PLUGIN.lock().unwrap().clear();
try_reload_lib();
match &*LIB_VIRTUAL_DISPLAY.lock().unwrap() {
Ok(lib) => unsafe {
match lib.get::<libloading::Symbol<fn()>>(b"close_device") {
Ok(func) => func(),
Err(..) => {}
}
},
Err(..) => {}
}
}
pub fn plug_in_monitor() -> ResultType<()> {
#[cfg(windows)]
unsafe {
let monitor_index = 0 as u32;
let mut plug_in_monitors = MONITOR_PLUGIN.lock().unwrap();
for i in 0..plug_in_monitors.len() {
if let Some(d) = plug_in_monitors.get(i) {
if *d == monitor_index {
return Ok(());
}
};
macro_rules! def_func_result {
($func:ident, $name: tt) => {
pub fn $func() -> ResultType<()> {
try_reload_lib();
match &*LIB_VIRTUAL_DISPLAY.lock().unwrap() {
Ok(lib) => unsafe {
match lib.get::<libloading::Symbol<fn() -> ResultType<()>>>($name.as_bytes()) {
Ok(func) => func(),
Err(e) => bail!("Failed to load func {}, {}", $name, e),
}
},
Err(e) => bail!("Failed to load library {}, {}", LIB_NAME_VIRTUAL_DISPLAY, e),
}
}
if win10::idd::MonitorPlugIn(monitor_index, 0, 30) == win10::idd::FALSE {
bail!("{}", win10::get_last_msg()?);
}
(*plug_in_monitors).push(monitor_index);
}
Ok(())
};
}
pub fn plug_out_monitor() -> ResultType<()> {
#[cfg(windows)]
unsafe {
let monitor_index = 0 as u32;
if win10::idd::MonitorPlugOut(monitor_index) == win10::idd::FALSE {
bail!("{}", win10::get_last_msg()?);
}
let mut plug_in_monitors = MONITOR_PLUGIN.lock().unwrap();
for i in 0..plug_in_monitors.len() {
if let Some(d) = plug_in_monitors.get(i) {
if *d == monitor_index {
plug_in_monitors.remove(i);
break;
}
};
}
pub fn install_update_driver(reboot_required: &mut bool) -> ResultType<()> {
try_reload_lib();
match &*LIB_VIRTUAL_DISPLAY.lock().unwrap() {
Ok(lib) => unsafe {
match lib.get::<libloading::Symbol<fn(&mut bool) -> ResultType<()>>>(
b"install_update_driver",
) {
Ok(func) => func(reboot_required),
Err(e) => bail!("Failed to load func install_update_driver, {}", e),
}
},
Err(e) => bail!("Failed to load library {}, {}", LIB_NAME_VIRTUAL_DISPLAY, e),
}
Ok(())
}
pub fn update_monitor_modes() -> ResultType<()> {
#[cfg(windows)]
unsafe {
let monitor_index = 0 as u32;
let mut modes = vec![win10::idd::MonitorMode {
width: 1920,
height: 1080,
sync: 60,
}];
if win10::idd::FALSE
== win10::idd::MonitorModesUpdate(
monitor_index as win10::idd::UINT,
modes.len() as win10::idd::UINT,
modes.as_mut_ptr(),
)
{
bail!("{}", win10::get_last_msg()?);
}
pub fn uninstall_driver(reboot_required: &mut bool) -> ResultType<()> {
try_reload_lib();
match &*LIB_VIRTUAL_DISPLAY.lock().unwrap() {
Ok(lib) => unsafe {
match lib
.get::<libloading::Symbol<fn(&mut bool) -> ResultType<()>>>(b"uninstall_driver")
{
Ok(func) => func(reboot_required),
Err(e) => bail!("Failed to load func uninstall_driver, {}", e),
}
},
Err(e) => bail!("Failed to load library {}, {}", LIB_NAME_VIRTUAL_DISPLAY, e),
}
Ok(())
}
def_func_result!(download_driver, "download_driver");
def_func_result!(create_device, "create_device");
def_func_result!(plug_in_monitor, "plug_in_monitor");
def_func_result!(plug_out_monitor, "plug_out_monitor");
def_func_result!(update_monitor_modes, "update_monitor_modes");